headless-survey-engine 0.0.0-stage → 4.4.0
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/LICENSE +201 -0
- package/README.md +89 -2
- package/dist/index.d.ts +826 -0
- package/dist/index.js +1503 -0
- package/package.json +51 -3
package/dist/index.js
ADDED
|
@@ -0,0 +1,1503 @@
|
|
|
1
|
+
import { MAX_SURVEY_EXPRESSION_LENGTH, checkSurveyExpression, runSurveyExpression, toSurveyLogicAnswer, toSurveyLogicAnswers } from "survey-expression";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { checkIsDeepEqual, createRecordSchema, createUniqueArraySchema, exhaustiveGuard, getResult, normalizeString, takeOne } from "@esposter/shared";
|
|
4
|
+
import { NO_BLOCK_SLOTS, createAcceptedTypesError, createBlockDocumentSchema, getBlockPropPointer } from "headless-block-editor";
|
|
5
|
+
import { RE2JS } from "re2js";
|
|
6
|
+
// src/models/SurveyAnswerValidationMode.ts
|
|
7
|
+
let SurveyAnswerValidationMode = /* @__PURE__ */ function(SurveyAnswerValidationMode) {
|
|
8
|
+
SurveyAnswerValidationMode["Draft"] = "draft";
|
|
9
|
+
SurveyAnswerValidationMode["Submit"] = "submit";
|
|
10
|
+
return SurveyAnswerValidationMode;
|
|
11
|
+
}({});
|
|
12
|
+
// src/models/SurveyBooleanDisplayStyle.ts
|
|
13
|
+
let SurveyBooleanDisplayStyle = /* @__PURE__ */ function(SurveyBooleanDisplayStyle) {
|
|
14
|
+
SurveyBooleanDisplayStyle["Checkbox"] = "checkbox";
|
|
15
|
+
SurveyBooleanDisplayStyle["Radio"] = "radio";
|
|
16
|
+
SurveyBooleanDisplayStyle["Switch"] = "switch";
|
|
17
|
+
return SurveyBooleanDisplayStyle;
|
|
18
|
+
}({});
|
|
19
|
+
// src/services/constants.ts
|
|
20
|
+
const MAX_SURVEY_QUESTION_NAME_LENGTH = 256;
|
|
21
|
+
const MAX_SURVEY_QUESTION_COUNT = 1e3;
|
|
22
|
+
const MAX_SURVEY_NODE_COUNT = 1500;
|
|
23
|
+
const MAX_SURVEY_CHOICE_COUNT = 200;
|
|
24
|
+
const MAX_SURVEY_MULTIPLE_TEXT_ITEM_COUNT = 50;
|
|
25
|
+
const MAX_SURVEY_MATRIX_COLUMN_COUNT = 50;
|
|
26
|
+
const MAX_SURVEY_MATRIX_ROW_COUNT = 100;
|
|
27
|
+
const MAX_SURVEY_TEXT_LENGTH = 1e3;
|
|
28
|
+
const MAX_SURVEY_IMAGE_SIZE = 2048;
|
|
29
|
+
const MAX_SURVEY_HTML_LENGTH = 2e4;
|
|
30
|
+
const MAX_SURVEY_ID_LENGTH = 64;
|
|
31
|
+
const MAX_SURVEY_VALIDATOR_COUNT = 20;
|
|
32
|
+
const MAX_SURVEY_CALCULATED_VALUE_COUNT = 100;
|
|
33
|
+
const MAX_SURVEY_PATTERN_LENGTH = 200;
|
|
34
|
+
const MAX_SURVEY_URL_LENGTH = 2048;
|
|
35
|
+
const MAX_SURVEY_ANSWER_LENGTH = 1e4;
|
|
36
|
+
const MAX_SURVEY_ANSWER_ENTRY_COUNT = 200;
|
|
37
|
+
// src/services/surveyExpressionSchema.ts
|
|
38
|
+
const surveyExpressionSchema = z.string().min(1).max(MAX_SURVEY_EXPRESSION_LENGTH);
|
|
39
|
+
// src/models/SurveyValidator.ts
|
|
40
|
+
const surveyValidatorSchema = z.object({
|
|
41
|
+
expression: surveyExpressionSchema,
|
|
42
|
+
text: z.string().min(1).max(MAX_SURVEY_TEXT_LENGTH)
|
|
43
|
+
});
|
|
44
|
+
// src/services/surveyConditionSchema.ts
|
|
45
|
+
const surveyConditionSchema = z.string().max(MAX_SURVEY_EXPRESSION_LENGTH).default("");
|
|
46
|
+
// src/services/surveyNameSchema.ts
|
|
47
|
+
const surveyNameSchema = z.string().max(256).regex(/^[^{}]+$/u);
|
|
48
|
+
// src/models/SurveyQuestionBaseProps.ts
|
|
49
|
+
const surveyQuestionBasePropsShape = {
|
|
50
|
+
description: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
51
|
+
enableIf: surveyConditionSchema,
|
|
52
|
+
isRequired: z.boolean().default(false),
|
|
53
|
+
name: surveyNameSchema,
|
|
54
|
+
requiredErrorText: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
55
|
+
requiredIf: surveyConditionSchema,
|
|
56
|
+
title: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
57
|
+
validators: z.array(surveyValidatorSchema).max(20).default([]),
|
|
58
|
+
visibleIf: surveyConditionSchema
|
|
59
|
+
};
|
|
60
|
+
// src/models/SurveyBooleanNodeProps.ts
|
|
61
|
+
const SURVEY_BOOLEAN_DISPLAY_STYLE_OPTIONS = [
|
|
62
|
+
"switch",
|
|
63
|
+
"checkbox",
|
|
64
|
+
"radio"
|
|
65
|
+
];
|
|
66
|
+
const surveyBooleanNodePropsSchema = z.object({
|
|
67
|
+
...surveyQuestionBasePropsShape,
|
|
68
|
+
displayStyle: z.enum(SURVEY_BOOLEAN_DISPLAY_STYLE_OPTIONS).default("switch"),
|
|
69
|
+
labelFalse: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
70
|
+
labelTrue: z.string().max(MAX_SURVEY_TEXT_LENGTH).default("")
|
|
71
|
+
});
|
|
72
|
+
// src/models/SurveyChoice.ts
|
|
73
|
+
const surveyChoiceSchema = z.object({
|
|
74
|
+
text: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
75
|
+
value: z.union([z.string().max(MAX_SURVEY_TEXT_LENGTH), z.number()])
|
|
76
|
+
});
|
|
77
|
+
// src/models/SurveyChoicesProps.ts
|
|
78
|
+
const surveyChoicesPropsShape = { choices: createUniqueArraySchema(surveyChoiceSchema, "value").max(200).default([]) };
|
|
79
|
+
// src/models/SurveyButtonGroupNodeProps.ts
|
|
80
|
+
const surveyButtonGroupNodePropsSchema = z.object({
|
|
81
|
+
...surveyQuestionBasePropsShape,
|
|
82
|
+
...surveyChoicesPropsShape
|
|
83
|
+
});
|
|
84
|
+
// src/models/SurveyCalculatedValue.ts
|
|
85
|
+
const surveyCalculatedValueSchema = z.object({
|
|
86
|
+
expression: surveyExpressionSchema,
|
|
87
|
+
includeIntoResult: z.boolean().default(false),
|
|
88
|
+
name: surveyNameSchema
|
|
89
|
+
});
|
|
90
|
+
// src/models/SurveyChoicesOrder.ts
|
|
91
|
+
let SurveyChoicesOrder = /* @__PURE__ */ function(SurveyChoicesOrder) {
|
|
92
|
+
SurveyChoicesOrder["Ascending"] = "asc";
|
|
93
|
+
SurveyChoicesOrder["Descending"] = "desc";
|
|
94
|
+
SurveyChoicesOrder["None"] = "none";
|
|
95
|
+
SurveyChoicesOrder["Random"] = "random";
|
|
96
|
+
return SurveyChoicesOrder;
|
|
97
|
+
}({});
|
|
98
|
+
// src/models/SurveyChoiceOptionsProps.ts
|
|
99
|
+
const surveyChoiceOptionsPropsShape = {
|
|
100
|
+
...surveyChoicesPropsShape,
|
|
101
|
+
choicesOrder: z.enum(SurveyChoicesOrder).default("none"),
|
|
102
|
+
hasOther: z.boolean().default(false),
|
|
103
|
+
otherText: z.string().max(MAX_SURVEY_TEXT_LENGTH).default("")
|
|
104
|
+
};
|
|
105
|
+
// src/models/SurveyNoneChoiceProps.ts
|
|
106
|
+
const surveyNoneChoicePropsShape = {
|
|
107
|
+
hasNone: z.boolean().default(false),
|
|
108
|
+
noneText: z.string().max(MAX_SURVEY_TEXT_LENGTH).default("")
|
|
109
|
+
};
|
|
110
|
+
// src/models/SurveyCheckboxNodeProps.ts
|
|
111
|
+
const surveyCheckboxNodePropsSchema = z.object({
|
|
112
|
+
...surveyQuestionBasePropsShape,
|
|
113
|
+
...surveyChoiceOptionsPropsShape,
|
|
114
|
+
...surveyNoneChoicePropsShape,
|
|
115
|
+
hasSelectAll: z.boolean().default(false),
|
|
116
|
+
maxSelected: z.int().positive().optional(),
|
|
117
|
+
minSelected: z.int().positive().optional(),
|
|
118
|
+
selectAllText: z.string().max(MAX_SURVEY_TEXT_LENGTH).default("")
|
|
119
|
+
});
|
|
120
|
+
// src/models/SurveyCommentNodeProps.ts
|
|
121
|
+
const MAX_SURVEY_COMMENT_ROWS = 20;
|
|
122
|
+
const surveyCommentNodePropsSchema = z.object({
|
|
123
|
+
...surveyQuestionBasePropsShape,
|
|
124
|
+
maxLength: z.int().positive().optional(),
|
|
125
|
+
placeholder: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
126
|
+
rows: z.int().min(1).max(MAX_SURVEY_COMMENT_ROWS).default(4)
|
|
127
|
+
});
|
|
128
|
+
// src/models/SurveyContainerBaseProps.ts
|
|
129
|
+
const surveyContainerBasePropsShape = {
|
|
130
|
+
description: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
131
|
+
title: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
132
|
+
visibleIf: surveyConditionSchema
|
|
133
|
+
};
|
|
134
|
+
// src/models/SurveyDropdownNodeProps.ts
|
|
135
|
+
const surveyDropdownNodePropsSchema = z.object({
|
|
136
|
+
...surveyQuestionBasePropsShape,
|
|
137
|
+
...surveyChoiceOptionsPropsShape,
|
|
138
|
+
placeholder: z.string().max(MAX_SURVEY_TEXT_LENGTH).default("")
|
|
139
|
+
});
|
|
140
|
+
// src/models/SurveyExpressionDisplayFormat.ts
|
|
141
|
+
let SurveyExpressionDisplayFormat = /* @__PURE__ */ function(SurveyExpressionDisplayFormat) {
|
|
142
|
+
SurveyExpressionDisplayFormat["Decimal"] = "decimal";
|
|
143
|
+
SurveyExpressionDisplayFormat["None"] = "none";
|
|
144
|
+
SurveyExpressionDisplayFormat["Percent"] = "percent";
|
|
145
|
+
return SurveyExpressionDisplayFormat;
|
|
146
|
+
}({});
|
|
147
|
+
// src/models/SurveyExpressionNodeProps.ts
|
|
148
|
+
const MIN_SURVEY_FRACTION_DIGITS = 0;
|
|
149
|
+
const MAX_SURVEY_FRACTION_DIGITS = 10;
|
|
150
|
+
const surveyExpressionNodePropsSchema = z.object({
|
|
151
|
+
...surveyQuestionBasePropsShape,
|
|
152
|
+
displayFormat: z.enum(SurveyExpressionDisplayFormat).default("none"),
|
|
153
|
+
expression: surveyConditionSchema,
|
|
154
|
+
maxFractionDigits: z.int().min(MIN_SURVEY_FRACTION_DIGITS).max(MAX_SURVEY_FRACTION_DIGITS).default(2)
|
|
155
|
+
});
|
|
156
|
+
// src/models/SurveyHtmlNodeProps.ts
|
|
157
|
+
const surveyHtmlNodePropsSchema = z.object({
|
|
158
|
+
html: z.string().max(MAX_SURVEY_HTML_LENGTH).default(""),
|
|
159
|
+
name: surveyNameSchema,
|
|
160
|
+
visibleIf: surveyConditionSchema
|
|
161
|
+
});
|
|
162
|
+
// src/models/SurveyImageChoice.ts
|
|
163
|
+
const surveyImageChoiceSchema = z.object({
|
|
164
|
+
...surveyChoiceSchema.shape,
|
|
165
|
+
imageLink: z.string().min(1).max(MAX_SURVEY_URL_LENGTH)
|
|
166
|
+
});
|
|
167
|
+
// src/models/SurveyImageFit.ts
|
|
168
|
+
let SurveyImageFit = /* @__PURE__ */ function(SurveyImageFit) {
|
|
169
|
+
SurveyImageFit["Contain"] = "contain";
|
|
170
|
+
SurveyImageFit["Cover"] = "cover";
|
|
171
|
+
SurveyImageFit["Fill"] = "fill";
|
|
172
|
+
SurveyImageFit["None"] = "none";
|
|
173
|
+
return SurveyImageFit;
|
|
174
|
+
}({});
|
|
175
|
+
// src/models/SurveyImageNodeProps.ts
|
|
176
|
+
const surveyImageNodePropsSchema = z.object({
|
|
177
|
+
altText: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
178
|
+
imageFit: z.enum(SurveyImageFit).default("contain"),
|
|
179
|
+
imageHeight: z.int().positive().max(MAX_SURVEY_IMAGE_SIZE).optional(),
|
|
180
|
+
imageLink: z.string().max(MAX_SURVEY_URL_LENGTH).default(""),
|
|
181
|
+
imageWidth: z.int().positive().max(MAX_SURVEY_IMAGE_SIZE).optional(),
|
|
182
|
+
name: surveyNameSchema,
|
|
183
|
+
visibleIf: surveyConditionSchema
|
|
184
|
+
});
|
|
185
|
+
// src/models/SurveyImagePickerNodeProps.ts
|
|
186
|
+
const surveyImagePickerNodePropsSchema = z.object({
|
|
187
|
+
...surveyQuestionBasePropsShape,
|
|
188
|
+
choices: createUniqueArraySchema(surveyImageChoiceSchema, "value").max(200).default([]),
|
|
189
|
+
imageFit: z.enum(SurveyImageFit).default("contain"),
|
|
190
|
+
imageHeight: z.int().positive().max(MAX_SURVEY_IMAGE_SIZE).optional(),
|
|
191
|
+
imageWidth: z.int().positive().max(MAX_SURVEY_IMAGE_SIZE).optional(),
|
|
192
|
+
isLabelVisible: z.boolean().default(true),
|
|
193
|
+
multiSelect: z.boolean().default(false)
|
|
194
|
+
});
|
|
195
|
+
// src/models/SurveyMatrixCellType.ts
|
|
196
|
+
let SurveyMatrixCellType = /* @__PURE__ */ function(SurveyMatrixCellType) {
|
|
197
|
+
SurveyMatrixCellType["Boolean"] = "boolean";
|
|
198
|
+
SurveyMatrixCellType["Checkbox"] = "checkbox";
|
|
199
|
+
SurveyMatrixCellType["Comment"] = "comment";
|
|
200
|
+
SurveyMatrixCellType["Dropdown"] = "dropdown";
|
|
201
|
+
SurveyMatrixCellType["Rating"] = "rating";
|
|
202
|
+
SurveyMatrixCellType["Text"] = "text";
|
|
203
|
+
return SurveyMatrixCellType;
|
|
204
|
+
}({});
|
|
205
|
+
// src/models/SurveyMatrixColumn.ts
|
|
206
|
+
const surveyMatrixColumnSchema = z.object({
|
|
207
|
+
cellType: z.enum(SurveyMatrixCellType),
|
|
208
|
+
choices: createUniqueArraySchema(surveyChoiceSchema, "value").max(200).default([]),
|
|
209
|
+
isRequired: z.boolean().default(false),
|
|
210
|
+
name: surveyNameSchema,
|
|
211
|
+
title: z.string().max(MAX_SURVEY_TEXT_LENGTH).default("")
|
|
212
|
+
});
|
|
213
|
+
// src/models/SurveyMatrixDynamicNodeProps.ts
|
|
214
|
+
const surveyMatrixDynamicNodePropsSchema = z.object({
|
|
215
|
+
...surveyQuestionBasePropsShape,
|
|
216
|
+
addRowText: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
217
|
+
columns: createUniqueArraySchema(surveyMatrixColumnSchema, "name").max(50).default([]),
|
|
218
|
+
maxRowCount: z.int().min(1).max(100).default(100),
|
|
219
|
+
minRowCount: z.int().min(0).max(100).default(0),
|
|
220
|
+
removeRowText: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
221
|
+
rowCount: z.int().min(0).max(100).default(2)
|
|
222
|
+
});
|
|
223
|
+
// src/models/SurveyMatrixNodeProps.ts
|
|
224
|
+
const surveyMatrixNodePropsSchema = z.object({
|
|
225
|
+
...surveyQuestionBasePropsShape,
|
|
226
|
+
columns: createUniqueArraySchema(surveyChoiceSchema, "value").max(200).default([]),
|
|
227
|
+
isAllRowRequired: z.boolean().default(false),
|
|
228
|
+
rows: createUniqueArraySchema(surveyChoiceSchema, "value").max(200).default([])
|
|
229
|
+
});
|
|
230
|
+
// src/models/SurveyMultipleTextItemInputType.ts
|
|
231
|
+
let SurveyMultipleTextItemInputType = /* @__PURE__ */ function(SurveyMultipleTextItemInputType) {
|
|
232
|
+
SurveyMultipleTextItemInputType["Email"] = "email";
|
|
233
|
+
SurveyMultipleTextItemInputType["Number"] = "number";
|
|
234
|
+
SurveyMultipleTextItemInputType["Text"] = "text";
|
|
235
|
+
return SurveyMultipleTextItemInputType;
|
|
236
|
+
}({});
|
|
237
|
+
// src/models/SurveyMultipleTextItem.ts
|
|
238
|
+
const surveyMultipleTextItemSchema = z.object({
|
|
239
|
+
inputType: z.enum(SurveyMultipleTextItemInputType),
|
|
240
|
+
isRequired: z.boolean().default(false),
|
|
241
|
+
name: surveyNameSchema,
|
|
242
|
+
title: z.string().max(MAX_SURVEY_TEXT_LENGTH).default("")
|
|
243
|
+
});
|
|
244
|
+
// src/models/SurveyMultipleTextNodeProps.ts
|
|
245
|
+
const surveyMultipleTextNodePropsSchema = z.object({
|
|
246
|
+
...surveyQuestionBasePropsShape,
|
|
247
|
+
items: createUniqueArraySchema(surveyMultipleTextItemSchema, "name").max(50).default([])
|
|
248
|
+
});
|
|
249
|
+
// src/models/SurveyNodeType.ts
|
|
250
|
+
let SurveyNodeType = /* @__PURE__ */ function(SurveyNodeType) {
|
|
251
|
+
SurveyNodeType["Boolean"] = "boolean";
|
|
252
|
+
SurveyNodeType["ButtonGroup"] = "buttongroup";
|
|
253
|
+
SurveyNodeType["Checkbox"] = "checkbox";
|
|
254
|
+
SurveyNodeType["Comment"] = "comment";
|
|
255
|
+
SurveyNodeType["Dropdown"] = "dropdown";
|
|
256
|
+
SurveyNodeType["Expression"] = "expression";
|
|
257
|
+
SurveyNodeType["Html"] = "html";
|
|
258
|
+
SurveyNodeType["Image"] = "image";
|
|
259
|
+
SurveyNodeType["ImagePicker"] = "imagepicker";
|
|
260
|
+
SurveyNodeType["Matrix"] = "matrix";
|
|
261
|
+
SurveyNodeType["MatrixDynamic"] = "matrixdynamic";
|
|
262
|
+
SurveyNodeType["MultipleText"] = "multipletext";
|
|
263
|
+
SurveyNodeType["Page"] = "page";
|
|
264
|
+
SurveyNodeType["Panel"] = "panel";
|
|
265
|
+
SurveyNodeType["PanelDynamic"] = "paneldynamic";
|
|
266
|
+
SurveyNodeType["RadioGroup"] = "radiogroup";
|
|
267
|
+
SurveyNodeType["Ranking"] = "ranking";
|
|
268
|
+
SurveyNodeType["Rating"] = "rating";
|
|
269
|
+
SurveyNodeType["Slider"] = "slider";
|
|
270
|
+
SurveyNodeType["TagBox"] = "tagbox";
|
|
271
|
+
SurveyNodeType["Text"] = "text";
|
|
272
|
+
return SurveyNodeType;
|
|
273
|
+
}({});
|
|
274
|
+
// src/models/SurveyPageNodeProps.ts
|
|
275
|
+
const surveyPageNodePropsSchema = z.object({ ...surveyContainerBasePropsShape });
|
|
276
|
+
// src/models/SurveyPanelDynamicNodeProps.ts
|
|
277
|
+
const MAX_SURVEY_PANEL_COUNT = 20;
|
|
278
|
+
const surveyPanelDynamicNodePropsSchema = z.object({
|
|
279
|
+
...surveyQuestionBasePropsShape,
|
|
280
|
+
addPanelText: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
281
|
+
maxPanelCount: z.int().min(1).max(MAX_SURVEY_PANEL_COUNT).default(MAX_SURVEY_PANEL_COUNT),
|
|
282
|
+
minPanelCount: z.int().min(0).max(MAX_SURVEY_PANEL_COUNT).default(0),
|
|
283
|
+
panelCount: z.int().min(0).max(MAX_SURVEY_PANEL_COUNT).default(1),
|
|
284
|
+
removePanelText: z.string().max(MAX_SURVEY_TEXT_LENGTH).default("")
|
|
285
|
+
});
|
|
286
|
+
// src/models/SurveyPanelNodeProps.ts
|
|
287
|
+
const surveyPanelNodePropsSchema = z.object({
|
|
288
|
+
...surveyContainerBasePropsShape,
|
|
289
|
+
enableIf: surveyConditionSchema
|
|
290
|
+
});
|
|
291
|
+
// src/models/SurveyProgressBarPlacement.ts
|
|
292
|
+
let SurveyProgressBarPlacement = /* @__PURE__ */ function(SurveyProgressBarPlacement) {
|
|
293
|
+
SurveyProgressBarPlacement["Bottom"] = "bottom";
|
|
294
|
+
SurveyProgressBarPlacement["Off"] = "off";
|
|
295
|
+
SurveyProgressBarPlacement["Top"] = "top";
|
|
296
|
+
return SurveyProgressBarPlacement;
|
|
297
|
+
}({});
|
|
298
|
+
// src/models/SurveyRadioGroupNodeProps.ts
|
|
299
|
+
const surveyRadioGroupNodePropsSchema = z.object({
|
|
300
|
+
...surveyQuestionBasePropsShape,
|
|
301
|
+
...surveyChoiceOptionsPropsShape,
|
|
302
|
+
...surveyNoneChoicePropsShape
|
|
303
|
+
});
|
|
304
|
+
// src/models/SurveyRankingNodeProps.ts
|
|
305
|
+
const surveyRankingNodePropsSchema = z.object({
|
|
306
|
+
...surveyQuestionBasePropsShape,
|
|
307
|
+
...surveyChoicesPropsShape
|
|
308
|
+
});
|
|
309
|
+
// src/models/SurveyRatingType.ts
|
|
310
|
+
let SurveyRatingType = /* @__PURE__ */ function(SurveyRatingType) {
|
|
311
|
+
SurveyRatingType["Labels"] = "labels";
|
|
312
|
+
SurveyRatingType["Smileys"] = "smileys";
|
|
313
|
+
SurveyRatingType["Stars"] = "stars";
|
|
314
|
+
return SurveyRatingType;
|
|
315
|
+
}({});
|
|
316
|
+
// src/models/SurveyRatingNodeProps.ts
|
|
317
|
+
const MIN_SURVEY_RATE_COUNT = 2;
|
|
318
|
+
const MAX_SURVEY_RATE_COUNT = 20;
|
|
319
|
+
const surveyRatingNodePropsSchema = z.object({
|
|
320
|
+
...surveyQuestionBasePropsShape,
|
|
321
|
+
maxRateDescription: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
322
|
+
minRateDescription: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
323
|
+
rateCount: z.int().min(MIN_SURVEY_RATE_COUNT).max(MAX_SURVEY_RATE_COUNT).default(5),
|
|
324
|
+
rateType: z.enum(SurveyRatingType).default("labels")
|
|
325
|
+
});
|
|
326
|
+
// src/models/SurveyRootProps.ts
|
|
327
|
+
const HEX_COLOR_REGEX = /^(?:#[\da-f]{6})?$/iu;
|
|
328
|
+
const surveyRootPropsSchema = z.strictObject({
|
|
329
|
+
accentColor: z.string().regex(HEX_COLOR_REGEX).default(""),
|
|
330
|
+
backgroundColor: z.string().regex(HEX_COLOR_REGEX).default(""),
|
|
331
|
+
calculatedValues: createUniqueArraySchema(surveyCalculatedValueSchema, "name").max(100).default([]),
|
|
332
|
+
completedHtml: z.string().max(MAX_SURVEY_HTML_LENGTH).default(""),
|
|
333
|
+
completeText: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
334
|
+
description: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
335
|
+
isQuestionNumbersVisible: z.boolean().default(false),
|
|
336
|
+
logo: z.string().max(MAX_SURVEY_URL_LENGTH).default(""),
|
|
337
|
+
pageNextText: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
338
|
+
pagePrevText: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
339
|
+
showProgressBar: z.enum(SurveyProgressBarPlacement).default("off"),
|
|
340
|
+
title: z.string().max(MAX_SURVEY_TEXT_LENGTH).default("")
|
|
341
|
+
});
|
|
342
|
+
// src/models/SurveySliderNodeProps.ts
|
|
343
|
+
const surveySliderNodePropsSchema = z.object({
|
|
344
|
+
...surveyQuestionBasePropsShape,
|
|
345
|
+
isValueVisible: z.boolean().default(true),
|
|
346
|
+
max: z.number().default(100),
|
|
347
|
+
min: z.number().default(0),
|
|
348
|
+
step: z.number().positive().default(1)
|
|
349
|
+
});
|
|
350
|
+
// src/models/SurveyTagBoxNodeProps.ts
|
|
351
|
+
const surveyTagBoxNodePropsSchema = z.object({
|
|
352
|
+
...surveyQuestionBasePropsShape,
|
|
353
|
+
...surveyChoiceOptionsPropsShape,
|
|
354
|
+
maxSelected: z.int().positive().optional(),
|
|
355
|
+
placeholder: z.string().max(MAX_SURVEY_TEXT_LENGTH).default("")
|
|
356
|
+
});
|
|
357
|
+
// src/models/SurveyTextInputType.ts
|
|
358
|
+
let SurveyTextInputType = /* @__PURE__ */ function(SurveyTextInputType) {
|
|
359
|
+
SurveyTextInputType["Date"] = "date";
|
|
360
|
+
SurveyTextInputType["DatetimeLocal"] = "datetime-local";
|
|
361
|
+
SurveyTextInputType["Email"] = "email";
|
|
362
|
+
SurveyTextInputType["Number"] = "number";
|
|
363
|
+
SurveyTextInputType["Password"] = "password";
|
|
364
|
+
SurveyTextInputType["Tel"] = "tel";
|
|
365
|
+
SurveyTextInputType["Text"] = "text";
|
|
366
|
+
SurveyTextInputType["Time"] = "time";
|
|
367
|
+
SurveyTextInputType["Url"] = "url";
|
|
368
|
+
return SurveyTextInputType;
|
|
369
|
+
}({});
|
|
370
|
+
// src/models/SurveyTextNodeProps.ts
|
|
371
|
+
const surveyTextNodePropsSchema = z.object({
|
|
372
|
+
...surveyQuestionBasePropsShape,
|
|
373
|
+
inputType: z.enum(SurveyTextInputType).default("text"),
|
|
374
|
+
max: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
375
|
+
maxLength: z.int().nonnegative().optional(),
|
|
376
|
+
min: z.string().max(MAX_SURVEY_TEXT_LENGTH).default(""),
|
|
377
|
+
minLength: z.int().nonnegative().optional(),
|
|
378
|
+
pattern: z.string().max(200).default(""),
|
|
379
|
+
placeholder: z.string().max(MAX_SURVEY_TEXT_LENGTH).default("")
|
|
380
|
+
});
|
|
381
|
+
// src/services/boundedChildren.ts
|
|
382
|
+
const boundedChildren = (schema) => z.array(schema).max(MAX_SURVEY_NODE_COUNT);
|
|
383
|
+
// src/services/checkSurveyExpressionField.ts
|
|
384
|
+
const checkSurveyExpressionField = (source, label, pointer, issues) => {
|
|
385
|
+
const expressionError = checkSurveyExpression(source);
|
|
386
|
+
if (expressionError === void 0) return;
|
|
387
|
+
issues.push({
|
|
388
|
+
message: `The ${label} does not parse: ${expressionError.message} (at position ${expressionError.position})`,
|
|
389
|
+
pointer
|
|
390
|
+
});
|
|
391
|
+
};
|
|
392
|
+
// src/services/checkSurveyCalculatedValues.ts
|
|
393
|
+
const checkSurveyCalculatedValues = (calculatedValues, listPointer, names, issues) => {
|
|
394
|
+
for (const [index, calculatedValue] of calculatedValues.entries()) {
|
|
395
|
+
const calculatedValuePointer = `${listPointer}/${index}`;
|
|
396
|
+
if (names.has(calculatedValue.name)) issues.push({
|
|
397
|
+
message: `The name "${calculatedValue.name}" is already used by a question or an earlier calculated value`,
|
|
398
|
+
pointer: `${calculatedValuePointer}/name`
|
|
399
|
+
});
|
|
400
|
+
names.add(calculatedValue.name);
|
|
401
|
+
checkSurveyExpressionField(calculatedValue.expression, "calculated value expression", `${calculatedValuePointer}/expression`, issues);
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
// src/services/runner/constants.ts
|
|
405
|
+
const SURVEY_REQUIRED_MESSAGE = "Please answer this question.";
|
|
406
|
+
const SURVEY_INVALID_ANSWER_MESSAGE = "This answer is not valid.";
|
|
407
|
+
const SURVEY_TOO_SHORT_MESSAGE = "This answer is too short.";
|
|
408
|
+
const SURVEY_TOO_LONG_MESSAGE = "This answer is too long.";
|
|
409
|
+
const SURVEY_TOO_FEW_SELECTED_MESSAGE = "Select more choices.";
|
|
410
|
+
const SURVEY_TOO_MANY_SELECTED_MESSAGE = "Select fewer choices.";
|
|
411
|
+
const SURVEY_OUT_OF_RANGE_MESSAGE = "This answer is out of range.";
|
|
412
|
+
const SURVEY_NOT_A_CHOICE_MESSAGE = "This answer is not one of the choices.";
|
|
413
|
+
const SURVEY_WRONG_COUNT_MESSAGE = "This answer has the wrong number of rows or panels.";
|
|
414
|
+
const MATRIX_CELL_RATING_COUNT = 5;
|
|
415
|
+
const SURVEY_NONE_ANSWER = "none";
|
|
416
|
+
const SURVEY_UNKNOWN_QUESTION_MESSAGE = "Unknown question";
|
|
417
|
+
const SURVEY_NOT_SHOWN_MESSAGE = "This question is not shown";
|
|
418
|
+
// src/services/checkSurveyNoneChoice.ts
|
|
419
|
+
const checkSurveyNoneChoice = (props, nodePointer, issues) => {
|
|
420
|
+
if (props.hasNone && props.choices.some(({ value }) => value === "none")) issues.push({
|
|
421
|
+
message: `A choice may not take the value "${SURVEY_NONE_ANSWER}", since the question offers none under it`,
|
|
422
|
+
pointer: getBlockPropPointer(nodePointer, "choices")
|
|
423
|
+
});
|
|
424
|
+
};
|
|
425
|
+
// src/services/checkSurveyOptionalExpression.ts
|
|
426
|
+
const checkSurveyOptionalExpression = (source, label, pointer, issues) => {
|
|
427
|
+
if (source === "") return;
|
|
428
|
+
checkSurveyExpressionField(source, label, pointer, issues);
|
|
429
|
+
};
|
|
430
|
+
// src/services/checkSurveyQuestion.ts
|
|
431
|
+
const checkSurveyQuestion = (props, nodePointer, names, issues) => {
|
|
432
|
+
if (names.has(props.name)) issues.push({
|
|
433
|
+
message: `The name "${props.name}" is already used by an earlier question`,
|
|
434
|
+
pointer: getBlockPropPointer(nodePointer, "name")
|
|
435
|
+
});
|
|
436
|
+
else names.add(props.name);
|
|
437
|
+
checkSurveyOptionalExpression(props.visibleIf, "visibility condition", getBlockPropPointer(nodePointer, "visibleIf"), issues);
|
|
438
|
+
checkSurveyOptionalExpression(props.enableIf, "enable condition", getBlockPropPointer(nodePointer, "enableIf"), issues);
|
|
439
|
+
checkSurveyOptionalExpression(props.requiredIf, "required condition", getBlockPropPointer(nodePointer, "requiredIf"), issues);
|
|
440
|
+
const validatorsPointer = getBlockPropPointer(nodePointer, "validators");
|
|
441
|
+
for (const [index, validator] of props.validators.entries()) checkSurveyExpressionField(validator.expression, "validator expression", `${validatorsPointer}/${index}/expression`, issues);
|
|
442
|
+
};
|
|
443
|
+
// src/services/checkSurveyNodes.ts
|
|
444
|
+
const checkSurveyNodes = (nodes, listPointer, names, issues) => {
|
|
445
|
+
for (const [index, node] of nodes.entries()) {
|
|
446
|
+
const nodePointer = `${listPointer}/${index}`;
|
|
447
|
+
if (node.type === "radiogroup" || node.type === "checkbox") checkSurveyNoneChoice(node.props, nodePointer, issues);
|
|
448
|
+
switch (node.type) {
|
|
449
|
+
case "expression":
|
|
450
|
+
checkSurveyQuestion(node.props, nodePointer, names, issues);
|
|
451
|
+
checkSurveyOptionalExpression(node.props.expression, "expression", getBlockPropPointer(nodePointer, "expression"), issues);
|
|
452
|
+
break;
|
|
453
|
+
case "html":
|
|
454
|
+
case "image":
|
|
455
|
+
checkSurveyOptionalExpression(node.props.visibleIf, "visibility condition", getBlockPropPointer(nodePointer, "visibleIf"), issues);
|
|
456
|
+
break;
|
|
457
|
+
case "page":
|
|
458
|
+
checkSurveyOptionalExpression(node.props.visibleIf, "visibility condition", getBlockPropPointer(nodePointer, "visibleIf"), issues);
|
|
459
|
+
checkSurveyNodes(node.props.children, getBlockPropPointer(nodePointer, "children"), names, issues);
|
|
460
|
+
break;
|
|
461
|
+
case "panel":
|
|
462
|
+
checkSurveyOptionalExpression(node.props.visibleIf, "visibility condition", getBlockPropPointer(nodePointer, "visibleIf"), issues);
|
|
463
|
+
checkSurveyOptionalExpression(node.props.enableIf, "enable condition", getBlockPropPointer(nodePointer, "enableIf"), issues);
|
|
464
|
+
checkSurveyNodes(node.props.children, getBlockPropPointer(nodePointer, "children"), names, issues);
|
|
465
|
+
break;
|
|
466
|
+
case "paneldynamic":
|
|
467
|
+
checkSurveyQuestion(node.props, nodePointer, names, issues);
|
|
468
|
+
checkSurveyNodes(node.props.template, getBlockPropPointer(nodePointer, "template"), /* @__PURE__ */ new Set(), issues);
|
|
469
|
+
break;
|
|
470
|
+
default: checkSurveyQuestion(node.props, nodePointer, names, issues);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
// src/services/checkSurveyDocument.ts
|
|
475
|
+
const checkSurveyDocument = (document) => {
|
|
476
|
+
const issues = [];
|
|
477
|
+
const names = /* @__PURE__ */ new Set();
|
|
478
|
+
checkSurveyNodes(document.content, "/content", names, issues);
|
|
479
|
+
checkSurveyCalculatedValues(document.root.props.calculatedValues, "/root/props/calculatedValues", names, issues);
|
|
480
|
+
return issues;
|
|
481
|
+
};
|
|
482
|
+
// src/services/createSeededRandom.ts
|
|
483
|
+
const createSeededRandom = (seed) => {
|
|
484
|
+
let state = seed;
|
|
485
|
+
return () => {
|
|
486
|
+
state = state + 1831565813 >>> 0;
|
|
487
|
+
let value = Math.imul(state ^ state >>> 15, 1 | state);
|
|
488
|
+
value ^= value + Math.imul(value ^ value >>> 7, 61 | value);
|
|
489
|
+
return ((value ^ value >>> 14) >>> 0) / 4294967296;
|
|
490
|
+
};
|
|
491
|
+
};
|
|
492
|
+
// src/services/surveyNodeTypeLists.ts
|
|
493
|
+
const SURVEY_ROOT_NODE_TYPES = ["page"];
|
|
494
|
+
const SURVEY_PLACEABLE_NODE_TYPES = Object.values(SurveyNodeType).filter((type) => type !== "page");
|
|
495
|
+
const SURVEY_TEMPLATE_NODE_TYPES = SURVEY_PLACEABLE_NODE_TYPES.filter((type) => type !== "panel" && type !== "paneldynamic");
|
|
496
|
+
// src/services/surveyPageNodeType.ts
|
|
497
|
+
const surveyPageNodeType = {
|
|
498
|
+
createDefaultProps: () => surveyPageNodePropsSchema.parse({}),
|
|
499
|
+
formSchema: surveyPageNodePropsSchema,
|
|
500
|
+
label: "Page",
|
|
501
|
+
propsSchema: surveyPageNodePropsSchema,
|
|
502
|
+
slots: { children: SURVEY_PLACEABLE_NODE_TYPES },
|
|
503
|
+
type: "page"
|
|
504
|
+
};
|
|
505
|
+
// src/services/createSurveyDocument.ts
|
|
506
|
+
const createSurveyDocument = () => {
|
|
507
|
+
return {
|
|
508
|
+
content: [{
|
|
509
|
+
props: {
|
|
510
|
+
...surveyPageNodeType.createDefaultProps(),
|
|
511
|
+
children: [],
|
|
512
|
+
id: crypto.randomUUID()
|
|
513
|
+
},
|
|
514
|
+
type: "page"
|
|
515
|
+
}],
|
|
516
|
+
root: { props: surveyRootPropsSchema.parse({}) }
|
|
517
|
+
};
|
|
518
|
+
};
|
|
519
|
+
// src/services/flattenSurveyQuestions.ts
|
|
520
|
+
const flattenSurveyQuestions = (nodes) => nodes.flatMap((node) => node.type === "page" || node.type === "panel" ? flattenSurveyQuestions(node.props.children) : [node]);
|
|
521
|
+
// src/services/getSurveyChoiceText.ts
|
|
522
|
+
const getSurveyChoiceText = ({ text, value }) => text || String(value);
|
|
523
|
+
// src/services/hashSurveySeed.ts
|
|
524
|
+
const hashSurveySeed = (seed) => {
|
|
525
|
+
let hash = 2166136261;
|
|
526
|
+
for (const character of seed) {
|
|
527
|
+
hash ^= character.codePointAt(0) ?? 0;
|
|
528
|
+
hash = Math.imul(hash, 16777619);
|
|
529
|
+
}
|
|
530
|
+
return hash >>> 0;
|
|
531
|
+
};
|
|
532
|
+
// src/services/getSurveyOrderedChoices.ts
|
|
533
|
+
const getSurveyOrderedChoices = (choices, choicesOrder, seed) => {
|
|
534
|
+
switch (choicesOrder) {
|
|
535
|
+
case "asc": return choices.toSorted((firstChoice, secondChoice) => getSurveyChoiceText(firstChoice).localeCompare(getSurveyChoiceText(secondChoice)));
|
|
536
|
+
case "desc": return choices.toSorted((firstChoice, secondChoice) => getSurveyChoiceText(secondChoice).localeCompare(getSurveyChoiceText(firstChoice)));
|
|
537
|
+
case "none": return choices;
|
|
538
|
+
case "random": {
|
|
539
|
+
const random = createSeededRandom(hashSurveySeed(seed));
|
|
540
|
+
const shuffled = [];
|
|
541
|
+
let remaining = choices;
|
|
542
|
+
while (remaining.length > 0) {
|
|
543
|
+
const index = Math.floor(random() * remaining.length);
|
|
544
|
+
shuffled.push(takeOne(remaining, index));
|
|
545
|
+
remaining = remaining.toSpliced(index, 1);
|
|
546
|
+
}
|
|
547
|
+
return shuffled;
|
|
548
|
+
}
|
|
549
|
+
default: return exhaustiveGuard(choicesOrder);
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
// src/services/runner/answer/createSurveyBooleanAnswerSchema.ts
|
|
553
|
+
const createSurveyBooleanAnswerSchema = () => z.boolean({ error: SURVEY_INVALID_ANSWER_MESSAGE });
|
|
554
|
+
// src/services/runner/answer/createSurveyStringAnswerSchema.ts
|
|
555
|
+
const createSurveyStringAnswerSchema = ({ maxLength, minLength }) => {
|
|
556
|
+
const bounded = z.string({ error: SURVEY_INVALID_ANSWER_MESSAGE }).max(MAX_SURVEY_ANSWER_LENGTH, { error: SURVEY_TOO_LONG_MESSAGE });
|
|
557
|
+
const minBounded = minLength === void 0 ? bounded : bounded.min(minLength, { error: SURVEY_TOO_SHORT_MESSAGE });
|
|
558
|
+
return maxLength === void 0 ? minBounded : minBounded.max(maxLength, { error: SURVEY_TOO_LONG_MESSAGE });
|
|
559
|
+
};
|
|
560
|
+
// src/services/runner/answer/createSurveyChoiceValueSchema.ts
|
|
561
|
+
const createSurveyChoiceValueSchema = ({ choices, hasNone = false, hasOther = false }) => {
|
|
562
|
+
const options = [
|
|
563
|
+
...choices.map((choice) => z.literal(choice.value, { error: SURVEY_NOT_A_CHOICE_MESSAGE })),
|
|
564
|
+
...hasNone ? [z.literal(SURVEY_NONE_ANSWER, { error: SURVEY_NOT_A_CHOICE_MESSAGE })] : [],
|
|
565
|
+
...hasOther ? [createSurveyStringAnswerSchema({}).min(1, { error: SURVEY_REQUIRED_MESSAGE })] : []
|
|
566
|
+
];
|
|
567
|
+
return options.length === 0 ? z.never({ error: SURVEY_NOT_A_CHOICE_MESSAGE }) : z.union(options, { error: SURVEY_NOT_A_CHOICE_MESSAGE });
|
|
568
|
+
};
|
|
569
|
+
// src/services/runner/answer/createSurveyButtonGroupAnswerSchema.ts
|
|
570
|
+
const createSurveyButtonGroupAnswerSchema = (node) => createSurveyChoiceValueSchema({ choices: node.props.choices });
|
|
571
|
+
// src/services/runner/answer/createSurveySelectionAnswerSchema.ts
|
|
572
|
+
const createSurveySelectionAnswerSchema = ({ choices, hasNone = false, hasOther = false, maxSelected, minSelected }) => createUniqueArraySchema(createSurveyChoiceValueSchema({
|
|
573
|
+
choices,
|
|
574
|
+
hasNone,
|
|
575
|
+
hasOther
|
|
576
|
+
})).min(minSelected ?? 0, { error: SURVEY_TOO_FEW_SELECTED_MESSAGE }).max(maxSelected ?? 200, { error: SURVEY_TOO_MANY_SELECTED_MESSAGE }).refine((selected) => !hasNone || !selected.includes("none") || selected.length === 1, { error: SURVEY_INVALID_ANSWER_MESSAGE });
|
|
577
|
+
// src/services/runner/answer/createSurveyCheckboxAnswerSchema.ts
|
|
578
|
+
const createSurveyCheckboxAnswerSchema = (node) => createSurveySelectionAnswerSchema({
|
|
579
|
+
choices: node.props.choices,
|
|
580
|
+
hasNone: node.props.hasNone,
|
|
581
|
+
hasOther: node.props.hasOther,
|
|
582
|
+
maxSelected: node.props.maxSelected,
|
|
583
|
+
minSelected: node.props.minSelected
|
|
584
|
+
});
|
|
585
|
+
// src/services/runner/answer/createSurveyCommentAnswerSchema.ts
|
|
586
|
+
const createSurveyCommentAnswerSchema = (node) => createSurveyStringAnswerSchema({ maxLength: node.props.maxLength });
|
|
587
|
+
// src/services/runner/answer/createSurveyDropdownAnswerSchema.ts
|
|
588
|
+
const createSurveyDropdownAnswerSchema = (node) => createSurveyChoiceValueSchema({
|
|
589
|
+
choices: node.props.choices,
|
|
590
|
+
hasOther: node.props.hasOther
|
|
591
|
+
});
|
|
592
|
+
// src/services/runner/answer/createSurveyNumberAnswerSchema.ts
|
|
593
|
+
const createSurveyNumberAnswerSchema = ({ max, min }) => {
|
|
594
|
+
const bounded = z.number({ error: SURVEY_INVALID_ANSWER_MESSAGE });
|
|
595
|
+
const minBounded = min === void 0 ? bounded : bounded.min(min, { error: SURVEY_OUT_OF_RANGE_MESSAGE });
|
|
596
|
+
return max === void 0 ? minBounded : minBounded.max(max, { error: SURVEY_OUT_OF_RANGE_MESSAGE });
|
|
597
|
+
};
|
|
598
|
+
// src/services/runner/surveyAnswerScalarSchema.ts
|
|
599
|
+
const surveyAnswerScalarSchema = z.union([
|
|
600
|
+
createSurveyStringAnswerSchema({}),
|
|
601
|
+
createSurveyNumberAnswerSchema({}),
|
|
602
|
+
createSurveyBooleanAnswerSchema()
|
|
603
|
+
], { error: SURVEY_INVALID_ANSWER_MESSAGE });
|
|
604
|
+
// src/services/runner/answer/createSurveyExpressionAnswerSchema.ts
|
|
605
|
+
const createSurveyExpressionAnswerSchema = () => surveyAnswerScalarSchema;
|
|
606
|
+
// src/services/runner/answer/createSurveyImagePickerAnswerSchema.ts
|
|
607
|
+
const createSurveyImagePickerAnswerSchema = (node) => node.props.multiSelect ? createSurveySelectionAnswerSchema({ choices: node.props.choices }) : createSurveyChoiceValueSchema({ choices: node.props.choices });
|
|
608
|
+
// src/services/runner/checkSurveyAnswerEmpty.ts
|
|
609
|
+
const checkSurveyAnswerEmpty = (value) => value === void 0 || typeof value === "string" && normalizeString(value) === "" || Array.isArray(value) && value.length === 0;
|
|
610
|
+
// src/services/runner/answer/createSurveyNamedAnswerSchema.ts
|
|
611
|
+
const createSurveyNamedAnswerSchema = (fields) => z.strictObject(Object.fromEntries(fields.map((field) => [field.name, z.preprocess((value) => checkSurveyAnswerEmpty(value) ? void 0 : value, field.schema.optional())])), { error: SURVEY_INVALID_ANSWER_MESSAGE }).superRefine((answer, ctx) => {
|
|
612
|
+
for (const field of fields) if (field.isRequired && checkSurveyAnswerEmpty(answer[field.name])) ctx.addIssue({
|
|
613
|
+
code: "custom",
|
|
614
|
+
message: SURVEY_REQUIRED_MESSAGE,
|
|
615
|
+
path: [field.name]
|
|
616
|
+
});
|
|
617
|
+
});
|
|
618
|
+
// src/services/runner/answer/createSurveyMatrixAnswerSchema.ts
|
|
619
|
+
const createSurveyMatrixAnswerSchema = (node) => {
|
|
620
|
+
const column = createSurveyChoiceValueSchema({ choices: node.props.columns });
|
|
621
|
+
return createSurveyNamedAnswerSchema(node.props.rows.map((row) => ({
|
|
622
|
+
isRequired: node.props.isAllRowRequired,
|
|
623
|
+
name: `${row.value}`,
|
|
624
|
+
schema: column
|
|
625
|
+
})));
|
|
626
|
+
};
|
|
627
|
+
// src/services/runner/answer/createSurveyRatingValueSchema.ts
|
|
628
|
+
const MIN_SURVEY_RATING = 1;
|
|
629
|
+
const createSurveyRatingValueSchema = (rateCount) => z.int({ error: SURVEY_INVALID_ANSWER_MESSAGE }).min(MIN_SURVEY_RATING, { error: SURVEY_OUT_OF_RANGE_MESSAGE }).max(rateCount, { error: SURVEY_OUT_OF_RANGE_MESSAGE });
|
|
630
|
+
// src/services/runner/answer/createSurveyMatrixCellAnswerSchema.ts
|
|
631
|
+
const createSurveyMatrixCellAnswerSchema = (column) => {
|
|
632
|
+
switch (column.cellType) {
|
|
633
|
+
case "boolean": return createSurveyBooleanAnswerSchema();
|
|
634
|
+
case "checkbox": return createSurveySelectionAnswerSchema({ choices: column.choices });
|
|
635
|
+
case "comment":
|
|
636
|
+
case "text": return createSurveyStringAnswerSchema({});
|
|
637
|
+
case "dropdown": return createSurveyChoiceValueSchema({ choices: column.choices });
|
|
638
|
+
case "rating": return createSurveyRatingValueSchema(5);
|
|
639
|
+
default: return exhaustiveGuard(column.cellType);
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
// src/services/runner/answer/createSurveyMatrixDynamicAnswerSchema.ts
|
|
643
|
+
const createSurveyMatrixDynamicAnswerSchema = (node) => {
|
|
644
|
+
const row = createSurveyNamedAnswerSchema(node.props.columns.map((column) => ({
|
|
645
|
+
isRequired: column.isRequired,
|
|
646
|
+
name: column.name,
|
|
647
|
+
schema: createSurveyMatrixCellAnswerSchema(column)
|
|
648
|
+
})));
|
|
649
|
+
return z.array(row, { error: SURVEY_INVALID_ANSWER_MESSAGE }).min(node.props.minRowCount, { error: SURVEY_WRONG_COUNT_MESSAGE }).max(node.props.maxRowCount, { error: SURVEY_WRONG_COUNT_MESSAGE });
|
|
650
|
+
};
|
|
651
|
+
// src/services/runner/answer/createSurveyMultipleTextAnswerSchema.ts
|
|
652
|
+
const createSurveyMultipleTextAnswerSchema = (node) => createSurveyNamedAnswerSchema(node.props.items.map((item) => ({
|
|
653
|
+
isRequired: item.isRequired,
|
|
654
|
+
name: item.name,
|
|
655
|
+
schema: item.inputType === "email" ? z.email({ error: SURVEY_INVALID_ANSWER_MESSAGE }) : createSurveyStringAnswerSchema({})
|
|
656
|
+
})));
|
|
657
|
+
// src/services/runner/checkIsSurveyAnsweringNode.ts
|
|
658
|
+
const NON_ANSWERING_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
659
|
+
"html",
|
|
660
|
+
"image",
|
|
661
|
+
"page",
|
|
662
|
+
"panel"
|
|
663
|
+
]);
|
|
664
|
+
const checkIsSurveyAnsweringNode = (node) => !NON_ANSWERING_NODE_TYPES.has(node.type);
|
|
665
|
+
// src/services/runner/checkSurveyExpressionHolds.ts
|
|
666
|
+
const checkSurveyExpressionHolds = (source, values, now, scopes = {}) => runSurveyExpression(source, {
|
|
667
|
+
now,
|
|
668
|
+
scopes,
|
|
669
|
+
values
|
|
670
|
+
}).map((value) => value === true).unwrapOr(false);
|
|
671
|
+
// src/services/runner/checkSurveyNodeEnabled.ts
|
|
672
|
+
const checkSurveyNodeEnabled = (node, values, now, scopes = {}) => {
|
|
673
|
+
if (node.type === "expression") return false;
|
|
674
|
+
if (node.type !== "page" && node.type !== "panel" && !checkIsSurveyAnsweringNode(node)) return false;
|
|
675
|
+
const enableIf = "enableIf" in node.props ? node.props.enableIf : "";
|
|
676
|
+
return enableIf === "" || checkSurveyExpressionHolds(enableIf, values, now, scopes);
|
|
677
|
+
};
|
|
678
|
+
// src/services/runner/checkSurveyNodeRequired.ts
|
|
679
|
+
const checkSurveyNodeRequired = (node, values, now, scopes = {}) => {
|
|
680
|
+
if ("isRequired" in node.props && node.props.isRequired) return true;
|
|
681
|
+
const requiredIf = "requiredIf" in node.props ? node.props.requiredIf : "";
|
|
682
|
+
return requiredIf !== "" && checkSurveyExpressionHolds(requiredIf, values, now, scopes);
|
|
683
|
+
};
|
|
684
|
+
// src/services/runner/checkSurveyNodeVisible.ts
|
|
685
|
+
const checkSurveyNodeVisible = (node, values, now, scopes = {}) => node.props.visibleIf === "" || checkSurveyExpressionHolds(node.props.visibleIf, values, now, scopes);
|
|
686
|
+
// src/services/runner/toSurveyPanelScope.ts
|
|
687
|
+
const toSurveyPanelScope = (row) => {
|
|
688
|
+
const scope = {};
|
|
689
|
+
for (const [name, answer] of Object.entries(row)) if (answer !== void 0) scope[name] = toSurveyLogicAnswer(answer);
|
|
690
|
+
return scope;
|
|
691
|
+
};
|
|
692
|
+
// src/services/runner/getSurveyPanelRowViews.ts
|
|
693
|
+
const getSurveyPanelRowViews = (node, row, values, now) => {
|
|
694
|
+
const scopes = { panel: toSurveyPanelScope(row) };
|
|
695
|
+
return node.props.template.flatMap((question) => checkSurveyNodeVisible(question, values, now, scopes) ? [{
|
|
696
|
+
isEnabled: checkSurveyNodeEnabled(question, values, now, scopes),
|
|
697
|
+
isRequired: checkSurveyNodeRequired(question, values, now, scopes),
|
|
698
|
+
node: question
|
|
699
|
+
}] : []);
|
|
700
|
+
};
|
|
701
|
+
// src/services/runner/createSurveyNestedAnswerSchema.ts
|
|
702
|
+
const createSurveyNestedAnswerSchema = (inner) => z.union([
|
|
703
|
+
surveyAnswerScalarSchema,
|
|
704
|
+
z.array(inner, { error: SURVEY_INVALID_ANSWER_MESSAGE }).max(200, { error: SURVEY_INVALID_ANSWER_MESSAGE }),
|
|
705
|
+
createRecordSchema(z.string().max(MAX_SURVEY_ANSWER_LENGTH), inner, 200)
|
|
706
|
+
], { error: SURVEY_INVALID_ANSWER_MESSAGE });
|
|
707
|
+
const surveyAnswerValueSchema = createSurveyNestedAnswerSchema(createSurveyNestedAnswerSchema(createSurveyNestedAnswerSchema(surveyAnswerScalarSchema)));
|
|
708
|
+
// src/services/runner/answer/createSurveyPanelDynamicAnswerSchema.ts
|
|
709
|
+
const createSurveyPanelDynamicAnswerSchema = (node, createTemplateAnswerSchema, values, now) => {
|
|
710
|
+
const templateFields = node.props.template.map((question) => ({
|
|
711
|
+
name: question.props.name,
|
|
712
|
+
schema: createTemplateAnswerSchema(question)
|
|
713
|
+
}));
|
|
714
|
+
const rowShapeSchema = z.strictObject(Object.fromEntries(templateFields.map(({ name }) => [name, surveyAnswerValueSchema.optional()])), { error: SURVEY_INVALID_ANSWER_MESSAGE });
|
|
715
|
+
return z.array(rowShapeSchema, { error: SURVEY_INVALID_ANSWER_MESSAGE }).min(node.props.minPanelCount, { error: SURVEY_WRONG_COUNT_MESSAGE }).max(node.props.maxPanelCount, { error: SURVEY_WRONG_COUNT_MESSAGE }).superRefine((rows, ctx) => {
|
|
716
|
+
for (const [index, row] of rows.entries()) {
|
|
717
|
+
const views = getSurveyPanelRowViews(node, row, values, now);
|
|
718
|
+
const result = createSurveyNamedAnswerSchema(templateFields.map(({ name, schema }) => {
|
|
719
|
+
const view = views.find((item) => item.node.props.name === name);
|
|
720
|
+
return view?.isEnabled ? {
|
|
721
|
+
isRequired: view.isRequired,
|
|
722
|
+
name,
|
|
723
|
+
schema
|
|
724
|
+
} : {
|
|
725
|
+
isRequired: false,
|
|
726
|
+
name,
|
|
727
|
+
schema: z.unknown()
|
|
728
|
+
};
|
|
729
|
+
})).safeParse(row);
|
|
730
|
+
if (!result.success) for (const issue of result.error.issues) ctx.addIssue({
|
|
731
|
+
code: "custom",
|
|
732
|
+
message: issue.message,
|
|
733
|
+
path: [index, ...issue.path]
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
});
|
|
737
|
+
};
|
|
738
|
+
// src/services/runner/answer/createSurveyPatternAnswerSchema.ts
|
|
739
|
+
const createSurveyPatternAnswerSchema = (schema, pattern) => getResult(() => RE2JS.compile(pattern, RE2JS.LOOKBEHINDS)).map((regex) => schema.refine((value) => regex.matcher(value).find(), { error: SURVEY_INVALID_ANSWER_MESSAGE })).unwrapOr(schema);
|
|
740
|
+
// src/services/runner/answer/createSurveyRadioGroupAnswerSchema.ts
|
|
741
|
+
const createSurveyRadioGroupAnswerSchema = (node) => createSurveyChoiceValueSchema({
|
|
742
|
+
choices: node.props.choices,
|
|
743
|
+
hasNone: node.props.hasNone,
|
|
744
|
+
hasOther: node.props.hasOther
|
|
745
|
+
});
|
|
746
|
+
// src/services/runner/answer/createSurveyRankingAnswerSchema.ts
|
|
747
|
+
const createSurveyRankingAnswerSchema = (node) => createSurveySelectionAnswerSchema({ choices: node.props.choices });
|
|
748
|
+
// src/services/runner/answer/createSurveyRatingAnswerSchema.ts
|
|
749
|
+
const createSurveyRatingAnswerSchema = (node) => createSurveyRatingValueSchema(node.props.rateCount);
|
|
750
|
+
// src/services/runner/answer/createSurveySliderAnswerSchema.ts
|
|
751
|
+
const SURVEY_SLIDER_STEP_TOLERANCE = 1e-9;
|
|
752
|
+
const createSurveySliderAnswerSchema = (node) => createSurveyNumberAnswerSchema({
|
|
753
|
+
max: node.props.max,
|
|
754
|
+
min: node.props.min
|
|
755
|
+
}).refine((value) => {
|
|
756
|
+
const steps = (value - node.props.min) / node.props.step;
|
|
757
|
+
return Math.abs(steps - Math.round(steps)) < SURVEY_SLIDER_STEP_TOLERANCE;
|
|
758
|
+
}, { error: SURVEY_INVALID_ANSWER_MESSAGE });
|
|
759
|
+
// src/services/runner/answer/createSurveyStringRangeAnswerSchema.ts
|
|
760
|
+
const createSurveyStringRangeAnswerSchema = ({ max, min }) => createSurveyStringAnswerSchema({}).min(1, { error: SURVEY_REQUIRED_MESSAGE }).refine((value) => min === "" || value >= min, { error: SURVEY_OUT_OF_RANGE_MESSAGE }).refine((value) => max === "" || value <= max, { error: SURVEY_OUT_OF_RANGE_MESSAGE });
|
|
761
|
+
// src/services/runner/answer/createSurveyTagBoxAnswerSchema.ts
|
|
762
|
+
const createSurveyTagBoxAnswerSchema = (node) => createSurveySelectionAnswerSchema({
|
|
763
|
+
choices: node.props.choices,
|
|
764
|
+
hasOther: node.props.hasOther,
|
|
765
|
+
maxSelected: node.props.maxSelected
|
|
766
|
+
});
|
|
767
|
+
// src/services/runner/answer/parseSurveyNumberBound.ts
|
|
768
|
+
const parseSurveyNumberBound = (bound) => {
|
|
769
|
+
const value = Number(bound);
|
|
770
|
+
return normalizeString(bound) !== "" && Number.isFinite(value) ? value : void 0;
|
|
771
|
+
};
|
|
772
|
+
// src/services/runner/answer/createSurveyTextAnswerSchema.ts
|
|
773
|
+
const createSurveyTextAnswerSchema = (node) => {
|
|
774
|
+
switch (node.props.inputType) {
|
|
775
|
+
case "date":
|
|
776
|
+
case "datetime-local":
|
|
777
|
+
case "time": return createSurveyPatternAnswerSchema(createSurveyStringRangeAnswerSchema({
|
|
778
|
+
max: node.props.max,
|
|
779
|
+
min: node.props.min
|
|
780
|
+
}), node.props.pattern);
|
|
781
|
+
case "email": return createSurveyPatternAnswerSchema(z.email({ error: SURVEY_INVALID_ANSWER_MESSAGE }), node.props.pattern);
|
|
782
|
+
case "number": return createSurveyNumberAnswerSchema({
|
|
783
|
+
max: parseSurveyNumberBound(node.props.max),
|
|
784
|
+
min: parseSurveyNumberBound(node.props.min)
|
|
785
|
+
});
|
|
786
|
+
case "password":
|
|
787
|
+
case "tel":
|
|
788
|
+
case "text": return createSurveyPatternAnswerSchema(createSurveyStringAnswerSchema({
|
|
789
|
+
maxLength: node.props.maxLength,
|
|
790
|
+
minLength: node.props.minLength
|
|
791
|
+
}), node.props.pattern);
|
|
792
|
+
case "url": return createSurveyPatternAnswerSchema(z.url({ error: SURVEY_INVALID_ANSWER_MESSAGE }), node.props.pattern);
|
|
793
|
+
default: return exhaustiveGuard(node.props.inputType);
|
|
794
|
+
}
|
|
795
|
+
};
|
|
796
|
+
// src/services/runner/getSurveyExpressionNodes.ts
|
|
797
|
+
const getSurveyExpressionNodes = (document) => flattenSurveyQuestions(document.content).filter((node) => node.type === "expression");
|
|
798
|
+
// src/services/runner/getSurveyRunnerValues.ts
|
|
799
|
+
const MAX_SURVEY_RUNNER_PASSES = 5;
|
|
800
|
+
const getSurveyRunnerValues = (document, answers, now) => {
|
|
801
|
+
const values = toSurveyLogicAnswers(answers);
|
|
802
|
+
const calculations = [...document.root.props.calculatedValues, ...getSurveyExpressionNodes(document).map((node) => node.props)].filter(({ name }) => !Object.hasOwn(answers, name));
|
|
803
|
+
let changedNames = [];
|
|
804
|
+
for (let pass = 0; pass < MAX_SURVEY_RUNNER_PASSES; pass++) {
|
|
805
|
+
changedNames = [];
|
|
806
|
+
for (const { expression, name } of calculations) {
|
|
807
|
+
const previous = values[name];
|
|
808
|
+
const next = runSurveyExpression(expression, {
|
|
809
|
+
now,
|
|
810
|
+
scopes: {},
|
|
811
|
+
values
|
|
812
|
+
}).unwrapOr(void 0);
|
|
813
|
+
if (next === void 0) delete values[name];
|
|
814
|
+
else values[name] = next;
|
|
815
|
+
if (!checkIsDeepEqual(previous, values[name])) changedNames.push(name);
|
|
816
|
+
}
|
|
817
|
+
if (changedNames.length === 0) return values;
|
|
818
|
+
}
|
|
819
|
+
for (const name of changedNames) delete values[name];
|
|
820
|
+
return values;
|
|
821
|
+
};
|
|
822
|
+
// src/services/runner/getSurveyElementViews.ts
|
|
823
|
+
const getSurveyElementViews = (nodes, listPointer, values, now, isParentEnabled) => nodes.flatMap((node, index) => {
|
|
824
|
+
const pointer = `${listPointer}/${index}`;
|
|
825
|
+
if (!checkSurveyNodeVisible(node, values, now)) return [];
|
|
826
|
+
const isEnabled = isParentEnabled && checkSurveyNodeEnabled(node, values, now);
|
|
827
|
+
const children = node.type === "panel" ? getSurveyElementViews(node.props.children, getBlockPropPointer(pointer, "children"), values, now, isEnabled) : [];
|
|
828
|
+
if (node.type === "panel" && children.length === 0) return [];
|
|
829
|
+
return [{
|
|
830
|
+
children,
|
|
831
|
+
isEnabled,
|
|
832
|
+
isRequired: checkSurveyNodeRequired(node, values, now),
|
|
833
|
+
node,
|
|
834
|
+
pointer
|
|
835
|
+
}];
|
|
836
|
+
});
|
|
837
|
+
// src/services/runner/getSurveyPageViews.ts
|
|
838
|
+
const getSurveyPageViews = (document, pageIndex, values, now) => {
|
|
839
|
+
const page = document.content.at(pageIndex);
|
|
840
|
+
if (page?.type !== "page" || !checkSurveyNodeVisible(page, values, now)) return [];
|
|
841
|
+
return getSurveyElementViews(page.props.children, getBlockPropPointer(`/content/${pageIndex}`, "children"), values, now, true);
|
|
842
|
+
};
|
|
843
|
+
// src/services/runner/getSurveyVisiblePageIndexesFromValues.ts
|
|
844
|
+
const getSurveyVisiblePageIndexesFromValues = (document, values, now) => document.content.flatMap((_node, index) => getSurveyPageViews(document, index, values, now).length > 0 ? [index] : []);
|
|
845
|
+
// src/services/runner/getSurveyVisiblePageIndexes.ts
|
|
846
|
+
const getSurveyVisiblePageIndexes = (document, answers, now) => getSurveyVisiblePageIndexesFromValues(document, getSurveyRunnerValues(document, answers, now), now);
|
|
847
|
+
// src/services/runner/checkIsLastSurveyPage.ts
|
|
848
|
+
const checkIsLastSurveyPage = (document, state, now) => !getSurveyVisiblePageIndexes(document, state.answers, now).some((pageIndex) => pageIndex > state.pageIndex);
|
|
849
|
+
// src/services/runner/flattenSurveyElementViews.ts
|
|
850
|
+
const flattenSurveyElementViews = (views) => views.flatMap((view) => [view, ...flattenSurveyElementViews(view.children)]);
|
|
851
|
+
// src/services/runner/createSurveyAnswerSchema.ts
|
|
852
|
+
const createSurveyAnswerSchema = (node, values, now) => {
|
|
853
|
+
switch (node.type) {
|
|
854
|
+
case "boolean": return createSurveyBooleanAnswerSchema();
|
|
855
|
+
case "buttongroup": return createSurveyButtonGroupAnswerSchema(node);
|
|
856
|
+
case "checkbox": return createSurveyCheckboxAnswerSchema(node);
|
|
857
|
+
case "comment": return createSurveyCommentAnswerSchema(node);
|
|
858
|
+
case "dropdown": return createSurveyDropdownAnswerSchema(node);
|
|
859
|
+
case "expression": return createSurveyExpressionAnswerSchema();
|
|
860
|
+
case "html":
|
|
861
|
+
case "image": return z.undefined({ error: SURVEY_INVALID_ANSWER_MESSAGE });
|
|
862
|
+
case "imagepicker": return createSurveyImagePickerAnswerSchema(node);
|
|
863
|
+
case "matrix": return createSurveyMatrixAnswerSchema(node);
|
|
864
|
+
case "matrixdynamic": return createSurveyMatrixDynamicAnswerSchema(node);
|
|
865
|
+
case "multipletext": return createSurveyMultipleTextAnswerSchema(node);
|
|
866
|
+
case "paneldynamic": return createSurveyPanelDynamicAnswerSchema(node, (question) => createSurveyAnswerSchema(question, values, now), values, now);
|
|
867
|
+
case "radiogroup": return createSurveyRadioGroupAnswerSchema(node);
|
|
868
|
+
case "ranking": return createSurveyRankingAnswerSchema(node);
|
|
869
|
+
case "rating": return createSurveyRatingAnswerSchema(node);
|
|
870
|
+
case "slider": return createSurveySliderAnswerSchema(node);
|
|
871
|
+
case "tagbox": return createSurveyTagBoxAnswerSchema(node);
|
|
872
|
+
case "text": return createSurveyTextAnswerSchema(node);
|
|
873
|
+
default: return exhaustiveGuard(node);
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
// src/services/runner/getSurveyQuestionErrors.ts
|
|
877
|
+
const getSurveyQuestionErrors = (view, answers, values, now) => {
|
|
878
|
+
const { node, pointer } = view;
|
|
879
|
+
if (!view.isEnabled || !checkIsSurveyAnsweringNode(node)) return [];
|
|
880
|
+
const { name } = node.props;
|
|
881
|
+
const answer = answers[name];
|
|
882
|
+
if (answer === void 0 || checkSurveyAnswerEmpty(answer)) {
|
|
883
|
+
const holdsRequiredItem = node.type === "multipletext" && node.props.items.some((item) => item.isRequired);
|
|
884
|
+
if (!view.isRequired && !holdsRequiredItem) return [];
|
|
885
|
+
return [{
|
|
886
|
+
message: node.props.requiredErrorText === "" ? SURVEY_REQUIRED_MESSAGE : node.props.requiredErrorText,
|
|
887
|
+
name,
|
|
888
|
+
pointer
|
|
889
|
+
}];
|
|
890
|
+
}
|
|
891
|
+
const result = createSurveyAnswerSchema(node, values, now).safeParse(answer);
|
|
892
|
+
if (!result.success) return [{
|
|
893
|
+
message: result.error.issues[0]?.message ?? "This answer is not valid.",
|
|
894
|
+
name,
|
|
895
|
+
pointer
|
|
896
|
+
}];
|
|
897
|
+
const value = toSurveyLogicAnswer(answer);
|
|
898
|
+
return node.props.validators.filter((validator) => !checkSurveyExpressionHolds(validator.expression, {
|
|
899
|
+
...values,
|
|
900
|
+
value
|
|
901
|
+
}, now)).map((validator) => ({
|
|
902
|
+
message: validator.text,
|
|
903
|
+
name,
|
|
904
|
+
pointer
|
|
905
|
+
}));
|
|
906
|
+
};
|
|
907
|
+
// src/services/runner/getSurveyPageErrors.ts
|
|
908
|
+
const getSurveyPageErrors = (document, pageIndex, answers, values, now) => flattenSurveyElementViews(getSurveyPageViews(document, pageIndex, values, now)).flatMap((view) => getSurveyQuestionErrors(view, answers, values, now));
|
|
909
|
+
// src/services/runner/getSurveyPanelRowAnswers.ts
|
|
910
|
+
const getSurveyPanelRowAnswers = (node, row, values, now) => {
|
|
911
|
+
const shownNames = new Set(getSurveyPanelRowViews(node, row, values, now).map((view) => view.node.props.name));
|
|
912
|
+
return Object.fromEntries(Object.entries(row).filter(([name]) => shownNames.has(name)));
|
|
913
|
+
};
|
|
914
|
+
// src/services/runner/toSurveyAnswerValue.ts
|
|
915
|
+
const toSurveyAnswerValue = (value) => {
|
|
916
|
+
if (value === void 0) return void 0;
|
|
917
|
+
if (typeof value !== "object") return value;
|
|
918
|
+
if (Array.isArray(value)) {
|
|
919
|
+
const items = [];
|
|
920
|
+
for (const item of value) {
|
|
921
|
+
const answerItem = toSurveyAnswerValue(item);
|
|
922
|
+
if (answerItem === void 0) return void 0;
|
|
923
|
+
items.push(answerItem);
|
|
924
|
+
}
|
|
925
|
+
return items;
|
|
926
|
+
}
|
|
927
|
+
const record = {};
|
|
928
|
+
for (const [name, field] of Object.entries(value)) {
|
|
929
|
+
const answerField = toSurveyAnswerValue(field);
|
|
930
|
+
if (answerField === void 0) return void 0;
|
|
931
|
+
record[name] = answerField;
|
|
932
|
+
}
|
|
933
|
+
return record;
|
|
934
|
+
};
|
|
935
|
+
// src/services/runner/completeSurvey.ts
|
|
936
|
+
const completeSurvey = (document, state, now) => {
|
|
937
|
+
const values = getSurveyRunnerValues(document, state.answers, now);
|
|
938
|
+
const pageIndexes = getSurveyVisiblePageIndexesFromValues(document, values, now);
|
|
939
|
+
for (const pageIndex of pageIndexes) {
|
|
940
|
+
const errors = getSurveyPageErrors(document, pageIndex, state.answers, values, now);
|
|
941
|
+
if (errors.length > 0) return {
|
|
942
|
+
answers: {},
|
|
943
|
+
errors,
|
|
944
|
+
state: {
|
|
945
|
+
...state,
|
|
946
|
+
isCompleted: false,
|
|
947
|
+
pageIndex
|
|
948
|
+
}
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
const visibleViews = pageIndexes.flatMap((pageIndex) => flattenSurveyElementViews(getSurveyPageViews(document, pageIndex, values, now)));
|
|
952
|
+
const visibleNodes = visibleViews.map((view) => view.node);
|
|
953
|
+
const visibleNames = new Set(visibleNodes.flatMap((node) => node.type === "panel" ? [] : [node.props.name]));
|
|
954
|
+
const answers = Object.fromEntries(Object.entries(state.answers).filter(([name]) => visibleNames.has(name)));
|
|
955
|
+
for (const { node } of visibleViews) {
|
|
956
|
+
if (node.type !== "paneldynamic") continue;
|
|
957
|
+
const rows = answers[node.props.name];
|
|
958
|
+
if (Array.isArray(rows)) answers[node.props.name] = rows.map((row) => typeof row === "object" && !Array.isArray(row) ? getSurveyPanelRowAnswers(node, row, values, now) : row);
|
|
959
|
+
}
|
|
960
|
+
const includedNames = [...visibleNodes.flatMap((node) => node.type === "expression" ? [node.props.name] : []), ...document.root.props.calculatedValues.filter(({ includeIntoResult }) => includeIntoResult).map(({ name }) => name)];
|
|
961
|
+
const completedValues = getSurveyRunnerValues(document, answers, now);
|
|
962
|
+
const resultAnswers = { ...answers };
|
|
963
|
+
for (const name of includedNames) {
|
|
964
|
+
const answer = toSurveyAnswerValue(completedValues[name]);
|
|
965
|
+
if (answer !== void 0) resultAnswers[name] = answer;
|
|
966
|
+
}
|
|
967
|
+
return {
|
|
968
|
+
answers: resultAnswers,
|
|
969
|
+
errors: [],
|
|
970
|
+
state: {
|
|
971
|
+
...state,
|
|
972
|
+
answers,
|
|
973
|
+
isCompleted: true
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
};
|
|
977
|
+
// src/services/runner/createSurveyRunnerState.ts
|
|
978
|
+
const createSurveyRunnerState = (document, answers, pageIndex) => {
|
|
979
|
+
const lastPageIndex = Math.max(document.content.length - 1, 0);
|
|
980
|
+
return {
|
|
981
|
+
answers,
|
|
982
|
+
isCompleted: false,
|
|
983
|
+
pageIndex: Math.min(Math.max(pageIndex, 0), lastPageIndex)
|
|
984
|
+
};
|
|
985
|
+
};
|
|
986
|
+
// src/services/runner/getSurveyPageElements.ts
|
|
987
|
+
const getSurveyPageElements = (document, state, now) => getSurveyPageViews(document, state.pageIndex, getSurveyRunnerValues(document, state.answers, now), now);
|
|
988
|
+
// src/services/runner/getSurveyProgress.ts
|
|
989
|
+
const getSurveyProgress = (document, state, now) => {
|
|
990
|
+
const pageIndexes = getSurveyVisiblePageIndexes(document, state.answers, now);
|
|
991
|
+
return {
|
|
992
|
+
current: pageIndexes.filter((pageIndex) => pageIndex <= state.pageIndex).length,
|
|
993
|
+
total: pageIndexes.length
|
|
994
|
+
};
|
|
995
|
+
};
|
|
996
|
+
// src/services/runner/validateSurveyPage.ts
|
|
997
|
+
const validateSurveyPage = (document, state, now) => getSurveyPageErrors(document, state.pageIndex, state.answers, getSurveyRunnerValues(document, state.answers, now), now);
|
|
998
|
+
// src/services/runner/goToNextSurveyPage.ts
|
|
999
|
+
const goToNextSurveyPage = (document, state, now) => {
|
|
1000
|
+
const errors = validateSurveyPage(document, state, now);
|
|
1001
|
+
if (errors.length > 0) return {
|
|
1002
|
+
errors,
|
|
1003
|
+
state
|
|
1004
|
+
};
|
|
1005
|
+
const nextPageIndex = getSurveyVisiblePageIndexes(document, state.answers, now).find((pageIndex) => pageIndex > state.pageIndex);
|
|
1006
|
+
return {
|
|
1007
|
+
errors,
|
|
1008
|
+
state: nextPageIndex === void 0 ? state : {
|
|
1009
|
+
...state,
|
|
1010
|
+
pageIndex: nextPageIndex
|
|
1011
|
+
}
|
|
1012
|
+
};
|
|
1013
|
+
};
|
|
1014
|
+
// src/services/runner/goToPreviousSurveyPage.ts
|
|
1015
|
+
const goToPreviousSurveyPage = (document, state, now) => {
|
|
1016
|
+
const previousPageIndex = getSurveyVisiblePageIndexes(document, state.answers, now).findLast((pageIndex) => pageIndex < state.pageIndex);
|
|
1017
|
+
return previousPageIndex === void 0 ? state : {
|
|
1018
|
+
...state,
|
|
1019
|
+
pageIndex: previousPageIndex
|
|
1020
|
+
};
|
|
1021
|
+
};
|
|
1022
|
+
// src/services/runner/setSurveyAnswer.ts
|
|
1023
|
+
const setSurveyAnswer = (state, name, value) => {
|
|
1024
|
+
const answers = Object.fromEntries(Object.entries(state.answers).filter(([answerName]) => answerName !== name));
|
|
1025
|
+
if (value === void 0 || checkSurveyAnswerEmpty(value)) return {
|
|
1026
|
+
...state,
|
|
1027
|
+
answers
|
|
1028
|
+
};
|
|
1029
|
+
return {
|
|
1030
|
+
...state,
|
|
1031
|
+
answers: {
|
|
1032
|
+
...answers,
|
|
1033
|
+
[name]: value
|
|
1034
|
+
}
|
|
1035
|
+
};
|
|
1036
|
+
};
|
|
1037
|
+
// src/services/runner/validateSurveyAnswers.ts
|
|
1038
|
+
const validateSurveyAnswers = (document, answers, mode, now) => {
|
|
1039
|
+
const isSubmit = mode === "submit";
|
|
1040
|
+
const values = getSurveyRunnerValues(document, answers, now);
|
|
1041
|
+
const views = flattenSurveyElementViews(document.content.flatMap((_node, pageIndex) => getSurveyPageViews(document, pageIndex, values, now)));
|
|
1042
|
+
const questionNames = new Set(flattenSurveyQuestions(document.content).filter((node) => checkIsSurveyAnsweringNode(node)).map((node) => node.props.name));
|
|
1043
|
+
const shownNames = new Set(views.flatMap(({ node }) => node.type === "panel" ? [] : [node.props.name]));
|
|
1044
|
+
const calculatedNames = new Set(isSubmit ? document.root.props.calculatedValues.map(({ name }) => name) : []);
|
|
1045
|
+
const issues = [];
|
|
1046
|
+
for (const name of Object.keys(answers)) {
|
|
1047
|
+
if (calculatedNames.has(name)) continue;
|
|
1048
|
+
if (!questionNames.has(name)) issues.push({
|
|
1049
|
+
message: SURVEY_UNKNOWN_QUESTION_MESSAGE,
|
|
1050
|
+
name
|
|
1051
|
+
});
|
|
1052
|
+
else if (isSubmit && !shownNames.has(name)) issues.push({
|
|
1053
|
+
message: SURVEY_NOT_SHOWN_MESSAGE,
|
|
1054
|
+
name
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
for (const { node } of views) {
|
|
1058
|
+
if (!isSubmit || node.type !== "paneldynamic") continue;
|
|
1059
|
+
const rows = answers[node.props.name];
|
|
1060
|
+
if (!Array.isArray(rows)) continue;
|
|
1061
|
+
for (const row of rows) {
|
|
1062
|
+
if (typeof row !== "object" || Array.isArray(row)) continue;
|
|
1063
|
+
const shownRow = getSurveyPanelRowAnswers(node, row, values, now);
|
|
1064
|
+
if (Object.keys(shownRow).length < Object.keys(row).length) issues.push({
|
|
1065
|
+
message: SURVEY_NOT_SHOWN_MESSAGE,
|
|
1066
|
+
name: node.props.name
|
|
1067
|
+
});
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
for (const view of views) {
|
|
1071
|
+
if (view.node.type === "panel") continue;
|
|
1072
|
+
if (!isSubmit && checkSurveyAnswerEmpty(answers[view.node.props.name])) continue;
|
|
1073
|
+
issues.push(...getSurveyQuestionErrors(view, answers, values, now).map(({ message, name }) => ({
|
|
1074
|
+
message,
|
|
1075
|
+
name
|
|
1076
|
+
})));
|
|
1077
|
+
}
|
|
1078
|
+
return issues;
|
|
1079
|
+
};
|
|
1080
|
+
// src/services/surveyBooleanNodeType.ts
|
|
1081
|
+
const surveyBooleanNodeType = {
|
|
1082
|
+
createDefaultProps: () => surveyBooleanNodePropsSchema.parse({ name: "question" }),
|
|
1083
|
+
formSchema: surveyBooleanNodePropsSchema,
|
|
1084
|
+
label: "Yes or no",
|
|
1085
|
+
propsSchema: surveyBooleanNodePropsSchema,
|
|
1086
|
+
slots: {},
|
|
1087
|
+
type: "boolean"
|
|
1088
|
+
};
|
|
1089
|
+
// src/services/surveyButtonGroupNodeType.ts
|
|
1090
|
+
const surveyButtonGroupNodeType = {
|
|
1091
|
+
createDefaultProps: () => surveyButtonGroupNodePropsSchema.parse({ name: "question" }),
|
|
1092
|
+
formSchema: surveyButtonGroupNodePropsSchema,
|
|
1093
|
+
label: "Button group",
|
|
1094
|
+
propsSchema: surveyButtonGroupNodePropsSchema,
|
|
1095
|
+
slots: {},
|
|
1096
|
+
type: "buttongroup"
|
|
1097
|
+
};
|
|
1098
|
+
// src/services/surveyCheckboxNodeType.ts
|
|
1099
|
+
const surveyCheckboxNodeType = {
|
|
1100
|
+
createDefaultProps: () => surveyCheckboxNodePropsSchema.parse({ name: "question" }),
|
|
1101
|
+
formSchema: surveyCheckboxNodePropsSchema,
|
|
1102
|
+
label: "Checkboxes",
|
|
1103
|
+
propsSchema: surveyCheckboxNodePropsSchema,
|
|
1104
|
+
slots: {},
|
|
1105
|
+
type: "checkbox"
|
|
1106
|
+
};
|
|
1107
|
+
// src/services/surveyCommentNodeType.ts
|
|
1108
|
+
const surveyCommentNodeType = {
|
|
1109
|
+
createDefaultProps: () => surveyCommentNodePropsSchema.parse({ name: "question" }),
|
|
1110
|
+
formSchema: surveyCommentNodePropsSchema,
|
|
1111
|
+
label: "Comment",
|
|
1112
|
+
propsSchema: surveyCommentNodePropsSchema,
|
|
1113
|
+
slots: {},
|
|
1114
|
+
type: "comment"
|
|
1115
|
+
};
|
|
1116
|
+
// src/services/surveyNodeChildren.ts
|
|
1117
|
+
const surveyNodeChildren = (node) => {
|
|
1118
|
+
switch (node.type) {
|
|
1119
|
+
case "boolean":
|
|
1120
|
+
case "buttongroup":
|
|
1121
|
+
case "checkbox":
|
|
1122
|
+
case "comment":
|
|
1123
|
+
case "dropdown":
|
|
1124
|
+
case "expression":
|
|
1125
|
+
case "html":
|
|
1126
|
+
case "image":
|
|
1127
|
+
case "imagepicker":
|
|
1128
|
+
case "matrix":
|
|
1129
|
+
case "matrixdynamic":
|
|
1130
|
+
case "multipletext":
|
|
1131
|
+
case "radiogroup":
|
|
1132
|
+
case "ranking":
|
|
1133
|
+
case "rating":
|
|
1134
|
+
case "slider":
|
|
1135
|
+
case "tagbox":
|
|
1136
|
+
case "text": return NO_BLOCK_SLOTS;
|
|
1137
|
+
case "page":
|
|
1138
|
+
case "panel": return { children: node.props.children };
|
|
1139
|
+
case "paneldynamic": return { template: node.props.template };
|
|
1140
|
+
default: return exhaustiveGuard(node);
|
|
1141
|
+
}
|
|
1142
|
+
};
|
|
1143
|
+
// src/services/surveyDropdownNodeType.ts
|
|
1144
|
+
const surveyDropdownNodeType = {
|
|
1145
|
+
createDefaultProps: () => surveyDropdownNodePropsSchema.parse({ name: "question" }),
|
|
1146
|
+
formSchema: surveyDropdownNodePropsSchema,
|
|
1147
|
+
label: "Dropdown",
|
|
1148
|
+
propsSchema: surveyDropdownNodePropsSchema,
|
|
1149
|
+
slots: {},
|
|
1150
|
+
type: "dropdown"
|
|
1151
|
+
};
|
|
1152
|
+
// src/services/surveyExpressionNodeType.ts
|
|
1153
|
+
const surveyExpressionNodeType = {
|
|
1154
|
+
createDefaultProps: () => surveyExpressionNodePropsSchema.parse({ name: "question" }),
|
|
1155
|
+
formSchema: surveyExpressionNodePropsSchema,
|
|
1156
|
+
label: "Calculated value",
|
|
1157
|
+
propsSchema: surveyExpressionNodePropsSchema,
|
|
1158
|
+
slots: {},
|
|
1159
|
+
type: "expression"
|
|
1160
|
+
};
|
|
1161
|
+
// src/services/surveyHtmlNodeType.ts
|
|
1162
|
+
const surveyHtmlNodeType = {
|
|
1163
|
+
createDefaultProps: () => surveyHtmlNodePropsSchema.parse({ name: "block" }),
|
|
1164
|
+
formSchema: surveyHtmlNodePropsSchema,
|
|
1165
|
+
label: "Text block",
|
|
1166
|
+
propsSchema: surveyHtmlNodePropsSchema,
|
|
1167
|
+
slots: {},
|
|
1168
|
+
type: "html"
|
|
1169
|
+
};
|
|
1170
|
+
const surveyIdSchema = z.string().max(64).regex(/^[\w-]+$/u);
|
|
1171
|
+
// src/services/surveyImageNodeType.ts
|
|
1172
|
+
const surveyImageNodeType = {
|
|
1173
|
+
createDefaultProps: () => surveyImageNodePropsSchema.parse({ name: "image" }),
|
|
1174
|
+
formSchema: surveyImageNodePropsSchema,
|
|
1175
|
+
label: "Image",
|
|
1176
|
+
propsSchema: surveyImageNodePropsSchema,
|
|
1177
|
+
slots: {},
|
|
1178
|
+
type: "image"
|
|
1179
|
+
};
|
|
1180
|
+
// src/services/surveyImagePickerNodeType.ts
|
|
1181
|
+
const surveyImagePickerNodeType = {
|
|
1182
|
+
createDefaultProps: () => surveyImagePickerNodePropsSchema.parse({ name: "question" }),
|
|
1183
|
+
formSchema: surveyImagePickerNodePropsSchema,
|
|
1184
|
+
label: "Image picker",
|
|
1185
|
+
propsSchema: surveyImagePickerNodePropsSchema,
|
|
1186
|
+
slots: {},
|
|
1187
|
+
type: "imagepicker"
|
|
1188
|
+
};
|
|
1189
|
+
// src/services/surveyMatrixDynamicNodeType.ts
|
|
1190
|
+
const surveyMatrixDynamicNodeType = {
|
|
1191
|
+
createDefaultProps: () => surveyMatrixDynamicNodePropsSchema.parse({ name: "question" }),
|
|
1192
|
+
formSchema: surveyMatrixDynamicNodePropsSchema,
|
|
1193
|
+
label: "Dynamic matrix",
|
|
1194
|
+
propsSchema: surveyMatrixDynamicNodePropsSchema,
|
|
1195
|
+
slots: {},
|
|
1196
|
+
type: "matrixdynamic"
|
|
1197
|
+
};
|
|
1198
|
+
// src/services/surveyMatrixNodeType.ts
|
|
1199
|
+
const surveyMatrixNodeType = {
|
|
1200
|
+
createDefaultProps: () => surveyMatrixNodePropsSchema.parse({ name: "question" }),
|
|
1201
|
+
formSchema: surveyMatrixNodePropsSchema,
|
|
1202
|
+
label: "Matrix",
|
|
1203
|
+
propsSchema: surveyMatrixNodePropsSchema,
|
|
1204
|
+
slots: {},
|
|
1205
|
+
type: "matrix"
|
|
1206
|
+
};
|
|
1207
|
+
// src/services/surveyMultipleTextNodeType.ts
|
|
1208
|
+
const surveyMultipleTextNodeType = {
|
|
1209
|
+
createDefaultProps: () => surveyMultipleTextNodePropsSchema.parse({ name: "question" }),
|
|
1210
|
+
formSchema: surveyMultipleTextNodePropsSchema,
|
|
1211
|
+
label: "Multiple text",
|
|
1212
|
+
propsSchema: surveyMultipleTextNodePropsSchema,
|
|
1213
|
+
slots: {},
|
|
1214
|
+
type: "multipletext"
|
|
1215
|
+
};
|
|
1216
|
+
// src/services/surveyPanelDynamicNodeType.ts
|
|
1217
|
+
const surveyPanelDynamicNodeType = {
|
|
1218
|
+
createDefaultProps: () => surveyPanelDynamicNodePropsSchema.parse({ name: "question" }),
|
|
1219
|
+
formSchema: surveyPanelDynamicNodePropsSchema,
|
|
1220
|
+
label: "Dynamic panel",
|
|
1221
|
+
propsSchema: surveyPanelDynamicNodePropsSchema,
|
|
1222
|
+
slots: { template: SURVEY_TEMPLATE_NODE_TYPES },
|
|
1223
|
+
type: "paneldynamic"
|
|
1224
|
+
};
|
|
1225
|
+
// src/services/surveyPanelNodeType.ts
|
|
1226
|
+
const surveyPanelNodeType = {
|
|
1227
|
+
createDefaultProps: () => surveyPanelNodePropsSchema.parse({}),
|
|
1228
|
+
formSchema: surveyPanelNodePropsSchema,
|
|
1229
|
+
label: "Panel",
|
|
1230
|
+
propsSchema: surveyPanelNodePropsSchema,
|
|
1231
|
+
slots: { children: SURVEY_PLACEABLE_NODE_TYPES },
|
|
1232
|
+
type: "panel"
|
|
1233
|
+
};
|
|
1234
|
+
// src/services/surveyRadioGroupNodeType.ts
|
|
1235
|
+
const surveyRadioGroupNodeType = {
|
|
1236
|
+
createDefaultProps: () => surveyRadioGroupNodePropsSchema.parse({ name: "question" }),
|
|
1237
|
+
formSchema: surveyRadioGroupNodePropsSchema,
|
|
1238
|
+
label: "Radio group",
|
|
1239
|
+
propsSchema: surveyRadioGroupNodePropsSchema,
|
|
1240
|
+
slots: {},
|
|
1241
|
+
type: "radiogroup"
|
|
1242
|
+
};
|
|
1243
|
+
// src/services/surveyRankingNodeType.ts
|
|
1244
|
+
const surveyRankingNodeType = {
|
|
1245
|
+
createDefaultProps: () => surveyRankingNodePropsSchema.parse({ name: "question" }),
|
|
1246
|
+
formSchema: surveyRankingNodePropsSchema,
|
|
1247
|
+
label: "Ranking",
|
|
1248
|
+
propsSchema: surveyRankingNodePropsSchema,
|
|
1249
|
+
slots: {},
|
|
1250
|
+
type: "ranking"
|
|
1251
|
+
};
|
|
1252
|
+
// src/services/surveyRatingNodeType.ts
|
|
1253
|
+
const surveyRatingNodeType = {
|
|
1254
|
+
createDefaultProps: () => surveyRatingNodePropsSchema.parse({ name: "question" }),
|
|
1255
|
+
formSchema: surveyRatingNodePropsSchema,
|
|
1256
|
+
label: "Rating",
|
|
1257
|
+
propsSchema: surveyRatingNodePropsSchema,
|
|
1258
|
+
slots: {},
|
|
1259
|
+
type: "rating"
|
|
1260
|
+
};
|
|
1261
|
+
// src/services/surveySliderNodeType.ts
|
|
1262
|
+
const surveySliderNodeType = {
|
|
1263
|
+
createDefaultProps: () => surveySliderNodePropsSchema.parse({ name: "question" }),
|
|
1264
|
+
formSchema: surveySliderNodePropsSchema,
|
|
1265
|
+
label: "Slider",
|
|
1266
|
+
propsSchema: surveySliderNodePropsSchema,
|
|
1267
|
+
slots: {},
|
|
1268
|
+
type: "slider"
|
|
1269
|
+
};
|
|
1270
|
+
// src/services/surveyTagBoxNodeType.ts
|
|
1271
|
+
const surveyTagBoxNodeType = {
|
|
1272
|
+
createDefaultProps: () => surveyTagBoxNodePropsSchema.parse({ name: "question" }),
|
|
1273
|
+
formSchema: surveyTagBoxNodePropsSchema,
|
|
1274
|
+
label: "Tag box",
|
|
1275
|
+
propsSchema: surveyTagBoxNodePropsSchema,
|
|
1276
|
+
slots: {},
|
|
1277
|
+
type: "tagbox"
|
|
1278
|
+
};
|
|
1279
|
+
// src/services/surveyTextNodeType.ts
|
|
1280
|
+
const surveyTextNodeType = {
|
|
1281
|
+
createDefaultProps: () => surveyTextNodePropsSchema.parse({ name: "question" }),
|
|
1282
|
+
formSchema: surveyTextNodePropsSchema,
|
|
1283
|
+
label: "Text",
|
|
1284
|
+
propsSchema: surveyTextNodePropsSchema,
|
|
1285
|
+
slots: {},
|
|
1286
|
+
type: "text"
|
|
1287
|
+
};
|
|
1288
|
+
// src/services/surveyNodeSchema.ts
|
|
1289
|
+
const placeableNodeSchema = z.lazy(() => surveyPlaceableNodeSchema);
|
|
1290
|
+
const templateNodeSchema = z.lazy(() => surveyTemplateNodeSchema);
|
|
1291
|
+
const surveyBooleanNodeSchemaValue = z.object({
|
|
1292
|
+
props: z.strictObject({
|
|
1293
|
+
...surveyBooleanNodeType.propsSchema.shape,
|
|
1294
|
+
id: surveyIdSchema
|
|
1295
|
+
}),
|
|
1296
|
+
type: z.literal("boolean")
|
|
1297
|
+
});
|
|
1298
|
+
const surveyButtonGroupNodeSchemaValue = z.object({
|
|
1299
|
+
props: z.strictObject({
|
|
1300
|
+
...surveyButtonGroupNodeType.propsSchema.shape,
|
|
1301
|
+
id: surveyIdSchema
|
|
1302
|
+
}),
|
|
1303
|
+
type: z.literal("buttongroup")
|
|
1304
|
+
});
|
|
1305
|
+
const surveyCheckboxNodeSchemaValue = z.object({
|
|
1306
|
+
props: z.strictObject({
|
|
1307
|
+
...surveyCheckboxNodeType.propsSchema.shape,
|
|
1308
|
+
id: surveyIdSchema
|
|
1309
|
+
}),
|
|
1310
|
+
type: z.literal("checkbox")
|
|
1311
|
+
});
|
|
1312
|
+
const surveyCommentNodeSchemaValue = z.object({
|
|
1313
|
+
props: z.strictObject({
|
|
1314
|
+
...surveyCommentNodeType.propsSchema.shape,
|
|
1315
|
+
id: surveyIdSchema
|
|
1316
|
+
}),
|
|
1317
|
+
type: z.literal("comment")
|
|
1318
|
+
});
|
|
1319
|
+
const surveyDropdownNodeSchemaValue = z.object({
|
|
1320
|
+
props: z.strictObject({
|
|
1321
|
+
...surveyDropdownNodeType.propsSchema.shape,
|
|
1322
|
+
id: surveyIdSchema
|
|
1323
|
+
}),
|
|
1324
|
+
type: z.literal("dropdown")
|
|
1325
|
+
});
|
|
1326
|
+
const surveyExpressionNodeSchemaValue = z.object({
|
|
1327
|
+
props: z.strictObject({
|
|
1328
|
+
...surveyExpressionNodeType.propsSchema.shape,
|
|
1329
|
+
id: surveyIdSchema
|
|
1330
|
+
}),
|
|
1331
|
+
type: z.literal("expression")
|
|
1332
|
+
});
|
|
1333
|
+
const surveyHtmlNodeSchemaValue = z.object({
|
|
1334
|
+
props: z.strictObject({
|
|
1335
|
+
...surveyHtmlNodeType.propsSchema.shape,
|
|
1336
|
+
id: surveyIdSchema
|
|
1337
|
+
}),
|
|
1338
|
+
type: z.literal("html")
|
|
1339
|
+
});
|
|
1340
|
+
const surveyImageNodeSchemaValue = z.object({
|
|
1341
|
+
props: z.strictObject({
|
|
1342
|
+
...surveyImageNodeType.propsSchema.shape,
|
|
1343
|
+
id: surveyIdSchema
|
|
1344
|
+
}),
|
|
1345
|
+
type: z.literal("image")
|
|
1346
|
+
});
|
|
1347
|
+
const surveyImagePickerNodeSchemaValue = z.object({
|
|
1348
|
+
props: z.strictObject({
|
|
1349
|
+
...surveyImagePickerNodeType.propsSchema.shape,
|
|
1350
|
+
id: surveyIdSchema
|
|
1351
|
+
}),
|
|
1352
|
+
type: z.literal("imagepicker")
|
|
1353
|
+
});
|
|
1354
|
+
const surveyMatrixNodeSchemaValue = z.object({
|
|
1355
|
+
props: z.strictObject({
|
|
1356
|
+
...surveyMatrixNodeType.propsSchema.shape,
|
|
1357
|
+
id: surveyIdSchema
|
|
1358
|
+
}),
|
|
1359
|
+
type: z.literal("matrix")
|
|
1360
|
+
});
|
|
1361
|
+
const surveyMatrixDynamicNodeSchemaValue = z.object({
|
|
1362
|
+
props: z.strictObject({
|
|
1363
|
+
...surveyMatrixDynamicNodeType.propsSchema.shape,
|
|
1364
|
+
id: surveyIdSchema
|
|
1365
|
+
}),
|
|
1366
|
+
type: z.literal("matrixdynamic")
|
|
1367
|
+
});
|
|
1368
|
+
const surveyMultipleTextNodeSchemaValue = z.object({
|
|
1369
|
+
props: z.strictObject({
|
|
1370
|
+
...surveyMultipleTextNodeType.propsSchema.shape,
|
|
1371
|
+
id: surveyIdSchema
|
|
1372
|
+
}),
|
|
1373
|
+
type: z.literal("multipletext")
|
|
1374
|
+
});
|
|
1375
|
+
const surveyPageNodeSchemaValue = z.object({
|
|
1376
|
+
props: z.strictObject({
|
|
1377
|
+
...surveyPageNodeType.propsSchema.shape,
|
|
1378
|
+
children: boundedChildren(placeableNodeSchema),
|
|
1379
|
+
id: surveyIdSchema
|
|
1380
|
+
}),
|
|
1381
|
+
type: z.literal("page")
|
|
1382
|
+
});
|
|
1383
|
+
const surveyPanelNodeSchemaValue = z.object({
|
|
1384
|
+
props: z.strictObject({
|
|
1385
|
+
...surveyPanelNodeType.propsSchema.shape,
|
|
1386
|
+
children: boundedChildren(placeableNodeSchema),
|
|
1387
|
+
id: surveyIdSchema
|
|
1388
|
+
}),
|
|
1389
|
+
type: z.literal("panel")
|
|
1390
|
+
});
|
|
1391
|
+
const surveyPanelDynamicNodeSchemaValue = z.object({
|
|
1392
|
+
props: z.strictObject({
|
|
1393
|
+
...surveyPanelDynamicNodeType.propsSchema.shape,
|
|
1394
|
+
id: surveyIdSchema,
|
|
1395
|
+
template: boundedChildren(templateNodeSchema)
|
|
1396
|
+
}),
|
|
1397
|
+
type: z.literal("paneldynamic")
|
|
1398
|
+
});
|
|
1399
|
+
const surveyRadioGroupNodeSchemaValue = z.object({
|
|
1400
|
+
props: z.strictObject({
|
|
1401
|
+
...surveyRadioGroupNodeType.propsSchema.shape,
|
|
1402
|
+
id: surveyIdSchema
|
|
1403
|
+
}),
|
|
1404
|
+
type: z.literal("radiogroup")
|
|
1405
|
+
});
|
|
1406
|
+
const surveyRankingNodeSchemaValue = z.object({
|
|
1407
|
+
props: z.strictObject({
|
|
1408
|
+
...surveyRankingNodeType.propsSchema.shape,
|
|
1409
|
+
id: surveyIdSchema
|
|
1410
|
+
}),
|
|
1411
|
+
type: z.literal("ranking")
|
|
1412
|
+
});
|
|
1413
|
+
const surveyRatingNodeSchemaValue = z.object({
|
|
1414
|
+
props: z.strictObject({
|
|
1415
|
+
...surveyRatingNodeType.propsSchema.shape,
|
|
1416
|
+
id: surveyIdSchema
|
|
1417
|
+
}),
|
|
1418
|
+
type: z.literal("rating")
|
|
1419
|
+
});
|
|
1420
|
+
const surveySliderNodeSchemaValue = z.object({
|
|
1421
|
+
props: z.strictObject({
|
|
1422
|
+
...surveySliderNodeType.propsSchema.shape,
|
|
1423
|
+
id: surveyIdSchema
|
|
1424
|
+
}),
|
|
1425
|
+
type: z.literal("slider")
|
|
1426
|
+
});
|
|
1427
|
+
const surveyTagBoxNodeSchemaValue = z.object({
|
|
1428
|
+
props: z.strictObject({
|
|
1429
|
+
...surveyTagBoxNodeType.propsSchema.shape,
|
|
1430
|
+
id: surveyIdSchema
|
|
1431
|
+
}),
|
|
1432
|
+
type: z.literal("tagbox")
|
|
1433
|
+
});
|
|
1434
|
+
const surveyTemplateNodeOptions = [
|
|
1435
|
+
z.object({
|
|
1436
|
+
props: z.strictObject({
|
|
1437
|
+
...surveyTextNodeType.propsSchema.shape,
|
|
1438
|
+
id: surveyIdSchema
|
|
1439
|
+
}),
|
|
1440
|
+
type: z.literal("text")
|
|
1441
|
+
}),
|
|
1442
|
+
surveyCommentNodeSchemaValue,
|
|
1443
|
+
surveyBooleanNodeSchemaValue,
|
|
1444
|
+
surveyRadioGroupNodeSchemaValue,
|
|
1445
|
+
surveyDropdownNodeSchemaValue,
|
|
1446
|
+
surveyCheckboxNodeSchemaValue,
|
|
1447
|
+
surveyTagBoxNodeSchemaValue,
|
|
1448
|
+
surveyRatingNodeSchemaValue,
|
|
1449
|
+
surveyRankingNodeSchemaValue,
|
|
1450
|
+
surveyMatrixNodeSchemaValue,
|
|
1451
|
+
surveyMatrixDynamicNodeSchemaValue,
|
|
1452
|
+
surveyMultipleTextNodeSchemaValue,
|
|
1453
|
+
surveySliderNodeSchemaValue,
|
|
1454
|
+
surveyButtonGroupNodeSchemaValue,
|
|
1455
|
+
surveyImagePickerNodeSchemaValue,
|
|
1456
|
+
surveyExpressionNodeSchemaValue,
|
|
1457
|
+
surveyHtmlNodeSchemaValue,
|
|
1458
|
+
surveyImageNodeSchemaValue
|
|
1459
|
+
];
|
|
1460
|
+
const surveyTemplateNodeSchema = z.discriminatedUnion("type", surveyTemplateNodeOptions, createAcceptedTypesError(SURVEY_TEMPLATE_NODE_TYPES));
|
|
1461
|
+
const surveyPlaceableNodeOptions = [
|
|
1462
|
+
...surveyTemplateNodeOptions,
|
|
1463
|
+
surveyPanelDynamicNodeSchemaValue,
|
|
1464
|
+
surveyPanelNodeSchemaValue
|
|
1465
|
+
];
|
|
1466
|
+
const surveyPlaceableNodeSchema = z.discriminatedUnion("type", surveyPlaceableNodeOptions, createAcceptedTypesError(SURVEY_PLACEABLE_NODE_TYPES));
|
|
1467
|
+
const surveyPageNodeSchema = surveyPageNodeSchemaValue;
|
|
1468
|
+
const surveyNodeSchema = z.discriminatedUnion("type", [...surveyPlaceableNodeOptions, surveyPageNodeSchemaValue], createAcceptedTypesError([...SURVEY_ROOT_NODE_TYPES, ...SURVEY_PLACEABLE_NODE_TYPES]));
|
|
1469
|
+
// src/services/surveyNodeTypeDefinitionMap.ts
|
|
1470
|
+
const surveyNodeTypeDefinitionMap = {
|
|
1471
|
+
["boolean"]: surveyBooleanNodeType,
|
|
1472
|
+
["buttongroup"]: surveyButtonGroupNodeType,
|
|
1473
|
+
["checkbox"]: surveyCheckboxNodeType,
|
|
1474
|
+
["comment"]: surveyCommentNodeType,
|
|
1475
|
+
["dropdown"]: surveyDropdownNodeType,
|
|
1476
|
+
["expression"]: surveyExpressionNodeType,
|
|
1477
|
+
["html"]: surveyHtmlNodeType,
|
|
1478
|
+
["image"]: surveyImageNodeType,
|
|
1479
|
+
["imagepicker"]: surveyImagePickerNodeType,
|
|
1480
|
+
["matrix"]: surveyMatrixNodeType,
|
|
1481
|
+
["matrixdynamic"]: surveyMatrixDynamicNodeType,
|
|
1482
|
+
["multipletext"]: surveyMultipleTextNodeType,
|
|
1483
|
+
["page"]: surveyPageNodeType,
|
|
1484
|
+
["panel"]: surveyPanelNodeType,
|
|
1485
|
+
["paneldynamic"]: surveyPanelDynamicNodeType,
|
|
1486
|
+
["radiogroup"]: surveyRadioGroupNodeType,
|
|
1487
|
+
["ranking"]: surveyRankingNodeType,
|
|
1488
|
+
["rating"]: surveyRatingNodeType,
|
|
1489
|
+
["slider"]: surveySliderNodeType,
|
|
1490
|
+
["tagbox"]: surveyTagBoxNodeType,
|
|
1491
|
+
["text"]: surveyTextNodeType
|
|
1492
|
+
};
|
|
1493
|
+
// src/services/surveyRegistry.ts
|
|
1494
|
+
const surveyRegistry = {
|
|
1495
|
+
root: {
|
|
1496
|
+
content: SURVEY_ROOT_NODE_TYPES,
|
|
1497
|
+
propsSchema: surveyRootPropsSchema
|
|
1498
|
+
},
|
|
1499
|
+
types: Object.values(surveyNodeTypeDefinitionMap)
|
|
1500
|
+
};
|
|
1501
|
+
// src/services/surveyDocumentSchema.ts
|
|
1502
|
+
const surveyDocumentSchema = createBlockDocumentSchema(surveyPageNodeSchema, surveyRegistry, surveyNodeChildren, MAX_SURVEY_NODE_COUNT);
|
|
1503
|
+
export { MATRIX_CELL_RATING_COUNT, MAX_SURVEY_ANSWER_ENTRY_COUNT, MAX_SURVEY_ANSWER_LENGTH, MAX_SURVEY_CALCULATED_VALUE_COUNT, MAX_SURVEY_CHOICE_COUNT, MAX_SURVEY_HTML_LENGTH, MAX_SURVEY_ID_LENGTH, MAX_SURVEY_IMAGE_SIZE, MAX_SURVEY_MATRIX_COLUMN_COUNT, MAX_SURVEY_MATRIX_ROW_COUNT, MAX_SURVEY_MULTIPLE_TEXT_ITEM_COUNT, MAX_SURVEY_NODE_COUNT, MAX_SURVEY_PATTERN_LENGTH, MAX_SURVEY_QUESTION_COUNT, MAX_SURVEY_QUESTION_NAME_LENGTH, MAX_SURVEY_TEXT_LENGTH, MAX_SURVEY_URL_LENGTH, MAX_SURVEY_VALIDATOR_COUNT, SURVEY_INVALID_ANSWER_MESSAGE, SURVEY_NONE_ANSWER, SURVEY_NOT_A_CHOICE_MESSAGE, SURVEY_NOT_SHOWN_MESSAGE, SURVEY_OUT_OF_RANGE_MESSAGE, SURVEY_PLACEABLE_NODE_TYPES, SURVEY_REQUIRED_MESSAGE, SURVEY_ROOT_NODE_TYPES, SURVEY_TEMPLATE_NODE_TYPES, SURVEY_TOO_FEW_SELECTED_MESSAGE, SURVEY_TOO_LONG_MESSAGE, SURVEY_TOO_MANY_SELECTED_MESSAGE, SURVEY_TOO_SHORT_MESSAGE, SURVEY_UNKNOWN_QUESTION_MESSAGE, SURVEY_WRONG_COUNT_MESSAGE, SurveyAnswerValidationMode, SurveyBooleanDisplayStyle, SurveyChoicesOrder, SurveyExpressionDisplayFormat, SurveyImageFit, SurveyMatrixCellType, SurveyMultipleTextItemInputType, SurveyNodeType, SurveyProgressBarPlacement, SurveyRatingType, SurveyTextInputType, boundedChildren, checkIsLastSurveyPage, checkIsSurveyAnsweringNode, checkSurveyAnswerEmpty, checkSurveyCalculatedValues, checkSurveyDocument, checkSurveyExpressionField, checkSurveyExpressionHolds, checkSurveyNodeEnabled, checkSurveyNodeRequired, checkSurveyNodeVisible, checkSurveyNodes, checkSurveyNoneChoice, checkSurveyOptionalExpression, checkSurveyQuestion, completeSurvey, createSeededRandom, createSurveyAnswerSchema, createSurveyBooleanAnswerSchema, createSurveyButtonGroupAnswerSchema, createSurveyCheckboxAnswerSchema, createSurveyChoiceValueSchema, createSurveyCommentAnswerSchema, createSurveyDocument, createSurveyDropdownAnswerSchema, createSurveyExpressionAnswerSchema, createSurveyImagePickerAnswerSchema, createSurveyMatrixAnswerSchema, createSurveyMatrixCellAnswerSchema, createSurveyMatrixDynamicAnswerSchema, createSurveyMultipleTextAnswerSchema, createSurveyNamedAnswerSchema, createSurveyNestedAnswerSchema, createSurveyNumberAnswerSchema, createSurveyPanelDynamicAnswerSchema, createSurveyPatternAnswerSchema, createSurveyRadioGroupAnswerSchema, createSurveyRankingAnswerSchema, createSurveyRatingAnswerSchema, createSurveyRatingValueSchema, createSurveyRunnerState, createSurveySelectionAnswerSchema, createSurveySliderAnswerSchema, createSurveyStringAnswerSchema, createSurveyStringRangeAnswerSchema, createSurveyTagBoxAnswerSchema, createSurveyTextAnswerSchema, flattenSurveyElementViews, flattenSurveyQuestions, getSurveyChoiceText, getSurveyElementViews, getSurveyExpressionNodes, getSurveyOrderedChoices, getSurveyPageElements, getSurveyPageErrors, getSurveyPageViews, getSurveyPanelRowAnswers, getSurveyPanelRowViews, getSurveyProgress, getSurveyQuestionErrors, getSurveyRunnerValues, getSurveyVisiblePageIndexes, getSurveyVisiblePageIndexesFromValues, goToNextSurveyPage, goToPreviousSurveyPage, hashSurveySeed, parseSurveyNumberBound, setSurveyAnswer, surveyAnswerScalarSchema, surveyAnswerValueSchema, surveyBooleanNodePropsSchema, surveyBooleanNodeType, surveyButtonGroupNodePropsSchema, surveyButtonGroupNodeType, surveyCalculatedValueSchema, surveyCheckboxNodePropsSchema, surveyCheckboxNodeType, surveyChoiceOptionsPropsShape, surveyChoiceSchema, surveyChoicesPropsShape, surveyCommentNodePropsSchema, surveyCommentNodeType, surveyConditionSchema, surveyContainerBasePropsShape, surveyDocumentSchema, surveyDropdownNodePropsSchema, surveyDropdownNodeType, surveyExpressionNodePropsSchema, surveyExpressionNodeType, surveyExpressionSchema, surveyHtmlNodePropsSchema, surveyHtmlNodeType, surveyIdSchema, surveyImageChoiceSchema, surveyImageNodePropsSchema, surveyImageNodeType, surveyImagePickerNodePropsSchema, surveyImagePickerNodeType, surveyMatrixColumnSchema, surveyMatrixDynamicNodePropsSchema, surveyMatrixDynamicNodeType, surveyMatrixNodePropsSchema, surveyMatrixNodeType, surveyMultipleTextItemSchema, surveyMultipleTextNodePropsSchema, surveyMultipleTextNodeType, surveyNameSchema, surveyNodeChildren, surveyNodeSchema, surveyNodeTypeDefinitionMap, surveyNoneChoicePropsShape, surveyPageNodePropsSchema, surveyPageNodeSchema, surveyPageNodeType, surveyPanelDynamicNodePropsSchema, surveyPanelDynamicNodeType, surveyPanelNodePropsSchema, surveyPanelNodeType, surveyPlaceableNodeSchema, surveyQuestionBasePropsShape, surveyRadioGroupNodePropsSchema, surveyRadioGroupNodeType, surveyRankingNodePropsSchema, surveyRankingNodeType, surveyRatingNodePropsSchema, surveyRatingNodeType, surveyRegistry, surveyRootPropsSchema, surveySliderNodePropsSchema, surveySliderNodeType, surveyTagBoxNodePropsSchema, surveyTagBoxNodeType, surveyTextNodePropsSchema, surveyTextNodeType, surveyValidatorSchema, toSurveyAnswerValue, toSurveyPanelScope, validateSurveyAnswers, validateSurveyPage };
|