@servicetitan/dte-pdf-editor 1.35.0 → 1.37.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/README.md +28 -12
- package/dist/components/field-config-panel/advanced-settings.d.ts.map +1 -1
- package/dist/components/field-config-panel/advanced-settings.js +20 -10
- package/dist/components/field-config-panel/advanced-settings.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 +2 -1
- 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 +48 -7
- package/dist/components/field-config-panel/formula-modal.js.map +1 -1
- package/dist/components/field-config-panel/formula-workspace.d.ts +1 -0
- package/dist/components/field-config-panel/formula-workspace.d.ts.map +1 -1
- package/dist/components/field-config-panel/formula-workspace.js +10 -4
- 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 +1 -0
- package/dist/components/field-config-panel/result-type-selector.js.map +1 -1
- package/dist/components/pdf-view/pdf-view-calculated.d.ts +1 -0
- package/dist/components/pdf-view/pdf-view-calculated.d.ts.map +1 -1
- package/dist/components/pdf-view/pdf-view-calculated.js +20 -3
- package/dist/components/pdf-view/pdf-view-calculated.js.map +1 -1
- package/dist/components/pdf-view/pdf-view-fillable.d.ts.map +1 -1
- package/dist/components/pdf-view/pdf-view-fillable.js +5 -2
- package/dist/components/pdf-view/pdf-view-fillable.js.map +1 -1
- package/dist/components/pdf-view/pdf-view.d.ts +6 -0
- package/dist/components/pdf-view/pdf-view.d.ts.map +1 -1
- package/dist/components/pdf-view/pdf-view.js +2 -2
- 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 -1
- package/dist/constants/calculated.constants.js +2 -0
- package/dist/constants/calculated.constants.js.map +1 -1
- package/dist/hooks/useFormulaEditor.d.ts +3 -0
- package/dist/hooks/useFormulaEditor.d.ts.map +1 -1
- package/dist/hooks/useFormulaEditor.js +24 -1
- package/dist/hooks/useFormulaEditor.js.map +1 -1
- package/dist/interface/types.d.ts +6 -2
- package/dist/interface/types.d.ts.map +1 -1
- package/dist/interface/types.js.map +1 -1
- package/dist/utils/data-model/extract-fields.utils.d.ts.map +1 -1
- package/dist/utils/data-model/extract-fields.utils.js +11 -1
- package/dist/utils/data-model/extract-fields.utils.js.map +1 -1
- package/dist/utils/formula/evaluate-formula.utils.d.ts +10 -2
- package/dist/utils/formula/evaluate-formula.utils.d.ts.map +1 -1
- package/dist/utils/formula/evaluate-formula.utils.js +205 -4
- package/dist/utils/formula/evaluate-formula.utils.js.map +1 -1
- package/dist/utils/formula/expression.utils.d.ts +3 -3
- package/dist/utils/formula/expression.utils.d.ts.map +1 -1
- package/dist/utils/formula/expression.utils.js +3 -5
- package/dist/utils/formula/expression.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 +29 -8
- package/dist/utils/formula/format-calculated-result.utils.js.map +1 -1
- package/dist/utils/formula/validate-formula.utils.d.ts +1 -1
- package/dist/utils/formula/validate-formula.utils.d.ts.map +1 -1
- package/dist/utils/formula/validate-formula.utils.js +18 -3
- package/dist/utils/formula/validate-formula.utils.js.map +1 -1
- package/dist/utils/shared/date.utils.d.ts +2 -0
- package/dist/utils/shared/date.utils.d.ts.map +1 -0
- package/dist/utils/shared/date.utils.js +6 -0
- package/dist/utils/shared/date.utils.js.map +1 -0
- package/dist/utils/shared/index.d.ts +1 -0
- package/dist/utils/shared/index.d.ts.map +1 -1
- package/dist/utils/shared/index.js +1 -0
- package/dist/utils/shared/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/field-config-panel/advanced-settings.tsx +103 -77
- package/src/components/field-config-panel/formula-generator.tsx +2 -1
- package/src/components/field-config-panel/formula-modal.tsx +48 -8
- package/src/components/field-config-panel/formula-workspace.tsx +21 -7
- package/src/components/field-config-panel/result-type-selector.tsx +1 -0
- package/src/components/pdf-view/pdf-view-calculated.tsx +20 -3
- package/src/components/pdf-view/pdf-view-fillable.tsx +6 -3
- package/src/components/pdf-view/pdf-view.tsx +8 -0
- package/src/constants/calculated.constants.ts +4 -0
- package/src/hooks/useFormulaEditor.ts +32 -1
- package/src/interface/types.ts +8 -2
- package/src/utils/data-model/extract-fields.utils.ts +13 -1
- package/src/utils/formula/evaluate-formula.utils.ts +271 -5
- package/src/utils/formula/expression.utils.ts +3 -8
- package/src/utils/formula/format-calculated-result.utils.ts +32 -10
- package/src/utils/formula/validate-formula.utils.ts +27 -1
- package/src/utils/shared/date.utils.ts +6 -0
- package/src/utils/shared/index.ts +1 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DEFAULT_DATE_FORMAT } from '../../constants';
|
|
1
2
|
import { CalculatedFieldFormat } from '../../interface/types';
|
|
2
3
|
|
|
3
4
|
function roundValue(
|
|
@@ -36,9 +37,33 @@ function formatIntegerPart(
|
|
|
36
37
|
return parts.join(sep);
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
const DATE_FORMAT_TOKENS: Record<string, (d: Date) => string> = {
|
|
41
|
+
YYYY: d => String(d.getFullYear()),
|
|
42
|
+
YY: d => String(d.getFullYear()).slice(-2),
|
|
43
|
+
MMMM: d => d.toLocaleString('en-US', { month: 'long' }),
|
|
44
|
+
MMM: d => d.toLocaleString('en-US', { month: 'short' }),
|
|
45
|
+
MM: d => String(d.getMonth() + 1).padStart(2, '0'),
|
|
46
|
+
M: d => String(d.getMonth() + 1),
|
|
47
|
+
DD: d => String(d.getDate()).padStart(2, '0'),
|
|
48
|
+
D: d => String(d.getDate()),
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const DATE_TOKEN_PATTERN = new RegExp(Object.keys(DATE_FORMAT_TOKENS).join('|'), 'g');
|
|
52
|
+
|
|
53
|
+
function formatDateValue(epochMs: number, dateFormat: string): string {
|
|
54
|
+
const date = new Date(epochMs);
|
|
55
|
+
if (isNaN(date.getTime())) {
|
|
56
|
+
return '';
|
|
57
|
+
}
|
|
58
|
+
return dateFormat.replace(DATE_TOKEN_PATTERN, match => {
|
|
59
|
+
const fn = DATE_FORMAT_TOKENS[match];
|
|
60
|
+
return fn ? fn(date) : match;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
39
64
|
/**
|
|
40
65
|
* Format a calculated formula result for display using advanced settings.
|
|
41
|
-
* Applies rounding, decimal places, thousands/decimal separators, result type (number/currency/percent), and prefix/postfix.
|
|
66
|
+
* Applies rounding, decimal places, thousands/decimal separators, result type (number/currency/percent/date), and prefix/postfix.
|
|
42
67
|
*/
|
|
43
68
|
export function formatCalculatedResult(
|
|
44
69
|
value: number,
|
|
@@ -48,23 +73,21 @@ export function formatCalculatedResult(
|
|
|
48
73
|
return String(value);
|
|
49
74
|
}
|
|
50
75
|
|
|
76
|
+
if (format.resultType === 'date') {
|
|
77
|
+
return formatDateValue(value, format.dateFormat ?? DEFAULT_DATE_FORMAT);
|
|
78
|
+
}
|
|
79
|
+
|
|
51
80
|
const {
|
|
52
81
|
decimalSeparator,
|
|
53
82
|
decimalSeparatorEnabled,
|
|
54
83
|
decimals,
|
|
55
84
|
postfixText,
|
|
56
85
|
prefixText,
|
|
57
|
-
resultType,
|
|
58
86
|
roundingMode,
|
|
59
87
|
thousandsSeparator,
|
|
60
88
|
} = format;
|
|
61
89
|
|
|
62
|
-
|
|
63
|
-
if (resultType === 'percent') {
|
|
64
|
-
num = value * 100;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const rounded = roundValue(num, decimals, roundingMode);
|
|
90
|
+
const rounded = roundValue(value, decimals, roundingMode);
|
|
68
91
|
const fixed = rounded.toFixed(decimals);
|
|
69
92
|
const [intPart, decPart] = fixed.split('.');
|
|
70
93
|
|
|
@@ -73,7 +96,6 @@ export function formatCalculatedResult(
|
|
|
73
96
|
const decSuffix = decimals > 0 ? decimalSep + (decPart ?? '') : '';
|
|
74
97
|
|
|
75
98
|
const numberStr = intFormatted + decSuffix;
|
|
76
|
-
const suffix = resultType === 'percent' ? '%' : '';
|
|
77
99
|
|
|
78
|
-
return `${prefixText}${numberStr}${
|
|
100
|
+
return `${prefixText}${numberStr}${postfixText}`;
|
|
79
101
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MAX_DATE_CALC_DAYS } from '../../constants';
|
|
1
2
|
import { FormulaToken, StructuredFormula } from '../../interface/types';
|
|
2
3
|
|
|
3
4
|
export interface FormulaValidationResult {
|
|
@@ -20,6 +21,8 @@ function isOperandToken(t: FormulaToken): boolean {
|
|
|
20
21
|
export function validateFormula(
|
|
21
22
|
formula: StructuredFormula | undefined | null,
|
|
22
23
|
validPaths: Set<string>,
|
|
24
|
+
knownDateFields?: Set<string>,
|
|
25
|
+
pathToLabel?: Map<string, string>,
|
|
23
26
|
): FormulaValidationResult {
|
|
24
27
|
const errors: string[] = [];
|
|
25
28
|
|
|
@@ -61,7 +64,8 @@ export function validateFormula(
|
|
|
61
64
|
}
|
|
62
65
|
} else if (t.type === 'field') {
|
|
63
66
|
if (!validPaths.has(t.path)) {
|
|
64
|
-
|
|
67
|
+
const label = pathToLabel?.get(t.path) ?? t.path;
|
|
68
|
+
errors.push(`Unknown field: "${label}" (path: ${t.path})`);
|
|
65
69
|
}
|
|
66
70
|
if (next != null && isOperandToken(next)) {
|
|
67
71
|
errors.push('Operator required between two fields or values');
|
|
@@ -90,6 +94,28 @@ export function validateFormula(
|
|
|
90
94
|
errors.push('Formula must end with an operand or closing parenthesis');
|
|
91
95
|
}
|
|
92
96
|
|
|
97
|
+
if (knownDateFields?.size) {
|
|
98
|
+
const hasDateField = tokens.some(t => t.type === 'field' && knownDateFields.has(t.path));
|
|
99
|
+
if (hasDateField) {
|
|
100
|
+
const hasMultiplyOrDivide = tokens.some(
|
|
101
|
+
t => t.type === 'operator' && (t.value === '*' || t.value === '/'),
|
|
102
|
+
);
|
|
103
|
+
if (hasMultiplyOrDivide) {
|
|
104
|
+
errors.push(
|
|
105
|
+
'Multiply (*) and divide (/) operators cannot be used with date fields. Only +, -, and parentheses are allowed.',
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
const hasLargeNumber = tokens.some(
|
|
109
|
+
t => t.type === 'number' && Math.abs(Number(t.value)) > MAX_DATE_CALC_DAYS,
|
|
110
|
+
);
|
|
111
|
+
if (hasLargeNumber) {
|
|
112
|
+
errors.push(
|
|
113
|
+
`Number of days cannot exceed ${MAX_DATE_CALC_DAYS} in date calculations.`,
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
93
119
|
return {
|
|
94
120
|
valid: errors.length === 0,
|
|
95
121
|
errors,
|