@oneblink/sdk-core 9.2.2-beta.1 → 10.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/LICENSE +21 -674
  2. package/dist/conditionalLogicService/conditionallyShowElement.d.ts +16 -8
  3. package/dist/conditionalLogicService/conditionallyShowElement.js +19 -11
  4. package/dist/conditionalLogicService/conditionallyShowElement.js.map +1 -1
  5. package/dist/conditionalLogicService/conditionallyShowOption.d.ts +6 -1
  6. package/dist/conditionalLogicService/conditionallyShowOption.js +43 -11
  7. package/dist/conditionalLogicService/conditionallyShowOption.js.map +1 -1
  8. package/dist/conditionalLogicService/evaluateConditionalSubmissionTimestampPredicate.d.ts +20 -0
  9. package/dist/conditionalLogicService/evaluateConditionalSubmissionTimestampPredicate.js +71 -0
  10. package/dist/conditionalLogicService/evaluateConditionalSubmissionTimestampPredicate.js.map +1 -0
  11. package/dist/conditionalLogicService/evaluateFormElementConditionalPredicate.d.ts +15 -0
  12. package/dist/conditionalLogicService/{evaluateConditionalPredicate.js → evaluateFormElementConditionalPredicate.js} +25 -12
  13. package/dist/conditionalLogicService/evaluateFormElementConditionalPredicate.js.map +1 -0
  14. package/dist/conditionalLogicService/generateFormElementsConditionallyShown.d.ts +21 -13
  15. package/dist/conditionalLogicService/generateFormElementsConditionallyShown.js +99 -23
  16. package/dist/conditionalLogicService/generateFormElementsConditionallyShown.js.map +1 -1
  17. package/dist/conditionalLogicService/types.d.ts +10 -0
  18. package/dist/conditionalLogicService/types.js.map +1 -1
  19. package/dist/conditionalLogicService.d.ts +15 -1
  20. package/dist/conditionalLogicService.js +24 -6
  21. package/dist/conditionalLogicService.js.map +1 -1
  22. package/dist/paymentService.d.ts +22 -4
  23. package/dist/paymentService.js +15 -4
  24. package/dist/paymentService.js.map +1 -1
  25. package/dist/schedulingService.d.ts +21 -6
  26. package/dist/schedulingService.js +14 -6
  27. package/dist/schedulingService.js.map +1 -1
  28. package/package.json +2 -2
  29. package/dist/conditionalLogicService/evaluateConditionalPredicate.d.ts +0 -6
  30. package/dist/conditionalLogicService/evaluateConditionalPredicate.js.map +0 -1
@@ -23,16 +23,22 @@ export type FormElementsConditionallyShownParameters = {
23
23
  submission: SubmissionTypes.S3SubmissionData['submission'];
24
24
  /** Optional callback for handling errors caught during the evaluation */
25
25
  errorCallback?: ErrorCallback;
26
+ /** Conditionally enable form submission based on predicates */
27
+ enableSubmission: FormTypes.Form['enableSubmission'] | undefined;
28
+ };
29
+ export type FormElementsConditionallyShownResult = {
30
+ formElementsConditionallyShown: FormElementsConditionallyShown;
31
+ isSubmissionEnabled: boolean;
26
32
  };
27
33
  /**
28
- * Given a form element and submission data, evaluate which elements are
29
- * currently shown. The function also takes an optional errorCallback for
30
- * handling errors caught during the evaluation.
34
+ * Given form elements and submission data, evaluate which elements are
35
+ * currently shown and whether submission is enabled. The function also takes an
36
+ * optional errorCallback for handling errors caught during the evaluation.
31
37
  *
32
38
  * #### Example
33
39
  *
34
40
  * ```js
35
- * const formElementsConditionallyShown =
41
+ * const { formElementsConditionallyShown, isSubmissionEnabled } =
36
42
  * conditionalLogicService.generateFormElementsConditionallyShown({
37
43
  * submission: {
38
44
  * radio: ['hide'],
@@ -85,7 +91,6 @@ export type FormElementsConditionallyShownParameters = {
85
91
  * isElementLookup: false,
86
92
  * },
87
93
  * ],
88
- * parentFormElementsCtrl: undefined,
89
94
  * errorCallback: (error) => {
90
95
  * //do something with the error here
91
96
  * console.error(error)
@@ -97,18 +102,21 @@ export type FormElementsConditionallyShownParameters = {
97
102
  *
98
103
  * ```json
99
104
  * {
100
- * "radio": {
101
- * "isHidden": false,
102
- * "type": "formElement"
105
+ * "formElementsConditionallyShown": {
106
+ * "radio": {
107
+ * "isHidden": false,
108
+ * "type": "formElement"
109
+ * },
110
+ * "text": {
111
+ * "isHidden": true,
112
+ * "type": "formElement"
113
+ * }
103
114
  * },
104
- * "text": {
105
- * "isHidden": true,
106
- * "type": "formElement"
107
- * }
115
+ * "isSubmissionEnabled": true
108
116
  * }
109
117
  * ```
110
118
  *
111
119
  * @param parameters
112
120
  * @returns
113
121
  */
114
- export declare function generateFormElementsConditionallyShown(parameters: FormElementsConditionallyShownParameters): FormElementsConditionallyShown;
122
+ export declare function generateFormElementsConditionallyShown({ formElements, submission, errorCallback, enableSubmission, }: FormElementsConditionallyShownParameters): FormElementsConditionallyShownResult;
@@ -2,18 +2,28 @@ import { flattenFormElements } from '../formElementsService.js';
2
2
  import conditionallyShowElement from './conditionallyShowElement.js';
3
3
  import conditionallyShowOption from './conditionallyShowOption.js';
4
4
  import { typeCastService } from '../index.js';
