@media-quest/builder 0.0.26 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/public-api.d.ts +820 -0
- package/dist/public-api.js +2740 -0
- package/dist/public-api.js.map +1 -0
- package/package.json +29 -15
- package/src/Builder-question.ts +0 -4
- package/src/Builder-schema.spec.ts +79 -60
- package/src/Builder-schema.ts +73 -63
- package/src/code-book/codebook-variable.ts +27 -29
- package/src/code-book/codebook.ts +81 -72
- package/src/page/Builder-page-collection.spec.ts +219 -0
- package/src/page/Builder-page-collection.ts +129 -0
- package/src/{Builder-page.spec.ts → page/Builder-page.spec.ts} +21 -6
- package/src/{Builder-page.ts → page/Builder-page.ts} +84 -16
- package/src/primitives/ID.ts +135 -138
- package/src/public-api.ts +28 -28
- package/src/rulebuilder/RuleAction.ts +105 -106
- package/src/sum-score/sum-score-variable-collection.spec.ts +68 -0
- package/src/sum-score/sum-score-variable-collection.ts +101 -0
- package/src/sum-score/sum-score-variable.spec.ts +308 -151
- package/src/sum-score/sum-score-variable.ts +102 -36
- package/src/sum-score/sum-score.ts +161 -122
- package/src/tag/BuilderTag.ts +45 -0
- package/src/tag/Tag-Collection.ts +53 -0
- package/src/theme/default-theme-compiler.ts +358 -358
- package/tsconfig.json +19 -15
- package/src/BuilderTag.ts +0 -96
- package/src/sum-score/sum-score-manager.spec.ts +0 -189
- package/src/sum-score/sum-score-manager.ts +0 -154
- package/src/sum-score/sum-score-membership.ts +0 -45
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -1,358 +1,358 @@
|
|
|
1
|
-
import { AbstractThemeCompiler } from "./AbstractThemeCompiler";
|
|
2
|
-
import type { BuilderSchemaDto } from "../Builder-schema";
|
|
3
|
-
import { BuilderSchema } from "../Builder-schema";
|
|
4
|
-
import type { BuilderPageDto } from "../Builder-page";
|
|
5
|
-
import { ThemeUtils } from "./theme-utils";
|
|
6
|
-
import { DefaultTheme, type IDefaultTheme } from "./IDefaultTheme";
|
|
7
|
-
import type { BuilderMainImageDto } from "../BuilderMainImageDto";
|
|
8
|
-
import type { BuilderMainVideoDto } from "../BuilderMainVideoDto";
|
|
9
|
-
import {
|
|
10
|
-
ButtonClickAction,
|
|
11
|
-
DDivDto,
|
|
12
|
-
DElementDto,
|
|
13
|
-
DImgDto,
|
|
14
|
-
DTextDto,
|
|
15
|
-
PageDto,
|
|
16
|
-
PageComponentDto,
|
|
17
|
-
RuleActionPageQue,
|
|
18
|
-
PlayAudioTask,
|
|
19
|
-
PlayVideoTask,
|
|
20
|
-
Rule,
|
|
21
|
-
SchemaDto,
|
|
22
|
-
DelayTask,
|
|
23
|
-
} from "@media-quest/engine";
|
|
24
|
-
|
|
25
|
-
import { AudioFile } from "../media-files";
|
|
26
|
-
import { BuilderRule } from "../rulebuilder";
|
|
27
|
-
|
|
28
|
-
export class DefaultThemeCompiler extends AbstractThemeCompiler<IDefaultTheme> {
|
|
29
|
-
readonly name = "Ispe default theme.";
|
|
30
|
-
private readonly TAG = "[ DEFAULT_THEME_COMPILER ]: ";
|
|
31
|
-
constructor() {
|
|
32
|
-
super(DefaultTheme);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
private compileRules(source: BuilderSchemaDto): Rule<RuleActionPageQue, never>[] {
|
|
36
|
-
const builderSchema = BuilderSchema.fromJson(source);
|
|
37
|
-
const ruleInput = builderSchema.getRuleInput();
|
|
38
|
-
const pageQueRules: Rule<RuleActionPageQue, never>[] = [];
|
|
39
|
-
source.rules.forEach((rule) => {
|
|
40
|
-
const engineRule = BuilderRule.fromDto(rule, ruleInput).toEngineRule();
|
|
41
|
-
if (!Rule.isEmpty(engineRule)) {
|
|
42
|
-
pageQueRules.push(engineRule);
|
|
43
|
-
} else {
|
|
44
|
-
console.log(this.TAG, "Throws away empty rule. " + rule.type + " " + rule.name);
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
return pageQueRules;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
compile(source: BuilderSchemaDto): SchemaDto {
|
|
51
|
-
const pages = source.pages.map((p) => this.compilePage(p, source.prefix));
|
|
52
|
-
const rules = this.compileRules(source);
|
|
53
|
-
|
|
54
|
-
const dto: SchemaDto = {
|
|
55
|
-
backgroundColor: source.backgroundColor,
|
|
56
|
-
baseHeight: source.baseHeight,
|
|
57
|
-
baseWidth: source.baseWidth,
|
|
58
|
-
id: source.id,
|
|
59
|
-
pageSequences: [],
|
|
60
|
-
pages,
|
|
61
|
-
predefinedFacts: [],
|
|
62
|
-
rules,
|
|
63
|
-
};
|
|
64
|
-
return dto;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
private compilePage(page: BuilderPageDto, modulePrefix: string): PageDto {
|
|
68
|
-
const tags = page.tags ?? [];
|
|
69
|
-
const { nextButton, mainText, id, mainMedia, _type, prefix } = page;
|
|
70
|
-
const staticElements: DElementDto[] = [];
|
|
71
|
-
let initialAudioTasks: Array<PlayAudioTask | DelayTask> = [];
|
|
72
|
-
let initialVideoTaskList: Array<PlayVideoTask | DelayTask> = [];
|
|
73
|
-
const newPage: PageDto = {
|
|
74
|
-
background: "white",
|
|
75
|
-
components: [],
|
|
76
|
-
staticElements,
|
|
77
|
-
id,
|
|
78
|
-
prefix,
|
|
79
|
-
initialTasks: [],
|
|
80
|
-
tags: [...tags],
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
if (page.mainText.audioFile) {
|
|
84
|
-
const autoPlay = page.mainText.autoplay;
|
|
85
|
-
const autoPlayDelay = page.mainText.autoplayDelay;
|
|
86
|
-
const res = this.compileMainTextAudio(page.mainText.audioFile, autoPlay, autoPlayDelay);
|
|
87
|
-
initialAudioTasks = [...res.initialTasks];
|
|
88
|
-
newPage.components.push(...res.components);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (_type === "question") {
|
|
92
|
-
const variableId = modulePrefix + "_" + page.prefix;
|
|
93
|
-
const { components, question } = this.compileQuestion(id, page, variableId);
|
|
94
|
-
newPage.components.push(...components);
|
|
95
|
-
newPage.staticElements.push(question);
|
|
96
|
-
// console.log(question);
|
|
97
|
-
// elements.push(...buttons, question);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (_type === "info-page") {
|
|
101
|
-
const infoText = mainText.text;
|
|
102
|
-
const nextButtonComponent = this.compileButton(nextButton, {
|
|
103
|
-
kind: "next-button",
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
const textStyle = mainMedia
|
|
107
|
-
? DefaultTheme.mainText.withMedia.text.css
|
|
108
|
-
: DefaultTheme.mainText.noMedia.text.css;
|
|
109
|
-
const infoTextElement: DElementDto = {
|
|
110
|
-
innerText: infoText,
|
|
111
|
-
_tag: "p",
|
|
112
|
-
style: textStyle,
|
|
113
|
-
};
|
|
114
|
-
newPage.staticElements.push(infoTextElement);
|
|
115
|
-
newPage.components.push(nextButtonComponent);
|
|
116
|
-
}
|
|
117
|
-
if (mainMedia && mainMedia.kind === "main-image") {
|
|
118
|
-
const mainImageElement = this.compileImage(mainMedia);
|
|
119
|
-
newPage.staticElements.push(mainImageElement);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (mainMedia && mainMedia.kind === "main-video") {
|
|
123
|
-
const videoOutput = this.compileVideo(mainMedia);
|
|
124
|
-
newPage.videoPlayer = videoOutput.videoPlayer;
|
|
125
|
-
newPage.components.push(...videoOutput.components);
|
|
126
|
-
initialVideoTaskList = [...videoOutput.autoPlayTasks];
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// ADDING INITIAL TASKS IN CORRECT ORDER
|
|
130
|
-
newPage.initialTasks.push(...initialVideoTaskList);
|
|
131
|
-
newPage.initialTasks.push(...initialAudioTasks);
|
|
132
|
-
const clone = JSON.parse(JSON.stringify(newPage));
|
|
133
|
-
return clone;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
private compileImage(image: BuilderMainImageDto) {
|
|
137
|
-
const img: DImgDto = {
|
|
138
|
-
_tag: "img",
|
|
139
|
-
style: this.theme.image.style,
|
|
140
|
-
url: image.file.downloadUrl,
|
|
141
|
-
};
|
|
142
|
-
return img;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
private compileMainTextAudio(
|
|
146
|
-
audioFile: AudioFile,
|
|
147
|
-
autoPlay: boolean,
|
|
148
|
-
autoPlayDelay: number,
|
|
149
|
-
): {
|
|
150
|
-
components: PageComponentDto[];
|
|
151
|
-
initialTasks: Array<PlayAudioTask | DelayTask>;
|
|
152
|
-
} {
|
|
153
|
-
const t = this.theme.mainText;
|
|
154
|
-
const audioId = audioFile.id;
|
|
155
|
-
const iconUrl =
|
|
156
|
-
"https://firebasestorage.googleapis.com/v0/b/ispe-backend-dev.appspot.com/o/public-assets%2Fvolume_up-24px.svg?alt=media&token=551bd0a6-a515-4f87-a245-da433f4833f9";
|
|
157
|
-
|
|
158
|
-
const playMainTextAudio: DImgDto = {
|
|
159
|
-
_tag: "img",
|
|
160
|
-
url: iconUrl,
|
|
161
|
-
style: { ...t.withMedia.audio.css },
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
const task: PlayAudioTask = {
|
|
165
|
-
audioId,
|
|
166
|
-
blockAudio: false,
|
|
167
|
-
blockFormInput: false,
|
|
168
|
-
blockResponseButton: false,
|
|
169
|
-
blockVideo: false,
|
|
170
|
-
kind: "play-audio-task",
|
|
171
|
-
priority: "replace-all",
|
|
172
|
-
url: audioFile.downloadUrl,
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
let initialAudioTasks: Array<PlayAudioTask | DelayTask> = [];
|
|
176
|
-
if (autoPlay) {
|
|
177
|
-
const playAudioTask: PlayAudioTask = { ...task, priority: "follow-queue" };
|
|
178
|
-
initialAudioTasks = [playAudioTask];
|
|
179
|
-
if (autoPlayDelay > 0) {
|
|
180
|
-
const delayTask: DelayTask = {
|
|
181
|
-
kind: "delay-task",
|
|
182
|
-
priority: "follow-queue",
|
|
183
|
-
duration: autoPlayDelay,
|
|
184
|
-
blockVideo: false,
|
|
185
|
-
blockAudio: false,
|
|
186
|
-
blockResponseButton: false,
|
|
187
|
-
blockFormInput: false,
|
|
188
|
-
};
|
|
189
|
-
initialAudioTasks = [delayTask, playAudioTask];
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
// const autoplayTask =
|
|
193
|
-
const playBtn: PageComponentDto = {
|
|
194
|
-
el: playMainTextAudio,
|
|
195
|
-
onClick: { kind: "play-audio", task },
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
return { components: [playBtn], initialTasks: [...initialAudioTasks] };
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
private compileVideo(video: BuilderMainVideoDto): {
|
|
202
|
-
videoPlayer: PageDto["videoPlayer"];
|
|
203
|
-
components: PageComponentDto[];
|
|
204
|
-
autoPlayTasks: Array<PlayVideoTask | DelayTask>;
|
|
205
|
-
} {
|
|
206
|
-
const t = this.theme.videoPlayer;
|
|
207
|
-
const mode = video.mode;
|
|
208
|
-
const components: PageComponentDto[] = [];
|
|
209
|
-
|
|
210
|
-
let autoPlayTasks: Array<PlayVideoTask | DelayTask> = [];
|
|
211
|
-
|
|
212
|
-
let autoplayVideoTask: PlayVideoTask | false = false;
|
|
213
|
-
let autoplayDelayTask: DelayTask | false = false;
|
|
214
|
-
|
|
215
|
-
const playButtonTask: PlayVideoTask = {
|
|
216
|
-
kind: "play-video-task",
|
|
217
|
-
url: video.file.downloadUrl,
|
|
218
|
-
videoId: video.file.id,
|
|
219
|
-
blockAudio: false,
|
|
220
|
-
blockFormInput: false,
|
|
221
|
-
blockResponseButton: false,
|
|
222
|
-
loop: mode === "gif-mode",
|
|
223
|
-
blockVideo: false,
|
|
224
|
-
priority: "replace-all",
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
if (video.mode === "autoplay" || video.mode === "gif-mode") {
|
|
228
|
-
autoplayVideoTask = { ...playButtonTask, priority: "follow-queue" };
|
|
229
|
-
autoPlayTasks = [autoplayVideoTask];
|
|
230
|
-
if (video.preDelay > 0) {
|
|
231
|
-
autoplayDelayTask = {
|
|
232
|
-
kind: "delay-task",
|
|
233
|
-
priority: "follow-queue",
|
|
234
|
-
duration: video.preDelay,
|
|
235
|
-
blockVideo: false,
|
|
236
|
-
blockAudio: false,
|
|
237
|
-
blockResponseButton: false,
|
|
238
|
-
blockFormInput: false,
|
|
239
|
-
};
|
|
240
|
-
autoPlayTasks = [autoplayDelayTask, autoplayVideoTask];
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const videoPlayer: PageDto["videoPlayer"] = {
|
|
245
|
-
playUrl: video.file.downloadUrl,
|
|
246
|
-
style: { h: 45, w: 100, x: 0, y: 55 },
|
|
247
|
-
};
|
|
248
|
-
const playButton: PageComponentDto = {
|
|
249
|
-
el: {
|
|
250
|
-
_tag: "img",
|
|
251
|
-
url: t.playButton.iconUrl,
|
|
252
|
-
style: { ...t.playButton.css, ...t.playButton.cssEnabled },
|
|
253
|
-
},
|
|
254
|
-
onClick: { kind: "play-video", task: playButtonTask },
|
|
255
|
-
whenVideoPlay: { visibility: "hidden" },
|
|
256
|
-
whenVideoPaused: { visibility: "visible" },
|
|
257
|
-
};
|
|
258
|
-
const pauseBtn: PageComponentDto = {
|
|
259
|
-
el: {
|
|
260
|
-
_tag: "img",
|
|
261
|
-
style: {
|
|
262
|
-
...t.pauseButton.css,
|
|
263
|
-
visibility: "hidden",
|
|
264
|
-
...t.pauseButton.cssEnabled,
|
|
265
|
-
},
|
|
266
|
-
url: t.pauseButton.iconUrl,
|
|
267
|
-
},
|
|
268
|
-
onClick: { kind: "pause-video" },
|
|
269
|
-
whenVideoPlay: { visibility: "visible" },
|
|
270
|
-
whenVideoPaused: { visibility: "hidden" },
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
if (mode !== "gif-mode") {
|
|
274
|
-
components.push(playButton);
|
|
275
|
-
components.push(pauseBtn);
|
|
276
|
-
}
|
|
277
|
-
return { videoPlayer, components, autoPlayTasks: [...autoPlayTasks] };
|
|
278
|
-
}
|
|
279
|
-
private compileQuestion(
|
|
280
|
-
pageId: string,
|
|
281
|
-
page: BuilderPageDto,
|
|
282
|
-
variableId: string,
|
|
283
|
-
): {
|
|
284
|
-
question: DTextDto;
|
|
285
|
-
components: PageComponentDto[];
|
|
286
|
-
} {
|
|
287
|
-
// TODO REFACTORE DEFAULT QUESTION TO - (REMOVE USE TEXT1)
|
|
288
|
-
// console.log(page);
|
|
289
|
-
const q = page.defaultQuestion;
|
|
290
|
-
const text = page.mainText.text;
|
|
291
|
-
const questionStyle = page.mainMedia
|
|
292
|
-
? DefaultTheme.mainText.withMedia.text.css
|
|
293
|
-
: DefaultTheme.mainText.noMedia.text.css;
|
|
294
|
-
const question: DTextDto = {
|
|
295
|
-
_tag: "p",
|
|
296
|
-
innerText: text,
|
|
297
|
-
style: questionStyle,
|
|
298
|
-
};
|
|
299
|
-
const buttons: PageComponentDto[] = q.options.map((o) => {
|
|
300
|
-
const btns = this.compileButton(o, {
|
|
301
|
-
kind: "response-button",
|
|
302
|
-
questionId: variableId,
|
|
303
|
-
questionText: text,
|
|
304
|
-
});
|
|
305
|
-
return btns;
|
|
306
|
-
});
|
|
307
|
-
const rootElements = buttons.map((b) => b.el);
|
|
308
|
-
ThemeUtils.spaceEvenlyX(rootElements);
|
|
309
|
-
return { question, components: buttons };
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
private compileButton(
|
|
313
|
-
buttonDto: BuilderPageDto["nextButton"],
|
|
314
|
-
options:
|
|
315
|
-
| { kind: "response-button"; questionId: string; questionText: string }
|
|
316
|
-
| { kind: "next-button" },
|
|
317
|
-
): PageComponentDto {
|
|
318
|
-
const { id, value, label } = buttonDto;
|
|
319
|
-
const onclickAction: ButtonClickAction =
|
|
320
|
-
options.kind === "response-button"
|
|
321
|
-
? {
|
|
322
|
-
kind: "submit-fact",
|
|
323
|
-
fact: {
|
|
324
|
-
kind: "numeric-fact",
|
|
325
|
-
label: label,
|
|
326
|
-
value: value,
|
|
327
|
-
referenceId: options.questionId,
|
|
328
|
-
referenceLabel: options.questionText,
|
|
329
|
-
},
|
|
330
|
-
}
|
|
331
|
-
: { kind: "next-page" };
|
|
332
|
-
|
|
333
|
-
const btnStyles =
|
|
334
|
-
value === 9 ? DefaultTheme.responseButtons.dontKnow : DefaultTheme.responseButtons.normal;
|
|
335
|
-
const btn: DDivDto = {
|
|
336
|
-
_tag: "div",
|
|
337
|
-
children: [
|
|
338
|
-
{
|
|
339
|
-
_tag: "p",
|
|
340
|
-
innerText: label,
|
|
341
|
-
style: btnStyles.text1,
|
|
342
|
-
},
|
|
343
|
-
],
|
|
344
|
-
style: { ...btnStyles.btn.css, ...btnStyles.btn.cssEnabled },
|
|
345
|
-
};
|
|
346
|
-
|
|
347
|
-
if (options.kind === "next-button") {
|
|
348
|
-
btn.style.x = 50;
|
|
349
|
-
btn.style.y = 8;
|
|
350
|
-
btn.style.transform = "translate(-50%, 0%)";
|
|
351
|
-
}
|
|
352
|
-
const component: PageComponentDto = {
|
|
353
|
-
el: btn,
|
|
354
|
-
onClick: onclickAction,
|
|
355
|
-
};
|
|
356
|
-
return component;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
1
|
+
import { AbstractThemeCompiler } from "./AbstractThemeCompiler";
|
|
2
|
+
import type { BuilderSchemaDto } from "../Builder-schema";
|
|
3
|
+
import { BuilderSchema } from "../Builder-schema";
|
|
4
|
+
import type { BuilderPageDto } from "../page/Builder-page";
|
|
5
|
+
import { ThemeUtils } from "./theme-utils";
|
|
6
|
+
import { DefaultTheme, type IDefaultTheme } from "./IDefaultTheme";
|
|
7
|
+
import type { BuilderMainImageDto } from "../BuilderMainImageDto";
|
|
8
|
+
import type { BuilderMainVideoDto } from "../BuilderMainVideoDto";
|
|
9
|
+
import {
|
|
10
|
+
ButtonClickAction,
|
|
11
|
+
DDivDto,
|
|
12
|
+
DElementDto,
|
|
13
|
+
DImgDto,
|
|
14
|
+
DTextDto,
|
|
15
|
+
PageDto,
|
|
16
|
+
PageComponentDto,
|
|
17
|
+
RuleActionPageQue,
|
|
18
|
+
PlayAudioTask,
|
|
19
|
+
PlayVideoTask,
|
|
20
|
+
Rule,
|
|
21
|
+
SchemaDto,
|
|
22
|
+
DelayTask,
|
|
23
|
+
} from "@media-quest/engine";
|
|
24
|
+
|
|
25
|
+
import { AudioFile } from "../media-files";
|
|
26
|
+
import { BuilderRule } from "../rulebuilder";
|
|
27
|
+
|
|
28
|
+
export class DefaultThemeCompiler extends AbstractThemeCompiler<IDefaultTheme> {
|
|
29
|
+
readonly name = "Ispe default theme.";
|
|
30
|
+
private readonly TAG = "[ DEFAULT_THEME_COMPILER ]: ";
|
|
31
|
+
constructor() {
|
|
32
|
+
super(DefaultTheme);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private compileRules(source: BuilderSchemaDto): Rule<RuleActionPageQue, never>[] {
|
|
36
|
+
const builderSchema = BuilderSchema.fromJson(source);
|
|
37
|
+
const ruleInput = builderSchema.getRuleInput();
|
|
38
|
+
const pageQueRules: Rule<RuleActionPageQue, never>[] = [];
|
|
39
|
+
source.rules.forEach((rule) => {
|
|
40
|
+
const engineRule = BuilderRule.fromDto(rule, ruleInput).toEngineRule();
|
|
41
|
+
if (!Rule.isEmpty(engineRule)) {
|
|
42
|
+
pageQueRules.push(engineRule);
|
|
43
|
+
} else {
|
|
44
|
+
console.log(this.TAG, "Throws away empty rule. " + rule.type + " " + rule.name);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return pageQueRules;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
compile(source: BuilderSchemaDto): SchemaDto {
|
|
51
|
+
const pages = source.pages.map((p) => this.compilePage(p, source.prefix));
|
|
52
|
+
const rules = this.compileRules(source);
|
|
53
|
+
|
|
54
|
+
const dto: SchemaDto = {
|
|
55
|
+
backgroundColor: source.backgroundColor,
|
|
56
|
+
baseHeight: source.baseHeight,
|
|
57
|
+
baseWidth: source.baseWidth,
|
|
58
|
+
id: source.id,
|
|
59
|
+
pageSequences: [],
|
|
60
|
+
pages,
|
|
61
|
+
predefinedFacts: [],
|
|
62
|
+
rules,
|
|
63
|
+
};
|
|
64
|
+
return dto;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private compilePage(page: BuilderPageDto, modulePrefix: string): PageDto {
|
|
68
|
+
const tags = page.tags ?? [];
|
|
69
|
+
const { nextButton, mainText, id, mainMedia, _type, prefix } = page;
|
|
70
|
+
const staticElements: DElementDto[] = [];
|
|
71
|
+
let initialAudioTasks: Array<PlayAudioTask | DelayTask> = [];
|
|
72
|
+
let initialVideoTaskList: Array<PlayVideoTask | DelayTask> = [];
|
|
73
|
+
const newPage: PageDto = {
|
|
74
|
+
background: "white",
|
|
75
|
+
components: [],
|
|
76
|
+
staticElements,
|
|
77
|
+
id,
|
|
78
|
+
prefix,
|
|
79
|
+
initialTasks: [],
|
|
80
|
+
tags: [...tags],
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
if (page.mainText.audioFile) {
|
|
84
|
+
const autoPlay = page.mainText.autoplay;
|
|
85
|
+
const autoPlayDelay = page.mainText.autoplayDelay;
|
|
86
|
+
const res = this.compileMainTextAudio(page.mainText.audioFile, autoPlay, autoPlayDelay);
|
|
87
|
+
initialAudioTasks = [...res.initialTasks];
|
|
88
|
+
newPage.components.push(...res.components);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (_type === "question") {
|
|
92
|
+
const variableId = modulePrefix + "_" + page.prefix;
|
|
93
|
+
const { components, question } = this.compileQuestion(id, page, variableId);
|
|
94
|
+
newPage.components.push(...components);
|
|
95
|
+
newPage.staticElements.push(question);
|
|
96
|
+
// console.log(question);
|
|
97
|
+
// elements.push(...buttons, question);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (_type === "info-page") {
|
|
101
|
+
const infoText = mainText.text;
|
|
102
|
+
const nextButtonComponent = this.compileButton(nextButton, {
|
|
103
|
+
kind: "next-button",
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const textStyle = mainMedia
|
|
107
|
+
? DefaultTheme.mainText.withMedia.text.css
|
|
108
|
+
: DefaultTheme.mainText.noMedia.text.css;
|
|
109
|
+
const infoTextElement: DElementDto = {
|
|
110
|
+
innerText: infoText,
|
|
111
|
+
_tag: "p",
|
|
112
|
+
style: textStyle,
|
|
113
|
+
};
|
|
114
|
+
newPage.staticElements.push(infoTextElement);
|
|
115
|
+
newPage.components.push(nextButtonComponent);
|
|
116
|
+
}
|
|
117
|
+
if (mainMedia && mainMedia.kind === "main-image") {
|
|
118
|
+
const mainImageElement = this.compileImage(mainMedia);
|
|
119
|
+
newPage.staticElements.push(mainImageElement);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (mainMedia && mainMedia.kind === "main-video") {
|
|
123
|
+
const videoOutput = this.compileVideo(mainMedia);
|
|
124
|
+
newPage.videoPlayer = videoOutput.videoPlayer;
|
|
125
|
+
newPage.components.push(...videoOutput.components);
|
|
126
|
+
initialVideoTaskList = [...videoOutput.autoPlayTasks];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ADDING INITIAL TASKS IN CORRECT ORDER
|
|
130
|
+
newPage.initialTasks.push(...initialVideoTaskList);
|
|
131
|
+
newPage.initialTasks.push(...initialAudioTasks);
|
|
132
|
+
const clone = JSON.parse(JSON.stringify(newPage));
|
|
133
|
+
return clone;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
private compileImage(image: BuilderMainImageDto) {
|
|
137
|
+
const img: DImgDto = {
|
|
138
|
+
_tag: "img",
|
|
139
|
+
style: this.theme.image.style,
|
|
140
|
+
url: image.file.downloadUrl,
|
|
141
|
+
};
|
|
142
|
+
return img;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private compileMainTextAudio(
|
|
146
|
+
audioFile: AudioFile,
|
|
147
|
+
autoPlay: boolean,
|
|
148
|
+
autoPlayDelay: number,
|
|
149
|
+
): {
|
|
150
|
+
components: PageComponentDto[];
|
|
151
|
+
initialTasks: Array<PlayAudioTask | DelayTask>;
|
|
152
|
+
} {
|
|
153
|
+
const t = this.theme.mainText;
|
|
154
|
+
const audioId = audioFile.id;
|
|
155
|
+
const iconUrl =
|
|
156
|
+
"https://firebasestorage.googleapis.com/v0/b/ispe-backend-dev.appspot.com/o/public-assets%2Fvolume_up-24px.svg?alt=media&token=551bd0a6-a515-4f87-a245-da433f4833f9";
|
|
157
|
+
|
|
158
|
+
const playMainTextAudio: DImgDto = {
|
|
159
|
+
_tag: "img",
|
|
160
|
+
url: iconUrl,
|
|
161
|
+
style: { ...t.withMedia.audio.css },
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const task: PlayAudioTask = {
|
|
165
|
+
audioId,
|
|
166
|
+
blockAudio: false,
|
|
167
|
+
blockFormInput: false,
|
|
168
|
+
blockResponseButton: false,
|
|
169
|
+
blockVideo: false,
|
|
170
|
+
kind: "play-audio-task",
|
|
171
|
+
priority: "replace-all",
|
|
172
|
+
url: audioFile.downloadUrl,
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
let initialAudioTasks: Array<PlayAudioTask | DelayTask> = [];
|
|
176
|
+
if (autoPlay) {
|
|
177
|
+
const playAudioTask: PlayAudioTask = { ...task, priority: "follow-queue" };
|
|
178
|
+
initialAudioTasks = [playAudioTask];
|
|
179
|
+
if (autoPlayDelay > 0) {
|
|
180
|
+
const delayTask: DelayTask = {
|
|
181
|
+
kind: "delay-task",
|
|
182
|
+
priority: "follow-queue",
|
|
183
|
+
duration: autoPlayDelay,
|
|
184
|
+
blockVideo: false,
|
|
185
|
+
blockAudio: false,
|
|
186
|
+
blockResponseButton: false,
|
|
187
|
+
blockFormInput: false,
|
|
188
|
+
};
|
|
189
|
+
initialAudioTasks = [delayTask, playAudioTask];
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// const autoplayTask =
|
|
193
|
+
const playBtn: PageComponentDto = {
|
|
194
|
+
el: playMainTextAudio,
|
|
195
|
+
onClick: { kind: "play-audio", task },
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
return { components: [playBtn], initialTasks: [...initialAudioTasks] };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
private compileVideo(video: BuilderMainVideoDto): {
|
|
202
|
+
videoPlayer: PageDto["videoPlayer"];
|
|
203
|
+
components: PageComponentDto[];
|
|
204
|
+
autoPlayTasks: Array<PlayVideoTask | DelayTask>;
|
|
205
|
+
} {
|
|
206
|
+
const t = this.theme.videoPlayer;
|
|
207
|
+
const mode = video.mode;
|
|
208
|
+
const components: PageComponentDto[] = [];
|
|
209
|
+
|
|
210
|
+
let autoPlayTasks: Array<PlayVideoTask | DelayTask> = [];
|
|
211
|
+
|
|
212
|
+
let autoplayVideoTask: PlayVideoTask | false = false;
|
|
213
|
+
let autoplayDelayTask: DelayTask | false = false;
|
|
214
|
+
|
|
215
|
+
const playButtonTask: PlayVideoTask = {
|
|
216
|
+
kind: "play-video-task",
|
|
217
|
+
url: video.file.downloadUrl,
|
|
218
|
+
videoId: video.file.id,
|
|
219
|
+
blockAudio: false,
|
|
220
|
+
blockFormInput: false,
|
|
221
|
+
blockResponseButton: false,
|
|
222
|
+
loop: mode === "gif-mode",
|
|
223
|
+
blockVideo: false,
|
|
224
|
+
priority: "replace-all",
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
if (video.mode === "autoplay" || video.mode === "gif-mode") {
|
|
228
|
+
autoplayVideoTask = { ...playButtonTask, priority: "follow-queue" };
|
|
229
|
+
autoPlayTasks = [autoplayVideoTask];
|
|
230
|
+
if (video.preDelay > 0) {
|
|
231
|
+
autoplayDelayTask = {
|
|
232
|
+
kind: "delay-task",
|
|
233
|
+
priority: "follow-queue",
|
|
234
|
+
duration: video.preDelay,
|
|
235
|
+
blockVideo: false,
|
|
236
|
+
blockAudio: false,
|
|
237
|
+
blockResponseButton: false,
|
|
238
|
+
blockFormInput: false,
|
|
239
|
+
};
|
|
240
|
+
autoPlayTasks = [autoplayDelayTask, autoplayVideoTask];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const videoPlayer: PageDto["videoPlayer"] = {
|
|
245
|
+
playUrl: video.file.downloadUrl,
|
|
246
|
+
style: { h: 45, w: 100, x: 0, y: 55 },
|
|
247
|
+
};
|
|
248
|
+
const playButton: PageComponentDto = {
|
|
249
|
+
el: {
|
|
250
|
+
_tag: "img",
|
|
251
|
+
url: t.playButton.iconUrl,
|
|
252
|
+
style: { ...t.playButton.css, ...t.playButton.cssEnabled },
|
|
253
|
+
},
|
|
254
|
+
onClick: { kind: "play-video", task: playButtonTask },
|
|
255
|
+
whenVideoPlay: { visibility: "hidden" },
|
|
256
|
+
whenVideoPaused: { visibility: "visible" },
|
|
257
|
+
};
|
|
258
|
+
const pauseBtn: PageComponentDto = {
|
|
259
|
+
el: {
|
|
260
|
+
_tag: "img",
|
|
261
|
+
style: {
|
|
262
|
+
...t.pauseButton.css,
|
|
263
|
+
visibility: "hidden",
|
|
264
|
+
...t.pauseButton.cssEnabled,
|
|
265
|
+
},
|
|
266
|
+
url: t.pauseButton.iconUrl,
|
|
267
|
+
},
|
|
268
|
+
onClick: { kind: "pause-video" },
|
|
269
|
+
whenVideoPlay: { visibility: "visible" },
|
|
270
|
+
whenVideoPaused: { visibility: "hidden" },
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
if (mode !== "gif-mode") {
|
|
274
|
+
components.push(playButton);
|
|
275
|
+
components.push(pauseBtn);
|
|
276
|
+
}
|
|
277
|
+
return { videoPlayer, components, autoPlayTasks: [...autoPlayTasks] };
|
|
278
|
+
}
|
|
279
|
+
private compileQuestion(
|
|
280
|
+
pageId: string,
|
|
281
|
+
page: BuilderPageDto,
|
|
282
|
+
variableId: string,
|
|
283
|
+
): {
|
|
284
|
+
question: DTextDto;
|
|
285
|
+
components: PageComponentDto[];
|
|
286
|
+
} {
|
|
287
|
+
// TODO REFACTORE DEFAULT QUESTION TO - (REMOVE USE TEXT1)
|
|
288
|
+
// console.log(page);
|
|
289
|
+
const q = page.defaultQuestion;
|
|
290
|
+
const text = page.mainText.text;
|
|
291
|
+
const questionStyle = page.mainMedia
|
|
292
|
+
? DefaultTheme.mainText.withMedia.text.css
|
|
293
|
+
: DefaultTheme.mainText.noMedia.text.css;
|
|
294
|
+
const question: DTextDto = {
|
|
295
|
+
_tag: "p",
|
|
296
|
+
innerText: text,
|
|
297
|
+
style: questionStyle,
|
|
298
|
+
};
|
|
299
|
+
const buttons: PageComponentDto[] = q.options.map((o) => {
|
|
300
|
+
const btns = this.compileButton(o, {
|
|
301
|
+
kind: "response-button",
|
|
302
|
+
questionId: variableId,
|
|
303
|
+
questionText: text,
|
|
304
|
+
});
|
|
305
|
+
return btns;
|
|
306
|
+
});
|
|
307
|
+
const rootElements = buttons.map((b) => b.el);
|
|
308
|
+
ThemeUtils.spaceEvenlyX(rootElements);
|
|
309
|
+
return { question, components: buttons };
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
private compileButton(
|
|
313
|
+
buttonDto: BuilderPageDto["nextButton"],
|
|
314
|
+
options:
|
|
315
|
+
| { kind: "response-button"; questionId: string; questionText: string }
|
|
316
|
+
| { kind: "next-button" },
|
|
317
|
+
): PageComponentDto {
|
|
318
|
+
const { id, value, label } = buttonDto;
|
|
319
|
+
const onclickAction: ButtonClickAction =
|
|
320
|
+
options.kind === "response-button"
|
|
321
|
+
? {
|
|
322
|
+
kind: "submit-fact",
|
|
323
|
+
fact: {
|
|
324
|
+
kind: "numeric-fact",
|
|
325
|
+
label: label,
|
|
326
|
+
value: value,
|
|
327
|
+
referenceId: options.questionId,
|
|
328
|
+
referenceLabel: options.questionText,
|
|
329
|
+
},
|
|
330
|
+
}
|
|
331
|
+
: { kind: "next-page" };
|
|
332
|
+
|
|
333
|
+
const btnStyles =
|
|
334
|
+
value === 9 ? DefaultTheme.responseButtons.dontKnow : DefaultTheme.responseButtons.normal;
|
|
335
|
+
const btn: DDivDto = {
|
|
336
|
+
_tag: "div",
|
|
337
|
+
children: [
|
|
338
|
+
{
|
|
339
|
+
_tag: "p",
|
|
340
|
+
innerText: label,
|
|
341
|
+
style: btnStyles.text1,
|
|
342
|
+
},
|
|
343
|
+
],
|
|
344
|
+
style: { ...btnStyles.btn.css, ...btnStyles.btn.cssEnabled },
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
if (options.kind === "next-button") {
|
|
348
|
+
btn.style.x = 50;
|
|
349
|
+
btn.style.y = 8;
|
|
350
|
+
btn.style.transform = "translate(-50%, 0%)";
|
|
351
|
+
}
|
|
352
|
+
const component: PageComponentDto = {
|
|
353
|
+
el: btn,
|
|
354
|
+
onClick: onclickAction,
|
|
355
|
+
};
|
|
356
|
+
return component;
|
|
357
|
+
}
|
|
358
|
+
}
|