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.
@@ -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 serve as the primary identifier for workflow documents. Note: existing mappings will be cleared when reconfigured. After updating, reselect the workflow above.",
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, 'documentSourceType'],
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
- label: 'Document options source type',
447
- defaultValue: 'default',
448
- clearOnChange: [
449
- [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'documentsSource'],
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
- expression: `documentSourceType === ${DataSources.Api}`,
468
- deepBind: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'documentSourceType'],
606
+ testType: 'exists',
607
+ deepBind: [AllFormInputPrimaryKeys.WorkflowPickerConfig, 'workflowId'],
469
608
  },
470
609
  ],
471
- clearOnChange: [
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
- AllFormInputPrimaryKeys.WorkflowPickerConfig, 'documentsSource',
482
- 'backEndConfig',
483
- 'minimumInputRequired',
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
- editType: ElementEditorTypes.MongoPipelineBuilder,
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
- getWorkflowDocuments: (workflowId: string, page: number, itemsPerPage: number, sort: Record<string, -1 | 1>, searchKey: string | undefined, filter?: Record<string, any>) => Observable<{
72
- footerConfig: {
73
- totalPages: number;
74
- totalItems: number;
75
- itemsPerPage: number;
76
- };
77
- formValues: Record<string, unknown>[];
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
- minimumInputRequired: MinimumInputRequiredInterface[];
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 { APIDataFetchingConfigurationInterface, DataSources, MongoDbPipeLineConfigInterface } from "./APIDataFetchingConfigurationInterface.js";
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
- documentSourceType: DataSources | 'default';
14
- documentsSource?: APIDataFetchingConfigurationInterface | MongoDbPipeLineConfigInterface;
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 { APIDataFetchingConfigurationSchema, MongoDbPipeLineConfigSchema } from './MatOptionsSchema.js';
3
- import { DataSources } from '../interfaces/FormBuilder/index.js';
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
- documentSourceType: Joi.string().valid(...Object.values(DataSources), 'default').required(),
10
- documentsSource: Joi.alternatives().try(APIDataFetchingConfigurationSchema, MongoDbPipeLineConfigSchema, Joi.object()).optional(),
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
- minimumInputRequired: Joi.array().items(minimumInputRequiredSchema).required()
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(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ngx-t-forms-types",
3
- "version": "0.0.24",
3
+ "version": "0.0.26",
4
4
  "description": "Typings and interfaces for the ngx-t-forms library for dynamic forms.",
5
5
  "keywords": [
6
6
  "typings",