5
- const handleConditionallyShowElement = (formElementsCtrl, element, errorCallback) => {
5
+ import evaluateFormElementConditionalPredicate from './evaluateFormElementConditionalPredicate.js';
6
+ const handleConditionallyShowElement = ({ formElementsCtrl, element, errorCallback, }) => {
6
7
  try {
7
- return conditionallyShowElement(formElementsCtrl, element, []);
8
+ return conditionallyShowElement({
9
+ formElementsCtrl,
10
+ elementToEvaluate: element,
11
+ elementsEvaluated: [],
12
+ });
8
13
  }
9
14
  catch (error) {
10
15
  errorCallback?.(error);
11
16
  return false;
12
17
  }
13
18
  };
14
- const handleConditionallyShowOption = (formElementsCtrl, element, option, errorCallback) => {
19
+ const handleConditionallyShowOption = ({ formElementsCtrl, element, option, errorCallback, }) => {
15
20
  try {
16
- return conditionallyShowOption(formElementsCtrl, element, option, []);
21
+ return conditionallyShowOption({
22
+ formElementsCtrl,
23
+ elementToEvaluate: element,
24
+ optionToEvaluate: option,
25
+ optionsEvaluated: [],
26
+ });
17
27
  }
18
28
  catch (error) {
19
29
  errorCallback?.(error);
@@ -33,7 +43,11 @@ const generateFormElementsConditionallyShownWithParent = ({ formElements, submis
33
43
  const formElementConditionallyShown = formElementsConditionallyShown[element.id];
34
44
  const isHidden = formElementConditionallyShown
35
45
  ? formElementConditionallyShown.isHidden
36
- : !handleConditionallyShowElement(formElementsCtrl, element, errorCallback);
46
+ : !handleConditionallyShowElement({
47
+ formElementsCtrl,
48
+ element,
49
+ errorCallback,
50
+ });
37
51
  formElementsConditionallyShown[element.id] = {
38
52
  type: 'formElement',
39
53
  isHidden,
@@ -69,11 +83,16 @@ const generateFormElementsConditionallyShownWithParent = ({ formElements, submis
69
83
  const nestedModel = submission[element.name];
70
84
  formElementsConditionallyShown[element.name] = {
71
85
  type: 'formElements',
72
- isHidden: !handleConditionallyShowElement(formElementsCtrl, element, errorCallback),
86
+ isHidden: !handleConditionallyShowElement({
87
+ formElementsCtrl,
88
+ element,
89
+ errorCallback,
90
+ }),
73
91
  formElements: generateFormElementsConditionallyShownWithParent({
74
92
  formElements: element.elements || [],
75
93
  submission: nestedModel || {},
76
94
  parentFormElementsCtrl: formElementsCtrl,
95
+ errorCallback,
77
96
  }),
78
97
  };
79
98
  break;
@@ -85,13 +104,18 @@ const generateFormElementsConditionallyShownWithParent = ({ formElements, submis
85
104
  const entries = formElementsCtrl.model?.[element.name];
86
105
  formElementsConditionallyShown[element.name] = {
87
106
  type: 'repeatableSet',
88
- isHidden: !handleConditionallyShowElement(formElementsCtrl, element, errorCallback),
107
+ isHidden: !handleConditionallyShowElement({
108
+ formElementsCtrl,
109
+ element,
110
+ errorCallback,
111
+ }),
89
112
  entries: (entries || []).reduce((result, entry, index) => {
90
113
  result[index.toString()] =
91
114
  generateFormElementsConditionallyShownWithParent({
92
115
  formElements: element.elements,
93
116
  submission: entry,
94
117
  parentFormElementsCtrl: formElementsCtrl,
118
+ errorCallback,
95
119
  });
96
120
  return result;
97
121
  }, {}),
@@ -104,7 +128,11 @@ const generateFormElementsConditionallyShownWithParent = ({ formElements, submis
104
128
  }
105
129
  const formElementConditionallyShown = {
106
130
  type: 'formElement',
107
- isHidden: !handleConditionallyShowElement(formElementsCtrl, element, errorCallback),
131
+ isHidden: !handleConditionallyShowElement({
132
+ formElementsCtrl,
133
+ element,
134
+ errorCallback,
135
+ }),
108
136
  };
109
137
  if (!formElementConditionallyShown.isHidden) {
110
138
  const optionsElement = typeCastService.formElements.toOptionsElement(element);
@@ -113,7 +141,12 @@ const generateFormElementsConditionallyShownWithParent = ({ formElements, submis
113
141
  Array.isArray(optionsElement.options)) {
114
142
  const newOptions = [];
115
143
  for (const option of optionsElement.options) {
116
- const optionPredicatesResult = handleConditionallyShowOption(formElementsCtrl, optionsElement, option, errorCallback);
144
+ const optionPredicatesResult = handleConditionallyShowOption({
145
+ formElementsCtrl,
146
+ element: optionsElement,
147
+ option,
148
+ errorCallback,
149
+ });
117
150
  switch (optionPredicatesResult) {
118
151
  case 'SHOW': {
119
152
  newOptions.push(option);
@@ -141,14 +174,14 @@ const generateFormElementsConditionallyShownWithParent = ({ formElements, submis
141
174
  }, {});
142
175
  };
143
176
  /**
144
- * Given a form element and submission data, evaluate which elements are
145
- * currently shown. The function also takes an optional errorCallback for
146
- * handling errors caught during the evaluation.
177
+ * Given form elements and submission data, evaluate which elements are
178
+ * currently shown and whether submission is enabled. The function also takes an
179
+ * optional errorCallback for handling errors caught during the evaluation.
147
180
  *
148
181
  * #### Example
149
182
  *
150
183
  * ```js
151
- * const formElementsConditionallyShown =
184
+ * const { formElementsConditionallyShown, isSubmissionEnabled } =
152
185
  * conditionalLogicService.generateFormElementsConditionallyShown({
153
186
  * submission: {
154
187
  * radio: ['hide'],
@@ -201,7 +234,6 @@ const generateFormElementsConditionallyShownWithParent = ({ formElements, submis
201
234
  * isElementLookup: false,
202
235
  * },
203
236
  * ],
204
- * parentFormElementsCtrl: undefined,
205
237
  * errorCallback: (error) => {
206
238
  * //do something with the error here
207
239
  * console.error(error)
@@ -213,21 +245,65 @@ const generateFormElementsConditionallyShownWithParent = ({ formElements, submis
213
245
  *
214
246
  * ```json
215
247
  * {
216
- * "radio": {
217
- * "isHidden": false,
218
- * "type": "formElement"
248
+ * "formElementsConditionallyShown": {
249
+ * "radio": {
250
+ * "isHidden": false,
251
+ * "type": "formElement"
252
+ * },
253
+ * "text": {
254
+ * "isHidden": true,
255
+ * "type": "formElement"
256
+ * }
219
257
  * },
220
- * "text": {
221
- * "isHidden": true,
222
- * "type": "formElement"
223
- * }
258
+ * "isSubmissionEnabled": true
224
259
  * }
225
260
  * ```
226
261
  *
227
262
  * @param parameters
228
263
  * @returns
229
264
  */
230
- export function generateFormElementsConditionallyShown(parameters) {
231
- return generateFormElementsConditionallyShownWithParent(parameters);
265
+ export function generateFormElementsConditionallyShown({ formElements, submission, errorCallback, enableSubmission, }) {
266
+ const formElementsConditionallyShown = generateFormElementsConditionallyShownWithParent({
267
+ formElements,
268
+ submission,
269
+ errorCallback,
270
+ parentFormElementsCtrl: undefined,
271
+ });
272
+ if (!enableSubmission?.conditionalPredicates.length) {
273
+ return {
274
+ formElementsConditionallyShown,
275
+ isSubmissionEnabled: true,
276
+ };
277
+ }
278
+ const formElementsCtrl = {
279
+ flattenedElements: flattenFormElements(formElements),
280
+ model: submission,
281
+ };
282
+ const predicateFn = (predicate) => {
283
+ try {
284
+ const predicateElement = evaluateFormElementConditionalPredicate({
285
+ predicate,
286
+ formElementsCtrl,
287
+ });
288
+ if (!predicateElement) {
289
+ return false;
290
+ }
291
+ // Reuse visibility already computed above instead of re-evaluating
292
+ // conditionally show predicates for the predicate element / parents.
293
+ const shown = formElementsConditionallyShown[predicateElement.name];
294
+ return !!shown && !shown.isHidden;
295
+ }
296
+ catch (error) {
297
+ errorCallback?.(error);
298
+ return false;
299
+ }
300
+ };
301
+ const isSubmissionEnabled = enableSubmission.requiresAllConditionalPredicates
302
+ ? enableSubmission.conditionalPredicates.every(predicateFn)
303
+ : enableSubmission.conditionalPredicates.some(predicateFn);
304
+ return {
305
+ formElementsConditionallyShown,
306
+ isSubmissionEnabled,
307
+ };
232
308
  }
233
309
  //# sourceMappingURL=generateFormElementsConditionallyShown.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"generateFormElementsConditionallyShown.js","sourceRoot":"","sources":["../../src/conditionalLogicService/generateFormElementsConditionallyShown.ts"],"names":[],"mappings":"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","sourcesContent":["import { FormTypes, SubmissionTypes } from '@oneblink/types'\nimport { FormElementsCtrl } from './types.js'\nimport { flattenFormElements } from '../formElementsService.js'\nimport conditionallyShowElement from './conditionallyShowElement.js'\nimport conditionallyShowOption, {\n ShouldShowOption,\n} from './conditionallyShowOption.js'\nimport { typeCastService } from '../index.js'\n\nexport type FormElementsConditionallyShown = Record<\n string,\n FormElementConditionallyShown\n>\n\nexport type FormElementConditionallyShownElement = {\n type: 'formElement'\n isHidden: boolean\n options?: FormTypes.ChoiceElementOption[]\n dependencyIsLoading?: boolean\n}\n\nexport type FormElementConditionallyShown =\n | undefined\n | FormElementConditionallyShownElement\n | {\n type: 'formElements'\n isHidden: boolean\n formElements: FormElementsConditionallyShown | undefined\n }\n | {\n type: 'repeatableSet'\n isHidden: boolean\n entries: Record<string, FormElementsConditionallyShown | undefined>\n }\n\nexport type ErrorCallback = (error: Error) => void\n\nconst handleConditionallyShowElement = (\n formElementsCtrl: FormElementsCtrl,\n element: FormTypes.FormElement,\n errorCallback: ErrorCallback | undefined,\n) => {\n try {\n return conditionallyShowElement(formElementsCtrl, element, [])\n } catch (error) {\n errorCallback?.(error as Error)\n return false\n }\n}\n\nconst handleConditionallyShowOption = (\n formElementsCtrl: FormElementsCtrl,\n element: FormTypes.FormElementWithOptions,\n option: FormTypes.ChoiceElementOption,\n errorCallback: ErrorCallback | undefined,\n): ShouldShowOption => {\n try {\n return conditionallyShowOption(formElementsCtrl, element, option, [])\n } catch (error) {\n errorCallback?.(error as Error)\n return 'HIDE'\n }\n}\n\nexport type FormElementsConditionallyShownParameters = {\n /** Form elements to evaluate */\n formElements: FormTypes.FormElement[]\n /** Current submission data */\n submission: SubmissionTypes.S3SubmissionData['submission']\n /** Optional callback for handling errors caught during the evaluation */\n errorCallback?: ErrorCallback\n}\n\nconst generateFormElementsConditionallyShownWithParent = ({\n formElements,\n submission,\n parentFormElementsCtrl,\n errorCallback,\n}: FormElementsConditionallyShownParameters & {\n parentFormElementsCtrl?: FormElementsCtrl['parentFormElementsCtrl']\n}): FormElementsConditionallyShown => {\n const formElementsCtrl = {\n flattenedElements: flattenFormElements(formElements),\n model: submission,\n parentFormElementsCtrl,\n }\n return formElementsCtrl.flattenedElements.reduce<FormElementsConditionallyShown>(\n (formElementsConditionallyShown, element) => {\n switch (element.type) {\n case 'section':\n case 'page': {\n const formElementConditionallyShown =\n formElementsConditionallyShown[element.id]\n const isHidden = formElementConditionallyShown\n ? formElementConditionallyShown.isHidden\n : !handleConditionallyShowElement(\n formElementsCtrl,\n element,\n errorCallback,\n )\n\n formElementsConditionallyShown[element.id] = {\n type: 'formElement',\n isHidden,\n }\n\n // If the parent element is hidden, hide all the child elements\n if (isHidden) {\n element.elements.forEach((childElement) => {\n switch (childElement.type) {\n case 'section':\n case 'page': {\n formElementsConditionallyShown[childElement.id] = {\n type: 'formElement',\n isHidden: true,\n }\n break\n }\n default: {\n formElementsConditionallyShown[childElement.name] = {\n type: 'formElement',\n isHidden: true,\n }\n }\n }\n })\n }\n break\n }\n case 'infoPage':\n case 'form': {\n if (formElementsConditionallyShown[element.name]) {\n break\n }\n const nestedModel = submission[element.name] as\n | SubmissionTypes.S3SubmissionData['submission']\n | undefined\n formElementsConditionallyShown[element.name] = {\n type: 'formElements',\n isHidden: !handleConditionallyShowElement(\n formElementsCtrl,\n element,\n errorCallback,\n ),\n formElements: generateFormElementsConditionallyShownWithParent({\n formElements: element.elements || [],\n submission: nestedModel || {},\n parentFormElementsCtrl: formElementsCtrl,\n }),\n }\n break\n }\n case 'repeatableSet': {\n if (formElementsConditionallyShown[element.name]) {\n break\n }\n const entries = formElementsCtrl.model?.[element.name] as\n | Array<SubmissionTypes.S3SubmissionData['submission']>\n | undefined\n formElementsConditionallyShown[element.name] = {\n type: 'repeatableSet',\n isHidden: !handleConditionallyShowElement(\n formElementsCtrl,\n element,\n errorCallback,\n ),\n entries: (entries || []).reduce(\n (\n result: Record<\n string,\n FormElementsConditionallyShown | undefined\n >,\n entry,\n index,\n ) => {\n result[index.toString()] =\n generateFormElementsConditionallyShownWithParent({\n formElements: element.elements,\n submission: entry,\n parentFormElementsCtrl: formElementsCtrl,\n })\n return result\n },\n {},\n ),\n }\n break\n }\n default: {\n if (formElementsConditionallyShown[element.name]) {\n break\n }\n const formElementConditionallyShown: FormElementConditionallyShown = {\n type: 'formElement',\n isHidden: !handleConditionallyShowElement(\n formElementsCtrl,\n element,\n errorCallback,\n ),\n }\n\n if (!formElementConditionallyShown.isHidden) {\n const optionsElement =\n typeCastService.formElements.toOptionsElement(element)\n if (\n optionsElement &&\n optionsElement.conditionallyShowOptions &&\n Array.isArray(optionsElement.options)\n ) {\n const newOptions = []\n for (const option of optionsElement.options) {\n const optionPredicatesResult = handleConditionallyShowOption(\n formElementsCtrl,\n optionsElement,\n option,\n errorCallback,\n )\n switch (optionPredicatesResult) {\n case 'SHOW': {\n newOptions.push(option)\n break\n }\n case 'LOADING_STATIC_DEPENDENCY': {\n newOptions.push(option)\n formElementConditionallyShown.dependencyIsLoading = true\n break\n }\n case 'LOADING_DYNAMIC_DEPENDENCY': {\n formElementConditionallyShown.dependencyIsLoading = true\n break\n }\n }\n }\n formElementConditionallyShown.options = newOptions\n }\n }\n\n formElementsConditionallyShown[element.name] =\n formElementConditionallyShown\n }\n }\n\n return formElementsConditionallyShown\n },\n {},\n )\n}\n\n/**\n * Given a form element and submission data, evaluate which elements are\n * currently shown. The function also takes an optional errorCallback for\n * handling errors caught during the evaluation.\n *\n * #### Example\n *\n * ```js\n * const formElementsConditionallyShown =\n * conditionalLogicService.generateFormElementsConditionallyShown({\n * submission: {\n * radio: ['hide'],\n * text: 'hidden text',\n * },\n * formElements: [\n * {\n * name: 'radio',\n * label: 'Radio',\n * type: 'radio',\n * required: false,\n * id: '5ef3beb8-8ac8-4c8d-9fd3-d8197113bf54',\n * conditionallyShow: false,\n * options: [\n * {\n * id: '9a44e15a-5929-419d-825e-b3dc0a29591f',\n * label: 'Show',\n * value: 'show',\n * },\n * {\n * id: 'd776ed42-072c-4bf8-9879-874b2bef85d3',\n * label: 'Hide',\n * value: 'Hide',\n * },\n * ],\n * readOnly: false,\n * isDataLookup: false,\n * isElementLookup: false,\n * buttons: false,\n * optionsType: 'CUSTOM',\n * conditionallyShowOptions: false,\n * },\n * {\n * name: 'text',\n * label: 'Text',\n * type: 'text',\n * required: false,\n * id: '8fbddb41-348d-494c-904b-56a2c4361f13',\n * requiresAllConditionallyShowPredicates: false,\n * conditionallyShow: true,\n * conditionallyShowPredicates: [\n * {\n * elementId: '5ef3beb8-8ac8-4c8d-9fd3-d8197113bf54',\n * optionIds: ['9a44e15a-5929-419d-825e-b3dc0a29591f'],\n * type: 'OPTIONS',\n * },\n * ],\n * readOnly: false,\n * isDataLookup: false,\n * isElementLookup: false,\n * },\n * ],\n * parentFormElementsCtrl: undefined,\n * errorCallback: (error) => {\n * //do something with the error here\n * console.error(error)\n * },\n * })\n * ```\n *\n * The above example returns an object like below\n *\n * ```json\n * {\n * \"radio\": {\n * \"isHidden\": false,\n * \"type\": \"formElement\"\n * },\n * \"text\": {\n * \"isHidden\": true,\n * \"type\": \"formElement\"\n * }\n * }\n * ```\n *\n * @param parameters\n * @returns\n */\nexport function generateFormElementsConditionallyShown(\n parameters: FormElementsConditionallyShownParameters,\n): FormElementsConditionallyShown {\n return generateFormElementsConditionallyShownWithParent(parameters)\n}\n"]}
1
+ {"version":3,"file":"generateFormElementsConditionallyShown.js","sourceRoot":"","sources":["../../src/conditionalLogicService/generateFormElementsConditionallyShown.ts"],"names":[],"mappings":"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","sourcesContent":["import { FormTypes, SubmissionTypes } from '@oneblink/types'\nimport { FormElementsCtrl } from './types.js'\nimport { flattenFormElements } from '../formElementsService.js'\nimport conditionallyShowElement from './conditionallyShowElement.js'\nimport conditionallyShowOption, {\n ShouldShowOption,\n} from './conditionallyShowOption.js'\nimport { typeCastService } from '../index.js'\nimport evaluateFormElementConditionalPredicate from './evaluateFormElementConditionalPredicate.js'\n\nexport type FormElementsConditionallyShown = Record<\n string,\n FormElementConditionallyShown\n>\n\nexport type FormElementConditionallyShownElement = {\n type: 'formElement'\n isHidden: boolean\n options?: FormTypes.ChoiceElementOption[]\n dependencyIsLoading?: boolean\n}\n\nexport type FormElementConditionallyShown =\n | undefined\n | FormElementConditionallyShownElement\n | {\n type: 'formElements'\n isHidden: boolean\n formElements: FormElementsConditionallyShown | undefined\n }\n | {\n type: 'repeatableSet'\n isHidden: boolean\n entries: Record<string, FormElementsConditionallyShown | undefined>\n }\n\nexport type ErrorCallback = (error: Error) => void\n\nconst handleConditionallyShowElement = ({\n formElementsCtrl,\n element,\n errorCallback,\n}: {\n formElementsCtrl: FormElementsCtrl\n element: FormTypes.FormElement\n errorCallback: ErrorCallback | undefined\n}) => {\n try {\n return conditionallyShowElement({\n formElementsCtrl,\n elementToEvaluate: element,\n elementsEvaluated: [],\n })\n } catch (error) {\n errorCallback?.(error as Error)\n return false\n }\n}\n\nconst handleConditionallyShowOption = ({\n formElementsCtrl,\n element,\n option,\n errorCallback,\n}: {\n formElementsCtrl: FormElementsCtrl\n element: FormTypes.FormElementWithOptions\n option: FormTypes.ChoiceElementOption\n errorCallback: ErrorCallback | undefined\n}): ShouldShowOption => {\n try {\n return conditionallyShowOption({\n formElementsCtrl,\n elementToEvaluate: element,\n optionToEvaluate: option,\n optionsEvaluated: [],\n })\n } catch (error) {\n errorCallback?.(error as Error)\n return 'HIDE'\n }\n}\n\nexport type FormElementsConditionallyShownParameters = {\n /** Form elements to evaluate */\n formElements: FormTypes.FormElement[]\n /** Current submission data */\n submission: SubmissionTypes.S3SubmissionData['submission']\n /** Optional callback for handling errors caught during the evaluation */\n errorCallback?: ErrorCallback\n /** Conditionally enable form submission based on predicates */\n enableSubmission: FormTypes.Form['enableSubmission'] | undefined\n}\n\nexport type FormElementsConditionallyShownResult = {\n formElementsConditionallyShown: FormElementsConditionallyShown\n isSubmissionEnabled: boolean\n}\n\nconst generateFormElementsConditionallyShownWithParent = ({\n formElements,\n submission,\n parentFormElementsCtrl,\n errorCallback,\n}: {\n formElements: FormTypes.FormElement[]\n submission: SubmissionTypes.S3SubmissionData['submission']\n errorCallback: ErrorCallback | undefined\n parentFormElementsCtrl: FormElementsCtrl['parentFormElementsCtrl'] | undefined\n}): FormElementsConditionallyShown => {\n const formElementsCtrl = {\n flattenedElements: flattenFormElements(formElements),\n model: submission,\n parentFormElementsCtrl,\n }\n return formElementsCtrl.flattenedElements.reduce<FormElementsConditionallyShown>(\n (formElementsConditionallyShown, element) => {\n switch (element.type) {\n case 'section':\n case 'page': {\n const formElementConditionallyShown =\n formElementsConditionallyShown[element.id]\n const isHidden = formElementConditionallyShown\n ? formElementConditionallyShown.isHidden\n : !handleConditionallyShowElement({\n formElementsCtrl,\n element,\n errorCallback,\n })\n\n formElementsConditionallyShown[element.id] = {\n type: 'formElement',\n isHidden,\n }\n\n // If the parent element is hidden, hide all the child elements\n if (isHidden) {\n element.elements.forEach((childElement) => {\n switch (childElement.type) {\n case 'section':\n case 'page': {\n formElementsConditionallyShown[childElement.id] = {\n type: 'formElement',\n isHidden: true,\n }\n break\n }\n default: {\n formElementsConditionallyShown[childElement.name] = {\n type: 'formElement',\n isHidden: true,\n }\n }\n }\n })\n }\n break\n }\n case 'infoPage':\n case 'form': {\n if (formElementsConditionallyShown[element.name]) {\n break\n }\n const nestedModel = submission[element.name] as\n | SubmissionTypes.S3SubmissionData['submission']\n | undefined\n formElementsConditionallyShown[element.name] = {\n type: 'formElements',\n isHidden: !handleConditionallyShowElement({\n formElementsCtrl,\n element,\n errorCallback,\n }),\n formElements: generateFormElementsConditionallyShownWithParent({\n formElements: element.elements || [],\n submission: nestedModel || {},\n parentFormElementsCtrl: formElementsCtrl,\n errorCallback,\n }),\n }\n break\n }\n case 'repeatableSet': {\n if (formElementsConditionallyShown[element.name]) {\n break\n }\n const entries = formElementsCtrl.model?.[element.name] as\n | Array<SubmissionTypes.S3SubmissionData['submission']>\n | undefined\n formElementsConditionallyShown[element.name] = {\n type: 'repeatableSet',\n isHidden: !handleConditionallyShowElement({\n formElementsCtrl,\n element,\n errorCallback,\n }),\n entries: (entries || []).reduce(\n (\n result: Record<\n string,\n FormElementsConditionallyShown | undefined\n >,\n entry,\n index,\n ) => {\n result[index.toString()] =\n generateFormElementsConditionallyShownWithParent({\n formElements: element.elements,\n submission: entry,\n parentFormElementsCtrl: formElementsCtrl,\n errorCallback,\n })\n return result\n },\n {},\n ),\n }\n break\n }\n default: {\n if (formElementsConditionallyShown[element.name]) {\n break\n }\n const formElementConditionallyShown: FormElementConditionallyShown = {\n type: 'formElement',\n isHidden: !handleConditionallyShowElement({\n formElementsCtrl,\n element,\n errorCallback,\n }),\n }\n\n if (!formElementConditionallyShown.isHidden) {\n const optionsElement =\n typeCastService.formElements.toOptionsElement(element)\n if (\n optionsElement &&\n optionsElement.conditionallyShowOptions &&\n Array.isArray(optionsElement.options)\n ) {\n const newOptions = []\n for (const option of optionsElement.options) {\n const optionPredicatesResult = handleConditionallyShowOption({\n formElementsCtrl,\n element: optionsElement,\n option,\n errorCallback,\n })\n switch (optionPredicatesResult) {\n case 'SHOW': {\n newOptions.push(option)\n break\n }\n case 'LOADING_STATIC_DEPENDENCY': {\n newOptions.push(option)\n formElementConditionallyShown.dependencyIsLoading = true\n break\n }\n case 'LOADING_DYNAMIC_DEPENDENCY': {\n formElementConditionallyShown.dependencyIsLoading = true\n break\n }\n }\n }\n formElementConditionallyShown.options = newOptions\n }\n }\n\n formElementsConditionallyShown[element.name] =\n formElementConditionallyShown\n }\n }\n\n return formElementsConditionallyShown\n },\n {},\n )\n}\n\n/**\n * Given form elements and submission data, evaluate which elements are\n * currently shown and whether submission is enabled. The function also takes an\n * optional errorCallback for handling errors caught during the evaluation.\n *\n * #### Example\n *\n * ```js\n * const { formElementsConditionallyShown, isSubmissionEnabled } =\n * conditionalLogicService.generateFormElementsConditionallyShown({\n * submission: {\n * radio: ['hide'],\n * text: 'hidden text',\n * },\n * formElements: [\n * {\n * name: 'radio',\n * label: 'Radio',\n * type: 'radio',\n * required: false,\n * id: '5ef3beb8-8ac8-4c8d-9fd3-d8197113bf54',\n * conditionallyShow: false,\n * options: [\n * {\n * id: '9a44e15a-5929-419d-825e-b3dc0a29591f',\n * label: 'Show',\n * value: 'show',\n * },\n * {\n * id: 'd776ed42-072c-4bf8-9879-874b2bef85d3',\n * label: 'Hide',\n * value: 'Hide',\n * },\n * ],\n * readOnly: false,\n * isDataLookup: false,\n * isElementLookup: false,\n * buttons: false,\n * optionsType: 'CUSTOM',\n * conditionallyShowOptions: false,\n * },\n * {\n * name: 'text',\n * label: 'Text',\n * type: 'text',\n * required: false,\n * id: '8fbddb41-348d-494c-904b-56a2c4361f13',\n * requiresAllConditionallyShowPredicates: false,\n * conditionallyShow: true,\n * conditionallyShowPredicates: [\n * {\n * elementId: '5ef3beb8-8ac8-4c8d-9fd3-d8197113bf54',\n * optionIds: ['9a44e15a-5929-419d-825e-b3dc0a29591f'],\n * type: 'OPTIONS',\n * },\n * ],\n * readOnly: false,\n * isDataLookup: false,\n * isElementLookup: false,\n * },\n * ],\n * errorCallback: (error) => {\n * //do something with the error here\n * console.error(error)\n * },\n * })\n * ```\n *\n * The above example returns an object like below\n *\n * ```json\n * {\n * \"formElementsConditionallyShown\": {\n * \"radio\": {\n * \"isHidden\": false,\n * \"type\": \"formElement\"\n * },\n * \"text\": {\n * \"isHidden\": true,\n * \"type\": \"formElement\"\n * }\n * },\n * \"isSubmissionEnabled\": true\n * }\n * ```\n *\n * @param parameters\n * @returns\n */\nexport function generateFormElementsConditionallyShown({\n formElements,\n submission,\n errorCallback,\n enableSubmission,\n}: FormElementsConditionallyShownParameters): FormElementsConditionallyShownResult {\n const formElementsConditionallyShown =\n generateFormElementsConditionallyShownWithParent({\n formElements,\n submission,\n errorCallback,\n parentFormElementsCtrl: undefined,\n })\n\n if (!enableSubmission?.conditionalPredicates.length) {\n return {\n formElementsConditionallyShown,\n isSubmissionEnabled: true,\n }\n }\n\n const formElementsCtrl: FormElementsCtrl = {\n flattenedElements: flattenFormElements(formElements),\n model: submission,\n }\n\n const predicateFn = (\n predicate: NonNullable<\n FormTypes.Form['enableSubmission']\n >['conditionalPredicates'][number],\n ) => {\n try {\n const predicateElement = evaluateFormElementConditionalPredicate({\n predicate,\n formElementsCtrl,\n })\n if (!predicateElement) {\n return false\n }\n\n // Reuse visibility already computed above instead of re-evaluating\n // conditionally show predicates for the predicate element / parents.\n const shown = formElementsConditionallyShown[predicateElement.name]\n return !!shown && !shown.isHidden\n } catch (error) {\n errorCallback?.(error as Error)\n return false\n }\n }\n\n const isSubmissionEnabled = enableSubmission.requiresAllConditionalPredicates\n ? enableSubmission.conditionalPredicates.every(predicateFn)\n : enableSubmission.conditionalPredicates.some(predicateFn)\n\n return {\n formElementsConditionallyShown,\n isSubmissionEnabled,\n }\n}\n"]}
@@ -1,4 +1,14 @@
1
1
  import { FormTypes, SubmissionTypes } from '@oneblink/types';
2
+ /**
3
+ * Parse a date/datetime string into a `Date`. Callers supply timezone-aware
4
+ * parsing (e.g. treating `YYYY-MM-DD` as the start of day in an organisation
5
+ * timezone).
6
+ */
7
+ export type ParseDate = (value: string) => Date;
8
+ /**
9
+ * Add an offset to a date. Callers supply timezone-aware calendar arithmetic.
10
+ */
11
+ export type AddOffsetToDate = (date: Date, offset: number) => Date;
2
12
  export type FormElementsCtrl = {
3
13
  model: SubmissionTypes.S3SubmissionData['submission'] | undefined;
4
14
  flattenedElements: FormTypes.FormElement[];
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/conditionalLogicService/types.ts"],"names":[],"mappings":"","sourcesContent":["import { FormTypes, SubmissionTypes } from '@oneblink/types'\n\nexport type FormElementsCtrl = {\n model: SubmissionTypes.S3SubmissionData['submission'] | undefined\n flattenedElements: FormTypes.FormElement[]\n parentFormElementsCtrl?: FormElementsCtrl\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/conditionalLogicService/types.ts"],"names":[],"mappings":"","sourcesContent":["import { FormTypes, SubmissionTypes } from '@oneblink/types'\n\n/**\n * Parse a date/datetime string into a `Date`. Callers supply timezone-aware\n * parsing (e.g. treating `YYYY-MM-DD` as the start of day in an organisation\n * timezone).\n */\nexport type ParseDate = (value: string) => Date\n\n/**\n * Add an offset to a date. Callers supply timezone-aware calendar arithmetic.\n */\nexport type AddOffsetToDate = (date: Date, offset: number) => Date\n\nexport type FormElementsCtrl = {\n model: SubmissionTypes.S3SubmissionData['submission'] | undefined\n flattenedElements: FormTypes.FormElement[]\n parentFormElementsCtrl?: FormElementsCtrl\n}\n"]}
@@ -1,5 +1,7 @@
1
1
  import { ConditionTypes, FormTypes, SubmissionTypes } from '@oneblink/types';
2
+ import { AddOffsetToDate, ParseDate } from './conditionalLogicService/types.js';
2
3
  export * from './conditionalLogicService/generateFormElementsConditionallyShown.js';
4
+ export type { AddOffsetToDate, ParseDate } from './conditionalLogicService/types.js';
3
5
  /**
4
6
  * Given a set of form elements and submission data, evaluate if predicates are
5
7
  * met or not.
@@ -55,6 +57,12 @@ export * from './conditionalLogicService/generateFormElementsConditionallyShown.
55
57
  * requiresAllConditionallyShowPredicates: false,
56
58
  * },
57
59
  * ],
60
+ * submissionTimestamp: new Date().toISOString(),
61
+ * parseDate: (value) => new Date(value),
62
+ * addDaysToDate: (date, days) => {
63
+ * date.setUTCDate(date.getUTCDate() + days)
64
+ * return date
65
+ * },
58
66
  * },
59
67
  * )
60
68
  * ```
@@ -62,10 +70,16 @@ export * from './conditionalLogicService/generateFormElementsConditionallyShown.
62
70
  * @param options
63
71
  * @returns
64
72
  */
65
- export declare function evaluateConditionalPredicates({ isConditional, requiresAllConditionalPredicates, conditionalPredicates, formElements, submission, }: {
73
+ export declare function evaluateConditionalPredicates({ isConditional, requiresAllConditionalPredicates, conditionalPredicates, formElements, submission, submissionTimestamp, parseDate, addDaysToDate, }: {
66
74
  isConditional: boolean;
67
75
  requiresAllConditionalPredicates: boolean;
68
76
  conditionalPredicates: ConditionTypes.ConditionalPredicate[];
69
77
  formElements: FormTypes.FormElement[];
70
78
  submission: SubmissionTypes.S3SubmissionData['submission'];
79
+ /** ISO timestamp the form was submitted. When evaluating during submission, pass `new Date().toISOString()`. */
80
+ submissionTimestamp: string;
81
+ /** Parse date/datetime strings when evaluating date based predicates */
82
+ parseDate: ParseDate;
83
+ /** Add days to a date when evaluating date based predicates */
84
+ addDaysToDate: AddOffsetToDate;
71
85
  }): boolean;
@@ -1,4 +1,5 @@
1
- import evaluateConditionalPredicate from './conditionalLogicService/evaluateConditionalPredicate.js';
1
+ import evaluateFormElementConditionalPredicate from './conditionalLogicService/evaluateFormElementConditionalPredicate.js';
2
+ import evaluateConditionalSubmissionTimestampPredicate from './conditionalLogicService/evaluateConditionalSubmissionTimestampPredicate.js';
2
3
  import { flattenFormElements } from './formElementsService.js';
3
4
  export * from './conditionalLogicService/generateFormElementsConditionallyShown.js';
4
5
  /**
@@ -56,6 +57,12 @@ export * from './conditionalLogicService/generateFormElementsConditionallyShown.
56
57
  * requiresAllConditionallyShowPredicates: false,
57
58
  * },
58
59
  * ],
60
+ * submissionTimestamp: new Date().toISOString(),
61
+ * parseDate: (value) => new Date(value),
62
+ * addDaysToDate: (date, days) => {
63
+ * date.setUTCDate(date.getUTCDate() + days)
64
+ * return date
65
+ * },
59
66
  * },
60
67
  * )
61
68
  * ```
@@ -63,7 +70,7 @@ export * from './conditionalLogicService/generateFormElementsConditionallyShown.
63
70
  * @param options
64
71
  * @returns
65
72
  */
66
- export function evaluateConditionalPredicates({ isConditional, requiresAllConditionalPredicates, conditionalPredicates, formElements, submission, }) {
73
+ export function evaluateConditionalPredicates({ isConditional, requiresAllConditionalPredicates, conditionalPredicates, formElements, submission, submissionTimestamp, parseDate, addDaysToDate, }) {
67
74
  if (!isConditional || !conditionalPredicates.length) {
68
75
  return true;
69
76
  }
@@ -71,10 +78,21 @@ export function evaluateConditionalPredicates({ isConditional, requiresAllCondit
71
78
  flattenedElements: flattenFormElements(formElements),
72
79
  model: submission,
73
80
  };
74
- const predicateFn = (predicate) => evaluateConditionalPredicate({
75
- predicate,
76
- formElementsCtrl,
77
- });
81
+ const predicateFn = (predicate) => {
82
+ if (predicate.type === 'SUBMISSION_TIMESTAMP') {
83
+ return evaluateConditionalSubmissionTimestampPredicate({
84
+ predicate,
85
+ formElementsCtrl,
86
+ submissionTimestamp,
87
+ parseDate,
88
+ addDaysToDate,
89
+ });
90
+ }
91
+ return !!evaluateFormElementConditionalPredicate({
92
+ predicate,
93
+ formElementsCtrl,
94
+ });
95
+ };
78
96
  if (requiresAllConditionalPredicates) {
79
97
  return conditionalPredicates.every(predicateFn);
80
98
  }
@@ -1 +1 @@
1
- {"version":3,"file":"conditionalLogicService.js","sourceRoot":"","sources":["../src/conditionalLogicService.ts"],"names":[],"mappings":"AAAA,OAAO,4BAA4B,MAAM,2DAA2D,CAAA;AACpG,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAG9D,cAAc,qEAAqE,CAAA;AAEnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,MAAM,UAAU,6BAA6B,CAAC,EAC5C,aAAa,EACb,gCAAgC,EAChC,qBAAqB,EACrB,YAAY,EACZ,UAAU,GAOX;IACC,IAAI,CAAC,aAAa,IAAI,CAAC,qBAAqB,CAAC,MAAM,EAAE,CAAC;QACpD,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,gBAAgB,GAAG;QACvB,iBAAiB,EAAE,mBAAmB,CAAC,YAAY,CAAC;QACpD,KAAK,EAAE,UAAU;KAClB,CAAA;IAED,MAAM,WAAW,GAAG,CAAC,SAA8C,EAAE,EAAE,CACrE,4BAA4B,CAAC;QAC3B,SAAS;QACT,gBAAgB;KACjB,CAAC,CAAA;IACJ,IAAI,gCAAgC,EAAE,CAAC;QACrC,OAAO,qBAAqB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;IACjD,CAAC;SAAM,CAAC;QACN,OAAO,qBAAqB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IAChD,CAAC;AACH,CAAC","sourcesContent":["import evaluateConditionalPredicate from './conditionalLogicService/evaluateConditionalPredicate.js'\nimport { flattenFormElements } from './formElementsService.js'\nimport { ConditionTypes, FormTypes, SubmissionTypes } from '@oneblink/types'\n\nexport * from './conditionalLogicService/generateFormElementsConditionallyShown.js'\n\n/**\n * Given a set of form elements and submission data, evaluate if predicates are\n * met or not.\n *\n * #### Example\n *\n * ```js\n * const evaluation = conditionalLogicService.evaluateConditionalPredicates(\n * {\n * isConditional: true,\n * requiresAllConditionalPredicates: false,\n * conditionalPredicates: [\n * {\n * type: 'OPTIONS',\n * elementId: '3534abe4-b0b5-4ffa-a216-49c223ab6f95',\n * optionIds: ['9ce633dd-22d6-4e0e-a9e0-1aa62d435e72'],\n * },\n * ],\n * submission: {\n * checkboxes: ['a'],\n * },\n * formElements: [\n * {\n * name: 'checkboxes',\n * label: 'Checkboxes',\n * type: 'checkboxes',\n * required: false,\n * id: '3534abe4-b0b5-4ffa-a216-49c223ab6f95',\n * options: [\n * {\n * id: '9ce633dd-22d6-4e0e-a9e0-1aa62d435e72',\n * label: 'First',\n * value: 'a',\n * },\n * {\n * id: '5850b32c-3833-4498-a072-47fcc8122242',\n * label: 'Second',\n * value: 'b',\n * },\n * {\n * id: 'ab363e9f-a63f-4923-ba0d-47892fc26a93',\n * label: 'Third',\n * value: 'c',\n * },\n * ],\n * readOnly: false,\n * buttons: false,\n * optionsType: 'CUSTOM',\n * conditionallyShowOptions: false,\n * isDataLookup: false,\n * isElementLookup: false,\n * conditionallyShow: false,\n * requiresAllConditionallyShowPredicates: false,\n * },\n * ],\n * },\n * )\n * ```\n *\n * @param options\n * @returns\n */\nexport function evaluateConditionalPredicates({\n isConditional,\n requiresAllConditionalPredicates,\n conditionalPredicates,\n formElements,\n submission,\n}: {\n isConditional: boolean\n requiresAllConditionalPredicates: boolean\n conditionalPredicates: ConditionTypes.ConditionalPredicate[]\n formElements: FormTypes.FormElement[]\n submission: SubmissionTypes.S3SubmissionData['submission']\n}): boolean {\n if (!isConditional || !conditionalPredicates.length) {\n return true\n }\n const formElementsCtrl = {\n flattenedElements: flattenFormElements(formElements),\n model: submission,\n }\n\n const predicateFn = (predicate: ConditionTypes.ConditionalPredicate) =>\n evaluateConditionalPredicate({\n predicate,\n formElementsCtrl,\n })\n if (requiresAllConditionalPredicates) {\n return conditionalPredicates.every(predicateFn)\n } else {\n return conditionalPredicates.some(predicateFn)\n }\n}\n"]}
1
+ {"version":3,"file":"conditionalLogicService.js","sourceRoot":"","sources":["../src/conditionalLogicService.ts"],"names":[],"mappings":"AAAA,OAAO,uCAAuC,MAAM,sEAAsE,CAAA;AAC1H,OAAO,+CAA+C,MAAM,8EAA8E,CAAA;AAC1I,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAI9D,cAAc,qEAAqE,CAAA;AAGnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AACH,MAAM,UAAU,6BAA6B,CAAC,EAC5C,aAAa,EACb,gCAAgC,EAChC,qBAAqB,EACrB,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,SAAS,EACT,aAAa,GAad;IACC,IAAI,CAAC,aAAa,IAAI,CAAC,qBAAqB,CAAC,MAAM,EAAE,CAAC;QACpD,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,gBAAgB,GAAG;QACvB,iBAAiB,EAAE,mBAAmB,CAAC,YAAY,CAAC;QACpD,KAAK,EAAE,UAAU;KAClB,CAAA;IAED,MAAM,WAAW,GAAG,CAAC,SAA8C,EAAE,EAAE;QACrE,IAAI,SAAS,CAAC,IAAI,KAAK,sBAAsB,EAAE,CAAC;YAC9C,OAAO,+CAA+C,CAAC;gBACrD,SAAS;gBACT,gBAAgB;gBAChB,mBAAmB;gBACnB,SAAS;gBACT,aAAa;aACd,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,CAAC,CAAC,uCAAuC,CAAC;YAC/C,SAAS;YACT,gBAAgB;SACjB,CAAC,CAAA;IACJ,CAAC,CAAA;IACD,IAAI,gCAAgC,EAAE,CAAC;QACrC,OAAO,qBAAqB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;IACjD,CAAC;SAAM,CAAC;QACN,OAAO,qBAAqB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IAChD,CAAC;AACH,CAAC","sourcesContent":["import evaluateFormElementConditionalPredicate from './conditionalLogicService/evaluateFormElementConditionalPredicate.js'\nimport evaluateConditionalSubmissionTimestampPredicate from './conditionalLogicService/evaluateConditionalSubmissionTimestampPredicate.js'\nimport { flattenFormElements } from './formElementsService.js'\nimport { ConditionTypes, FormTypes, SubmissionTypes } from '@oneblink/types'\nimport { AddOffsetToDate, ParseDate } from './conditionalLogicService/types.js'\n\nexport * from './conditionalLogicService/generateFormElementsConditionallyShown.js'\nexport type { AddOffsetToDate, ParseDate } from './conditionalLogicService/types.js'\n\n/**\n * Given a set of form elements and submission data, evaluate if predicates are\n * met or not.\n *\n * #### Example\n *\n * ```js\n * const evaluation = conditionalLogicService.evaluateConditionalPredicates(\n * {\n * isConditional: true,\n * requiresAllConditionalPredicates: false,\n * conditionalPredicates: [\n * {\n * type: 'OPTIONS',\n * elementId: '3534abe4-b0b5-4ffa-a216-49c223ab6f95',\n * optionIds: ['9ce633dd-22d6-4e0e-a9e0-1aa62d435e72'],\n * },\n * ],\n * submission: {\n * checkboxes: ['a'],\n * },\n * formElements: [\n * {\n * name: 'checkboxes',\n * label: 'Checkboxes',\n * type: 'checkboxes',\n * required: false,\n * id: '3534abe4-b0b5-4ffa-a216-49c223ab6f95',\n * options: [\n * {\n * id: '9ce633dd-22d6-4e0e-a9e0-1aa62d435e72',\n * label: 'First',\n * value: 'a',\n * },\n * {\n * id: '5850b32c-3833-4498-a072-47fcc8122242',\n * label: 'Second',\n * value: 'b',\n * },\n * {\n * id: 'ab363e9f-a63f-4923-ba0d-47892fc26a93',\n * label: 'Third',\n * value: 'c',\n * },\n * ],\n * readOnly: false,\n * buttons: false,\n * optionsType: 'CUSTOM',\n * conditionallyShowOptions: false,\n * isDataLookup: false,\n * isElementLookup: false,\n * conditionallyShow: false,\n * requiresAllConditionallyShowPredicates: false,\n * },\n * ],\n * submissionTimestamp: new Date().toISOString(),\n * parseDate: (value) => new Date(value),\n * addDaysToDate: (date, days) => {\n * date.setUTCDate(date.getUTCDate() + days)\n * return date\n * },\n * },\n * )\n * ```\n *\n * @param options\n * @returns\n */\nexport function evaluateConditionalPredicates({\n isConditional,\n requiresAllConditionalPredicates,\n conditionalPredicates,\n formElements,\n submission,\n submissionTimestamp,\n parseDate,\n addDaysToDate,\n}: {\n isConditional: boolean\n requiresAllConditionalPredicates: boolean\n conditionalPredicates: ConditionTypes.ConditionalPredicate[]\n formElements: FormTypes.FormElement[]\n submission: SubmissionTypes.S3SubmissionData['submission']\n /** ISO timestamp the form was submitted. When evaluating during submission, pass `new Date().toISOString()`. */\n submissionTimestamp: string\n /** Parse date/datetime strings when evaluating date based predicates */\n parseDate: ParseDate\n /** Add days to a date when evaluating date based predicates */\n addDaysToDate: AddOffsetToDate\n}): boolean {\n if (!isConditional || !conditionalPredicates.length) {\n return true\n }\n const formElementsCtrl = {\n flattenedElements: flattenFormElements(formElements),\n model: submission,\n }\n\n const predicateFn = (predicate: ConditionTypes.ConditionalPredicate) => {\n if (predicate.type === 'SUBMISSION_TIMESTAMP') {\n return evaluateConditionalSubmissionTimestampPredicate({\n predicate,\n formElementsCtrl,\n submissionTimestamp,\n parseDate,\n addDaysToDate,\n })\n }\n\n return !!evaluateFormElementConditionalPredicate({\n predicate,\n formElementsCtrl,\n })\n }\n if (requiresAllConditionalPredicates) {\n return conditionalPredicates.every(predicateFn)\n } else {\n return conditionalPredicates.some(predicateFn)\n }\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { FormTypes, SubmissionEventTypes, SubmissionTypes } from '@oneblink/types';
2
2
  import { ReplaceInjectablesFormatters } from './submissionService.js';
3
+ import { AddOffsetToDate, ParseDate } from './conditionalLogicService/types.js';
3
4
  /**
4
5
  * Examine a submission and its form definition to validate whether a payment
5
6
  * workflow event needs to run.
@@ -7,14 +8,31 @@ import { ReplaceInjectablesFormatters } from './submissionService.js';
7
8
  * #### Example
8
9
  *
9
10
  * ```js
10
- * const result = paymentService.checkForPaymentEvent(form, submission)
11
+ * const result = paymentService.checkForPaymentEvent({
12
+ * definition: form,
13
+ * submission,
14
+ * submissionTimestamp,
15
+ * parseDate: (value) => new Date(value),
16
+ * addDaysToDate: (date, days) => {
17
+ * date.setUTCDate(date.getUTCDate() + days)
18
+ * return date
19
+ * },
20
+ * })
11
21
  * ```
12
22
  *
13
- * @param definition
14
- * @param submission
23
+ * @param options
15
24
  * @returns
16
25
  */
17
- export declare function checkForPaymentEvent(definition: FormTypes.Form, submission: SubmissionTypes.S3SubmissionData['submission']): {
26
+ export declare function checkForPaymentEvent({ definition, submission, submissionTimestamp, parseDate, addDaysToDate, }: {
27
+ definition: FormTypes.Form;
28
+ submission: SubmissionTypes.S3SubmissionData['submission'];
29
+ /** ISO timestamp the form was submitted. When evaluating during submission, pass `new Date().toISOString()`. */
30
+ submissionTimestamp: string;
31
+ /** Parse date/datetime strings when evaluating date based predicates */
32
+ parseDate: ParseDate;
33
+ /** Add days to a date when evaluating date based predicates */
34
+ addDaysToDate: AddOffsetToDate;
35
+ }): {
18
36
  paymentSubmissionEvent: SubmissionEventTypes.FormPaymentEvent;
19
37
  amount: number;
20
38
  } | undefined;
@@ -7,14 +7,22 @@ import { getRootElementValueById, } from './submissionService.js';
7
7
  * #### Example
8
8
  *
9
9
  * ```js
10
- * const result = paymentService.checkForPaymentEvent(form, submission)
10
+ * const result = paymentService.checkForPaymentEvent({
11
+ * definition: form,
12
+ * submission,
13
+ * submissionTimestamp,
14
+ * parseDate: (value) => new Date(value),
15
+ * addDaysToDate: (date, days) => {
16
+ * date.setUTCDate(date.getUTCDate() + days)
17
+ * return date
18
+ * },
19
+ * })
11
20
  * ```
12
21
  *
13
- * @param definition
14
- * @param submission
22
+ * @param options
15
23
  * @returns
16
24
  */
17
- export function checkForPaymentEvent(definition, submission) {
25
+ export function checkForPaymentEvent({ definition, submission, submissionTimestamp, parseDate, addDaysToDate, }) {
18
26
  const paymentSubmissionEvents = definition.paymentEvents || [];
19
27
  const paymentSubmissionEvent = paymentSubmissionEvents.find((paymentSubmissionEvent) => {
20
28
  return (paymentSubmissionEvent &&
@@ -24,6 +32,9 @@ export function checkForPaymentEvent(definition, submission) {
24
32
  conditionalPredicates: paymentSubmissionEvent.conditionallyExecutePredicates || [],
25
33
  submission: submission,
26
34
  formElements: definition.elements,
35
+ submissionTimestamp,
36
+ parseDate,
37
+ addDaysToDate,
27
38
  }));
28
39
  });
29
40
  if (!paymentSubmissionEvent) {