@servicetitan/dte-pdf-editor 1.39.0 → 1.41.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 +4 -1
- package/dist/components/display-conditions/condition-group.d.ts.map +1 -1
- package/dist/components/display-conditions/condition-group.js +6 -20
- package/dist/components/display-conditions/condition-group.js.map +1 -1
- package/dist/components/display-conditions/condition-groups-section.d.ts +2 -1
- package/dist/components/display-conditions/condition-groups-section.d.ts.map +1 -1
- package/dist/components/display-conditions/condition-groups-section.js +4 -9
- package/dist/components/display-conditions/condition-groups-section.js.map +1 -1
- package/dist/components/display-conditions/condition-row.d.ts.map +1 -1
- package/dist/components/display-conditions/condition-row.js +1 -1
- package/dist/components/display-conditions/condition-row.js.map +1 -1
- package/dist/components/display-conditions/display-condition-modal.d.ts.map +1 -1
- package/dist/components/display-conditions/display-condition-modal.js +41 -8
- package/dist/components/display-conditions/display-condition-modal.js.map +1 -1
- package/dist/components/field-sidebar/field-sidebar.d.ts +2 -1
- package/dist/components/field-sidebar/field-sidebar.d.ts.map +1 -1
- package/dist/components/field-sidebar/field-sidebar.js +9 -3
- package/dist/components/field-sidebar/field-sidebar.js.map +1 -1
- package/dist/components/pdf-editor/pdf-editor.d.ts +2 -1
- package/dist/components/pdf-editor/pdf-editor.d.ts.map +1 -1
- package/dist/components/pdf-editor/pdf-editor.js +2 -2
- package/dist/components/pdf-editor/pdf-editor.js.map +1 -1
- package/dist/constants/calculated.constants.d.ts +1 -0
- package/dist/constants/calculated.constants.d.ts.map +1 -1
- package/dist/constants/calculated.constants.js +1 -0
- package/dist/constants/calculated.constants.js.map +1 -1
- package/dist/constants/conditions.constants.d.ts +5 -0
- package/dist/constants/conditions.constants.d.ts.map +1 -1
- package/dist/constants/conditions.constants.js +5 -0
- package/dist/constants/conditions.constants.js.map +1 -1
- package/dist/interface/types.d.ts +0 -1
- package/dist/interface/types.d.ts.map +1 -1
- package/dist/utils/conditions/schema-data-points.utils.d.ts.map +1 -1
- package/dist/utils/conditions/schema-data-points.utils.js +0 -2
- package/dist/utils/conditions/schema-data-points.utils.js.map +1 -1
- package/dist/utils/formula/format-calculated-result.utils.d.ts +1 -1
- package/dist/utils/formula/format-calculated-result.utils.d.ts.map +1 -1
- package/dist/utils/formula/format-calculated-result.utils.js +24 -9
- package/dist/utils/formula/format-calculated-result.utils.js.map +1 -1
- package/package.json +1 -1
- package/src/components/display-conditions/condition-group.tsx +26 -53
- package/src/components/display-conditions/condition-groups-section.tsx +13 -27
- package/src/components/display-conditions/condition-row.tsx +0 -1
- package/src/components/display-conditions/display-condition-modal.tsx +78 -18
- package/src/components/field-sidebar/field-sidebar.tsx +11 -3
- package/src/components/pdf-editor/pdf-editor.tsx +4 -1
- package/src/constants/calculated.constants.ts +2 -0
- package/src/constants/conditions.constants.ts +6 -0
- package/src/interface/types.ts +0 -1
- package/src/utils/conditions/schema-data-points.utils.ts +0 -2
- package/src/utils/formula/format-calculated-result.utils.ts +28 -12
|
@@ -24,7 +24,6 @@ function walkSchema(schema, prefix, parentTitles) {
|
|
|
24
24
|
result.push({
|
|
25
25
|
fieldType,
|
|
26
26
|
fullKey,
|
|
27
|
-
group: fieldType === 'number' ? 'Numeric Fields' : 'Data Model',
|
|
28
27
|
title: fullTitle || fullKey,
|
|
29
28
|
});
|
|
30
29
|
}
|
|
@@ -52,7 +51,6 @@ export function getDocumentFieldsDataPointOptions(fields) {
|
|
|
52
51
|
result.push({
|
|
53
52
|
fieldType,
|
|
54
53
|
fullKey: f.path,
|
|
55
|
-
group: 'Document Fields',
|
|
56
54
|
title: f.label || f.path,
|
|
57
55
|
});
|
|
58
56
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-data-points.utils.js","sourceRoot":"","sources":["../../../src/utils/conditions/schema-data-points.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,aAAa,GAIhB,MAAM,uBAAuB,CAAC;AAE/B,SAAS,mBAAmB,CACxB,IAEe;;IAEf,OAAO,CACH,CAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,OAAO,0CAAE,iBAAiB,MAAK,IAAI,IAAI,CAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,OAAO,0CAAE,qBAAqB,MAAK,IAAI,CAC7F,CAAC;AACN,CAAC;AAED,SAAS,WAAW,CAChB,IAAgB;IAEhB,OAAO,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,MAAK,QAAQ,IAAI,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,MAAK,QAAQ,CAAC;AAC9D,CAAC;AAED,SAAS,UAAU,CACf,MAAgC,EAChC,MAAc,EACd,YAAsB;;IAEtB,IAAI,CAAC,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,UAAU,CAAA,EAAE,CAAC;QACtB,OAAO,EAAE,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1D,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QAClD,MAAM,KAAK,GAAG,MAAC,IAA2B,CAAC,KAAK,mCAAI,GAAG,CAAC;QACxD,MAAM,SAAS,GAAG,CAAC,GAAG,YAAY,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEvD,IAAI,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,MAAK,QAAQ,EAAE,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,IAAoB,EAAE,OAAO,EAAE,CAAC,GAAG,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QACxF,CAAC;aAAM,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;YACxD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/D,MAAM,CAAC,IAAI,CAAC;gBACR,SAAS;gBACT,OAAO;gBACP,KAAK,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"schema-data-points.utils.js","sourceRoot":"","sources":["../../../src/utils/conditions/schema-data-points.utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,5 +3,5 @@ import { CalculatedFieldFormat } from '../../interface/types';
|
|
|
3
3
|
* Format a calculated formula result for display using advanced settings.
|
|
4
4
|
* Applies rounding, decimal places, thousands/decimal separators, result type (number/currency/percent/date), and prefix/postfix.
|
|
5
5
|
*/
|
|
6
|
-
export declare
|
|
6
|
+
export declare const formatCalculatedResult: (value: number, format: CalculatedFieldFormat | undefined) => string;
|
|
7
7
|
//# sourceMappingURL=format-calculated-result.utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-calculated-result.utils.d.ts","sourceRoot":"","sources":["../../../src/utils/formula/format-calculated-result.utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAA6B,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"format-calculated-result.utils.d.ts","sourceRoot":"","sources":["../../../src/utils/formula/format-calculated-result.utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAA6B,MAAM,uBAAuB,CAAC;AA2EzF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GAC/B,OAAO,MAAM,EACb,QAAQ,qBAAqB,GAAG,SAAS,KAC1C,MAiCF,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DEFAULT_DATE_FORMAT } from '../../constants';
|
|
2
|
-
|
|
1
|
+
import { DEFAULT_DATE_FORMAT, MAX_DATE_DISPLAY_RANGE_YEARS } from '../../constants';
|
|
2
|
+
const roundValue = (value, decimals, mode) => {
|
|
3
3
|
const factor = 10 ** decimals;
|
|
4
4
|
const scaled = value * factor;
|
|
5
5
|
switch (mode) {
|
|
@@ -10,8 +10,8 @@ function roundValue(value, decimals, mode) {
|
|
|
10
10
|
default:
|
|
11
11
|
return Math.round(scaled) / factor;
|
|
12
12
|
}
|
|
13
|
-
}
|
|
14
|
-
|
|
13
|
+
};
|
|
14
|
+
const formatIntegerPart = (s, thousandsSeparator, decimalSeparator) => {
|
|
15
15
|
if (!thousandsSeparator) {
|
|
16
16
|
return s;
|
|
17
17
|
}
|
|
@@ -24,7 +24,7 @@ function formatIntegerPart(s, thousandsSeparator, decimalSeparator) {
|
|
|
24
24
|
i = start;
|
|
25
25
|
}
|
|
26
26
|
return parts.join(sep);
|
|
27
|
-
}
|
|
27
|
+
};
|
|
28
28
|
const DATE_FORMAT_TOKENS = {
|
|
29
29
|
YYYY: d => String(d.getFullYear()),
|
|
30
30
|
YY: d => String(d.getFullYear()).slice(-2),
|
|
@@ -36,7 +36,7 @@ const DATE_FORMAT_TOKENS = {
|
|
|
36
36
|
D: d => String(d.getDate()),
|
|
37
37
|
};
|
|
38
38
|
const DATE_TOKEN_PATTERN = new RegExp(Object.keys(DATE_FORMAT_TOKENS).join('|'), 'g');
|
|
39
|
-
|
|
39
|
+
const formatDateValue = (epochMs, dateFormat) => {
|
|
40
40
|
const date = new Date(epochMs);
|
|
41
41
|
if (isNaN(date.getTime())) {
|
|
42
42
|
return '';
|
|
@@ -45,17 +45,32 @@ function formatDateValue(epochMs, dateFormat) {
|
|
|
45
45
|
const fn = DATE_FORMAT_TOKENS[match];
|
|
46
46
|
return fn ? fn(date) : match;
|
|
47
47
|
});
|
|
48
|
-
}
|
|
48
|
+
};
|
|
49
|
+
const isDateWithinDisplayRange = (epochMs, referenceMs = Date.now()) => {
|
|
50
|
+
const date = new Date(epochMs);
|
|
51
|
+
if (isNaN(date.getTime())) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
const ref = new Date(referenceMs);
|
|
55
|
+
const min = new Date(ref);
|
|
56
|
+
min.setFullYear(min.getFullYear() - MAX_DATE_DISPLAY_RANGE_YEARS);
|
|
57
|
+
const max = new Date(ref);
|
|
58
|
+
max.setFullYear(max.getFullYear() + MAX_DATE_DISPLAY_RANGE_YEARS);
|
|
59
|
+
return date >= min && date <= max;
|
|
60
|
+
};
|
|
49
61
|
/**
|
|
50
62
|
* Format a calculated formula result for display using advanced settings.
|
|
51
63
|
* Applies rounding, decimal places, thousands/decimal separators, result type (number/currency/percent/date), and prefix/postfix.
|
|
52
64
|
*/
|
|
53
|
-
export
|
|
65
|
+
export const formatCalculatedResult = (value, format) => {
|
|
54
66
|
var _a;
|
|
55
67
|
if (format == null) {
|
|
56
68
|
return String(value);
|
|
57
69
|
}
|
|
58
70
|
if (format.resultType === 'date') {
|
|
71
|
+
if (!isDateWithinDisplayRange(value)) {
|
|
72
|
+
return '';
|
|
73
|
+
}
|
|
59
74
|
return formatDateValue(value, (_a = format.dateFormat) !== null && _a !== void 0 ? _a : DEFAULT_DATE_FORMAT);
|
|
60
75
|
}
|
|
61
76
|
const { decimalSeparator, decimalSeparatorEnabled, decimals, postfixText, prefixText, roundingMode, thousandsSeparator, } = format;
|
|
@@ -67,5 +82,5 @@ export function formatCalculatedResult(value, format) {
|
|
|
67
82
|
const decSuffix = decimals > 0 ? decimalSep + (decPart !== null && decPart !== void 0 ? decPart : '') : '';
|
|
68
83
|
const numberStr = intFormatted + decSuffix;
|
|
69
84
|
return `${prefixText}${numberStr}${postfixText}`;
|
|
70
|
-
}
|
|
85
|
+
};
|
|
71
86
|
//# sourceMappingURL=format-calculated-result.utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-calculated-result.utils.js","sourceRoot":"","sources":["../../../src/utils/formula/format-calculated-result.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"format-calculated-result.utils.js","sourceRoot":"","sources":["../../../src/utils/formula/format-calculated-result.utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Button, Flex,
|
|
1
|
+
import { Button, Flex, Text } from '@servicetitan/anvil2';
|
|
2
2
|
import PlusIcon from '@servicetitan/anvil2/assets/icons/material/round/add.svg';
|
|
3
3
|
import TrashIcon from '@servicetitan/anvil2/assets/icons/material/round/delete.svg';
|
|
4
4
|
import { useCallback } from 'react';
|
|
@@ -12,31 +12,36 @@ import { ConditionRow } from './condition-row';
|
|
|
12
12
|
|
|
13
13
|
export interface ConditionGroupProps {
|
|
14
14
|
canDelete: boolean;
|
|
15
|
+
conditionJoinOperator: 'and' | 'or';
|
|
15
16
|
dataPointOptions: DataPointOption[];
|
|
16
17
|
group: DisplayConditionGroup;
|
|
17
18
|
onDelete: () => void;
|
|
18
19
|
onUpdate: (g: DisplayConditionGroup) => void;
|
|
19
20
|
ruleIndex: number;
|
|
21
|
+
/** When 1, the UI hides the per-rule title (single-rule layout). */
|
|
22
|
+
totalRuleCount: number;
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
export function ConditionGroup({
|
|
23
26
|
canDelete,
|
|
27
|
+
conditionJoinOperator,
|
|
24
28
|
dataPointOptions,
|
|
25
29
|
group,
|
|
26
30
|
onDelete,
|
|
27
31
|
onUpdate,
|
|
28
32
|
ruleIndex,
|
|
33
|
+
totalRuleCount,
|
|
29
34
|
}: Readonly<ConditionGroupProps>) {
|
|
30
35
|
const addCondition = useCallback(() => {
|
|
31
36
|
const newCondition: DisplayConditionSingle = {
|
|
32
37
|
...defaultCondition(),
|
|
33
|
-
logicalOperator:
|
|
38
|
+
logicalOperator: conditionJoinOperator,
|
|
34
39
|
};
|
|
35
40
|
onUpdate({
|
|
36
41
|
...group,
|
|
37
42
|
conditions: [...group.conditions, newCondition],
|
|
38
43
|
});
|
|
39
|
-
}, [group, onUpdate]);
|
|
44
|
+
}, [conditionJoinOperator, group, onUpdate]);
|
|
40
45
|
|
|
41
46
|
const updateCondition = useCallback(
|
|
42
47
|
(index: number, c: DisplayConditionSingle) => {
|
|
@@ -62,61 +67,29 @@ export function ConditionGroup({
|
|
|
62
67
|
[group, onUpdate],
|
|
63
68
|
);
|
|
64
69
|
|
|
65
|
-
const
|
|
66
|
-
(conditionIndex: number, value: string) => {
|
|
67
|
-
const next = [...group.conditions];
|
|
68
|
-
next[conditionIndex] = {
|
|
69
|
-
...next[conditionIndex],
|
|
70
|
-
logicalOperator: value as 'and' | 'or',
|
|
71
|
-
};
|
|
72
|
-
onUpdate({ ...group, conditions: next });
|
|
73
|
-
},
|
|
74
|
-
[group, onUpdate],
|
|
75
|
-
);
|
|
70
|
+
const showRuleHeading = totalRuleCount > 1;
|
|
76
71
|
|
|
77
72
|
return (
|
|
78
73
|
<Flex direction="column" gap="2" flex={1}>
|
|
79
|
-
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
flex={1}
|
|
97
|
-
style={{
|
|
98
|
-
border: '1px solid #e0e0e0',
|
|
99
|
-
borderRadius: 8,
|
|
100
|
-
padding: 12,
|
|
101
|
-
}}
|
|
102
|
-
>
|
|
74
|
+
{showRuleHeading && (
|
|
75
|
+
<Flex direction="row" alignItems="center" justifyContent="space-between" flex={1}>
|
|
76
|
+
<Text size="medium" variant="body" style={{ fontWeight: 'bold' }}>
|
|
77
|
+
Rule {ruleIndex + 1}
|
|
78
|
+
</Text>
|
|
79
|
+
{canDelete && (
|
|
80
|
+
<Button
|
|
81
|
+
appearance="ghost"
|
|
82
|
+
aria-label="Delete rule"
|
|
83
|
+
icon={{ before: TrashIcon }}
|
|
84
|
+
size="large"
|
|
85
|
+
onClick={onDelete}
|
|
86
|
+
/>
|
|
87
|
+
)}
|
|
88
|
+
</Flex>
|
|
89
|
+
)}
|
|
90
|
+
<Flex direction="column" gap="3" flex={1}>
|
|
103
91
|
{group.conditions.map((c, i) => (
|
|
104
92
|
<Flex key={c.id} direction="column" gap="3" style={{ padding: '8px 0' }}>
|
|
105
|
-
{i > 0 && (
|
|
106
|
-
<Flex justifyContent="center" alignItems="center" gap="2">
|
|
107
|
-
<SegmentedControl
|
|
108
|
-
selected={c.logicalOperator ?? 'and'}
|
|
109
|
-
onChange={(v: string) => handleLogicalOperatorChange(i, v)}
|
|
110
|
-
>
|
|
111
|
-
<SegmentedControl.Segment value="and">
|
|
112
|
-
And
|
|
113
|
-
</SegmentedControl.Segment>
|
|
114
|
-
<SegmentedControl.Segment value="or">
|
|
115
|
-
Or
|
|
116
|
-
</SegmentedControl.Segment>
|
|
117
|
-
</SegmentedControl>
|
|
118
|
-
</Flex>
|
|
119
|
-
)}
|
|
120
93
|
<ConditionRow
|
|
121
94
|
canRemove
|
|
122
95
|
condition={c}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { Button, Flex
|
|
1
|
+
import { Button, Flex } from '@servicetitan/anvil2';
|
|
2
2
|
import PlusIcon from '@servicetitan/anvil2/assets/icons/material/round/add.svg';
|
|
3
|
+
import { MAX_DISPLAY_CONDITION_RULES_UI } from '../../constants';
|
|
3
4
|
import type { DataPointOption, DisplayConditionGroup } from '../../interface/types';
|
|
4
5
|
import { ConditionGroup } from './condition-group';
|
|
5
6
|
|
|
6
7
|
export interface ConditionGroupsSectionProps {
|
|
8
|
+
conditionJoinOperator: 'and' | 'or';
|
|
7
9
|
dataPointOptions: DataPointOption[];
|
|
8
10
|
groups: DisplayConditionGroup[];
|
|
9
11
|
onAddGroup: () => void;
|
|
@@ -12,6 +14,7 @@ export interface ConditionGroupsSectionProps {
|
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
export function ConditionGroupsSection({
|
|
17
|
+
conditionJoinOperator,
|
|
15
18
|
dataPointOptions,
|
|
16
19
|
groups,
|
|
17
20
|
onAddGroup,
|
|
@@ -22,42 +25,25 @@ export function ConditionGroupsSection({
|
|
|
22
25
|
<Flex direction="column" gap="4">
|
|
23
26
|
{groups.map((group, index) => (
|
|
24
27
|
<Flex key={group.id} direction="column" gap="3">
|
|
25
|
-
{index > 0 && (
|
|
26
|
-
<Flex
|
|
27
|
-
justifyContent="center"
|
|
28
|
-
alignItems="center"
|
|
29
|
-
gap="2"
|
|
30
|
-
style={{ padding: '12px' }}
|
|
31
|
-
>
|
|
32
|
-
<SegmentedControl
|
|
33
|
-
selected={group.logicalOperator ?? 'and'}
|
|
34
|
-
onChange={(value: string) =>
|
|
35
|
-
onUpdateGroup(index, {
|
|
36
|
-
...group,
|
|
37
|
-
logicalOperator: value as 'and' | 'or',
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
|
-
>
|
|
41
|
-
<SegmentedControl.Segment value="and">And</SegmentedControl.Segment>
|
|
42
|
-
<SegmentedControl.Segment value="or">Or</SegmentedControl.Segment>
|
|
43
|
-
</SegmentedControl>
|
|
44
|
-
</Flex>
|
|
45
|
-
)}
|
|
46
28
|
<ConditionGroup
|
|
47
29
|
canDelete={groups.length > 1}
|
|
30
|
+
conditionJoinOperator={conditionJoinOperator}
|
|
48
31
|
dataPointOptions={dataPointOptions}
|
|
49
32
|
group={group}
|
|
50
33
|
onDelete={() => onRemoveGroup(index)}
|
|
51
34
|
onUpdate={g => onUpdateGroup(index, g)}
|
|
52
35
|
ruleIndex={index}
|
|
36
|
+
totalRuleCount={groups.length}
|
|
53
37
|
/>
|
|
54
38
|
</Flex>
|
|
55
39
|
))}
|
|
56
|
-
|
|
57
|
-
<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
40
|
+
{groups.length < MAX_DISPLAY_CONDITION_RULES_UI && (
|
|
41
|
+
<Flex justifyContent="center" flex={1} style={{ paddingTop: 8 }}>
|
|
42
|
+
<Button appearance="secondary" icon={{ before: PlusIcon }} onClick={onAddGroup}>
|
|
43
|
+
Add Rule
|
|
44
|
+
</Button>
|
|
45
|
+
</Flex>
|
|
46
|
+
)}
|
|
61
47
|
</Flex>
|
|
62
48
|
);
|
|
63
49
|
}
|
|
@@ -100,7 +100,6 @@ export function ConditionRow({
|
|
|
100
100
|
<Flex flex={1}>
|
|
101
101
|
<Combobox
|
|
102
102
|
flex={1}
|
|
103
|
-
groupBy="group"
|
|
104
103
|
itemToKey={(item: DataPointOption | null) => item?.fullKey ?? ''}
|
|
105
104
|
itemToString={(item: DataPointOption | null) => item?.title ?? ''}
|
|
106
105
|
items={dataPointOptions}
|
|
@@ -1,10 +1,45 @@
|
|
|
1
|
-
import { Button,
|
|
1
|
+
import { Button, Chip, Dialog, Flex, SegmentedControl, Text } from '@servicetitan/anvil2';
|
|
2
2
|
import { useCallback, useMemo, useState } from 'react';
|
|
3
3
|
import { defaultGroup, defaultState, MODAL_CONTENT_MAX_HEIGHT } from '../../constants';
|
|
4
4
|
import type { DisplayConditionState, PdfField, SchemaObject } from '../../interface/types';
|
|
5
5
|
import { getDataPointOptions, isValidNumber } from '../../utils';
|
|
6
6
|
import { ConditionGroupsSection } from './condition-groups-section';
|
|
7
7
|
|
|
8
|
+
type ConditionMatchType = 'and' | 'or';
|
|
9
|
+
|
|
10
|
+
const deriveConditionMatchType = (conditionState: DisplayConditionState): ConditionMatchType => {
|
|
11
|
+
for (let g = 0; g < conditionState.groups.length; g++) {
|
|
12
|
+
const group = conditionState.groups[g];
|
|
13
|
+
if (g > 0 && group.logicalOperator === 'or') {
|
|
14
|
+
return 'or';
|
|
15
|
+
}
|
|
16
|
+
for (let i = 1; i < group.conditions.length; i++) {
|
|
17
|
+
if (group.conditions[i]?.logicalOperator === 'or') {
|
|
18
|
+
return 'or';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return 'and';
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const applyConditionMatchType = (
|
|
26
|
+
conditionState: DisplayConditionState,
|
|
27
|
+
matchType: ConditionMatchType,
|
|
28
|
+
): DisplayConditionState => {
|
|
29
|
+
return {
|
|
30
|
+
...conditionState,
|
|
31
|
+
groups: conditionState.groups.map((group, groupIndex) => ({
|
|
32
|
+
...group,
|
|
33
|
+
...(groupIndex > 0 ? { logicalOperator: matchType } : {}),
|
|
34
|
+
conditions: group.conditions.map((c, i) =>
|
|
35
|
+
i === 0
|
|
36
|
+
? { ...c, logicalOperator: undefined }
|
|
37
|
+
: { ...c, logicalOperator: matchType },
|
|
38
|
+
),
|
|
39
|
+
})),
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
|
|
8
43
|
const BEHAVIOR_OPTIONS = [
|
|
9
44
|
{ label: 'Show', value: 'show' },
|
|
10
45
|
{ label: 'Hide', value: 'hide' },
|
|
@@ -30,6 +65,9 @@ export function DisplayConditionModal({
|
|
|
30
65
|
const [state, setState] = useState<DisplayConditionState>(() =>
|
|
31
66
|
initialState?.groups?.length ? initialState : defaultState(),
|
|
32
67
|
);
|
|
68
|
+
const [matchType, setMatchType] = useState<ConditionMatchType>(() =>
|
|
69
|
+
deriveConditionMatchType(initialState?.groups?.length ? initialState : defaultState()),
|
|
70
|
+
);
|
|
33
71
|
|
|
34
72
|
const dataPointOptions = useMemo(
|
|
35
73
|
() => getDataPointOptions(schema, documentFields),
|
|
@@ -41,7 +79,8 @@ export function DisplayConditionModal({
|
|
|
41
79
|
}, [onClose]);
|
|
42
80
|
|
|
43
81
|
const handleSave = useCallback(() => {
|
|
44
|
-
const
|
|
82
|
+
const finalState = applyConditionMatchType(state, matchType);
|
|
83
|
+
const hasValidGroup = finalState.groups.some(group =>
|
|
45
84
|
group.conditions.some(
|
|
46
85
|
c =>
|
|
47
86
|
c.dataPointKey &&
|
|
@@ -51,12 +90,12 @@ export function DisplayConditionModal({
|
|
|
51
90
|
),
|
|
52
91
|
);
|
|
53
92
|
if (hasValidGroup) {
|
|
54
|
-
onSave(
|
|
93
|
+
onSave(finalState);
|
|
55
94
|
} else {
|
|
56
95
|
onSave(null);
|
|
57
96
|
}
|
|
58
97
|
onClose();
|
|
59
|
-
}, [onSave, state, onClose]);
|
|
98
|
+
}, [onSave, state, matchType, onClose]);
|
|
60
99
|
|
|
61
100
|
const updateGroup = useCallback((index: number, group: DisplayConditionState['groups'][0]) => {
|
|
62
101
|
setState(prev => {
|
|
@@ -86,14 +125,19 @@ export function DisplayConditionModal({
|
|
|
86
125
|
const addGroup = useCallback(() => {
|
|
87
126
|
setState(prev => ({
|
|
88
127
|
...prev,
|
|
89
|
-
groups: [...prev.groups, { ...defaultGroup(), logicalOperator:
|
|
128
|
+
groups: [...prev.groups, { ...defaultGroup(), logicalOperator: matchType }],
|
|
90
129
|
}));
|
|
91
|
-
}, []);
|
|
130
|
+
}, [matchType]);
|
|
92
131
|
|
|
93
132
|
const handleBehaviorChange = useCallback((behavior: DisplayConditionState['behavior']) => {
|
|
94
133
|
setState(prev => ({ ...prev, behavior }));
|
|
95
134
|
}, []);
|
|
96
135
|
|
|
136
|
+
const handleConditionMatchTypeChange = useCallback((value: ConditionMatchType) => {
|
|
137
|
+
setMatchType(value);
|
|
138
|
+
setState(prev => applyConditionMatchType(prev, value));
|
|
139
|
+
}, []);
|
|
140
|
+
|
|
97
141
|
const canSave = useMemo(() => {
|
|
98
142
|
for (const group of state.groups) {
|
|
99
143
|
for (const condition of group.conditions) {
|
|
@@ -120,7 +164,7 @@ export function DisplayConditionModal({
|
|
|
120
164
|
|
|
121
165
|
return (
|
|
122
166
|
<Dialog open onClose={handleClose} size="xlarge">
|
|
123
|
-
<Dialog.Header>
|
|
167
|
+
<Dialog.Header>Conditions</Dialog.Header>
|
|
124
168
|
<Dialog.Content>
|
|
125
169
|
<Flex
|
|
126
170
|
direction="column"
|
|
@@ -132,12 +176,34 @@ export function DisplayConditionModal({
|
|
|
132
176
|
}}
|
|
133
177
|
>
|
|
134
178
|
<Flex direction="column" gap="3">
|
|
135
|
-
<
|
|
136
|
-
|
|
137
|
-
|
|
179
|
+
<Flex
|
|
180
|
+
direction="row"
|
|
181
|
+
alignItems="center"
|
|
182
|
+
gap="2"
|
|
183
|
+
style={{ flexWrap: 'wrap' }}
|
|
184
|
+
>
|
|
185
|
+
<Text size="medium" variant="body" style={{ fontWeight: 'bold' }}>
|
|
186
|
+
When
|
|
187
|
+
</Text>
|
|
188
|
+
<SegmentedControl
|
|
189
|
+
size="small"
|
|
190
|
+
selected={matchType}
|
|
191
|
+
onChange={handleConditionMatchTypeChange}
|
|
192
|
+
>
|
|
193
|
+
<SegmentedControl.Segment value="and">All</SegmentedControl.Segment>
|
|
194
|
+
<SegmentedControl.Segment value="or">Any</SegmentedControl.Segment>
|
|
195
|
+
</SegmentedControl>
|
|
196
|
+
<Text size="medium" variant="body" style={{ fontWeight: 'bold' }}>
|
|
197
|
+
of the
|
|
198
|
+
</Text>
|
|
199
|
+
<Chip label="IF" size="small" />
|
|
200
|
+
<Text size="medium" variant="body" style={{ fontWeight: 'bold' }}>
|
|
201
|
+
conditions are met
|
|
202
|
+
</Text>
|
|
203
|
+
</Flex>
|
|
138
204
|
<Flex direction="row" alignItems="center" gap="3">
|
|
139
205
|
<Text size="small" subdued variant="body">
|
|
140
|
-
Select to
|
|
206
|
+
Select to include or exclude selected template/file.
|
|
141
207
|
</Text>
|
|
142
208
|
|
|
143
209
|
<SegmentedControl
|
|
@@ -153,20 +219,14 @@ export function DisplayConditionModal({
|
|
|
153
219
|
</SegmentedControl>
|
|
154
220
|
</Flex>
|
|
155
221
|
</Flex>
|
|
156
|
-
<Divider />
|
|
157
222
|
<ConditionGroupsSection
|
|
223
|
+
conditionJoinOperator={matchType}
|
|
158
224
|
dataPointOptions={dataPointOptions}
|
|
159
225
|
groups={state.groups}
|
|
160
226
|
onAddGroup={addGroup}
|
|
161
227
|
onRemoveGroup={removeGroup}
|
|
162
228
|
onUpdateGroup={updateGroup}
|
|
163
229
|
/>
|
|
164
|
-
{!canSave && (
|
|
165
|
-
<Text size="small" subdued variant="body">
|
|
166
|
-
Complete each condition before saving. Data point and value are
|
|
167
|
-
required, and numeric fields must contain a valid number.
|
|
168
|
-
</Text>
|
|
169
|
-
)}
|
|
170
230
|
</Flex>
|
|
171
231
|
</Dialog.Content>
|
|
172
232
|
<Dialog.Footer sticky>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Button, Flex, Icon, Text } from '@servicetitan/anvil2';
|
|
2
2
|
import IconMenuOpen from '@servicetitan/anvil2/assets/icons/material/round/menu_open.svg';
|
|
3
|
-
|
|
4
|
-
import { FC, useState } from 'react';
|
|
3
|
+
import { FC, useMemo, useState } from 'react';
|
|
5
4
|
import { menuGroups } from '../../constants';
|
|
6
5
|
import { useToggle } from '../../hooks';
|
|
7
6
|
import { DataModelFieldGroup, FieldTypeEnum, FieldTypeOption } from '../../interface/types';
|
|
@@ -14,12 +13,14 @@ import { GenericFieldTypeList } from './generic-field-type-list';
|
|
|
14
13
|
|
|
15
14
|
interface FieldSidebarProps {
|
|
16
15
|
dataModelGroups?: DataModelFieldGroup[];
|
|
16
|
+
hideFields?: FieldTypeEnum[];
|
|
17
17
|
onDragEnd(): void;
|
|
18
18
|
onDragStart(fieldOption: FieldTypeOption): void;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export const FieldSidebar: FC<FieldSidebarProps> = ({
|
|
22
22
|
dataModelGroups = [],
|
|
23
|
+
hideFields,
|
|
23
24
|
onDragEnd,
|
|
24
25
|
onDragStart,
|
|
25
26
|
}) => {
|
|
@@ -31,10 +32,17 @@ export const FieldSidebar: FC<FieldSidebarProps> = ({
|
|
|
31
32
|
open();
|
|
32
33
|
};
|
|
33
34
|
|
|
35
|
+
const filteredMenuGroups = useMemo(() => {
|
|
36
|
+
if (hideFields?.length) {
|
|
37
|
+
return menuGroups.filter(menuGroup => !hideFields.includes(menuGroup.key));
|
|
38
|
+
}
|
|
39
|
+
return menuGroups;
|
|
40
|
+
}, [hideFields]);
|
|
41
|
+
|
|
34
42
|
return (
|
|
35
43
|
<Flex className="dte-field-sidebar-container skeleton-item">
|
|
36
44
|
<FieldMenuGroup
|
|
37
|
-
menuGroups={
|
|
45
|
+
menuGroups={filteredMenuGroups}
|
|
38
46
|
onClickMenu={handleActiveFieldTypeChange}
|
|
39
47
|
activeFieldKey={activeFieldType}
|
|
40
48
|
/>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Flex } from '@servicetitan/anvil2';
|
|
2
2
|
import { FC, ReactNode, useCallback, useMemo, useRef } from 'react';
|
|
3
3
|
import { usePdfFieldDnD, usePdfFieldSelection } from '../../hooks';
|
|
4
|
-
import { PdfField, RecipientInfo, SchemaObject } from '../../interface/types';
|
|
4
|
+
import { FieldTypeEnum, PdfField, RecipientInfo, SchemaObject } from '../../interface/types';
|
|
5
5
|
import { extractGroupedFieldsFromDataModel, mapColorsToRecipients } from '../../utils';
|
|
6
6
|
import { FieldConfigPanelOverlay } from '../field-config-panel/field-config-panel-overlay';
|
|
7
7
|
import { FieldSidebar } from '../field-sidebar/field-sidebar';
|
|
@@ -18,6 +18,7 @@ export interface PdfEditorProps {
|
|
|
18
18
|
dataModel?: SchemaObject;
|
|
19
19
|
recipients?: RecipientInfo[];
|
|
20
20
|
fields?: PdfField[];
|
|
21
|
+
hideFields?: FieldTypeEnum[];
|
|
21
22
|
onLoadSuccess?(numPages: number): void;
|
|
22
23
|
onFieldsChange(fields: PdfField[]): void;
|
|
23
24
|
}
|
|
@@ -27,6 +28,7 @@ export const PdfEditor: FC<PdfEditorProps> = ({
|
|
|
27
28
|
errorPlaceholder,
|
|
28
29
|
errors = {},
|
|
29
30
|
fields = [],
|
|
31
|
+
hideFields,
|
|
30
32
|
loading = false,
|
|
31
33
|
loadingPlaceholder,
|
|
32
34
|
onFieldsChange,
|
|
@@ -83,6 +85,7 @@ export const PdfEditor: FC<PdfEditorProps> = ({
|
|
|
83
85
|
|
|
84
86
|
<Flex className="dte-pdf-editor-sidebar-container">
|
|
85
87
|
<FieldSidebar
|
|
88
|
+
hideFields={hideFields}
|
|
86
89
|
dataModelGroups={dataModelGroups}
|
|
87
90
|
onDragStart={pdfFieldDnd.handleDragStart}
|
|
88
91
|
onDragEnd={pdfFieldDnd.handleDragEnd}
|
|
@@ -24,3 +24,9 @@ export const defaultState = (): DisplayConditionState => ({
|
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
export const MODAL_CONTENT_MAX_HEIGHT = '70vh';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Temporary product limit: the editor UI allows only this many rules (groups).
|
|
30
|
+
* The data model and evaluation still support multiple groups for existing templates.
|
|
31
|
+
*/
|
|
32
|
+
export const MAX_DISPLAY_CONDITION_RULES_UI = 1;
|
package/src/interface/types.ts
CHANGED
|
@@ -43,7 +43,6 @@ function walkSchema(
|
|
|
43
43
|
result.push({
|
|
44
44
|
fieldType,
|
|
45
45
|
fullKey,
|
|
46
|
-
group: fieldType === 'number' ? 'Numeric Fields' : 'Data Model',
|
|
47
46
|
title: fullTitle || fullKey,
|
|
48
47
|
});
|
|
49
48
|
}
|
|
@@ -75,7 +74,6 @@ export function getDocumentFieldsDataPointOptions(
|
|
|
75
74
|
result.push({
|
|
76
75
|
fieldType,
|
|
77
76
|
fullKey: f.path,
|
|
78
|
-
group: 'Document Fields',
|
|
79
77
|
title: f.label || f.path,
|
|
80
78
|
});
|
|
81
79
|
}
|