@media-quest/builder 0.0.25 → 0.0.27
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 +819 -0
- package/dist/public-api.js +2696 -0
- package/dist/public-api.js.map +1 -0
- package/package.json +20 -6
- package/src/Builder-option.ts +64 -64
- package/src/Builder-question.spec.ts +68 -68
- package/src/Builder-question.ts +98 -102
- package/src/Builder-schema.spec.ts +135 -144
- package/src/Builder-schema.ts +70 -69
- package/src/Builder-text.spec.ts +24 -24
- package/src/Builder-text.ts +57 -57
- package/src/BuilderObject.ts +30 -29
- package/src/builder-compiler.ts +1 -1
- package/src/code-book/codebook-variable.ts +27 -0
- package/src/code-book/codebook.ts +81 -0
- package/src/page/Builder-page-collection.spec.ts +209 -0
- package/src/page/Builder-page-collection.ts +113 -0
- package/src/page/Builder-page.spec.ts +163 -0
- package/src/{Builder-page.ts → page/Builder-page.ts} +74 -95
- package/src/primitives/ID.spec.ts +39 -39
- package/src/primitives/ID.ts +26 -10
- package/src/primitives/page-prefix.ts +59 -59
- package/src/primitives/varID.ts +12 -12
- package/src/public-api.ts +8 -6
- package/src/rulebuilder/Builder-rule.spec.ts +323 -323
- package/src/rulebuilder/Builder-rule.ts +191 -191
- package/src/rulebuilder/RuleAction.ts +105 -106
- package/src/rulebuilder/RuleBuilder-test-utils.ts +320 -320
- package/src/rulebuilder/RuleInput.ts +30 -30
- package/src/rulebuilder/RuleVariable.ts +34 -48
- package/src/rulebuilder/SingleSelectItem.ts +9 -8
- package/src/rulebuilder/condition/Builder-condition-group.ts +14 -6
- package/src/rulebuilder/condition/Builder-condition.spec.ts +12 -12
- package/src/rulebuilder/condition/Builder-condition.ts +17 -13
- package/src/rulebuilder/index.ts +16 -3
- package/src/rulebuilder/page-action-manager.ts +33 -33
- package/src/rulebuilder/rule2/Rule2.ts +211 -215
- package/src/schema-config.ts +25 -25
- package/src/sum-score/sum-score-answer.ts +6 -0
- 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 +253 -0
- package/src/sum-score/sum-score-variable.ts +98 -0
- package/src/{variable → sum-score}/sum-score.ts +57 -26
- 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/Builder-page.spec.ts +0 -320
- package/src/BuilderTag.ts +0 -96
- package/src/codebook.ts +0 -72
- package/src/variable/b-variable.ts +0 -68
- package/src/variable/mq-variable.spec.ts +0 -147
- package/src/variable/sum-score-variable.ts +0 -50
- package/tsconfig.tsbuildinfo +0 -1
package/src/Builder-text.spec.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import type { BuilderTextDto } from "./Builder-text";
|
|
2
|
-
import { BuilderText } from "./Builder-text";
|
|
3
|
-
import { TextID } from "./primitives/ID";
|
|
4
|
-
|
|
5
|
-
const textDto: BuilderTextDto = {
|
|
6
|
-
id: "dto1" as TextID,
|
|
7
|
-
name: "dto1-name",
|
|
8
|
-
text: "text one",
|
|
9
|
-
translationRequired: true,
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
let text1 = BuilderText.create("text one created");
|
|
13
|
-
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
text1 = BuilderText.create("text one created");
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
describe("Builder Text", () => {
|
|
19
|
-
test("Can serialize", () => {
|
|
20
|
-
const instance1 = BuilderText.fromJson(textDto);
|
|
21
|
-
const json = instance1.toJson();
|
|
22
|
-
expect(textDto).toStrictEqual(json);
|
|
23
|
-
});
|
|
24
|
-
});
|
|
1
|
+
import type { BuilderTextDto } from "./Builder-text";
|
|
2
|
+
import { BuilderText } from "./Builder-text";
|
|
3
|
+
import { TextID } from "./primitives/ID";
|
|
4
|
+
|
|
5
|
+
const textDto: BuilderTextDto = {
|
|
6
|
+
id: "dto1" as TextID,
|
|
7
|
+
name: "dto1-name",
|
|
8
|
+
text: "text one",
|
|
9
|
+
translationRequired: true,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
let text1 = BuilderText.create("text one created");
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
text1 = BuilderText.create("text one created");
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe("Builder Text", () => {
|
|
19
|
+
test("Can serialize", () => {
|
|
20
|
+
const instance1 = BuilderText.fromJson(textDto);
|
|
21
|
+
const json = instance1.toJson();
|
|
22
|
+
expect(textDto).toStrictEqual(json);
|
|
23
|
+
});
|
|
24
|
+
});
|
package/src/Builder-text.ts
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
import { BuilderObject } from "./BuilderObject";
|
|
2
|
-
import { TextID } from "./primitives/ID";
|
|
3
|
-
|
|
4
|
-
export interface BuilderTextDto {
|
|
5
|
-
readonly id: TextID;
|
|
6
|
-
text: string;
|
|
7
|
-
name: string;
|
|
8
|
-
translationRequired: boolean;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export class BuilderText extends BuilderObject<"builder-text", BuilderTextDto> {
|
|
12
|
-
readonly objectType = "builder-text";
|
|
13
|
-
id: TextID;
|
|
14
|
-
text = "";
|
|
15
|
-
name = "";
|
|
16
|
-
translateRequired = false;
|
|
17
|
-
// audio: {id: B}
|
|
18
|
-
private constructor(dto: BuilderTextDto) {
|
|
19
|
-
super(dto);
|
|
20
|
-
this.id = dto.id;
|
|
21
|
-
this.translateRequired = dto.translationRequired;
|
|
22
|
-
this.name = dto.name;
|
|
23
|
-
this.text = dto.text;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
public static create(name: string) {
|
|
27
|
-
const id = TextID.create();
|
|
28
|
-
const dto: BuilderTextDto = {
|
|
29
|
-
id,
|
|
30
|
-
name,
|
|
31
|
-
text: "",
|
|
32
|
-
translationRequired: false,
|
|
33
|
-
};
|
|
34
|
-
const instance = new BuilderText(dto);
|
|
35
|
-
return instance;
|
|
36
|
-
}
|
|
37
|
-
public static fromJson(dto: BuilderTextDto) {
|
|
38
|
-
const instance = new BuilderText(dto);
|
|
39
|
-
return instance;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
clone(): BuilderTextDto {
|
|
43
|
-
const dto = this.toJson();
|
|
44
|
-
const withNewId: BuilderTextDto = { ...dto, id: TextID.create() };
|
|
45
|
-
return withNewId;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
toJson(): BuilderTextDto {
|
|
49
|
-
const dto: BuilderTextDto = {
|
|
50
|
-
id: this.id,
|
|
51
|
-
name: this.name,
|
|
52
|
-
text: this.text,
|
|
53
|
-
translationRequired: this.translateRequired,
|
|
54
|
-
};
|
|
55
|
-
return dto;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
1
|
+
import { BuilderObject } from "./BuilderObject";
|
|
2
|
+
import { TextID } from "./primitives/ID";
|
|
3
|
+
|
|
4
|
+
export interface BuilderTextDto {
|
|
5
|
+
readonly id: TextID;
|
|
6
|
+
text: string;
|
|
7
|
+
name: string;
|
|
8
|
+
translationRequired: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class BuilderText extends BuilderObject<"builder-text", BuilderTextDto> {
|
|
12
|
+
readonly objectType = "builder-text";
|
|
13
|
+
id: TextID;
|
|
14
|
+
text = "";
|
|
15
|
+
name = "";
|
|
16
|
+
translateRequired = false;
|
|
17
|
+
// audio: {id: B}
|
|
18
|
+
private constructor(dto: BuilderTextDto) {
|
|
19
|
+
super(dto);
|
|
20
|
+
this.id = dto.id;
|
|
21
|
+
this.translateRequired = dto.translationRequired;
|
|
22
|
+
this.name = dto.name;
|
|
23
|
+
this.text = dto.text;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public static create(name: string) {
|
|
27
|
+
const id = TextID.create();
|
|
28
|
+
const dto: BuilderTextDto = {
|
|
29
|
+
id,
|
|
30
|
+
name,
|
|
31
|
+
text: "",
|
|
32
|
+
translationRequired: false,
|
|
33
|
+
};
|
|
34
|
+
const instance = new BuilderText(dto);
|
|
35
|
+
return instance;
|
|
36
|
+
}
|
|
37
|
+
public static fromJson(dto: BuilderTextDto) {
|
|
38
|
+
const instance = new BuilderText(dto);
|
|
39
|
+
return instance;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
clone(): BuilderTextDto {
|
|
43
|
+
const dto = this.toJson();
|
|
44
|
+
const withNewId: BuilderTextDto = { ...dto, id: TextID.create() };
|
|
45
|
+
return withNewId;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
toJson(): BuilderTextDto {
|
|
49
|
+
const dto: BuilderTextDto = {
|
|
50
|
+
id: this.id,
|
|
51
|
+
name: this.name,
|
|
52
|
+
text: this.text,
|
|
53
|
+
translationRequired: this.translateRequired,
|
|
54
|
+
};
|
|
55
|
+
return dto;
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/BuilderObject.ts
CHANGED
|
@@ -1,29 +1,30 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Builder objects are complex objects that are embedded inside
|
|
3
|
-
* a Builder-schema, and needs to be serialized to json. Often these objects
|
|
4
|
-
* are used in collections, and that is why most of them need an id.
|
|
5
|
-
*/
|
|
6
|
-
type BuilderObjectType =
|
|
7
|
-
| "builder-page"
|
|
8
|
-
| "builder-question-option"
|
|
9
|
-
| "builder-question"
|
|
10
|
-
| "builder-main-text"
|
|
11
|
-
| "builder-text"
|
|
12
|
-
| "builder-rule"
|
|
13
|
-
| "builder-tag"
|
|
14
|
-
| "builder-sum-score-variable"
|
|
15
|
-
| "builder-
|
|
16
|
-
| "builder-
|
|
17
|
-
| "builder-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
abstract readonly
|
|
22
|
-
abstract
|
|
23
|
-
abstract
|
|
24
|
-
|
|
25
|
-
protected
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Builder objects are complex objects that are embedded inside
|
|
3
|
+
* a Builder-schema, and needs to be serialized to json. Often these objects
|
|
4
|
+
* are used in collections, and that is why most of them need an id.
|
|
5
|
+
*/
|
|
6
|
+
type BuilderObjectType =
|
|
7
|
+
| "builder-page"
|
|
8
|
+
| "builder-question-option"
|
|
9
|
+
| "builder-question"
|
|
10
|
+
| "builder-main-text"
|
|
11
|
+
| "builder-text"
|
|
12
|
+
| "builder-rule"
|
|
13
|
+
| "builder-tag"
|
|
14
|
+
| "builder-sum-score-variable"
|
|
15
|
+
| "builder-sum-score-membership"
|
|
16
|
+
| "builder-condition"
|
|
17
|
+
| "builder-variable"
|
|
18
|
+
| "builder-condition-group";
|
|
19
|
+
|
|
20
|
+
export abstract class BuilderObject<T extends BuilderObjectType, Dto extends {}> {
|
|
21
|
+
// abstract readonly id: string;
|
|
22
|
+
abstract readonly objectType: T;
|
|
23
|
+
abstract toJson(): Dto;
|
|
24
|
+
abstract clone(): Dto;
|
|
25
|
+
protected readonly originalDto: Dto;
|
|
26
|
+
protected constructor(dto: Dto) {
|
|
27
|
+
this.originalDto = dto;
|
|
28
|
+
// this.objectId = dto.objectId;
|
|
29
|
+
}
|
|
30
|
+
}
|
package/src/builder-compiler.ts
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { PageID } from "../primitives/ID";
|
|
2
|
+
import { SumScoreVariableDto } from "../sum-score/sum-score-variable";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Interface representing a code book question sum-score.
|
|
6
|
+
*
|
|
7
|
+
* @interface
|
|
8
|
+
*/
|
|
9
|
+
export interface CodeBookQuestionVariable {
|
|
10
|
+
readonly kind: "codebook-question-variable";
|
|
11
|
+
readonly label: string;
|
|
12
|
+
readonly varId: string;
|
|
13
|
+
readonly pageId: PageID;
|
|
14
|
+
readonly pagePrefix: string;
|
|
15
|
+
readonly modulePrefix: string;
|
|
16
|
+
readonly pagePosition: number;
|
|
17
|
+
readonly options: ReadonlyArray<{ label: string; value: number }>;
|
|
18
|
+
readonly includedInSumScores: ReadonlyArray<SumScoreVariableDto>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface CodebookPredefinedVariable {
|
|
22
|
+
readonly kind: "codebook-predefined-variable";
|
|
23
|
+
readonly modulePrefix: string;
|
|
24
|
+
readonly moduleID: string;
|
|
25
|
+
defaultValue: number;
|
|
26
|
+
options: Array<{ label: string; value: number }>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { BuilderPageDto } from "../page/Builder-page";
|
|
2
|
+
import { BuilderSchemaDto } from "../Builder-schema";
|
|
3
|
+
import { CodeBookQuestionVariable, CodebookPredefinedVariable } from "./codebook-variable";
|
|
4
|
+
import { SumScoreVariableDto } from "../sum-score/sum-score-variable";
|
|
5
|
+
|
|
6
|
+
export interface Codebook {
|
|
7
|
+
readonly predefinedVariables: ReadonlyArray<CodebookPredefinedVariable>;
|
|
8
|
+
readonly pageVariables: ReadonlyArray<CodeBookQuestionVariable>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const fromPage = (
|
|
12
|
+
page: BuilderPageDto,
|
|
13
|
+
sumScoreVariables: ReadonlyArray<SumScoreVariableDto>,
|
|
14
|
+
pagePosition: number,
|
|
15
|
+
modulePrefix: string,
|
|
16
|
+
): CodeBookQuestionVariable[] => {
|
|
17
|
+
const variables: CodeBookQuestionVariable[] = [];
|
|
18
|
+
|
|
19
|
+
if (page._type !== "question") {
|
|
20
|
+
// TODO Implement form field variables
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const options: CodeBookQuestionVariable["options"] = page.defaultQuestion.options.map((o) => {
|
|
25
|
+
return { value: o.value, label: o.label };
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const varId = modulePrefix + "_" + page.prefix;
|
|
29
|
+
|
|
30
|
+
const includedInSumScores = page.includedInSumScores.filter((a) => true);
|
|
31
|
+
|
|
32
|
+
const variable: CodeBookQuestionVariable = {
|
|
33
|
+
kind: "codebook-question-variable",
|
|
34
|
+
label: page.mainText.text,
|
|
35
|
+
pageId: page.id,
|
|
36
|
+
pagePrefix: page.prefix,
|
|
37
|
+
options,
|
|
38
|
+
modulePrefix,
|
|
39
|
+
pagePosition,
|
|
40
|
+
varId,
|
|
41
|
+
includedInSumScores: [],
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
variables.push(variable);
|
|
45
|
+
|
|
46
|
+
return variables;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Converts a list of pages into a list of question-variables
|
|
51
|
+
* @param pages
|
|
52
|
+
* @param sumScoreVariables
|
|
53
|
+
* @param modulePrefix
|
|
54
|
+
*/
|
|
55
|
+
const getPageVariablesFromPages = (
|
|
56
|
+
pages: ReadonlyArray<BuilderPageDto>,
|
|
57
|
+
sumScoreVariables: ReadonlyArray<SumScoreVariableDto>,
|
|
58
|
+
modulePrefix: string,
|
|
59
|
+
): CodeBookQuestionVariable[] => {
|
|
60
|
+
const variables: CodeBookQuestionVariable[] = [];
|
|
61
|
+
pages.forEach((page, index) => {
|
|
62
|
+
const pageVariables = fromPage(page, sumScoreVariables, index, modulePrefix);
|
|
63
|
+
variables.push(...pageVariables);
|
|
64
|
+
});
|
|
65
|
+
return variables;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const fromSchema = (schema: BuilderSchemaDto): Codebook => {
|
|
69
|
+
const modulePrefix = schema.prefix;
|
|
70
|
+
const sumScoreVariables = schema.sumScoreVariables ?? [];
|
|
71
|
+
const pageVariables = getPageVariablesFromPages(schema.pages, sumScoreVariables, modulePrefix);
|
|
72
|
+
const vs = schema.predefinedVariables;
|
|
73
|
+
const predefinedVariables: CodebookPredefinedVariable[] = vs ? [...vs] : [];
|
|
74
|
+
return { pageVariables, predefinedVariables };
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const _CodeBook = {
|
|
78
|
+
fromSchema,
|
|
79
|
+
} as const;
|
|
80
|
+
|
|
81
|
+
export const CodeBook = Object.freeze(_CodeBook);
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { BuilderTag, BuilderTagDto } from "../tag/BuilderTag";
|
|
2
|
+
import { PagePrefix } from "../primitives/page-prefix";
|
|
3
|
+
import { BuilderPageCollection } from "./Builder-page-collection";
|
|
4
|
+
import { OptionID, PageID, QuestionID } from "../primitives/ID";
|
|
5
|
+
import { BuilderPage, BuilderPageDto } from "./Builder-page";
|
|
6
|
+
import { SumScoreVariable } from "../sum-score/sum-score-variable";
|
|
7
|
+
import { SumScoreVariableCollection } from "../sum-score/sum-score-variable-collection";
|
|
8
|
+
|
|
9
|
+
const tag1: BuilderTagDto = BuilderTag.create("tag1", "This tag is defined in schemaDto1").toJson();
|
|
10
|
+
|
|
11
|
+
const tag2: BuilderTagDto = BuilderTag.create("tag2", "This tag is defined in schemaDto1").toJson();
|
|
12
|
+
const tag3: BuilderTagDto = BuilderTag.create("tag3", "This tag is defined in schemaDto1").toJson();
|
|
13
|
+
|
|
14
|
+
const sumScoreVariable1 = SumScoreVariable.create({
|
|
15
|
+
name: "ss1",
|
|
16
|
+
useAvg: true,
|
|
17
|
+
description: "ss1 description",
|
|
18
|
+
});
|
|
19
|
+
const sumScoreVariable2 = SumScoreVariable.create({
|
|
20
|
+
name: "ss2",
|
|
21
|
+
useAvg: true,
|
|
22
|
+
description: "ss2 description",
|
|
23
|
+
});
|
|
24
|
+
const sumScoreVariable3 = SumScoreVariable.create({
|
|
25
|
+
name: "ss3",
|
|
26
|
+
useAvg: true,
|
|
27
|
+
description: "ss3 description",
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const pages: BuilderPageDto[] = [
|
|
31
|
+
{
|
|
32
|
+
id: PageID.validateOrCreate("a".repeat(24)),
|
|
33
|
+
_type: "info-page",
|
|
34
|
+
prefix: PagePrefix.fromStringOrThrow("p1"),
|
|
35
|
+
mainText: {
|
|
36
|
+
text: "hello from test",
|
|
37
|
+
autoplay: false,
|
|
38
|
+
autoplayDelay: 0,
|
|
39
|
+
audioFile: false,
|
|
40
|
+
},
|
|
41
|
+
includedInSumScores: [{ sumScoreVariableId: sumScoreVariable1.id, weight: 1 }],
|
|
42
|
+
|
|
43
|
+
nextButton: {
|
|
44
|
+
id: OptionID.create(),
|
|
45
|
+
label: "Neste",
|
|
46
|
+
value: -1,
|
|
47
|
+
},
|
|
48
|
+
defaultQuestion: {
|
|
49
|
+
id: QuestionID.create(),
|
|
50
|
+
prefix: "one-prefix",
|
|
51
|
+
_type: "select-one",
|
|
52
|
+
text: "q1-text",
|
|
53
|
+
options: [
|
|
54
|
+
{
|
|
55
|
+
id: "opt-nei" as OptionID,
|
|
56
|
+
value: 0,
|
|
57
|
+
label: "Nei",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: "opt-ja" as OptionID,
|
|
61
|
+
value: 1,
|
|
62
|
+
label: "Ja",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: "opt-vet-ikke" as OptionID,
|
|
66
|
+
value: 9,
|
|
67
|
+
label: "Vet ikke",
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
tags: [
|
|
72
|
+
tag1.tag,
|
|
73
|
+
tag2.tag,
|
|
74
|
+
// { tag: 'can_read', description: 'The patient can read' },
|
|
75
|
+
// { tag: 'is grown up', description: 'Is grownUp.' }
|
|
76
|
+
],
|
|
77
|
+
autoplaySequence: [],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: PageID.dummy.b,
|
|
81
|
+
_type: "question",
|
|
82
|
+
prefix: PagePrefix.fromStringOrThrow("page2-prefix"),
|
|
83
|
+
tags: [tag3.tag],
|
|
84
|
+
includedInSumScores: [],
|
|
85
|
+
mainText: {
|
|
86
|
+
text: "hello from test",
|
|
87
|
+
autoplay: false,
|
|
88
|
+
autoplayDelay: 0,
|
|
89
|
+
audioFile: false,
|
|
90
|
+
},
|
|
91
|
+
nextButton: {
|
|
92
|
+
id: "next-button-id-page2" as OptionID,
|
|
93
|
+
label: "Neste",
|
|
94
|
+
value: -1,
|
|
95
|
+
},
|
|
96
|
+
defaultQuestion: {
|
|
97
|
+
id: QuestionID.validateOrCreate("default-question-id"),
|
|
98
|
+
prefix: "one-prefix",
|
|
99
|
+
_type: "select-one",
|
|
100
|
+
text: "q1",
|
|
101
|
+
options: [],
|
|
102
|
+
},
|
|
103
|
+
autoplaySequence: [],
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
let sumScoreVariableCollection = SumScoreVariableCollection.create([
|
|
108
|
+
sumScoreVariable1,
|
|
109
|
+
sumScoreVariable2,
|
|
110
|
+
sumScoreVariable3,
|
|
111
|
+
]);
|
|
112
|
+
let empty = BuilderPageCollection.create([]);
|
|
113
|
+
beforeEach(() => {
|
|
114
|
+
sumScoreVariableCollection = SumScoreVariableCollection.create([
|
|
115
|
+
sumScoreVariable1,
|
|
116
|
+
sumScoreVariable2,
|
|
117
|
+
sumScoreVariable3,
|
|
118
|
+
]);
|
|
119
|
+
empty = BuilderPageCollection.create([]);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
describe("Builder page collection", () => {
|
|
123
|
+
test("Can add pages.", () => {
|
|
124
|
+
const p1 = empty.add("question");
|
|
125
|
+
const p2 = empty.add("info-page");
|
|
126
|
+
expect(empty.size).toBe(2);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("Can delete page by id,", () => {
|
|
130
|
+
const p1 = empty.add("question");
|
|
131
|
+
const p2 = empty.add("question");
|
|
132
|
+
const p3 = empty.add("info-page");
|
|
133
|
+
expect(empty.size).toBe(3);
|
|
134
|
+
const result = empty.deleteById(p1.id);
|
|
135
|
+
expect(empty.size).toBe(2);
|
|
136
|
+
expect(result).toBe(true);
|
|
137
|
+
const result2 = empty.deleteById(p2.id);
|
|
138
|
+
expect(result2).toBe(true);
|
|
139
|
+
expect(empty.size).toBe(1);
|
|
140
|
+
expect(empty.pages[0]).toBe(p3);
|
|
141
|
+
const result3 = empty.deleteById(PageID.create());
|
|
142
|
+
expect(result3).toBe(false);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test("fromJson === toJson", () => {
|
|
146
|
+
const col = BuilderPageCollection.create(pages);
|
|
147
|
+
const json = col.toJson();
|
|
148
|
+
expect(pages).toStrictEqual(json);
|
|
149
|
+
});
|
|
150
|
+
//
|
|
151
|
+
|
|
152
|
+
test("Can add page at concrete index", () => {
|
|
153
|
+
const p1 = empty.add("question");
|
|
154
|
+
expect(p1.pageType).toBe("question");
|
|
155
|
+
const p2 = empty.add("info-page", 0);
|
|
156
|
+
expect(p2.pageType).toBe("info-page");
|
|
157
|
+
|
|
158
|
+
expect(empty.pages[0].id).toBe(p2.id);
|
|
159
|
+
empty.add("question");
|
|
160
|
+
empty.add("question");
|
|
161
|
+
const last = empty.add("question");
|
|
162
|
+
expect(empty.pages[empty.pages.length - 1]).toBe(last);
|
|
163
|
+
const p3 = empty.add("info-page", 4);
|
|
164
|
+
expect(empty.pages[4].id).toBe(p3.id);
|
|
165
|
+
});
|
|
166
|
+
//
|
|
167
|
+
test("Can move page up and down", () => {
|
|
168
|
+
const p1 = empty.add("question");
|
|
169
|
+
const p2 = empty.add("question");
|
|
170
|
+
const p3 = empty.add("question");
|
|
171
|
+
const p4 = empty.add("info-page");
|
|
172
|
+
const last = empty.add("question");
|
|
173
|
+
empty.movePage(p2, 0);
|
|
174
|
+
expect(empty.pages[0]).toBe(p2);
|
|
175
|
+
expect(empty.pages[1]).toBe(p1);
|
|
176
|
+
expect(empty.movePage(p4, 4)).toBeTruthy();
|
|
177
|
+
expect(empty.movePage(p4, 5)).toBeFalsy();
|
|
178
|
+
expect(empty.movePage(p4, 10)).toBeFalsy();
|
|
179
|
+
|
|
180
|
+
expect(empty.pages[4].id).toBe(p4.id);
|
|
181
|
+
expect(empty.pages[3].id).toBe(last.id);
|
|
182
|
+
});
|
|
183
|
+
//
|
|
184
|
+
test("Can clone a page and insert at index", () => {
|
|
185
|
+
const p1 = empty.add("question");
|
|
186
|
+
const p2 = empty.add("question");
|
|
187
|
+
const p3 = empty.add("question");
|
|
188
|
+
const mainTextContent = "Hello from test";
|
|
189
|
+
const p4 = empty.add("info-page");
|
|
190
|
+
p3.mainText.text = mainTextContent;
|
|
191
|
+
const p1Clone = BuilderPage.fromJson(p1.clone());
|
|
192
|
+
const beforSize = empty.size;
|
|
193
|
+
empty.insertPage(p1Clone, 2);
|
|
194
|
+
// const pages = s1.pages;
|
|
195
|
+
expect(beforSize + 1).toBe(empty.size);
|
|
196
|
+
expect(empty.pages[2]).toBe(p1Clone);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test("Will not insert a page that is already in array.", () => {
|
|
200
|
+
const p1 = empty.add("question");
|
|
201
|
+
const p2 = empty.add("question");
|
|
202
|
+
const p3 = empty.add("question");
|
|
203
|
+
const beforeSize = empty.size;
|
|
204
|
+
const result = empty.insertPage(p1, 0);
|
|
205
|
+
const pages = empty.pages;
|
|
206
|
+
expect(beforeSize).toBe(empty.size);
|
|
207
|
+
expect(result).toBe(false);
|
|
208
|
+
});
|
|
209
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { DUtil } from "@media-quest/engine";
|
|
2
|
+
import { BuilderPage, BuilderPageDto } from "./Builder-page";
|
|
3
|
+
import { PageID, PagePrefix, SumScoreVariableID } from "../public-api";
|
|
4
|
+
import { SumScoreVariableCollection } from "../sum-score/sum-score-variable-collection";
|
|
5
|
+
import { SumScoreVariable } from "../sum-score/sum-score-variable";
|
|
6
|
+
|
|
7
|
+
const U = DUtil;
|
|
8
|
+
export type BuilderPageType = "info-page" | "question";
|
|
9
|
+
|
|
10
|
+
export class BuilderPageCollection implements Iterable<BuilderPage> {
|
|
11
|
+
private _all: Array<BuilderPage> = [];
|
|
12
|
+
|
|
13
|
+
public static create(pages: BuilderPageDto[]) {
|
|
14
|
+
const page = new BuilderPageCollection(pages);
|
|
15
|
+
page._all = pages.map((p) => BuilderPage.fromJson(p));
|
|
16
|
+
return page;
|
|
17
|
+
}
|
|
18
|
+
private constructor(initialPages: BuilderPageDto[]) {}
|
|
19
|
+
|
|
20
|
+
/** @internal - used by Schema*/
|
|
21
|
+
_init(pages: BuilderPageDto[]) {
|
|
22
|
+
this._all = pages.map(BuilderPage.fromJson);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
add(type: BuilderPageType, atIndex = -1): BuilderPage {
|
|
26
|
+
const pagePrefix = PagePrefix.create();
|
|
27
|
+
const newPage = BuilderPage.create(type, pagePrefix.value);
|
|
28
|
+
if (atIndex >= 0 && atIndex < this._all.length) {
|
|
29
|
+
this._all.splice(atIndex, 0, newPage);
|
|
30
|
+
} else {
|
|
31
|
+
this._all.push(newPage);
|
|
32
|
+
}
|
|
33
|
+
return newPage;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
deleteById(id: PageID) {
|
|
37
|
+
const index = this._all.findIndex((p) => p.id === id);
|
|
38
|
+
if (index !== -1) {
|
|
39
|
+
this._all.splice(index, 1);
|
|
40
|
+
return true;
|
|
41
|
+
} else {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private getPageById(pageId: PageID) {
|
|
47
|
+
const maybePage = this._all.find((p) => p.id === pageId);
|
|
48
|
+
return maybePage ?? false;
|
|
49
|
+
}
|
|
50
|
+
get size() {
|
|
51
|
+
return this._all.length;
|
|
52
|
+
}
|
|
53
|
+
get pages(): ReadonlyArray<BuilderPage> {
|
|
54
|
+
return [...this._all];
|
|
55
|
+
}
|
|
56
|
+
toJson(): ReadonlyArray<BuilderPageDto> {
|
|
57
|
+
return this._all.map((p) => p.toJson());
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
[Symbol.iterator]() {
|
|
61
|
+
const list = [...this._all];
|
|
62
|
+
return list[Symbol.iterator]();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
movePage(page: BuilderPage, toIndex: number) {
|
|
66
|
+
const index = this._all.indexOf(page);
|
|
67
|
+
if (index < 0) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
const isValidIndex = U.isInRange(0, this._all.length - 1);
|
|
71
|
+
if (!isValidIndex(toIndex)) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
// console.log('Moving from :' + index + ' to: ' + toIndex);
|
|
75
|
+
this._all.splice(index, 1);
|
|
76
|
+
this._all.splice(toIndex, 0, page);
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
insertPage(page: BuilderPage, atIndex: number) {
|
|
81
|
+
const isValidIndex = U.isInRange(0, this._all.length - 1);
|
|
82
|
+
if (!isValidIndex(atIndex)) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
const exists = !!this._all.find((p) => p.id === page.id);
|
|
86
|
+
if (exists) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
this._all.splice(atIndex, 0, page);
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
addSumScoreVariable(sumScoreVariable: SumScoreVariable, pageId: PageID, weight: number) {
|
|
94
|
+
const maybePage = this.getPageById(pageId);
|
|
95
|
+
if (!maybePage) return false;
|
|
96
|
+
maybePage.sumScoreVariableSet(sumScoreVariable, weight);
|
|
97
|
+
|
|
98
|
+
// maybePage.addSumScoreVariable(maybeVariable, weight);
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
updateAllData(context: { sumScoreVariables: ReadonlyArray<SumScoreVariable> }) {
|
|
103
|
+
this._all.forEach((p) => {
|
|
104
|
+
p.sumScoreVariableUpdateData(context.sumScoreVariables);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
sumScoreVariableDelete(sumScoreVariableID: SumScoreVariableID) {
|
|
109
|
+
this._all.forEach((p) => {
|
|
110
|
+
p.sumScoreVariableDelete(sumScoreVariableID);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|