ngx-t-forms-types 0.0.24 → 0.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/interfaces/FormBuilder/elementEditor.d.ts +3 -1
- package/dist/interfaces/FormBuilder/elementEditor.js +2 -0
- package/dist/interfaces/FormBuilder/inputConfig/ElementEditConfig.js +280 -77
- package/dist/interfaces/FormBuilder/workflowSelectionConfig.d.ts +27 -0
- package/dist/interfaces/environment/IStoreFunctions.d.ts +24 -9
- package/dist/interfaces/formInput/APIDataFetchingConfigurationInterface.d.ts +85 -1
- package/dist/interfaces/formInput/WorkflowDocumentPicker.d.ts +184 -3
- package/dist/interfaces/formInput/WorkflowDocumentPicker.js +17 -0
- package/dist/interfaces/formInput/index.d.ts +4 -4
- package/dist/interfaces/formInput/index.js +2 -2
- package/dist/schemas/DocmentPickerInputSchema.d.ts +3 -1
- package/dist/schemas/DocmentPickerInputSchema.js +33 -5
- package/dist/schemas/MatOptionsSchema.js +10 -1
- package/package.json +1 -1
|
@@ -36,7 +36,9 @@ export declare enum ElementEditorTypes {
|
|
|
36
36
|
DecisionGateSettings = "decisionGateSettings",
|
|
37
37
|
RecordListManager = "recordListManager",
|
|
38
38
|
MapMatOptionsKeys = "mapMatOptionsKeys",
|
|
39
|
-
FormPayloadProjection = "formPayloadProjection"
|
|
39
|
+
FormPayloadProjection = "formPayloadProjection",
|
|
40
|
+
/** Opt-in JSON body template ({@link PayloadTemplate}) for a POST value/options fetch. */
|
|
41
|
+
PayloadTemplate = "payloadTemplate"
|
|
40
42
|
}
|
|
41
43
|
export interface ElementEditorConfigInterface {
|
|
42
44
|
editorSections: Array<ElementEditorConfigSectionInterface>;
|
|
@@ -31,6 +31,8 @@ export var ElementEditorTypes;
|
|
|
31
31
|
ElementEditorTypes["RecordListManager"] = "recordListManager";
|
|
32
32
|
ElementEditorTypes["MapMatOptionsKeys"] = "mapMatOptionsKeys";
|
|
33
33
|
ElementEditorTypes["FormPayloadProjection"] = "formPayloadProjection";
|
|
34
|
+
/** Opt-in JSON body template ({@link PayloadTemplate}) for a POST value/options fetch. */
|
|
35
|
+
ElementEditorTypes["PayloadTemplate"] = "payloadTemplate";
|
|
34
36
|
})(ElementEditorTypes || (ElementEditorTypes = {}));
|
|
35
37
|
// interface TStringExpressionValidationTest{
|
|
36
38
|
// expression: string;
|
|
@@ -10,6 +10,159 @@ import { RichTextEditorType } from "../../formInput/RichTextEditorInput.js";
|
|
|
10
10
|
import { LabelPosition } from "../../formInput/ToggleInputInterface.js";
|
|
11
11
|
import { AllFormInputPrimaryKeys, SpecialElementKeys } from "../FormInputKeys.js";
|
|
12
12
|
import { BlurHandleTypes, ElementEditorTypes } from "../elementEditor.js";
|
|
13
|
+
import { DOCUMENT_PICKER_FILTER_OPERATORS, DOCUMENT_PICKER_FILTER_VALUE_SOURCES, DOCUMENT_PICKER_FILTER_VALUE_TYPES } from "../../formInput/WorkflowDocumentPicker.js";
|
|
14
|
+
/** Human-facing names for the document-picker filter operators. */
|
|
15
|
+
const DOCUMENT_PICKER_FILTER_OPERATOR_LABELS = {
|
|
16
|
+
eq: 'Is',
|
|
17
|
+
ne: 'Is not',
|
|
18
|
+
in: 'Is any of',
|
|
19
|
+
nin: 'Is none of',
|
|
20
|
+
gt: 'Greater than',
|
|
21
|
+
gte: 'Greater than or equal to',
|
|
22
|
+
lt: 'Less than',
|
|
23
|
+
lte: 'Less than or equal to',
|
|
24
|
+
regex: 'Contains',
|
|
25
|
+
exists: 'Has a value',
|
|
26
|
+
};
|
|
27
|
+
/** Human-facing names for the two mutually exclusive filter value sources. */
|
|
28
|
+
const DOCUMENT_PICKER_FILTER_VALUE_SOURCE_LABELS = {
|
|
29
|
+
fixed: 'Fixed value',
|
|
30
|
+
input: 'From another input',
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Shows a row only while the filter is NOT input-bound.
|
|
34
|
+
*
|
|
35
|
+
* Deliberately written as `!== input` rather than `=== fixed`: `valueSource` is
|
|
36
|
+
* absent on every filter saved before the switch existed and on a brand-new
|
|
37
|
+
* record, and `testAgainstItem` resolves an absent deep-bound key to `undefined`.
|
|
38
|
+
* `undefined !== 'input'` is true, so the fixed-value rows stay visible for those
|
|
39
|
+
* records instead of silently becoming uneditable.
|
|
40
|
+
*/
|
|
41
|
+
const DOCUMENT_PICKER_FILTER_IS_FIXED_TEST = `valueSource !== input`;
|
|
42
|
+
/** Shows a row only once the administrator has explicitly chosen the input source. */
|
|
43
|
+
const DOCUMENT_PICKER_FILTER_IS_INPUT_TEST = `valueSource === input`;
|
|
44
|
+
/**
|
|
45
|
+
* Per-record editor for one preset filter (`IDocumentPickerFilter`) inside the
|
|
46
|
+
* document picker's "Preset filters" list.
|
|
47
|
+
*/
|
|
48
|
+
const DOCUMENT_PICKER_FILTER_EDITOR = () => [
|
|
49
|
+
{
|
|
50
|
+
label: 'Filter',
|
|
51
|
+
id: "0f0a5c1e-1d3b-4a76-9e2c-6b8f4a91d0c7",
|
|
52
|
+
elements: [
|
|
53
|
+
{
|
|
54
|
+
name: SpecialElementKeys.Default,
|
|
55
|
+
deepBind: ['path'],
|
|
56
|
+
editType: ElementEditorTypes.Input,
|
|
57
|
+
label: 'Field',
|
|
58
|
+
required: true,
|
|
59
|
+
placeholder: 'form.status',
|
|
60
|
+
hint: `The document field to filter on. Form fields are written as form.<field name>; reference, status and archive live on the document itself.`,
|
|
61
|
+
id: "5c9d2f70-8e41-4b0a-9d63-2a7c5e18b4f2"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: SpecialElementKeys.Default,
|
|
65
|
+
deepBind: ['op'],
|
|
66
|
+
editType: ElementEditorTypes.ChipSelect,
|
|
67
|
+
label: 'Operator',
|
|
68
|
+
defaultValue: 'eq',
|
|
69
|
+
options: DOCUMENT_PICKER_FILTER_OPERATORS.map((op) => ({
|
|
70
|
+
label: DOCUMENT_PICKER_FILTER_OPERATOR_LABELS[op],
|
|
71
|
+
value: op,
|
|
72
|
+
})),
|
|
73
|
+
id: "b1e74a63-0c95-4d8e-8f27-3d6a9c02e5b8"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: SpecialElementKeys.Default,
|
|
77
|
+
deepBind: ['valueSource'],
|
|
78
|
+
editType: ElementEditorTypes.ChipSelect,
|
|
79
|
+
label: 'Where the value comes from',
|
|
80
|
+
hint: `A filter compares against one value only. Pick a fixed value you type here, or follow an input the user fills in earlier on this form.`,
|
|
81
|
+
options: DOCUMENT_PICKER_FILTER_VALUE_SOURCES.map((source) => ({
|
|
82
|
+
label: DOCUMENT_PICKER_FILTER_VALUE_SOURCE_LABELS[source],
|
|
83
|
+
value: source,
|
|
84
|
+
})),
|
|
85
|
+
// NO defaultValue. The nested editor emits `defaultValue` on init when the
|
|
86
|
+
// bound key is absent, which would stamp `fixed` onto every filter saved
|
|
87
|
+
// before this switch existed — silently converting an input-bound filter
|
|
88
|
+
// the moment an administrator merely opened it. The two `additionalTest`
|
|
89
|
+
// expressions below tolerate an absent `valueSource` on their own instead.
|
|
90
|
+
//
|
|
91
|
+
// `clearOnChange` drops the input-bound side, so switching to a fixed value
|
|
92
|
+
// can never leave a live binding behind. It is deliberately one-sided: the
|
|
93
|
+
// fixed `value` is NOT listed, because a leftover `value` under the input
|
|
94
|
+
// source is hidden here and ignored by `buildDocumentFilter`, whereas
|
|
95
|
+
// clearing it would throw away typed work every time the source is toggled.
|
|
96
|
+
// RecordListManager applies these paths only when `valueSource` moves away
|
|
97
|
+
// from a value the record already held, so opening a filter saved before
|
|
98
|
+
// this switch existed never clears anything.
|
|
99
|
+
clearOnChange: [
|
|
100
|
+
['fromInputId'],
|
|
101
|
+
['omitWhenEmpty'],
|
|
102
|
+
],
|
|
103
|
+
id: "2f6b8d04-91c7-4a5e-b3f0-7d2e6a148c15",
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: SpecialElementKeys.Default,
|
|
107
|
+
deepBind: ['fromInputId'],
|
|
108
|
+
editType: ElementEditorTypes.FormInputSelector,
|
|
109
|
+
label: 'Take the value from another input',
|
|
110
|
+
hint: `The filter follows that input's current value — use it to show only transactions matching something the user picked earlier in this form.`,
|
|
111
|
+
additionalTest: [
|
|
112
|
+
{
|
|
113
|
+
expression: DOCUMENT_PICKER_FILTER_IS_INPUT_TEST,
|
|
114
|
+
deepBind: ['valueSource'],
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
id: "7a3f8d21-4b60-4e19-a5c8-91d4e7f36b0a"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: SpecialElementKeys.Default,
|
|
121
|
+
deepBind: ['omitWhenEmpty'],
|
|
122
|
+
editType: ElementEditorTypes.Toggle,
|
|
123
|
+
label: 'Ignore this filter when the value is empty',
|
|
124
|
+
hint: `On: the filter is skipped until that input has a value. Off: an empty value is filtered on literally.`,
|
|
125
|
+
additionalTest: [
|
|
126
|
+
{
|
|
127
|
+
expression: DOCUMENT_PICKER_FILTER_IS_INPUT_TEST,
|
|
128
|
+
deepBind: ['valueSource'],
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
id: "9b52c7e3-6d81-40af-a7c9-4e13b805d6f2"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: SpecialElementKeys.Default,
|
|
135
|
+
deepBind: ['value'],
|
|
136
|
+
editType: ElementEditorTypes.Input,
|
|
137
|
+
label: 'Fixed value',
|
|
138
|
+
hint: `For "Is any of" / "Is none of", separate values with commas.`,
|
|
139
|
+
additionalTest: [
|
|
140
|
+
{
|
|
141
|
+
expression: DOCUMENT_PICKER_FILTER_IS_FIXED_TEST,
|
|
142
|
+
deepBind: ['valueSource'],
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
id: "e6c05b94-2f78-4a3d-b1e5-8c07f9a24d63"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: SpecialElementKeys.Default,
|
|
149
|
+
deepBind: ['valueType'],
|
|
150
|
+
editType: ElementEditorTypes.ChipSelect,
|
|
151
|
+
label: 'Value type',
|
|
152
|
+
defaultValue: 'string',
|
|
153
|
+
hint: `How the fixed value is read. Pick Number or Boolean when the stored field is not text, otherwise the comparison never matches.`,
|
|
154
|
+
options: DOCUMENT_PICKER_FILTER_VALUE_TYPES.map((type) => ({ label: type, value: type })),
|
|
155
|
+
additionalTest: [
|
|
156
|
+
{
|
|
157
|
+
expression: DOCUMENT_PICKER_FILTER_IS_FIXED_TEST,
|
|
158
|
+
deepBind: ['valueSource'],
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
id: "3d8b1e07-9a24-4c65-8f0b-52e7a6c91f4d"
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
},
|
|
165
|
+
];
|
|
13
166
|
export var ElementConfig = {
|
|
14
167
|
editorSections: [
|
|
15
168
|
{
|
|
@@ -424,8 +577,13 @@ export var ElementConfig = {
|
|
|
424
577
|
name: AllFormInputPrimaryKeys.WorkflowPickerConfig,
|
|
425
578
|
deepBind: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'primaryIdentifierKey'],
|
|
426
579
|
label: "Select primary identifier key",
|
|
427
|
-
hint: "Choose a key other than _id to
|
|
580
|
+
hint: "Choose a key other than _id to identify the selected transaction. Leave it unset to use _id.",
|
|
428
581
|
editType: ElementEditorTypes.MapMatOptionsKeys,
|
|
582
|
+
// The key tree is built from `sampleDocument`. This row must NOT clear it:
|
|
583
|
+
// `clearOnChange` runs on every emission from this editor, so clearing the
|
|
584
|
+
// sample here wiped the tree the moment a key was picked — the options
|
|
585
|
+
// appeared, then vanished on first click. The sample is owned by the
|
|
586
|
+
// workflow selection above and is refreshed whenever the workflow changes.
|
|
429
587
|
fetchOptions: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'sampleDocument'],
|
|
430
588
|
additionalTest: [
|
|
431
589
|
{
|
|
@@ -433,98 +591,43 @@ export var ElementConfig = {
|
|
|
433
591
|
testType: 'exists',
|
|
434
592
|
}
|
|
435
593
|
],
|
|
436
|
-
clearOnChange: [
|
|
437
|
-
[AllFormInputPrimaryKeys.WorkflowPickerConfig, 'sampleDocument'],
|
|
438
|
-
],
|
|
439
594
|
id: "c9396a58-1d72-4ef9-8eff-5a28e8f738a1"
|
|
440
595
|
},
|
|
441
596
|
{
|
|
442
597
|
name: AllFormInputPrimaryKeys.WorkflowPickerConfig,
|
|
443
|
-
deepBind: [AllFormInputPrimaryKeys.WorkflowPickerConfig, '
|
|
444
|
-
hint: `Choose the source type for document options: 'Postman API' fetches from an external API, 'Data Pipeline' pulls from MongoDB.`,
|
|
598
|
+
deepBind: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'stepFilter', 'stepIds'],
|
|
445
599
|
editType: ElementEditorTypes.ChipSelect,
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
],
|
|
451
|
-
options: [
|
|
452
|
-
{
|
|
453
|
-
label: 'Default',
|
|
454
|
-
value: 'default'
|
|
455
|
-
},
|
|
456
|
-
{ label: 'Postman API', value: DataSources.Api },
|
|
457
|
-
// { label: 'Data Pipeline', value: DataSources.MongoDb },
|
|
458
|
-
],
|
|
459
|
-
id: "f04cc297-9b22-403a-afe4-4fb2e84fa503"
|
|
460
|
-
},
|
|
461
|
-
{
|
|
462
|
-
name: AllFormInputPrimaryKeys.WorkflowPickerConfig,
|
|
463
|
-
deepBind: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'documentsSource'],
|
|
464
|
-
editType: ElementEditorTypes.ApiCall,
|
|
600
|
+
multipleSelection: true,
|
|
601
|
+
label: 'Limit to workflow steps',
|
|
602
|
+
hint: `Optional. Restricts the picker to transactions currently sitting on the selected steps. Leave empty to let the user choose a step while browsing.`,
|
|
603
|
+
fetchOptions: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'availableSteps'],
|
|
465
604
|
additionalTest: [
|
|
466
605
|
{
|
|
467
|
-
|
|
468
|
-
deepBind: [AllFormInputPrimaryKeys.WorkflowPickerConfig, '
|
|
606
|
+
testType: 'exists',
|
|
607
|
+
deepBind: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'workflowId'],
|
|
469
608
|
},
|
|
470
609
|
],
|
|
471
|
-
|
|
472
|
-
[AllFormInputPrimaryKeys.WorkflowPickerConfig, 'documentsSource'],
|
|
473
|
-
],
|
|
474
|
-
hint: `Select an API endpoint from your Postman collection to fetch document options. Configure headers, payload format, and response mapping as needed.`,
|
|
475
|
-
label: 'Select doc option API endpoint',
|
|
476
|
-
id: "ecb1ea0e-3d2d-447f-a68e-48f1378fc0a7"
|
|
610
|
+
id: "f04cc297-9b22-403a-afe4-4fb2e84fa503"
|
|
477
611
|
},
|
|
478
612
|
{
|
|
479
613
|
name: AllFormInputPrimaryKeys.WorkflowPickerConfig,
|
|
480
|
-
deepBind: [
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
614
|
+
deepBind: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'presetFilters'],
|
|
615
|
+
editType: ElementEditorTypes.RecordListManager,
|
|
616
|
+
label: 'Preset filters',
|
|
617
|
+
hint: `Optional. Narrows the transactions a user can pick from, before they search. Each filter targets a document field: form fields are written as form.<field name>, and the document itself exposes reference, status and archive.`,
|
|
618
|
+
secondaryElementEditorConfig: DOCUMENT_PICKER_FILTER_EDITOR(),
|
|
619
|
+
options: [
|
|
620
|
+
{ label: 'Field', value: 'path' },
|
|
621
|
+
{ label: 'Operator', value: 'op' },
|
|
622
|
+
{ label: 'Value', value: 'value' },
|
|
484
623
|
],
|
|
485
624
|
additionalTest: [
|
|
486
625
|
{
|
|
487
626
|
testType: 'exists',
|
|
488
|
-
deepBind: [
|
|
489
|
-
AllFormInputPrimaryKeys.WorkflowPickerConfig, 'documentsSource',
|
|
490
|
-
'backEndConfig',
|
|
491
|
-
'minimumInputRequired',
|
|
492
|
-
],
|
|
493
|
-
}
|
|
494
|
-
],
|
|
495
|
-
hint: `These are payload fields that are required to be filled in order to fetch data from the selected source`,
|
|
496
|
-
editType: ElementEditorTypes.RequiredInputs,
|
|
497
|
-
label: 'Set up required inputs',
|
|
498
|
-
id: "c1e79e55-18b7-4c4c-8b16-5f792f34e0be"
|
|
499
|
-
},
|
|
500
|
-
{
|
|
501
|
-
name: AllFormInputPrimaryKeys.WorkflowPickerConfig,
|
|
502
|
-
deepBind: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'documentsSource', 'valueAccessRules'],
|
|
503
|
-
hint: `Map the fetched data to the input value. This is useful when the fetched data is an object and you want to map a specific field to the input value.It also allow data transformation before setting the value`,
|
|
504
|
-
fetchOptions: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'documentsSource', '_id'],
|
|
505
|
-
additionalTest: [
|
|
506
|
-
{
|
|
507
|
-
expression: `documentSourceType === ${DataSources.Api}`,
|
|
508
|
-
deepBind: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'documentSourceType'],
|
|
509
|
-
},
|
|
510
|
-
],
|
|
511
|
-
editType: ElementEditorTypes.ApiValueAccessRules,
|
|
512
|
-
label: 'Map value to fetched data',
|
|
513
|
-
id: "9ccb074d-00be-4c90-8989-2309e9faed10"
|
|
514
|
-
},
|
|
515
|
-
{
|
|
516
|
-
name: AllFormInputPrimaryKeys.WorkflowPickerConfig,
|
|
517
|
-
deepBind: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'documentsSource'],
|
|
518
|
-
additionalTest: [
|
|
519
|
-
{
|
|
520
|
-
expression: "documentSourceType === mongoPipeline",
|
|
521
|
-
deepBind: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'documentSourceType'],
|
|
627
|
+
deepBind: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'workflowId'],
|
|
522
628
|
},
|
|
523
629
|
],
|
|
524
|
-
|
|
525
|
-
label: 'Configure MongoDB pipeline',
|
|
526
|
-
hint: `Create a MongoDB aggregation pipeline to fetch document options from your database.`,
|
|
527
|
-
id: "1b826f36-08ad-46b5-86ea-c1c48fd90f51"
|
|
630
|
+
id: "ecb1ea0e-3d2d-447f-a68e-48f1378fc0a7"
|
|
528
631
|
},
|
|
529
632
|
//********************** */
|
|
530
633
|
{
|
|
@@ -745,6 +848,34 @@ export var ElementConfig = {
|
|
|
745
848
|
label: 'Configure MongoDB pipeline',
|
|
746
849
|
id: "7b2989ae-2f54-4849-93d0-aff56ac12ef2"
|
|
747
850
|
},
|
|
851
|
+
{
|
|
852
|
+
name: SpecialElementKeys.Default,
|
|
853
|
+
deepBind: ['matOptions', 'fetch', 'value', 'backEndConfig', 'requestBodyMode'],
|
|
854
|
+
additionalTest: [
|
|
855
|
+
{
|
|
856
|
+
// Only once an API endpoint is configured for the value.
|
|
857
|
+
testType: 'exists',
|
|
858
|
+
deepBind: ['matOptions', 'fetch', 'value'],
|
|
859
|
+
},
|
|
860
|
+
],
|
|
861
|
+
editType: ElementEditorTypes.ChipSelect,
|
|
862
|
+
label: 'Request body configuration',
|
|
863
|
+
hint: 'Choose how the POST body is built: map required inputs, or author a JSON payload template. Only one is used.',
|
|
864
|
+
defaultValue: 'mappedInputs',
|
|
865
|
+
// NO clearOnChange. Both configurations are kept side by side —
|
|
866
|
+
// `requestBodyMode` alone decides which one the runtime uses, and the
|
|
867
|
+
// two editors below are shown/hidden by their `additionalTest`. Clearing
|
|
868
|
+
// here destroyed the author's work on every mode toggle, and — because
|
|
869
|
+
// the editor emits `defaultValue` on init when the bound key is absent —
|
|
870
|
+
// wiped `minimumInputRequired` merely on OPENING an existing POST fetch.
|
|
871
|
+
// A fetch left with no `minimumInputRequired` key then crashed
|
|
872
|
+
// `getAllFunctionTypes`, silently disabling the whole input.
|
|
873
|
+
options: [
|
|
874
|
+
{ label: 'Map inputs', value: 'mappedInputs' },
|
|
875
|
+
{ label: 'JSON template', value: 'template' },
|
|
876
|
+
],
|
|
877
|
+
id: "a1d2f3e4-5b6c-4d7e-8f90-1a2b3c4d5e6f"
|
|
878
|
+
},
|
|
748
879
|
{
|
|
749
880
|
name: SpecialElementKeys.Default,
|
|
750
881
|
deepBind: [
|
|
@@ -764,13 +895,39 @@ export var ElementConfig = {
|
|
|
764
895
|
'backEndConfig',
|
|
765
896
|
'minimumInputRequired',
|
|
766
897
|
],
|
|
767
|
-
}
|
|
898
|
+
},
|
|
899
|
+
{
|
|
900
|
+
// Hidden while the author is using a payload template instead.
|
|
901
|
+
expression: 'requestBodyMode !== template',
|
|
902
|
+
deepBind: ['matOptions', 'fetch', 'value', 'backEndConfig', 'requestBodyMode'],
|
|
903
|
+
},
|
|
768
904
|
],
|
|
769
905
|
hint: `These are payload fields that are required to be filled in order to fetch data from the selected source`,
|
|
770
906
|
editType: ElementEditorTypes.RequiredInputs,
|
|
771
907
|
label: 'Set up required inputs',
|
|
772
908
|
id: "2d0f1e18-897b-4c28-97bc-3078be09f8ee"
|
|
773
909
|
},
|
|
910
|
+
{
|
|
911
|
+
name: SpecialElementKeys.Default,
|
|
912
|
+
deepBind: [
|
|
913
|
+
'matOptions',
|
|
914
|
+
'fetch',
|
|
915
|
+
'value',
|
|
916
|
+
'backEndConfig',
|
|
917
|
+
'payloadTemplate',
|
|
918
|
+
],
|
|
919
|
+
additionalTest: [
|
|
920
|
+
{
|
|
921
|
+
// Shown only when the author has chosen template mode.
|
|
922
|
+
expression: 'requestBodyMode === template',
|
|
923
|
+
deepBind: ['matOptions', 'fetch', 'value', 'backEndConfig', 'requestBodyMode'],
|
|
924
|
+
},
|
|
925
|
+
],
|
|
926
|
+
hint: `Author the POST request body as JSON. Type $ to insert a field as {{inputId}}; every other literal is a fixed default. This supersedes the required-input mapping.`,
|
|
927
|
+
editType: ElementEditorTypes.PayloadTemplate,
|
|
928
|
+
label: 'Payload template',
|
|
929
|
+
id: "b3f6a1c2-7d8e-4a90-8c11-2e5f0a9b7c34"
|
|
930
|
+
},
|
|
774
931
|
{
|
|
775
932
|
name: SpecialElementKeys.Default,
|
|
776
933
|
deepBind: ['matOptions', 'fetch', 'value', 'valueAccessRules'],
|
|
@@ -878,6 +1035,28 @@ export var ElementConfig = {
|
|
|
878
1035
|
label: 'Select API to fetch data from',
|
|
879
1036
|
id: "df9e2a34-7bf5-411e-a265-14ca4f85166d"
|
|
880
1037
|
},
|
|
1038
|
+
{
|
|
1039
|
+
name: SpecialElementKeys.Default,
|
|
1040
|
+
deepBind: ['matOptions', 'fetch', 'options', 'backEndConfig', 'requestBodyMode'],
|
|
1041
|
+
additionalTest: [
|
|
1042
|
+
{
|
|
1043
|
+
testType: 'exists',
|
|
1044
|
+
deepBind: ['matOptions', 'fetch', 'options'],
|
|
1045
|
+
},
|
|
1046
|
+
],
|
|
1047
|
+
editType: ElementEditorTypes.ChipSelect,
|
|
1048
|
+
label: 'Request body configuration',
|
|
1049
|
+
hint: 'Choose how the POST body is built: map required inputs, or author a JSON payload template. Only one is used.',
|
|
1050
|
+
defaultValue: 'mappedInputs',
|
|
1051
|
+
// NO clearOnChange — see the value-slot twin above. This one cleared
|
|
1052
|
+
// ['matOptions','fetch','options'], i.e. the ENTIRE options fetch config
|
|
1053
|
+
// (endpoint, method, source and all), on the editor's init emit.
|
|
1054
|
+
options: [
|
|
1055
|
+
{ label: 'Map required inputs', value: 'mappedInputs' },
|
|
1056
|
+
{ label: 'Payload template (JSON)', value: 'template' },
|
|
1057
|
+
],
|
|
1058
|
+
id: "e2c4a6b8-1d3f-4a5b-9c7e-0f1a2b3c4d5e"
|
|
1059
|
+
},
|
|
881
1060
|
{
|
|
882
1061
|
name: SpecialElementKeys.Default,
|
|
883
1062
|
deepBind: [
|
|
@@ -897,12 +1076,36 @@ export var ElementConfig = {
|
|
|
897
1076
|
'backEndConfig',
|
|
898
1077
|
'minimumInputRequired',
|
|
899
1078
|
],
|
|
900
|
-
}
|
|
1079
|
+
},
|
|
1080
|
+
{
|
|
1081
|
+
expression: 'requestBodyMode !== template',
|
|
1082
|
+
deepBind: ['matOptions', 'fetch', 'options', 'backEndConfig', 'requestBodyMode'],
|
|
1083
|
+
},
|
|
901
1084
|
],
|
|
902
1085
|
editType: ElementEditorTypes.RequiredInputs,
|
|
903
1086
|
label: 'Set up required inputs',
|
|
904
1087
|
id: "ce8f3b42-340d-4f3e-8d6a-13c93251173f"
|
|
905
1088
|
},
|
|
1089
|
+
{
|
|
1090
|
+
name: SpecialElementKeys.Default,
|
|
1091
|
+
deepBind: [
|
|
1092
|
+
'matOptions',
|
|
1093
|
+
'fetch',
|
|
1094
|
+
'options',
|
|
1095
|
+
'backEndConfig',
|
|
1096
|
+
'payloadTemplate',
|
|
1097
|
+
],
|
|
1098
|
+
additionalTest: [
|
|
1099
|
+
{
|
|
1100
|
+
expression: 'requestBodyMode === template',
|
|
1101
|
+
deepBind: ['matOptions', 'fetch', 'options', 'backEndConfig', 'requestBodyMode'],
|
|
1102
|
+
},
|
|
1103
|
+
],
|
|
1104
|
+
hint: `Author the POST request body as JSON. Type $ to insert a field as {{inputId}}; every other literal is a fixed default. This supersedes the required-input mapping.`,
|
|
1105
|
+
editType: ElementEditorTypes.PayloadTemplate,
|
|
1106
|
+
label: 'Payload template',
|
|
1107
|
+
id: "c7a2e4d1-9b0f-4e63-a5d8-71f3b2c6e089"
|
|
1108
|
+
},
|
|
906
1109
|
{
|
|
907
1110
|
name: SpecialElementKeys.Default,
|
|
908
1111
|
deepBind: ['matOptions', 'fetch', 'options', 'valueAccessRules'],
|
|
@@ -8,8 +8,35 @@ export interface IWorkflowOption {
|
|
|
8
8
|
isDocument: boolean;
|
|
9
9
|
id: string;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* A column of the workflow's transaction list, as configured on the workflow itself.
|
|
13
|
+
*
|
|
14
|
+
* `formControlName` names the form field; `path` is where that field actually lives
|
|
15
|
+
* in the stored document and is what sorting and searching must address — a form
|
|
16
|
+
* field sorted by its bare control name silently sorts on a non-existent root field.
|
|
17
|
+
*/
|
|
11
18
|
export interface IWorkflowDocListCols {
|
|
12
19
|
label: string;
|
|
13
20
|
formControlName: string;
|
|
14
21
|
type?: DocumentLitsLabelConfigInterfaceValueType | InputDataTypes | undefined | InputPipeTypes;
|
|
22
|
+
/**
|
|
23
|
+
* Where the column's value actually lives in the stored document — `form.amount`
|
|
24
|
+
* for a form field, or a root field such as `reference`. Sorting and searching
|
|
25
|
+
* address this path: a form field addressed by its bare control name resolves to
|
|
26
|
+
* a non-existent root field and silently returns unordered, unsearched results.
|
|
27
|
+
*/
|
|
28
|
+
path: string;
|
|
29
|
+
/** `true` when the workflow marks the column hidden from its transaction list. */
|
|
30
|
+
hidden: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** A step of a workflow, as offered to a user filtering transactions by step. */
|
|
33
|
+
export interface IWorkflowStepOption {
|
|
34
|
+
/** Matches the transaction's `currentStepID`. */
|
|
35
|
+
stepId: string;
|
|
36
|
+
/** Human-facing step name. */
|
|
37
|
+
label: string;
|
|
38
|
+
/** Zero-based position in the workflow's process tree. */
|
|
39
|
+
index: number;
|
|
40
|
+
/** Step kind, e.g. `initiate`, `review`, `edit`. */
|
|
41
|
+
stepType?: string;
|
|
15
42
|
}
|
|
@@ -4,7 +4,8 @@ import { IWorkflowOption } from "../FormBuilder/index.js";
|
|
|
4
4
|
import { AccountingBasis, AdjResponseReviewColumnMapping, IGetTreeResponse, ScoaSegmentValue, WorkflowAdjudicationScoreSheetValue } from "../formInput/index.js";
|
|
5
5
|
import { FormListSection } from "../Form/IFormsInitStateInterface.js";
|
|
6
6
|
import { IUserSignature, PointGroup } from "../formInput/userSignature.js";
|
|
7
|
-
import { IWorkflowDocListCols } from "../FormBuilder/workflowSelectionConfig.js";
|
|
7
|
+
import { IWorkflowDocListCols, IWorkflowStepOption } from "../FormBuilder/workflowSelectionConfig.js";
|
|
8
|
+
import { IDocumentPage, IDocumentQueryRequest } from "../formInput/WorkflowDocumentPicker.js";
|
|
8
9
|
import { IFinancialCycles } from "./environment.js";
|
|
9
10
|
export interface DialogConfig {
|
|
10
11
|
title: string;
|
|
@@ -68,14 +69,28 @@ export interface IStoreFunctions {
|
|
|
68
69
|
results: any;
|
|
69
70
|
message: string;
|
|
70
71
|
}>;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
/**
|
|
73
|
+
* The single query used by every document picker. One request carries paging,
|
|
74
|
+
* sorting, filtering and search, and one page comes back.
|
|
75
|
+
*
|
|
76
|
+
* Paging is keyset-based: omit `cursor` for the first page, then pass the
|
|
77
|
+
* previous page's `nextCursor`. `sort` must stay identical for the life of a
|
|
78
|
+
* cursor sequence — a changed sort invalidates outstanding cursors, so reset
|
|
79
|
+
* paging whenever the sort, filter or search term changes.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* queryDocuments({
|
|
83
|
+
* workflowId,
|
|
84
|
+
* itemsPerPage: 10,
|
|
85
|
+
* sort: { updatedAt: -1 },
|
|
86
|
+
* filter: { archive: false, currentStep: stepId },
|
|
87
|
+
* searchKey: 'chairs',
|
|
88
|
+
* schema: { reference: 'string', 'form.description': 'string' },
|
|
89
|
+
* })
|
|
90
|
+
*/
|
|
91
|
+
queryDocuments: (request: IDocumentQueryRequest) => Observable<IDocumentPage>;
|
|
92
|
+
/** Steps of a workflow, in process-tree order, for the picker's step filter. */
|
|
93
|
+
getWorkflowSteps: (workflowId: string) => Observable<IWorkflowStepOption[]>;
|
|
79
94
|
fileUpload: FileUploadFn;
|
|
80
95
|
formSubmittedSuccessfully: (formId: string) => void;
|
|
81
96
|
getUserSignature: () => Observable<IUserSignature>;
|
|
@@ -12,6 +12,59 @@ export interface DataFetchingBaseConfig {
|
|
|
12
12
|
source: DataSources;
|
|
13
13
|
projectFormData?: string;
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* A single node in a {@link PayloadTemplate}.
|
|
17
|
+
*
|
|
18
|
+
* - Literals (`string`/`number`/`boolean`/`null`) are sent verbatim — a plain
|
|
19
|
+
* literal is a **typed default**.
|
|
20
|
+
* - A string that is EXACTLY `"{{inputId}}"` is replaced by that input's live,
|
|
21
|
+
* raw (type-preserving) value.
|
|
22
|
+
* - A string that merely CONTAINS `{{inputId}}` token(s) is interpolated to a
|
|
23
|
+
* string (`"prefix-{{x}}"`).
|
|
24
|
+
* - Objects and arrays nest arbitrarily; object keys are literal, so Mongo-style
|
|
25
|
+
* dotted keys such as `"form.contractType"` are preserved as authored.
|
|
26
|
+
*/
|
|
27
|
+
export type PayloadTemplateValue = string | number | boolean | null | PayloadTemplateValue[] | {
|
|
28
|
+
[key: string]: PayloadTemplateValue;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Declarative JSON body for a POST value/options fetch.
|
|
32
|
+
*
|
|
33
|
+
* When present on {@link APIDataFetchingConfigurationInterface.backEndConfig} it
|
|
34
|
+
* SUPERSEDES `minimumInputRequired` for request shaping: the resolved object is
|
|
35
|
+
* sent to the endpoint verbatim (no `data` envelope). `{{inputId}}` string
|
|
36
|
+
* tokens map to live form values; every other literal is a typed default. The
|
|
37
|
+
* fetch stays idle (fires no request) until every referenced input has a
|
|
38
|
+
* non-empty value, then re-fires whenever a mapped value changes.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* payloadTemplate: {
|
|
42
|
+
* workflowId: '65035743e948659eff7f6b5f',
|
|
43
|
+
* valueKey: 'budgetCost',
|
|
44
|
+
* reduce: 'sum',
|
|
45
|
+
* isComplete: true,
|
|
46
|
+
* filter: {
|
|
47
|
+
* archive: false,
|
|
48
|
+
* 'form.contractType': '{{contractType}}',
|
|
49
|
+
* },
|
|
50
|
+
* }
|
|
51
|
+
*/
|
|
52
|
+
export type PayloadTemplate = {
|
|
53
|
+
[key: string]: PayloadTemplateValue;
|
|
54
|
+
} | PayloadTemplateValue[];
|
|
55
|
+
/**
|
|
56
|
+
* Which mechanism shapes a POST fetch's request body.
|
|
57
|
+
*
|
|
58
|
+
* - `'mappedInputs'` — the classic `minimumInputRequired` default/mapTo mapping
|
|
59
|
+
* (also the effective default when unset, for backward compatibility).
|
|
60
|
+
* - `'template'` — the declarative {@link PayloadTemplate}.
|
|
61
|
+
*
|
|
62
|
+
* The two are mutually exclusive in the form builder (one editor at a time) and
|
|
63
|
+
* at runtime: a `payloadTemplate` supersedes the mapping ONLY when the mode is
|
|
64
|
+
* not explicitly `'mappedInputs'`, so switching modes never discards either
|
|
65
|
+
* configuration.
|
|
66
|
+
*/
|
|
67
|
+
export type RequestBodyMode = 'mappedInputs' | 'template';
|
|
15
68
|
export interface APIDataFetchingConfigurationInterface extends DataFetchingBaseConfig {
|
|
16
69
|
_id: string;
|
|
17
70
|
name: string;
|
|
@@ -37,7 +90,38 @@ export interface APIDataFetchingConfigurationInterface extends DataFetchingBaseC
|
|
|
37
90
|
} | boolean;
|
|
38
91
|
};
|
|
39
92
|
backEndConfig: {
|
|
40
|
-
|
|
93
|
+
/**
|
|
94
|
+
* The default/mapTo mapping that shapes the POST body in `'mappedInputs'` mode.
|
|
95
|
+
*
|
|
96
|
+
* **Optional**, and genuinely absent in practice: a `'template'`-mode fetch shapes
|
|
97
|
+
* its body from {@link payloadTemplate} and needs no mapping at all, GET fetches
|
|
98
|
+
* never had one, and older persisted configs predate the key. Read it as
|
|
99
|
+
* `backEndConfig?.minimumInputRequired ?? []` — a bare
|
|
100
|
+
* `.minimumInputRequired.every(…)` once threw inside `getAllFunctionTypes`, whose
|
|
101
|
+
* `catch` then erased *every* function type for the input, silently disabling its
|
|
102
|
+
* resource, refresh button, calculation and validators.
|
|
103
|
+
*/
|
|
104
|
+
minimumInputRequired?: MinimumInputRequiredInterface[];
|
|
105
|
+
/**
|
|
106
|
+
* Which request-body mechanism is active (see {@link RequestBodyMode}).
|
|
107
|
+
* Unset is treated as `'mappedInputs'` for backward compatibility. The form
|
|
108
|
+
* builder shows exactly one editor per mode; the runtime uses
|
|
109
|
+
* `payloadTemplate` only when this is not `'mappedInputs'`.
|
|
110
|
+
*/
|
|
111
|
+
requestBodyMode?: RequestBodyMode;
|
|
112
|
+
/**
|
|
113
|
+
* Optional deep JSON template for the POST body (see {@link PayloadTemplate}).
|
|
114
|
+
* When present AND {@link requestBodyMode} is not `'mappedInputs'`, it
|
|
115
|
+
* supersedes `minimumInputRequired` for request shaping. Kept independently of
|
|
116
|
+
* the mapping so toggling {@link requestBodyMode} discards neither.
|
|
117
|
+
*/
|
|
118
|
+
payloadTemplate?: PayloadTemplate;
|
|
119
|
+
/**
|
|
120
|
+
* The raw request body captured from the selected endpoint (e.g. a Postman
|
|
121
|
+
* collection). Persisted only to seed the template editor's default when the
|
|
122
|
+
* author switches to template mode with nothing authored yet; never sent.
|
|
123
|
+
*/
|
|
124
|
+
requestBody?: PayloadTemplate;
|
|
41
125
|
};
|
|
42
126
|
}
|
|
43
127
|
export interface MongoDbPipeLineConfigInterface extends DataFetchingBaseConfig {
|
|
@@ -1,17 +1,198 @@
|
|
|
1
1
|
import { AllFormInputPrimaryKeys } from "../FormBuilder/FormInputKeys.js";
|
|
2
2
|
import { TreeNode } from "../FormSlide/accessTree.js";
|
|
3
|
-
import {
|
|
3
|
+
import { FormInputBasicOptionInterface } from "./FormInputBasicOptionInterface.js";
|
|
4
4
|
import { IBasicFormInput } from "./BasicFormInputInterface.js";
|
|
5
5
|
export interface IWorkflowDocumentPicker extends IBasicFormInput {
|
|
6
6
|
workflowPickerConfig: IWorkflowDocumentPickerConfig;
|
|
7
7
|
[AllFormInputPrimaryKeys.AllowMultipleSelection]: boolean;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Document-picker configuration.
|
|
11
|
+
*
|
|
12
|
+
* The only field an administrator must supply is `workflowId` — the table columns,
|
|
13
|
+
* the search schema, the sortable fields and the runtime step chooser are all
|
|
14
|
+
* derived from the selected workflow. Everything after it is optional and exists
|
|
15
|
+
* only to pin a picker to a narrower slice of transactions.
|
|
16
|
+
*/
|
|
9
17
|
export interface IWorkflowDocumentPickerConfig {
|
|
10
18
|
workflowId: string;
|
|
11
19
|
primaryIdentifierKey?: TreeNode[];
|
|
12
20
|
sampleDocument?: Record<string, unknown>;
|
|
13
|
-
|
|
14
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Restricts the picker to transactions currently sitting on specific workflow
|
|
23
|
+
* steps. Omitted — or an empty `stepIds` — means every step is eligible and the
|
|
24
|
+
* end user gets a step chooser in the browse dialog.
|
|
25
|
+
*/
|
|
26
|
+
stepFilter?: IWorkflowDocumentStepFilter;
|
|
27
|
+
/**
|
|
28
|
+
* Filters applied on top of the workflow scope before the user sees anything.
|
|
29
|
+
* Static values are baked in by the administrator; `fromFormControl` reads the
|
|
30
|
+
* value off a sibling control of the same form at query time.
|
|
31
|
+
*/
|
|
32
|
+
presetFilters?: IDocumentPickerFilter[];
|
|
33
|
+
/**
|
|
34
|
+
* Step options captured when `workflowId` was chosen, so the builder can render
|
|
35
|
+
* a step multi-select without a live workflow round-trip. Refreshed whenever the
|
|
36
|
+
* workflow changes; the runtime step chooser always uses live steps, never this.
|
|
37
|
+
*/
|
|
38
|
+
availableSteps?: FormInputBasicOptionInterface[];
|
|
39
|
+
}
|
|
40
|
+
/** Step restriction for a document picker. */
|
|
41
|
+
export interface IWorkflowDocumentStepFilter {
|
|
42
|
+
/**
|
|
43
|
+
* Workflow step ids (`currentStepID` values) the picker is limited to.
|
|
44
|
+
*
|
|
45
|
+
* Optional, because the whole step restriction is: the builder writes a
|
|
46
|
+
* `stepFilter` record as soon as the administrator opens that control, and an
|
|
47
|
+
* empty or absent list means "every step is eligible" — the same thing as
|
|
48
|
+
* omitting `stepFilter` altogether. The runtime already reads it as
|
|
49
|
+
* `stepFilter?.stepIds ?? []`.
|
|
50
|
+
*/
|
|
51
|
+
stepIds?: string[];
|
|
52
|
+
}
|
|
53
|
+
/** Comparison operators a {@link IDocumentPickerFilter} may apply. */
|
|
54
|
+
export declare const DOCUMENT_PICKER_FILTER_OPERATORS: readonly ["eq", "ne", "in", "nin", "gt", "gte", "lt", "lte", "regex", "exists"];
|
|
55
|
+
/** Comparison operator applied by a {@link IDocumentPickerFilter}. */
|
|
56
|
+
export type DocumentPickerFilterOperator = typeof DOCUMENT_PICKER_FILTER_OPERATORS[number];
|
|
57
|
+
/** How a filter's configured value is coerced before it is sent. */
|
|
58
|
+
export declare const DOCUMENT_PICKER_FILTER_VALUE_TYPES: readonly ["string", "number", "boolean"];
|
|
59
|
+
/** Declared type of a {@link IDocumentPickerFilter} value. */
|
|
60
|
+
export type DocumentPickerFilterValueType = typeof DOCUMENT_PICKER_FILTER_VALUE_TYPES[number];
|
|
61
|
+
/** Where a {@link IDocumentPickerFilter} reads its comparison value from. */
|
|
62
|
+
export declare const DOCUMENT_PICKER_FILTER_VALUE_SOURCES: readonly ["fixed", "input"];
|
|
63
|
+
/** Declared value source of a {@link IDocumentPickerFilter}. */
|
|
64
|
+
export type DocumentPickerFilterValueSource = typeof DOCUMENT_PICKER_FILTER_VALUE_SOURCES[number];
|
|
65
|
+
/**
|
|
66
|
+
* One administrator-configured filter clause.
|
|
67
|
+
*
|
|
68
|
+
* Exactly one value source is used, chosen by `valueSource`: the static `value`
|
|
69
|
+
* (`'fixed'`) or the current value of a sibling input (`'input'`, via `fromInputId`).
|
|
70
|
+
* For the `in` / `nin` operators a static value is split on commas before coercion.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* // Only requisitions already approved
|
|
74
|
+
* { path: 'form.status', op: 'eq', valueSource: 'fixed', value: 'approved' }
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* // Only transactions for the department chosen earlier in this form
|
|
78
|
+
* { path: 'form.departmentId', op: 'eq', valueSource: 'input', fromInputId: '9f2c…', omitWhenEmpty: true }
|
|
79
|
+
*/
|
|
80
|
+
export interface IDocumentPickerFilter {
|
|
81
|
+
/**
|
|
82
|
+
* Stable identity of this clause, stamped by the builder's record-list editor the
|
|
83
|
+
* first time the filter is saved. It is the key that editor tracks a row by — for
|
|
84
|
+
* edit and for delete — so it is written to every persisted filter and has to
|
|
85
|
+
* round-trip through validation.
|
|
86
|
+
*/
|
|
87
|
+
id?: string;
|
|
88
|
+
/**
|
|
89
|
+
* Document path to filter on. Form fields are addressed as `form.<name>`; the
|
|
90
|
+
* document root exposes `reference`, `status`, `currentStep` and `archive`.
|
|
91
|
+
*/
|
|
92
|
+
path: string;
|
|
93
|
+
/** Comparison operator. Defaults to `eq` when omitted. */
|
|
94
|
+
op?: DocumentPickerFilterOperator;
|
|
95
|
+
/**
|
|
96
|
+
* Which of the two mutually exclusive value sources this clause uses.
|
|
97
|
+
*
|
|
98
|
+
* - `'fixed'` — use the static {@link IDocumentPickerFilter.value}, coerced by
|
|
99
|
+
* {@link IDocumentPickerFilter.valueType}. Any `fromInputId` is ignored.
|
|
100
|
+
* - `'input'` — use the current value of {@link IDocumentPickerFilter.fromInputId}.
|
|
101
|
+
* Any static `value` is ignored.
|
|
102
|
+
* - omitted — the source is inferred from what is set, so filters saved before
|
|
103
|
+
* this field existed keep working: a present `fromInputId` means `'input'`,
|
|
104
|
+
* otherwise `'fixed'`.
|
|
105
|
+
*/
|
|
106
|
+
valueSource?: DocumentPickerFilterValueSource;
|
|
107
|
+
/**
|
|
108
|
+
* Static value supplied by the administrator. Used when `valueSource` is
|
|
109
|
+
* `'fixed'`, or — for filters saved before `valueSource` existed — when no
|
|
110
|
+
* `fromInputId` is set.
|
|
111
|
+
*/
|
|
112
|
+
value?: unknown;
|
|
113
|
+
/** Coercion applied to the resolved value. Defaults to `string`. */
|
|
114
|
+
valueType?: DocumentPickerFilterValueType;
|
|
115
|
+
/**
|
|
116
|
+
* Id of a sibling input on the same form whose current value supplies the
|
|
117
|
+
* comparison value. The runtime form group is keyed by input id, not by
|
|
118
|
+
* form-control name. Used when `valueSource` is `'input'`, or — for filters
|
|
119
|
+
* saved before `valueSource` existed — whenever it is set.
|
|
120
|
+
*/
|
|
121
|
+
fromInputId?: string;
|
|
122
|
+
/**
|
|
123
|
+
* Drops the clause entirely when the resolved value is empty, instead of matching
|
|
124
|
+
* on an empty value. Only meaningful for the input-bound source.
|
|
125
|
+
*/
|
|
126
|
+
omitWhenEmpty?: boolean;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* A single page of documents.
|
|
130
|
+
*
|
|
131
|
+
* Cursor-native: `nextCursor` drives forward navigation, and `totalItems` /
|
|
132
|
+
* `totalPages` are populated only on the first page — the request that carried no
|
|
133
|
+
* cursor — because the count scan is skipped on continuation pages. Cache the totals
|
|
134
|
+
* client-side rather than expecting them on every page.
|
|
135
|
+
*/
|
|
136
|
+
export interface IDocumentPage {
|
|
137
|
+
items: Record<string, unknown>[];
|
|
138
|
+
/** Effective page size applied, which may be clamped below the requested size. */
|
|
139
|
+
itemsPerPage: number;
|
|
140
|
+
/** `true` when another page exists after this one. */
|
|
141
|
+
hasMore: boolean;
|
|
142
|
+
/** Token to send back as `cursor` for the next page, or `null` at the end. */
|
|
143
|
+
nextCursor: string | null;
|
|
144
|
+
/** Total records matching the query. First page only. */
|
|
145
|
+
totalItems?: number;
|
|
146
|
+
/** Total page count for the query. First page only. */
|
|
147
|
+
totalPages?: number;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The one request shape every document-picker query uses.
|
|
151
|
+
*
|
|
152
|
+
* Sort and filter keys are document paths, not form-control names: root fields
|
|
153
|
+
* (`updatedAt`, `reference`, `currentStep`, `archive`) stay as they are, while form
|
|
154
|
+
* fields are addressed as `form.<name>`.
|
|
155
|
+
*/
|
|
156
|
+
export interface IDocumentQueryRequest {
|
|
157
|
+
workflowId: string;
|
|
158
|
+
itemsPerPage: number;
|
|
159
|
+
/** Omit for the first page; otherwise the previous page's `nextCursor`. */
|
|
160
|
+
cursor?: string;
|
|
161
|
+
/**
|
|
162
|
+
* Sort descriptor. Only the first entry is honoured, and `_id` is appended as a
|
|
163
|
+
* tiebreaker. Must stay identical across a cursor sequence — changing it
|
|
164
|
+
* invalidates every outstanding cursor, so reset paging when the sort changes.
|
|
165
|
+
*/
|
|
166
|
+
sort: Record<string, 1 | -1>;
|
|
167
|
+
/**
|
|
168
|
+
* Merged step, preset and user filters. `_id: { $in: [...] }` is how a selection
|
|
169
|
+
* spanning several pages is hydrated in one request.
|
|
170
|
+
*/
|
|
171
|
+
filter: Record<string, unknown>;
|
|
172
|
+
/**
|
|
173
|
+
* Free-text term. Requires {@link IDocumentQueryRequest.schema}: without it the
|
|
174
|
+
* term is silently ignored and an unfiltered page comes back.
|
|
175
|
+
*/
|
|
176
|
+
searchKey?: string;
|
|
177
|
+
/** Path → type map scoping which fields `searchKey` searches. */
|
|
178
|
+
schema?: Record<string, string>;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* The value a document picker writes to its form control — one entry per linked
|
|
182
|
+
* transaction, or a single entry when the input is not multi-select.
|
|
183
|
+
*
|
|
184
|
+
* Carries enough context to render the link without re-reading the builder config or
|
|
185
|
+
* re-fetching the document.
|
|
186
|
+
*/
|
|
187
|
+
export interface IDocumentReference {
|
|
188
|
+
/** Value of the picker's primary identifier key — `_id` unless configured otherwise. */
|
|
189
|
+
id: string;
|
|
190
|
+
/** Workflow the transaction belongs to. */
|
|
191
|
+
workflowId: string;
|
|
192
|
+
/** Human-facing transaction reference, e.g. `REQ-00412`. */
|
|
193
|
+
reference?: string;
|
|
194
|
+
/** Short descriptive label drawn from the workflow's first configured column. */
|
|
195
|
+
label?: string;
|
|
15
196
|
}
|
|
16
197
|
export declare enum workflowStepStatus {
|
|
17
198
|
PENDING = "pending",
|
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
import { AllFormInputPrimaryKeys } from "../FormBuilder/FormInputKeys.js";
|
|
2
|
+
/** Comparison operators a {@link IDocumentPickerFilter} may apply. */
|
|
3
|
+
export const DOCUMENT_PICKER_FILTER_OPERATORS = [
|
|
4
|
+
'eq',
|
|
5
|
+
'ne',
|
|
6
|
+
'in',
|
|
7
|
+
'nin',
|
|
8
|
+
'gt',
|
|
9
|
+
'gte',
|
|
10
|
+
'lt',
|
|
11
|
+
'lte',
|
|
12
|
+
'regex',
|
|
13
|
+
'exists',
|
|
14
|
+
];
|
|
15
|
+
/** How a filter's configured value is coerced before it is sent. */
|
|
16
|
+
export const DOCUMENT_PICKER_FILTER_VALUE_TYPES = ['string', 'number', 'boolean'];
|
|
17
|
+
/** Where a {@link IDocumentPickerFilter} reads its comparison value from. */
|
|
18
|
+
export const DOCUMENT_PICKER_FILTER_VALUE_SOURCES = ['fixed', 'input'];
|
|
2
19
|
export var workflowStepStatus;
|
|
3
20
|
(function (workflowStepStatus) {
|
|
4
21
|
workflowStepStatus["PENDING"] = "pending";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IFolderItem, IPostmanCollection } from "../FormBuilder/postmanCollection.js";
|
|
2
|
-
import { IWorkflowDocListCols } from "../FormBuilder/workflowSelectionConfig.js";
|
|
2
|
+
import { IWorkflowDocListCols, IWorkflowStepOption } from "../FormBuilder/workflowSelectionConfig.js";
|
|
3
3
|
import { TreeNode } from "../FormSlide/accessTree.js";
|
|
4
|
-
import { APIDataFetchingConfigurationInterface, InputAPIDataId, MongoDbPipeLineConfigInterface } from "./APIDataFetchingConfigurationInterface.js";
|
|
4
|
+
import { APIDataFetchingConfigurationInterface, InputAPIDataId, MongoDbPipeLineConfigInterface, PayloadTemplate, PayloadTemplateValue, RequestBodyMode } from "./APIDataFetchingConfigurationInterface.js";
|
|
5
5
|
import { AutocapitalizeOptions, AutocompleteOptions, ElementTypes, IBasicFormInput, IFormElementTemplate, InputDataTypes, InputPipeTypes, InputTypes, OptionSelectTypes } from "./BasicFormInputInterface.js";
|
|
6
6
|
import { IDateRangePickerInput } from "./DateRangePickerInput.js";
|
|
7
7
|
import { AllDocumentFileExtensions, AllImageFileExtensions, FileUploadInputValueInterface, IFileUploadInput, InputFileType, UploadTypes } from "./FileUploadInputInterface.js";
|
|
@@ -19,10 +19,10 @@ import { TableColumnConfigInterface, TableConfigurationsInterface } from "./Tabl
|
|
|
19
19
|
import { ITextareaProperties } from "./TextAreaInput.js";
|
|
20
20
|
import { IToggleInput } from "./ToggleInputInterface.js";
|
|
21
21
|
import { AdjResponseReviewColumnMapping, AdjudicationSteps, IWorkflowAdjudicationInput, WorkflowAdjudicationMicroFlowReviewValue, WorkflowAdjudicationResponseElectedSupplierSelectionValue, WorkflowAdjudicationScoreSheetValue } from "./WorkflowAdjudication.js";
|
|
22
|
-
import { IWorkflowDocumentPicker, IWorkflowDocumentPickerConfig, workflowStepStatus } from "./WorkflowDocumentPicker.js";
|
|
22
|
+
import { DOCUMENT_PICKER_FILTER_OPERATORS, DOCUMENT_PICKER_FILTER_VALUE_SOURCES, DOCUMENT_PICKER_FILTER_VALUE_TYPES, DocumentPickerFilterOperator, DocumentPickerFilterValueSource, DocumentPickerFilterValueType, IDocumentPage, IDocumentPickerFilter, IDocumentQueryRequest, IDocumentReference, IWorkflowDocumentPicker, IWorkflowDocumentPickerConfig, IWorkflowDocumentStepFilter, workflowStepStatus } from "./WorkflowDocumentPicker.js";
|
|
23
23
|
import { CalculatedFieldRules } from "./calculatedFieldRules.js";
|
|
24
24
|
import { CalculationFunctions, calculationVariableInterface } from "./calculationVariableInterface.js";
|
|
25
25
|
import { IRichTextEditor, RichTextEditorType } from "./RichTextEditorInput.js";
|
|
26
26
|
import { ValidationError, ValidationOptions } from "./schema.js";
|
|
27
27
|
import { IUserSignature } from "./userSignature.js";
|
|
28
|
-
export { ElementTypes, InputTypes, InputPipeTypes, AutocapitalizeOptions, AutocompleteOptions, InputDataTypes, MinInputTypes, IFormElementTemplate, IBasicFormInput, IFileUploadInput, IDateRangePickerInput, ITextareaProperties, IToggleInput, IMatrixInput, IMultiple, IMultipleInputCal, IScoaInput, TableConfigurationsInterface, TableColumnConfigInterface, FormControlCustomValidatorsInterface, InputObservedForChange, DraftFormControlCustomValidator, IFormValidationOverride, MinimumInputRequiredInterface, MinInputMapInput, CalculatedFieldRules, calculationVariableInterface, APIDataFetchingConfigurationInterface, IGetTreeResponse, CalculationFunctions, TreeNode, IPostmanCollection, IFolderItem, FileUploadInputValueInterface, AllDocumentFileExtensions, AllImageFileExtensions, UploadTypes, InputFileType, IScoaAccount, IScoaInputConfig, ITableScoaSelectionRow, ScoaSegmentValue, ScoaSegmentValueBag, IIncludedSegmentConfig, AccountingBasis, ScoaAccountTree, IUserSignature, ValidationOptions, ValidationError, MatDataOptionsInterface, MongoDbPipeLineConfigInterface, InputAPIDataId, FormInputBasicOptionInterface, ScoaInterface, ScoaInnerInput, IAccountSegmentTreeKeys, IWorkflowDocumentPicker, IWorkflowDocumentPickerConfig, workflowStepStatus, IWorkflowDocListCols, JsDataTypes, AdjudicationSteps, IWorkflowAdjudicationInput, WorkflowAdjudicationScoreSheetValue, WorkflowAdjudicationMicroFlowReviewValue, WorkflowAdjudicationResponseElectedSupplierSelectionValue, ScoreSheetItem, AdjResponseReviewColumnMapping, OptionSelectTypes, ISelectInputInterface, MultipleInputAvailableOperations, RichTextEditorType, IRichTextEditor, };
|
|
28
|
+
export { ElementTypes, InputTypes, InputPipeTypes, AutocapitalizeOptions, AutocompleteOptions, InputDataTypes, MinInputTypes, IFormElementTemplate, IBasicFormInput, IFileUploadInput, IDateRangePickerInput, ITextareaProperties, IToggleInput, IMatrixInput, IMultiple, IMultipleInputCal, IScoaInput, TableConfigurationsInterface, TableColumnConfigInterface, FormControlCustomValidatorsInterface, InputObservedForChange, DraftFormControlCustomValidator, IFormValidationOverride, MinimumInputRequiredInterface, MinInputMapInput, CalculatedFieldRules, calculationVariableInterface, APIDataFetchingConfigurationInterface, PayloadTemplate, PayloadTemplateValue, RequestBodyMode, IGetTreeResponse, CalculationFunctions, TreeNode, IPostmanCollection, IFolderItem, FileUploadInputValueInterface, AllDocumentFileExtensions, AllImageFileExtensions, UploadTypes, InputFileType, IScoaAccount, IScoaInputConfig, ITableScoaSelectionRow, ScoaSegmentValue, ScoaSegmentValueBag, IIncludedSegmentConfig, AccountingBasis, ScoaAccountTree, IUserSignature, ValidationOptions, ValidationError, MatDataOptionsInterface, MongoDbPipeLineConfigInterface, InputAPIDataId, FormInputBasicOptionInterface, ScoaInterface, ScoaInnerInput, IAccountSegmentTreeKeys, IWorkflowDocumentPicker, IWorkflowDocumentPickerConfig, IWorkflowDocumentStepFilter, IDocumentPickerFilter, IDocumentPage, IDocumentQueryRequest, IDocumentReference, DocumentPickerFilterOperator, DocumentPickerFilterValueSource, DocumentPickerFilterValueType, DOCUMENT_PICKER_FILTER_OPERATORS, DOCUMENT_PICKER_FILTER_VALUE_SOURCES, DOCUMENT_PICKER_FILTER_VALUE_TYPES, workflowStepStatus, IWorkflowDocListCols, IWorkflowStepOption, JsDataTypes, AdjudicationSteps, IWorkflowAdjudicationInput, WorkflowAdjudicationScoreSheetValue, WorkflowAdjudicationMicroFlowReviewValue, WorkflowAdjudicationResponseElectedSupplierSelectionValue, ScoreSheetItem, AdjResponseReviewColumnMapping, OptionSelectTypes, ISelectInputInterface, MultipleInputAvailableOperations, RichTextEditorType, IRichTextEditor, };
|
|
@@ -4,7 +4,7 @@ import { AccountingBasis } from "./IMscoaAccount.js";
|
|
|
4
4
|
import { JsDataTypes, MinInputTypes } from "./MinimumInputRequiredInterface.js";
|
|
5
5
|
import { MultipleInputAvailableOperations } from "./MultipleInterface.js";
|
|
6
6
|
import { AdjudicationSteps } from "./WorkflowAdjudication.js";
|
|
7
|
-
import { workflowStepStatus } from "./WorkflowDocumentPicker.js";
|
|
7
|
+
import { DOCUMENT_PICKER_FILTER_OPERATORS, DOCUMENT_PICKER_FILTER_VALUE_SOURCES, DOCUMENT_PICKER_FILTER_VALUE_TYPES, workflowStepStatus, } from "./WorkflowDocumentPicker.js";
|
|
8
8
|
import { CalculationFunctions } from "./calculationVariableInterface.js";
|
|
9
9
|
import { RichTextEditorType } from "./RichTextEditorInput.js";
|
|
10
10
|
// H-018b (Worker T-C): `OLD_FormInterface` and `FormInterfaceMigration` are
|
|
@@ -14,4 +14,4 @@ import { RichTextEditorType } from "./RichTextEditorInput.js";
|
|
|
14
14
|
// would otherwise trigger TS2300 "Duplicate identifier".
|
|
15
15
|
export {
|
|
16
16
|
///ENUMS
|
|
17
|
-
ElementTypes, InputTypes, InputPipeTypes, AutocapitalizeOptions, AutocompleteOptions, InputDataTypes, MinInputTypes, CalculationFunctions, AllDocumentFileExtensions, AllImageFileExtensions, UploadTypes, InputFileType, AccountingBasis, workflowStepStatus, JsDataTypes, AdjudicationSteps, OptionSelectTypes, MultipleInputAvailableOperations, RichTextEditorType, };
|
|
17
|
+
ElementTypes, InputTypes, InputPipeTypes, AutocapitalizeOptions, AutocompleteOptions, InputDataTypes, MinInputTypes, CalculationFunctions, AllDocumentFileExtensions, AllImageFileExtensions, UploadTypes, InputFileType, AccountingBasis, DOCUMENT_PICKER_FILTER_OPERATORS, DOCUMENT_PICKER_FILTER_VALUE_SOURCES, DOCUMENT_PICKER_FILTER_VALUE_TYPES, workflowStepStatus, JsDataTypes, AdjudicationSteps, OptionSelectTypes, MultipleInputAvailableOperations, RichTextEditorType, };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import Joi from 'joi';
|
|
2
|
+
declare const documentPickerFilterSchema: Joi.ObjectSchema<any>;
|
|
3
|
+
declare const workflowDocumentStepFilterSchema: Joi.ObjectSchema<any>;
|
|
2
4
|
declare const workflowDocumentPickerConfigSchema: Joi.ObjectSchema<any>;
|
|
3
|
-
export { workflowDocumentPickerConfigSchema };
|
|
5
|
+
export { workflowDocumentPickerConfigSchema, documentPickerFilterSchema, workflowDocumentStepFilterSchema };
|
|
@@ -1,12 +1,40 @@
|
|
|
1
1
|
import Joi from 'joi';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { DOCUMENT_PICKER_FILTER_OPERATORS, DOCUMENT_PICKER_FILTER_VALUE_SOURCES, DOCUMENT_PICKER_FILTER_VALUE_TYPES, } from '../interfaces/formInput/WorkflowDocumentPicker.js';
|
|
3
|
+
// Schema for IDocumentPickerFilter
|
|
4
|
+
const documentPickerFilterSchema = Joi.object({
|
|
5
|
+
// The record-list editor stamps an id on every filter it saves and tracks the row
|
|
6
|
+
// by it, so a persisted filter always carries one. Rejecting it made every saved
|
|
7
|
+
// preset filter fail validation on the next open.
|
|
8
|
+
id: Joi.string().optional(),
|
|
9
|
+
path: Joi.string().required(),
|
|
10
|
+
op: Joi.string().valid(...DOCUMENT_PICKER_FILTER_OPERATORS).optional(),
|
|
11
|
+
// Optional: absent means "infer from what is set", so filters saved before
|
|
12
|
+
// `valueSource` existed still validate.
|
|
13
|
+
valueSource: Joi.string().valid(...DOCUMENT_PICKER_FILTER_VALUE_SOURCES).optional(),
|
|
14
|
+
value: Joi.any().optional(),
|
|
15
|
+
valueType: Joi.string().valid(...DOCUMENT_PICKER_FILTER_VALUE_TYPES).optional(),
|
|
16
|
+
fromInputId: Joi.string().allow('').optional(),
|
|
17
|
+
omitWhenEmpty: Joi.boolean().optional(),
|
|
18
|
+
});
|
|
19
|
+
// Schema for IWorkflowDocumentStepFilter
|
|
20
|
+
const workflowDocumentStepFilterSchema = Joi.object({
|
|
21
|
+
// Optional, because the step restriction itself is. The builder writes a stepFilter
|
|
22
|
+
// record as soon as the administrator opens that control, so requiring stepIds made
|
|
23
|
+
// "I looked at the step chooser and picked nothing" a validation failure. An empty
|
|
24
|
+
// or absent list means every step is eligible — what the runtime already assumes
|
|
25
|
+
// via `stepFilter?.stepIds ?? []`.
|
|
26
|
+
stepIds: Joi.array().items(Joi.string()).optional(),
|
|
27
|
+
});
|
|
4
28
|
// Schema for IWorkflowDocumentPickerConfig
|
|
5
29
|
const workflowDocumentPickerConfigSchema = Joi.object({
|
|
6
30
|
workflowId: Joi.string().required(),
|
|
7
31
|
primaryIdentifierKey: Joi.array().items(Joi.object()).optional(),
|
|
8
32
|
sampleDocument: Joi.object().optional(), // Optional field for sample document structure
|
|
9
|
-
|
|
10
|
-
|
|
33
|
+
stepFilter: workflowDocumentStepFilterSchema.optional(),
|
|
34
|
+
presetFilters: Joi.array().items(documentPickerFilterSchema).optional(),
|
|
35
|
+
availableSteps: Joi.array().items(Joi.object({
|
|
36
|
+
label: Joi.string().optional(),
|
|
37
|
+
value: Joi.string().required(),
|
|
38
|
+
})).optional(),
|
|
11
39
|
});
|
|
12
|
-
export { workflowDocumentPickerConfigSchema };
|
|
40
|
+
export { workflowDocumentPickerConfigSchema, documentPickerFilterSchema, workflowDocumentStepFilterSchema };
|
|
@@ -43,7 +43,16 @@ const APIDataFetchingConfigurationSchema = Joi.object({
|
|
|
43
43
|
transferCache: Joi.alternatives().try(Joi.object({ includeHeaders: Joi.array().items(Joi.string()).optional() }), Joi.boolean()).optional()
|
|
44
44
|
}).optional(),
|
|
45
45
|
backEndConfig: Joi.object({
|
|
46
|
-
|
|
46
|
+
// Optional: a 'template'-mode fetch shapes its body from payloadTemplate and
|
|
47
|
+
// carries no mapping; GET fetches never had one. Readers default it to [].
|
|
48
|
+
minimumInputRequired: Joi.array().items(minimumInputRequiredSchema).optional(),
|
|
49
|
+
// Which body mechanism is active; unset ⇒ 'mappedInputs' (backward compatible).
|
|
50
|
+
requestBodyMode: Joi.string().valid('mappedInputs', 'template').optional(),
|
|
51
|
+
// Free-form JSON body template ({{inputId}} tokens + typed default literals).
|
|
52
|
+
// Supersedes minimumInputRequired when set and mode is not 'mappedInputs'.
|
|
53
|
+
payloadTemplate: Joi.alternatives().try(Joi.object(), Joi.array()).optional(),
|
|
54
|
+
// Raw request body captured from the endpoint, used to seed the template editor.
|
|
55
|
+
requestBody: Joi.alternatives().try(Joi.object(), Joi.array()).optional()
|
|
47
56
|
}).optional(),
|
|
48
57
|
valueAccessRules: Joi.alternatives().try(FormInputBasicOptionSchema, Joi.array().items(Joi.object())).optional(),
|
|
49
58
|
source: Joi.string().valid('local', 'api', 'mongoPipeline', 'customOptions').required(),
|