@media-quest/builder 0.0.22 → 0.0.23

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.
Files changed (56) hide show
  1. package/package.json +1 -1
  2. package/src/Builder-option.ts +66 -66
  3. package/src/Builder-page.spec.ts +320 -320
  4. package/src/Builder-page.ts +257 -257
  5. package/src/Builder-question.spec.ts +68 -68
  6. package/src/Builder-question.ts +101 -101
  7. package/src/Builder-schema.spec.ts +357 -306
  8. package/src/Builder-schema.ts +287 -254
  9. package/src/Builder-text.spec.ts +24 -24
  10. package/src/Builder-text.ts +57 -57
  11. package/src/BuilderMainImageDto.ts +7 -7
  12. package/src/BuilderMainText.ts +81 -81
  13. package/src/BuilderMainVideoDto.ts +10 -10
  14. package/src/BuilderObject.ts +61 -61
  15. package/src/BuilderTag.ts +97 -97
  16. package/src/builder-compiler.ts +14 -0
  17. package/src/codebook.ts +72 -72
  18. package/src/media-files.ts +28 -28
  19. package/src/primitives/page-prefix.ts +58 -58
  20. package/src/primitives/prefix.spec.ts +5 -5
  21. package/src/primitives/schema-prefix.ts +52 -52
  22. package/src/primitives/varID.ts +11 -11
  23. package/src/public-api.ts +3 -1
  24. package/src/rulebuilder/Builder-rule.spec.ts +322 -322
  25. package/src/rulebuilder/Builder-rule.ts +190 -190
  26. package/src/rulebuilder/RuleAction.ts +106 -106
  27. package/src/rulebuilder/RuleBuilder-test-utils.ts +316 -316
  28. package/src/rulebuilder/RuleInput.ts +44 -44
  29. package/src/rulebuilder/RuleVariable.ts +49 -49
  30. package/src/rulebuilder/SingleSelectItem.ts +135 -135
  31. package/src/rulebuilder/condition/Builder-condition-group.spec.ts +47 -47
  32. package/src/rulebuilder/condition/Builder-condition-group.ts +118 -118
  33. package/src/rulebuilder/condition/Builder-condition.spec.ts +195 -195
  34. package/src/rulebuilder/condition/Builder-condition.ts +208 -208
  35. package/src/rulebuilder/condition/Builder-operator.spec.ts +9 -9
  36. package/src/rulebuilder/condition/Builder-operator.ts +31 -31
  37. package/src/rulebuilder/index.ts +22 -22
  38. package/src/rulebuilder/jump-to-action-manager.ts +33 -33
  39. package/src/rulebuilder/multi-select-item.ts +73 -73
  40. package/src/rulebuilder/page-action-manager.ts +31 -31
  41. package/src/rulebuilder/rule2/Rule2.ts +211 -211
  42. package/src/rulebuilder/tag-action-manager.spec.ts +44 -44
  43. package/src/rulebuilder/tag-action-manager.ts +28 -28
  44. package/src/schema-config.ts +25 -25
  45. package/src/theme/AbstractThemeCompiler.ts +7 -7
  46. package/src/theme/IDefaultTheme.ts +226 -226
  47. package/src/theme/css-theme.ts +7 -7
  48. package/src/theme/default-theme-compiler.ts +358 -358
  49. package/src/theme/icon-urls.ts +29 -29
  50. package/src/theme/theme-utils.ts +57 -57
  51. package/src/theme/theme1.spec.ts +52 -52
  52. package/src/variable/mq-variable.spec.ts +91 -0
  53. package/src/{mq-variable.ts → variable/mq-variable.ts} +63 -61
  54. package/src/variable/sum-score-variable.ts +56 -0
  55. package/tsconfig.json +15 -15
  56. package/tsconfig.tsbuildinfo +1 -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 "../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
+ }