@servicetitan/dte-pdf-editor 1.20.0 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/display-conditions/condition-group.d.ts +11 -0
- package/dist/components/display-conditions/condition-group.d.ts.map +1 -0
- package/dist/components/display-conditions/condition-group.js +52 -0
- package/dist/components/display-conditions/condition-group.js.map +1 -0
- package/dist/components/display-conditions/condition-groups-section.d.ts +10 -0
- package/dist/components/display-conditions/condition-groups-section.d.ts.map +1 -0
- package/dist/components/display-conditions/condition-groups-section.js +14 -0
- package/dist/components/display-conditions/condition-groups-section.js.map +1 -0
- package/dist/components/display-conditions/condition-row.d.ts +10 -0
- package/dist/components/display-conditions/condition-row.d.ts.map +1 -0
- package/dist/components/display-conditions/condition-row.js +60 -0
- package/dist/components/display-conditions/condition-row.js.map +1 -0
- package/dist/components/display-conditions/display-condition-modal.d.ts +12 -0
- package/dist/components/display-conditions/display-condition-modal.d.ts.map +1 -0
- package/dist/components/display-conditions/display-condition-modal.js +89 -0
- package/dist/components/display-conditions/display-condition-modal.js.map +1 -0
- package/dist/components/display-conditions/display-condition.d.ts +9 -0
- package/dist/components/display-conditions/display-condition.d.ts.map +1 -0
- package/dist/components/display-conditions/display-condition.js +10 -0
- package/dist/components/display-conditions/display-condition.js.map +1 -0
- package/dist/components/field-config-panel/advanced-settings.d.ts.map +1 -1
- package/dist/components/field-config-panel/advanced-settings.js +10 -8
- package/dist/components/field-config-panel/advanced-settings.js.map +1 -1
- package/dist/components/field-config-panel/field-config-panel.d.ts +1 -1
- package/dist/components/field-config-panel/field-config-panel.d.ts.map +1 -1
- package/dist/components/field-config-panel/field-config-panel.js +4 -2
- package/dist/components/field-config-panel/field-config-panel.js.map +1 -1
- package/dist/components/field-config-panel/formula-generator.d.ts.map +1 -1
- package/dist/components/field-config-panel/formula-generator.js +3 -20
- package/dist/components/field-config-panel/formula-generator.js.map +1 -1
- package/dist/components/field-config-panel/formula-modal.d.ts.map +1 -1
- package/dist/components/field-config-panel/formula-modal.js +9 -3
- package/dist/components/field-config-panel/formula-modal.js.map +1 -1
- package/dist/components/field-config-panel/formula-workspace.d.ts.map +1 -1
- package/dist/components/field-config-panel/formula-workspace.js +4 -3
- package/dist/components/field-config-panel/formula-workspace.js.map +1 -1
- package/dist/components/field-config-panel/result-type-selector.d.ts.map +1 -1
- package/dist/components/field-config-panel/result-type-selector.js +2 -2
- package/dist/components/field-config-panel/result-type-selector.js.map +1 -1
- package/dist/components/pdf-view/pdf-view-field-container.d.ts +2 -1
- package/dist/components/pdf-view/pdf-view-field-container.d.ts.map +1 -1
- package/dist/components/pdf-view/pdf-view-field-container.js +6 -2
- package/dist/components/pdf-view/pdf-view-field-container.js.map +1 -1
- package/dist/components/pdf-view/pdf-view.d.ts.map +1 -1
- package/dist/components/pdf-view/pdf-view.js +1 -1
- package/dist/components/pdf-view/pdf-view.js.map +1 -1
- package/dist/constants/calculated.constants.d.ts +2 -0
- package/dist/constants/calculated.constants.d.ts.map +1 -0
- package/dist/constants/calculated.constants.js +2 -0
- package/dist/constants/calculated.constants.js.map +1 -0
- package/dist/constants/conditions.constants.d.ts +6 -0
- package/dist/constants/conditions.constants.d.ts.map +1 -0
- package/dist/constants/conditions.constants.js +17 -0
- package/dist/constants/conditions.constants.js.map +1 -0
- package/dist/constants/index.d.ts +3 -0
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +3 -0
- package/dist/constants/index.js.map +1 -1
- package/dist/interface/types.d.ts +78 -1
- package/dist/interface/types.d.ts.map +1 -1
- package/dist/interface/types.js +25 -0
- package/dist/interface/types.js.map +1 -1
- package/dist/utils/conditions/evaluate.utils.d.ts +6 -0
- package/dist/utils/conditions/evaluate.utils.d.ts.map +1 -0
- package/dist/utils/conditions/evaluate.utils.js +95 -0
- package/dist/utils/conditions/evaluate.utils.js.map +1 -0
- package/dist/utils/conditions/index.d.ts +3 -0
- package/dist/utils/conditions/index.d.ts.map +1 -0
- package/dist/utils/conditions/index.js +3 -0
- package/dist/utils/conditions/index.js.map +1 -0
- package/dist/utils/conditions/schema-data-points.utils.d.ts +12 -0
- package/dist/utils/conditions/schema-data-points.utils.d.ts.map +1 -0
- package/dist/utils/conditions/schema-data-points.utils.js +67 -0
- package/dist/utils/conditions/schema-data-points.utils.js.map +1 -0
- package/dist/utils/data-model/extract-fields.utils.d.ts +1 -0
- package/dist/utils/data-model/extract-fields.utils.d.ts.map +1 -1
- package/dist/utils/data-model/extract-fields.utils.js +6 -3
- package/dist/utils/data-model/extract-fields.utils.js.map +1 -1
- package/dist/utils/formula/render-formula.utils.d.ts +0 -6
- package/dist/utils/formula/render-formula.utils.d.ts.map +1 -1
- package/dist/utils/formula/render-formula.utils.js +0 -17
- package/dist/utils/formula/render-formula.utils.js.map +1 -1
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/shared/index.d.ts +2 -0
- package/dist/utils/shared/index.d.ts.map +1 -0
- package/dist/utils/shared/index.js +2 -0
- package/dist/utils/shared/index.js.map +1 -0
- package/dist/utils/shared/number.utils.d.ts +2 -0
- package/dist/utils/shared/number.utils.d.ts.map +1 -0
- package/dist/utils/shared/number.utils.js +12 -0
- package/dist/utils/shared/number.utils.js.map +1 -0
- package/package.json +1 -1
- package/src/components/display-conditions/condition-group.tsx +141 -0
- package/src/components/display-conditions/condition-groups-section.tsx +63 -0
- package/src/components/display-conditions/condition-row.tsx +182 -0
- package/src/components/display-conditions/display-condition-modal.tsx +180 -0
- package/src/components/display-conditions/display-condition.tsx +41 -0
- package/src/components/field-config-panel/advanced-settings.tsx +42 -46
- package/src/components/field-config-panel/field-config-panel.tsx +12 -2
- package/src/components/field-config-panel/formula-generator.tsx +9 -44
- package/src/components/field-config-panel/formula-modal.tsx +72 -82
- package/src/components/field-config-panel/formula-workspace.tsx +6 -5
- package/src/components/field-config-panel/result-type-selector.tsx +8 -11
- package/src/components/pdf-view/pdf-view-field-container.tsx +11 -2
- package/src/components/pdf-view/pdf-view.tsx +1 -0
- package/src/constants/calculated.constants.ts +1 -0
- package/src/constants/conditions.constants.ts +26 -0
- package/src/constants/index.ts +3 -0
- package/src/interface/types.ts +64 -1
- package/src/styles/formula-modal.css +1 -155
- package/src/utils/conditions/evaluate.utils.ts +134 -0
- package/src/utils/conditions/index.ts +2 -0
- package/src/utils/conditions/schema-data-points.utils.ts +93 -0
- package/src/utils/data-model/extract-fields.utils.ts +12 -7
- package/src/utils/formula/render-formula.utils.ts +0 -19
- package/src/utils/index.ts +2 -0
- package/src/utils/shared/index.ts +1 -0
- package/src/utils/shared/number.utils.ts +13 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Button,
|
|
2
|
-
import IconClose from '@servicetitan/anvil2/assets/icons/material/round/close.svg';
|
|
1
|
+
import { Button, Dialog, Divider, Flex } from '@servicetitan/anvil2';
|
|
3
2
|
import IconRedo from '@servicetitan/anvil2/assets/icons/material/round/redo.svg';
|
|
4
3
|
import IconUndo from '@servicetitan/anvil2/assets/icons/material/round/undo.svg';
|
|
5
4
|
import { FC, useCallback, useMemo, useState } from 'react';
|
|
5
|
+
import { MODAL_CONTENT_MAX_HEIGHT } from '../../constants';
|
|
6
6
|
import { useFormulaEditor } from '../../hooks';
|
|
7
7
|
import {
|
|
8
8
|
CalculatedFieldFormat,
|
|
@@ -132,6 +132,10 @@ export const FormulaModal: FC<FormulaModalProps> = ({
|
|
|
132
132
|
const canSave =
|
|
133
133
|
formulaValidation.valid && unknownFieldErrors.length === 0 && parsedTokens.length > 0;
|
|
134
134
|
|
|
135
|
+
const handleClose = useCallback(() => {
|
|
136
|
+
onClose();
|
|
137
|
+
}, [onClose]);
|
|
138
|
+
|
|
135
139
|
const handleSave = useCallback(() => {
|
|
136
140
|
if (!canSave) {
|
|
137
141
|
return;
|
|
@@ -141,89 +145,75 @@ export const FormulaModal: FC<FormulaModalProps> = ({
|
|
|
141
145
|
}, [canSave, format, onClose, onSave, parsedTokens]);
|
|
142
146
|
|
|
143
147
|
return (
|
|
144
|
-
<
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
role="dialog"
|
|
149
|
-
aria-modal="true"
|
|
150
|
-
aria-label="Formula"
|
|
151
|
-
>
|
|
152
|
-
<Flex direction="column" className="dte-formula-modal ">
|
|
148
|
+
<Dialog open onClose={handleClose} size="xlarge">
|
|
149
|
+
<Dialog.Header>Formula Builder</Dialog.Header>
|
|
150
|
+
<Divider />
|
|
151
|
+
<Dialog.Content>
|
|
153
152
|
<Flex
|
|
154
|
-
|
|
155
|
-
alignItems="
|
|
156
|
-
|
|
153
|
+
flex={1}
|
|
154
|
+
alignItems="stretch"
|
|
155
|
+
gap={2}
|
|
156
|
+
style={{
|
|
157
|
+
height: MODAL_CONTENT_MAX_HEIGHT,
|
|
158
|
+
overflowY: 'auto',
|
|
159
|
+
}}
|
|
157
160
|
>
|
|
158
|
-
<
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
161
|
+
<FieldSidebar
|
|
162
|
+
fillableOptions={fillableFieldsFromDocument}
|
|
163
|
+
mergeTagOptions={allFields}
|
|
164
|
+
highlightElementPath={highlightElementPath}
|
|
165
|
+
onHover={setHighlightElementPath}
|
|
166
|
+
onSelect={formulaEditor.insertField}
|
|
167
|
+
selectedPaths={formulaEditor.selectedFieldPaths}
|
|
168
|
+
/>
|
|
169
|
+
<FormulaWorkspace
|
|
170
|
+
editorRef={formulaEditor.editorRef}
|
|
171
|
+
isInvalid={isInvalid && formulaEditor.isDirty}
|
|
172
|
+
validationError={validationError}
|
|
173
|
+
format={format}
|
|
174
|
+
onResultTypeChange={nextType =>
|
|
175
|
+
setFormat(prev => ({ ...prev, resultType: nextType }))
|
|
176
|
+
}
|
|
177
|
+
advancedOpen={advancedOpen}
|
|
178
|
+
onToggleAdvanced={() => setAdvancedOpen(prev => !prev)}
|
|
179
|
+
setFormat={setFormat}
|
|
180
|
+
onInput={formulaEditor.handleEditorInput}
|
|
181
|
+
onKeyDown={formulaEditor.handleKeyDown}
|
|
182
|
+
onClick={() => {}}
|
|
183
|
+
onMouseUp={formulaEditor.handleEditorInput}
|
|
184
|
+
onPaste={formulaEditor.handlePaste}
|
|
185
|
+
onOperatorSelect={formulaEditor.insertOperator}
|
|
186
|
+
onRemoveField={formulaEditor.removeFieldAtIndex}
|
|
187
|
+
actions={
|
|
188
|
+
<Flex gap="1" alignItems="center">
|
|
189
|
+
<Button
|
|
190
|
+
appearance="ghost"
|
|
191
|
+
size="small"
|
|
192
|
+
onClick={formulaEditor.undo}
|
|
193
|
+
disabled={!formulaEditor.canUndo}
|
|
194
|
+
aria-label="Undo"
|
|
195
|
+
icon={IconUndo}
|
|
196
|
+
/>
|
|
197
|
+
<Button
|
|
198
|
+
appearance="ghost"
|
|
199
|
+
size="small"
|
|
200
|
+
onClick={formulaEditor.redo}
|
|
201
|
+
disabled={!formulaEditor.canRedo}
|
|
202
|
+
aria-label="Redo"
|
|
203
|
+
icon={IconRedo}
|
|
204
|
+
/>
|
|
205
|
+
</Flex>
|
|
206
|
+
}
|
|
167
207
|
/>
|
|
168
208
|
</Flex>
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
/>
|
|
179
|
-
<FormulaWorkspace
|
|
180
|
-
editorRef={formulaEditor.editorRef}
|
|
181
|
-
isInvalid={isInvalid && formulaEditor.isDirty}
|
|
182
|
-
validationError={validationError}
|
|
183
|
-
format={format}
|
|
184
|
-
onResultTypeChange={nextType =>
|
|
185
|
-
setFormat(prev => ({ ...prev, resultType: nextType }))
|
|
186
|
-
}
|
|
187
|
-
advancedOpen={advancedOpen}
|
|
188
|
-
onToggleAdvanced={() => setAdvancedOpen(prev => !prev)}
|
|
189
|
-
setFormat={setFormat}
|
|
190
|
-
onInput={formulaEditor.handleEditorInput}
|
|
191
|
-
onKeyDown={formulaEditor.handleKeyDown}
|
|
192
|
-
onClick={() => {}}
|
|
193
|
-
onMouseUp={formulaEditor.handleEditorInput}
|
|
194
|
-
onPaste={formulaEditor.handlePaste}
|
|
195
|
-
onOperatorSelect={formulaEditor.insertOperator}
|
|
196
|
-
onRemoveField={formulaEditor.removeFieldAtIndex}
|
|
197
|
-
actions={
|
|
198
|
-
<Flex gap="1" alignItems="center">
|
|
199
|
-
<Button
|
|
200
|
-
appearance="ghost"
|
|
201
|
-
size="small"
|
|
202
|
-
onClick={formulaEditor.undo}
|
|
203
|
-
disabled={!formulaEditor.canUndo}
|
|
204
|
-
aria-label="Undo"
|
|
205
|
-
icon={IconUndo}
|
|
206
|
-
/>
|
|
207
|
-
<Button
|
|
208
|
-
appearance="ghost"
|
|
209
|
-
size="small"
|
|
210
|
-
onClick={formulaEditor.redo}
|
|
211
|
-
disabled={!formulaEditor.canRedo}
|
|
212
|
-
aria-label="Redo"
|
|
213
|
-
icon={IconRedo}
|
|
214
|
-
/>
|
|
215
|
-
</Flex>
|
|
216
|
-
}
|
|
217
|
-
/>
|
|
218
|
-
</Flex>
|
|
219
|
-
</div>
|
|
220
|
-
<Flex className="dte-formula-modal-footer" gap="2" justifyContent="flex-end">
|
|
221
|
-
<Button onClick={onClose}>Cancel</Button>
|
|
222
|
-
<Button onClick={handleSave} appearance="primary" disabled={!canSave}>
|
|
223
|
-
Save
|
|
224
|
-
</Button>
|
|
225
|
-
</Flex>
|
|
226
|
-
</Flex>
|
|
227
|
-
</Flex>
|
|
209
|
+
</Dialog.Content>
|
|
210
|
+
<Divider />
|
|
211
|
+
<Dialog.Footer sticky>
|
|
212
|
+
<Dialog.CancelButton onClick={handleClose}>Cancel</Dialog.CancelButton>
|
|
213
|
+
<Button onClick={handleSave} appearance="primary" disabled={!canSave}>
|
|
214
|
+
Save
|
|
215
|
+
</Button>
|
|
216
|
+
</Dialog.Footer>
|
|
217
|
+
</Dialog>
|
|
228
218
|
);
|
|
229
219
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Alert, Button, Flex, Text } from '@servicetitan/anvil2';
|
|
1
|
+
import { Alert, Button, Flex, LinkButton, Text } from '@servicetitan/anvil2';
|
|
2
2
|
import {
|
|
3
3
|
Dispatch,
|
|
4
4
|
FC,
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
SetStateAction,
|
|
10
10
|
useCallback,
|
|
11
11
|
} from 'react';
|
|
12
|
+
import { CALCULATED_OPERATIONS } from '../../constants';
|
|
12
13
|
import { CalculatedFieldFormat } from '../../interface/types';
|
|
13
14
|
import { AdvancedSettings } from './advanced-settings';
|
|
14
15
|
import { ResultTypeSelector } from './result-type-selector';
|
|
@@ -70,7 +71,7 @@ export const FormulaWorkspace: FC<FormulaWorkspaceProps> = ({
|
|
|
70
71
|
);
|
|
71
72
|
|
|
72
73
|
return (
|
|
73
|
-
<Flex direction="column" flex={1} gap={2}>
|
|
74
|
+
<Flex direction="column" flex={1} gap={2} style={{ padding: '12px' }}>
|
|
74
75
|
<Text variant="body" size="small">
|
|
75
76
|
Click a field on the left to add it. Use +, -, *, /, and parentheses to build
|
|
76
77
|
formulas.
|
|
@@ -100,16 +101,16 @@ export const FormulaWorkspace: FC<FormulaWorkspaceProps> = ({
|
|
|
100
101
|
/>
|
|
101
102
|
{isInvalid && validationError && <Alert status="danger" title={validationError} />}
|
|
102
103
|
<Flex gap={1}>
|
|
103
|
-
{
|
|
104
|
+
{CALCULATED_OPERATIONS.map(op => (
|
|
104
105
|
<Button key={op} onClick={() => onOperatorSelect(op)} size="small">
|
|
105
106
|
{op}
|
|
106
107
|
</Button>
|
|
107
108
|
))}
|
|
108
109
|
</Flex>
|
|
109
110
|
<ResultTypeSelector format={format} onChange={onResultTypeChange} />
|
|
110
|
-
<
|
|
111
|
+
<LinkButton appearance="primary" onClick={onToggleAdvanced}>
|
|
111
112
|
{advancedOpen ? 'Hide advanced settings' : 'Show advanced settings'}
|
|
112
|
-
</
|
|
113
|
+
</LinkButton>
|
|
113
114
|
{advancedOpen && <AdvancedSettings format={format} setFormat={setFormat} />}
|
|
114
115
|
</Flex>
|
|
115
116
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Flex, SegmentedControl, Text } from '@servicetitan/anvil2';
|
|
2
2
|
import { FC, Fragment } from 'react';
|
|
3
3
|
import { CalculatedFieldFormat } from '../../interface/types';
|
|
4
4
|
|
|
@@ -19,16 +19,13 @@ export const ResultTypeSelector: FC<ResultTypeSelectorProps> = ({ format, onChan
|
|
|
19
19
|
Result type
|
|
20
20
|
</Text>
|
|
21
21
|
<Flex gap={2}>
|
|
22
|
-
{
|
|
23
|
-
|
|
24
|
-
key={value}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
{label}
|
|
30
|
-
</Button>
|
|
31
|
-
))}
|
|
22
|
+
<SegmentedControl size="medium" selected={format.resultType} onChange={onChange} fill>
|
|
23
|
+
{RESULT_TYPE_OPTIONS.map(opt => (
|
|
24
|
+
<SegmentedControl.Segment key={opt.value} value={opt.value}>
|
|
25
|
+
{opt.label}
|
|
26
|
+
</SegmentedControl.Segment>
|
|
27
|
+
))}
|
|
28
|
+
</SegmentedControl>
|
|
32
29
|
</Flex>
|
|
33
30
|
</Fragment>
|
|
34
31
|
);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { FC, PropsWithChildren, RefObject } from 'react';
|
|
2
|
-
import { PdfField } from '../../interface/types';
|
|
3
|
-
import { getFieldBackgroundColor, getPagePosition } from '../../utils';
|
|
2
|
+
import { DataModelValues, PdfField } from '../../interface/types';
|
|
3
|
+
import { evaluateDisplayCondition, getFieldBackgroundColor, getPagePosition } from '../../utils';
|
|
4
4
|
|
|
5
5
|
interface PdfViewFieldContainer {
|
|
6
6
|
pdfWrapperRef: RefObject<HTMLDivElement>;
|
|
7
|
+
data?: DataModelValues;
|
|
7
8
|
error?: string;
|
|
8
9
|
field: PdfField;
|
|
9
10
|
recipientsColors: Record<string, string>;
|
|
@@ -11,11 +12,19 @@ interface PdfViewFieldContainer {
|
|
|
11
12
|
|
|
12
13
|
export const PdfViewFieldContainer: FC<PropsWithChildren<PdfViewFieldContainer>> = ({
|
|
13
14
|
children,
|
|
15
|
+
data,
|
|
14
16
|
error,
|
|
15
17
|
field,
|
|
16
18
|
pdfWrapperRef,
|
|
17
19
|
recipientsColors,
|
|
18
20
|
}) => {
|
|
21
|
+
const visible =
|
|
22
|
+
!field.displayCondition || evaluateDisplayCondition(field.displayCondition, data);
|
|
23
|
+
|
|
24
|
+
if (!visible) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
19
28
|
const pagePos = getPagePosition(field.page, pdfWrapperRef);
|
|
20
29
|
const bgColor = getFieldBackgroundColor(field.recipient, recipientsColors);
|
|
21
30
|
return (
|
|
@@ -90,6 +90,7 @@ export const PdfView: FC<PdfViewProps> = ({
|
|
|
90
90
|
<PdfViewFieldContainer
|
|
91
91
|
key={field.id}
|
|
92
92
|
field={field}
|
|
93
|
+
data={previewMode === 'fillable' ? previewData : data}
|
|
93
94
|
error={errors[field.path!] || ''}
|
|
94
95
|
recipientsColors={recipientsColors}
|
|
95
96
|
pdfWrapperRef={pdfWrapperRef}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const CALCULATED_OPERATIONS = ['+', '-', '*', '/', '(', ')'];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
DisplayConditionGroup,
|
|
5
|
+
DisplayConditionSingle,
|
|
6
|
+
DisplayConditionState,
|
|
7
|
+
} from '../interface/types';
|
|
8
|
+
|
|
9
|
+
export const defaultCondition = (): DisplayConditionSingle => ({
|
|
10
|
+
dataPointKey: '',
|
|
11
|
+
id: uuidv4(),
|
|
12
|
+
operator: 'is_equal_to',
|
|
13
|
+
value: '',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const defaultGroup = (): DisplayConditionGroup => ({
|
|
17
|
+
conditions: [defaultCondition()],
|
|
18
|
+
id: uuidv4(),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const defaultState = (): DisplayConditionState => ({
|
|
22
|
+
behavior: 'show',
|
|
23
|
+
groups: [defaultGroup()],
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const MODAL_CONTENT_MAX_HEIGHT = '70vh';
|
package/src/constants/index.ts
CHANGED
package/src/interface/types.ts
CHANGED
|
@@ -16,6 +16,25 @@ export type FillableFieldType = 'text' | 'date' | 'checkbox' | 'radio' | 'number
|
|
|
16
16
|
|
|
17
17
|
export type PdfFieldSubType = FillableFieldType | ESignFieldType;
|
|
18
18
|
|
|
19
|
+
export interface DisplayConditionState {
|
|
20
|
+
behavior: 'show' | 'hide';
|
|
21
|
+
groups: DisplayConditionGroup[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface DisplayConditionGroup {
|
|
25
|
+
id: string;
|
|
26
|
+
logicalOperator?: 'and' | 'or';
|
|
27
|
+
conditions: DisplayConditionSingle[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface DisplayConditionSingle {
|
|
31
|
+
id: string;
|
|
32
|
+
dataPointKey: string;
|
|
33
|
+
logicalOperator?: 'and' | 'or';
|
|
34
|
+
operator: string;
|
|
35
|
+
value: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
19
38
|
export interface PdfField {
|
|
20
39
|
id: string;
|
|
21
40
|
type: FieldTypeEnum;
|
|
@@ -32,6 +51,7 @@ export interface PdfField {
|
|
|
32
51
|
description?: string;
|
|
33
52
|
formula?: StructuredFormula;
|
|
34
53
|
formulaFormat?: CalculatedFieldFormat;
|
|
54
|
+
displayCondition?: DisplayConditionState | null;
|
|
35
55
|
}
|
|
36
56
|
|
|
37
57
|
export interface FieldTypeOption {
|
|
@@ -112,7 +132,11 @@ export interface SchemaSimpleNumber extends SchemaNodeProps {
|
|
|
112
132
|
type: 'number';
|
|
113
133
|
}
|
|
114
134
|
|
|
115
|
-
export
|
|
135
|
+
export interface SchemaSimpleDate extends SchemaNodeProps {
|
|
136
|
+
type: 'date';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export type SchemaSimple = SchemaSimpleString | SchemaSimpleNumber | SchemaSimpleDate;
|
|
116
140
|
|
|
117
141
|
export type DataModelValues = Record<string, any>;
|
|
118
142
|
|
|
@@ -140,3 +164,42 @@ export interface DataChangePayload {
|
|
|
140
164
|
* it is displayed.
|
|
141
165
|
*/
|
|
142
166
|
export type PreviewMode = 'fillable' | 'view';
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Display condition types for the Rules and Conditions modal and evaluation.
|
|
170
|
+
*/
|
|
171
|
+
|
|
172
|
+
/** Operators for string-type fields. */
|
|
173
|
+
export const STRING_OPERATORS = [
|
|
174
|
+
{ label: 'Contains', value: 'contains' },
|
|
175
|
+
{ label: 'Does not contain', value: 'does_not_contain' },
|
|
176
|
+
{ label: 'Is equal to', value: 'is_equal_to' },
|
|
177
|
+
{ label: 'Is not equal to', value: 'is_not_equal_to' },
|
|
178
|
+
{ label: 'Starts with', value: 'starts_with' },
|
|
179
|
+
{ label: 'Ends with', value: 'ends_with' },
|
|
180
|
+
{ label: 'Is empty', value: 'is_empty' },
|
|
181
|
+
{ label: 'Is not empty', value: 'is_not_empty' },
|
|
182
|
+
] as const;
|
|
183
|
+
|
|
184
|
+
/** Operators for number-type fields. */
|
|
185
|
+
export const NUMBER_OPERATORS = [
|
|
186
|
+
{ label: '== (equal to)', value: 'num_eq' },
|
|
187
|
+
{ label: '!= (not equal to)', value: 'num_neq' },
|
|
188
|
+
{ label: '> (greater than)', value: 'num_gt' },
|
|
189
|
+
{ label: '< (less than)', value: 'num_lt' },
|
|
190
|
+
{ label: '>= (greater than or equal to)', value: 'num_gte' },
|
|
191
|
+
{ label: '<= (less than or equal to)', value: 'num_lte' },
|
|
192
|
+
] as const;
|
|
193
|
+
|
|
194
|
+
export type ConditionOperator =
|
|
195
|
+
| (typeof STRING_OPERATORS)[number]['value']
|
|
196
|
+
| (typeof NUMBER_OPERATORS)[number]['value'];
|
|
197
|
+
|
|
198
|
+
/** Operators that do not require a value (empty/is not empty) */
|
|
199
|
+
export const VALUE_LESS_OPERATORS: ConditionOperator[] = ['is_empty', 'is_not_empty'];
|
|
200
|
+
|
|
201
|
+
export interface DataPointOption {
|
|
202
|
+
fieldType: 'number' | 'string';
|
|
203
|
+
fullKey: string;
|
|
204
|
+
title: string;
|
|
205
|
+
}
|
|
@@ -15,19 +15,9 @@
|
|
|
15
15
|
max-height: 85vh;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
.dte-formula-modal-body {
|
|
19
|
-
padding: var(--spacing-2);
|
|
20
|
-
overflow: auto;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
.dte-formula-modal-columns {
|
|
24
|
-
min-height: 280px;
|
|
25
|
-
max-height: 60vh;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
18
|
/* Field sidebar (left) */
|
|
29
19
|
.dte-formula-sidebar {
|
|
30
|
-
flex: 0 0
|
|
20
|
+
flex: 0 0 250px;
|
|
31
21
|
border-right: 1px solid var(--border-color);
|
|
32
22
|
padding-right: var(--spacing-2);
|
|
33
23
|
gap: var(--spacing-2);
|
|
@@ -115,20 +105,6 @@
|
|
|
115
105
|
opacity: 1;
|
|
116
106
|
}
|
|
117
107
|
|
|
118
|
-
.dte-formula-advanced-toggle {
|
|
119
|
-
background: none;
|
|
120
|
-
border: none;
|
|
121
|
-
padding: var(--spacing-0);
|
|
122
|
-
font-size: var(--typescale-2);
|
|
123
|
-
color: var(--menu-active-color, #0265dc);
|
|
124
|
-
cursor: pointer;
|
|
125
|
-
text-decoration: none;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
.dte-formula-advanced-toggle:hover {
|
|
129
|
-
text-decoration: underline;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
108
|
.dte-formula-advanced {
|
|
133
109
|
margin-top: var(--spacing-2);
|
|
134
110
|
padding-top: var(--spacing-2);
|
|
@@ -138,30 +114,10 @@
|
|
|
138
114
|
gap: var(--spacing-2);
|
|
139
115
|
}
|
|
140
116
|
|
|
141
|
-
.dte-formula-advanced-row {
|
|
142
|
-
margin-bottom: var(--spacing-0);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
117
|
.dte-formula-advanced-value {
|
|
146
118
|
color: var(--color-neutral-300);
|
|
147
119
|
}
|
|
148
120
|
|
|
149
|
-
.dte-formula-advanced-range {
|
|
150
|
-
width: 100%;
|
|
151
|
-
margin: var(--spacing-0);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
.dte-formula-advanced-checkbox {
|
|
155
|
-
display: flex;
|
|
156
|
-
align-items: center;
|
|
157
|
-
gap: var(--spacing-1);
|
|
158
|
-
cursor: pointer;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
.dte-formula-advanced-checkbox input {
|
|
162
|
-
margin: var(--spacing-0);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
121
|
.dte-formula-advanced-input {
|
|
166
122
|
flex: 1;
|
|
167
123
|
min-width: 0;
|
|
@@ -182,70 +138,6 @@
|
|
|
182
138
|
border-top: 1px solid var(--border-color);
|
|
183
139
|
}
|
|
184
140
|
|
|
185
|
-
/* Token input */
|
|
186
|
-
.dte-formula-token-input-wrapper {
|
|
187
|
-
display: flex;
|
|
188
|
-
flex-direction: row;
|
|
189
|
-
align-items: stretch;
|
|
190
|
-
gap: var(--spacing-2);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
.dte-formula-token-input {
|
|
194
|
-
flex: 1;
|
|
195
|
-
padding: var(--spacing-1) var(--spacing-2);
|
|
196
|
-
border: 1px solid var(--border-color);
|
|
197
|
-
border-radius: 4px;
|
|
198
|
-
outline: none;
|
|
199
|
-
flex-wrap: wrap;
|
|
200
|
-
gap: 2px;
|
|
201
|
-
cursor: text;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
.dte-formula-token-input:focus {
|
|
205
|
-
border-color: var(--border-color-active);
|
|
206
|
-
box-shadow: 0 0 0 1px var(--border-color-active);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
.dte-formula-placeholder {
|
|
210
|
-
color: var(--color-neutral-200);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
.dte-formula-token {
|
|
214
|
-
margin: var(--spacing-half);
|
|
215
|
-
user-select: none;
|
|
216
|
-
font-size: var(--typescale-2);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
.dte-formula-token-field {
|
|
220
|
-
padding: 2px var(--spacing-half);
|
|
221
|
-
background: var(--menu-active-color, #0265dc);
|
|
222
|
-
border-radius: var(--spacing-half, 4px);
|
|
223
|
-
color: var(--white);
|
|
224
|
-
flex-shrink: 0;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
.dte-formula-token-delete {
|
|
228
|
-
display: inline-flex;
|
|
229
|
-
align-items: center;
|
|
230
|
-
justify-content: center;
|
|
231
|
-
padding: var(--spacing-0);
|
|
232
|
-
margin: var(--spacing-0);
|
|
233
|
-
margin-left: 2px;
|
|
234
|
-
border: none;
|
|
235
|
-
background: transparent;
|
|
236
|
-
color: var(--color-neutral-200);
|
|
237
|
-
cursor: pointer;
|
|
238
|
-
border-radius: 2px;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
.dte-formula-token-delete:hover {
|
|
242
|
-
color: var(--danger, #dc3545);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
.dte-formula-token-number {
|
|
246
|
-
font-variant-numeric: tabular-nums;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
141
|
.dte-formula-caret {
|
|
250
142
|
width: 0;
|
|
251
143
|
height: 1em;
|
|
@@ -259,49 +151,3 @@
|
|
|
259
151
|
opacity: 0;
|
|
260
152
|
}
|
|
261
153
|
}
|
|
262
|
-
|
|
263
|
-
/* Autosuggest - left side, always visible */
|
|
264
|
-
.dte-formula-autosuggest {
|
|
265
|
-
margin: var(--spacing-0);
|
|
266
|
-
padding: var(--spacing-0);
|
|
267
|
-
list-style: none;
|
|
268
|
-
width: 200px;
|
|
269
|
-
min-width: 200px;
|
|
270
|
-
max-height: 200px;
|
|
271
|
-
overflow-y: auto;
|
|
272
|
-
background: var(--white);
|
|
273
|
-
border: 1px solid var(--border-color);
|
|
274
|
-
border-radius: 4px;
|
|
275
|
-
flex-shrink: 0;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
.dte-formula-autosuggest-item {
|
|
279
|
-
padding: var(--spacing-1) var(--spacing-2);
|
|
280
|
-
cursor: pointer;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
.dte-formula-autosuggest-item:hover,
|
|
284
|
-
.dte-formula-autosuggest-item.--highlight {
|
|
285
|
-
color: var(--menu-active-color);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
.dte-formula-autosuggest-item.empty {
|
|
289
|
-
cursor: default;
|
|
290
|
-
color: var(--color-neutral-200);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
.dte-formula-box {
|
|
294
|
-
padding: var(--spacing-1) var(--spacing-2);
|
|
295
|
-
border: 1px solid var(--border-color);
|
|
296
|
-
border-radius: 4px;
|
|
297
|
-
background: var(--color-neutral-0);
|
|
298
|
-
cursor: pointer;
|
|
299
|
-
display: flex;
|
|
300
|
-
overflow-x: auto;
|
|
301
|
-
align-items: center;
|
|
302
|
-
gap: 2px;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
.dte-formula-box:hover {
|
|
306
|
-
border-color: var(--border-color-hover);
|
|
307
|
-
}
|