@servicetitan/dte-pdf-editor 1.96.1 → 1.96.2

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 CHANGED
@@ -31,6 +31,9 @@ formulas.
31
31
 
32
32
  ### Recent changes
33
33
 
34
+ - **fix/hide-sceduler** (schedule UI) — the schedule switch, picker and the e-sign schedule are shown only when
35
+ `onScheduleBindingsChange` is passed. See [RELEASE_NOTES.md](./RELEASE_NOTES.md) and
36
+ [Business-day calendars](#business-day-calendars).
34
37
  - **fix/shared-incloud-on-BYOD-build** (installable package) — the package no longer depends on the unpublished
35
38
  `@servicetitan/dte-shared`; its code is bundled in, so `npm install` works. See
36
39
  [RELEASE_NOTES.md](./RELEASE_NOTES.md).
@@ -138,16 +141,16 @@ The main component for editing PDF documents and placing fields.
138
141
  | `holidays` | `string[]` | No | Holidays of the default business-day calendar, for the formula builder preview; as on `PdfView` |
139
142
  | `fieldCalendars` | `Record<string, BusinessCalendar>` | No | Calendars of date calculated fields bound to a schedule, by field id; as on `PdfView` |
140
143
  | `scheduleBindings` | `FieldScheduleBinding[]` | No | Date fields whose exclusion toggle is on, and the schedule each uses; as on `PdfView` — see [Business-day calendars](#business-day-calendars) |
141
- | `onScheduleBindingsChange` | `(bindings: FieldScheduleBinding[]) => void` | No | Called with the complete desired `scheduleBindings` when the toggle or picker changes the selected field's binding |
142
- | `holidayCatalog` | `HolidayCatalog` | No | The tenant's known holidays, for the schedule editor's checklist |
144
+ | `onScheduleBindingsChange` | `(bindings: FieldScheduleBinding[]) => void` | No | Called with the complete desired `scheduleBindings` when the toggle or picker changes the selected field's binding. Passing it turns the schedule UI on; without it the switch, picker and e-sign schedule are not shown. It is not called for the e-sign schedule, which is stored in the field's `data` |
145
+ | `holidayCatalog` | `HolidayCatalog` | No | The tenant's known holidays, for the schedule editor's checklist (the schedule UI needs `onScheduleBindingsChange`) |
143
146
  | `holidayCatalogLoading`| `boolean` | No | Whether `holidayCatalog` is still loading |
144
147
  | `holidayCatalogError` | `string` | No | Error message shown in the schedule editor if the catalog failed to load |
145
- | `schedules` | `BusinessDaySchedule[]` | No | The schedules the tenant can pick from the Formula Builder's schedule picker, default schedule first |
148
+ | `schedules` | `BusinessDaySchedule[]` | No | The schedules the tenant can pick from the Formula Builder's schedule picker, default schedule first (the schedule UI needs `onScheduleBindingsChange`) |
146
149
  | `schedulesLoading` | `boolean` | No | Whether `schedules` is still loading |
147
150
  | `schedulesError` | `string` | No | Error message shown in the picker if the schedule list failed to load |
148
- | `onCreateSchedule` | `(request: SaveScheduleRequest) => Promise<BusinessDaySchedule>` | No | Creates a tenant schedule from the "Create New Schedule" drawer; a rejected promise's `message` is shown as its error |
149
- | `onUpdateSchedule` | `(id: number, request: SaveScheduleRequest) => Promise<BusinessDaySchedule>` | No | Replaces a tenant schedule in place from the picker's "Edit" action; same error handling as `onCreateSchedule` |
150
- | `onDeleteSchedule` | `(id: number) => Promise<void>` | No | Permanently deletes a tenant schedule from the picker's delete action |
151
+ | `onCreateSchedule` | `(request: SaveScheduleRequest) => Promise<BusinessDaySchedule>` | No | Creates a tenant schedule from the "Create New Schedule" drawer; a rejected promise's `message` is shown as its error (the schedule UI needs `onScheduleBindingsChange`) |
152
+ | `onUpdateSchedule` | `(id: number, request: SaveScheduleRequest) => Promise<BusinessDaySchedule>` | No | Replaces a tenant schedule in place from the picker's "Edit" action; same error handling as `onCreateSchedule` (the schedule UI needs `onScheduleBindingsChange`) |
153
+ | `onDeleteSchedule` | `(id: number) => Promise<void>` | No | Permanently deletes a tenant schedule from the picker's delete action (the schedule UI needs `onScheduleBindingsChange`) |
151
154
 
152
155
  #### Example
153
156
 
@@ -340,7 +343,9 @@ Types of e-signature fields:
340
343
  backend, at signing time.
341
344
  - **`businessCalendarEnabled`** / **`scheduleId`**: the same business-day exclusion toggle and schedule choice as a
342
345
  calculated field's (see **Business-day calendars** below), stored here instead of in `scheduleBindings` because,
343
- like `rules`, it applies to every `dateSignedOffset` field in the document at once, not one field at a time.
346
+ like `rules`, it applies to every `dateSignedOffset` field in the document at once, not one field at a time. The
347
+ e-sign schedule is shown only when `onScheduleBindingsChange` is passed to `PdfEditor`; the callback is not called
348
+ for it.
344
349
 
345
350
  All `dateSignedOffset` fields in a document share one `data` object — editing any one of them (days, rules, or the
346
351
  business-calendar toggle) updates every sibling via `onMatchingFieldsConfigChange`, and a newly dropped
@@ -407,6 +412,10 @@ shown inline in its own config panel (see **ESignDateSignedOffsetSettings** abov
407
412
  schedules (`holidayCatalog`, `schedules`, `onCreateSchedule`/`onUpdateSchedule`/`onDeleteSchedule`) but storing the
408
413
  choice on the field's `data` instead of in `scheduleBindings`.
409
414
 
415
+ - **Showing and hiding the UI**: the switch, the picker and the e-sign schedule are offered only when
416
+ `onScheduleBindingsChange` is passed. A host that cannot save bindings (for example one without a tenant, or whose
417
+ schedules failed to load) leaves it out, and the editor then shows none of them. The formula preview still follows
418
+ `scheduleBindings`, `fieldCalendars` and `holidays`.
410
419
  - **`scheduleBindings`** (`FieldScheduleBinding[]`, `{ fieldKey, scheduleId? }`, `fieldKey` = `PdfField.id`) is the
411
420
  source of truth for which fields have the toggle on, and which schedule each uses (`scheduleId` undefined = the
412
421
  default schedule). A field with no entry here is unaffected by `holidays` / `fieldCalendars`.
@@ -1 +1 @@
1
- {"version":3,"file":"field-config-panel-overlay.d.ts","sourceRoot":"","sources":["../../../src/components/field-config-panel/field-config-panel-overlay.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,EAAE,EAAwB,MAAM,OAAO,CAAC;AACjD,OAAO,EACH,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACpB,MAAM,uBAAuB,CAAC;AAI/B,UAAU,4BAA4B;IAClC,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC5B,kBAAkB,EAAE,mBAAmB,CAAC;IACxC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,aAAa,EAAE,QAAQ,CAAC;IACxB,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAClD,gBAAgB,CAAC,EAAE,oBAAoB,EAAE,CAAC;IAC1C,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wBAAwB,CAAC,CAAC,QAAQ,EAAE,oBAAoB,EAAE,GAAG,IAAI,CAAC;IAClE,gBAAgB,CAAC,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9E,gBAAgB,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC1F,gBAAgB,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;IACtD,4BAA4B,CAAC,CACzB,SAAS,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,EACvC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,GACtE,IAAI,CAAC;IACR,aAAa,IAAI,IAAI,CAAC;IACtB,eAAe,CAAC,IAAI,IAAI,CAAC;IACzB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7C;AAED,eAAO,MAAM,uBAAuB,EAAE,EAAE,CAAC,4BAA4B,CA+HpE,CAAC"}
1
+ {"version":3,"file":"field-config-panel-overlay.d.ts","sourceRoot":"","sources":["../../../src/components/field-config-panel/field-config-panel-overlay.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,EAAE,EAAwB,MAAM,OAAO,CAAC;AACjD,OAAO,EACH,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACpB,MAAM,uBAAuB,CAAC;AAI/B,UAAU,4BAA4B;IAClC,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC5B,kBAAkB,EAAE,mBAAmB,CAAC;IACxC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,aAAa,EAAE,QAAQ,CAAC;IACxB,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAClD,gBAAgB,CAAC,EAAE,oBAAoB,EAAE,CAAC;IAC1C,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wBAAwB,CAAC,CAAC,QAAQ,EAAE,oBAAoB,EAAE,GAAG,IAAI,CAAC;IAClE,gBAAgB,CAAC,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9E,gBAAgB,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC1F,gBAAgB,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;IACtD,4BAA4B,CAAC,CACzB,SAAS,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,EACvC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,GACtE,IAAI,CAAC;IACR,aAAa,IAAI,IAAI,CAAC;IACtB,eAAe,CAAC,IAAI,IAAI,CAAC;IACzB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7C;AAED,eAAO,MAAM,uBAAuB,EAAE,EAAE,CAAC,4BAA4B,CAwIpE,CAAC"}
@@ -14,21 +14,29 @@ export const FieldConfigPanelOverlay = ({ dataModel, documentFields = [], fieldC
14
14
  const handleSelectSchedule = useCallback((scheduleId) => {
15
15
  onScheduleBindingsChange === null || onScheduleBindingsChange === void 0 ? void 0 : onScheduleBindingsChange(setFieldSchedule(scheduleBindings !== null && scheduleBindings !== void 0 ? scheduleBindings : [], selectedFieldId, scheduleId));
16
16
  }, [scheduleBindings, selectedFieldId, onScheduleBindingsChange]);
17
- const businessCalendar = useMemo(() => ({
18
- enabled: !!selectedBinding,
19
- selectedScheduleId: selectedBinding === null || selectedBinding === void 0 ? void 0 : selectedBinding.scheduleId,
20
- onToggle: handleToggle,
21
- onSelectSchedule: handleSelectSchedule,
22
- holidayCatalog,
23
- holidayCatalogLoading,
24
- holidayCatalogError,
25
- schedules,
26
- schedulesLoading,
27
- schedulesError,
28
- onCreateSchedule,
29
- onUpdateSchedule,
30
- onDeleteSchedule,
31
- }), [
17
+ /*
18
+ * The schedule UI (the Formula Builder's switch and the e-sign day offset's schedule) is offered
19
+ * only to a host that passes `onScheduleBindingsChange`. Without it there is no context, and
20
+ * everything that renders the schedule UI checks for one.
21
+ */
22
+ const businessCalendar = useMemo(() => onScheduleBindingsChange
23
+ ? {
24
+ enabled: !!selectedBinding,
25
+ selectedScheduleId: selectedBinding === null || selectedBinding === void 0 ? void 0 : selectedBinding.scheduleId,
26
+ onToggle: handleToggle,
27
+ onSelectSchedule: handleSelectSchedule,
28
+ holidayCatalog,
29
+ holidayCatalogLoading,
30
+ holidayCatalogError,
31
+ schedules,
32
+ schedulesLoading,
33
+ schedulesError,
34
+ onCreateSchedule,
35
+ onUpdateSchedule,
36
+ onDeleteSchedule,
37
+ }
38
+ : undefined, [
39
+ onScheduleBindingsChange,
32
40
  selectedBinding,
33
41
  handleToggle,
34
42
  handleSelectSchedule,
@@ -1 +1 @@
1
- {"version":3,"file":"field-config-panel-overlay.js","sourceRoot":"","sources":["../../../src/components/field-config-panel/field-config-panel-overlay.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"field-config-panel-overlay.js","sourceRoot":"","sources":["../../../src/components/field-config-panel/field-config-panel-overlay.tsx"],"names":[],"mappings":"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"}
@@ -27,7 +27,7 @@ export interface PdfEditorProps {
27
27
  /**
28
28
  * Date calculated fields whose custom business-day exclusion toggle is on, and the schedule
29
29
  * each uses (`PdfField.id` as `fieldKey`), as `PdfView`'s. Also drives the Formula Builder's
30
- * toggle/picker for the selected field.
30
+ * toggle/picker for the selected field, which are shown only with `onScheduleBindingsChange`.
31
31
  */
32
32
  scheduleBindings?: FieldScheduleBinding[];
33
33
  /** The tenant's known holidays, for the schedule editor's checklist. */
@@ -45,6 +45,11 @@ export interface PdfEditorProps {
45
45
  * `PUT api/holidays/templates/{id}/bindings`). `PdfEditor` does not persist this itself —
46
46
  * the host is expected to save it (and the bindings are typically saved separately from the
47
47
  * template's own fields).
48
+ *
49
+ * Passing it also turns the schedule UI on: without it the Formula Builder has no "Exclude
50
+ * weekends & holidays" switch and the e-sign day offset has no schedule. A host that cannot save
51
+ * bindings (for example one without a tenant) leaves it out. It is not called for the e-sign
52
+ * schedule, which is stored in the field's `data`.
48
53
  */
49
54
  onScheduleBindingsChange?(bindings: FieldScheduleBinding[]): void;
50
55
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"pdf-editor.d.ts","sourceRoot":"","sources":["../../../src/components/pdf-editor/pdf-editor.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,SAAS,EAAgC,MAAM,OAAO,CAAC;AAEpE,OAAO,EACH,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACpB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAAa,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAErE,OAAO,wBAAwB,CAAC;AAEhC,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,kBAAkB,CAAC,EAAE,SAAS,CAAC;IAC/B,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,gGAAgG;IAChG,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAClD;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,oBAAoB,EAAE,CAAC;IAC1C,wEAAwE;IACxE,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oFAAoF;IACpF,SAAS,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,CACX,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,CAAC,kBAAkB,EAAE,mBAAmB,KAAK,IAAI,KAChE,IAAI,CAAC;IACV;;;;;;OAMG;IACH,wBAAwB,CAAC,CAAC,QAAQ,EAAE,oBAAoB,EAAE,GAAG,IAAI,CAAC;IAClE;;;;;OAKG;IACH,gBAAgB,CAAC,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9E;;;;OAIG;IACH,gBAAgB,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC1F;;;;;;OAMG;IACH,gBAAgB,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,aAAa,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,cAAc,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;CAC5C;AAED,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,cAAc,CA0IxC,CAAC"}
1
+ {"version":3,"file":"pdf-editor.d.ts","sourceRoot":"","sources":["../../../src/components/pdf-editor/pdf-editor.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,SAAS,EAAgC,MAAM,OAAO,CAAC;AAEpE,OAAO,EACH,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACpB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAAa,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAErE,OAAO,wBAAwB,CAAC;AAEhC,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,kBAAkB,CAAC,EAAE,SAAS,CAAC;IAC/B,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,gGAAgG;IAChG,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAClD;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,oBAAoB,EAAE,CAAC;IAC1C,wEAAwE;IACxE,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oFAAoF;IACpF,SAAS,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,CACX,OAAO,EAAE,MAAM,EAAE,EACjB,cAAc,EAAE,CAAC,kBAAkB,EAAE,mBAAmB,KAAK,IAAI,KAChE,IAAI,CAAC;IACV;;;;;;;;;;;OAWG;IACH,wBAAwB,CAAC,CAAC,QAAQ,EAAE,oBAAoB,EAAE,GAAG,IAAI,CAAC;IAClE;;;;;OAKG;IACH,gBAAgB,CAAC,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9E;;;;OAIG;IACH,gBAAgB,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC1F;;;;;;OAMG;IACH,gBAAgB,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,aAAa,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,cAAc,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;CAC5C;AAED,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,cAAc,CA0IxC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"pdf-editor.js","sourceRoot":"","sources":["../../../src/components/pdf-editor/pdf-editor.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pdf-editor.js","sourceRoot":"","sources":["../../../src/components/pdf-editor/pdf-editor.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/dte-pdf-editor",
3
- "version": "1.96.1",
3
+ "version": "1.96.2",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "typings": "./dist/index.d.ts",
@@ -0,0 +1,184 @@
1
+ /*
2
+ * The schedule UI is offered only to a host that passes `onScheduleBindingsChange`. The overlay
3
+ * decides that, and every place that renders the schedule UI checks the context it builds, so the
4
+ * panel below is replaced by a stand-in that records what the overlay gives it.
5
+ */
6
+ jest.mock('../field-config-panel', () => ({ FieldConfigPanel: jest.fn(() => null) }));
7
+ // A Proxy is what `.svg` imports become under test; it is not a component.
8
+ jest.mock('@servicetitan/anvil2/assets/icons/material/round/close.svg', () => ({
9
+ __esModule: true,
10
+ default: () => null,
11
+ }));
12
+
13
+ import { TextDecoder, TextEncoder } from 'util';
14
+
15
+ // jsdom has no TextEncoder; anvil2 reads it when it is loaded, so this must run before it is imported.
16
+ Object.assign(globalThis, { TextEncoder, TextDecoder });
17
+
18
+ import { act, type ComponentProps } from 'react';
19
+ import { createRoot, type Root } from 'react-dom/client';
20
+ import { type FieldScheduleBinding, type PdfField } from '../../../interface/types';
21
+ import { FieldConfigPanel } from '../field-config-panel';
22
+ import { FieldConfigPanelOverlay } from '../field-config-panel-overlay';
23
+
24
+ const panel = FieldConfigPanel as unknown as jest.Mock;
25
+ const lastBusinessCalendar = () =>
26
+ panel.mock.calls[panel.mock.calls.length - 1][0].businessCalendar;
27
+
28
+ const defaultSchedule = {
29
+ name: 'Default',
30
+ isDefault: true,
31
+ calendar: { weekendDays: [0, 6] as (0 | 6)[], knownHolidays: [], customDates: [] },
32
+ };
33
+
34
+ describe('FieldConfigPanelOverlay', () => {
35
+ let container: HTMLDivElement;
36
+ let root: Root;
37
+
38
+ // Async, so the state anvil2 sets right after mounting is flushed inside `act`.
39
+ const render = (props: Partial<ComponentProps<typeof FieldConfigPanelOverlay>> = {}) =>
40
+ act(async () => {
41
+ root.render(
42
+ <FieldConfigPanelOverlay
43
+ selectedField={{ id: 'f1', type: 'calculated' } as PdfField}
44
+ recipients={[]}
45
+ forms={[]}
46
+ formFieldsByFormId={{}}
47
+ onFieldConfigChange={() => {}}
48
+ onDeleteField={() => {}}
49
+ onRequestFormFields={() => {}}
50
+ {...props}
51
+ />,
52
+ );
53
+ });
54
+
55
+ beforeAll(() => {
56
+ (globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
57
+ });
58
+
59
+ beforeEach(() => {
60
+ panel.mockClear();
61
+ container = document.createElement('div');
62
+ document.body.appendChild(container);
63
+ root = createRoot(container);
64
+ });
65
+
66
+ afterEach(async () => {
67
+ await act(async () => root.unmount());
68
+ container.remove();
69
+ });
70
+
71
+ describe('without onScheduleBindingsChange', () => {
72
+ test('gives the panel no schedule context', async () => {
73
+ await render();
74
+
75
+ expect(lastBusinessCalendar()).toBeUndefined();
76
+ });
77
+
78
+ test('gives the panel no schedule context although the host passed schedules', async () => {
79
+ await render({
80
+ scheduleBindings: [{ fieldKey: 'f1' }],
81
+ schedules: [defaultSchedule],
82
+ holidayCatalog: { jurisdiction: 'US', holidays: [] },
83
+ onCreateSchedule: jest.fn(),
84
+ onUpdateSchedule: jest.fn(),
85
+ onDeleteSchedule: jest.fn(),
86
+ });
87
+
88
+ expect(lastBusinessCalendar()).toBeUndefined();
89
+ });
90
+
91
+ test('adds the schedule context when the host starts passing the handler', async () => {
92
+ await render();
93
+ expect(lastBusinessCalendar()).toBeUndefined();
94
+
95
+ await render({ onScheduleBindingsChange: jest.fn() });
96
+
97
+ expect(lastBusinessCalendar()).toBeDefined();
98
+ });
99
+
100
+ test('removes the schedule context when the host stops passing the handler', async () => {
101
+ await render({ onScheduleBindingsChange: jest.fn() });
102
+ expect(lastBusinessCalendar()).toBeDefined();
103
+
104
+ await render({ onScheduleBindingsChange: undefined });
105
+
106
+ expect(lastBusinessCalendar()).toBeUndefined();
107
+ });
108
+ });
109
+
110
+ describe('with onScheduleBindingsChange', () => {
111
+ let onScheduleBindingsChange: jest.Mock;
112
+
113
+ beforeEach(() => {
114
+ onScheduleBindingsChange = jest.fn();
115
+ });
116
+
117
+ test('gives the panel a schedule context with the switch off for a field without a binding', async () => {
118
+ await render({ onScheduleBindingsChange, scheduleBindings: [] });
119
+
120
+ expect(lastBusinessCalendar()).toMatchObject({ enabled: false });
121
+ });
122
+
123
+ test('gives the panel the schedule of the field and what the host loaded', async () => {
124
+ const schedules = [defaultSchedule];
125
+ const holidayCatalog = { jurisdiction: 'US', holidays: [] };
126
+ const onCreateSchedule = jest.fn();
127
+ await render({
128
+ onScheduleBindingsChange,
129
+ scheduleBindings: [{ fieldKey: 'f1', scheduleId: 3 }],
130
+ schedules,
131
+ holidayCatalog,
132
+ onCreateSchedule,
133
+ });
134
+
135
+ expect(lastBusinessCalendar()).toMatchObject({
136
+ enabled: true,
137
+ selectedScheduleId: 3,
138
+ schedules,
139
+ holidayCatalog,
140
+ onCreateSchedule,
141
+ });
142
+ });
143
+
144
+ test('follows the binding of the field that is selected next', async () => {
145
+ const scheduleBindings = [{ fieldKey: 'f2', scheduleId: 3 }];
146
+ await render({ onScheduleBindingsChange, scheduleBindings });
147
+ expect(lastBusinessCalendar()).toMatchObject({ enabled: false });
148
+
149
+ await render({
150
+ onScheduleBindingsChange,
151
+ scheduleBindings,
152
+ selectedField: { id: 'f2', type: 'calculated' } as PdfField,
153
+ });
154
+
155
+ expect(lastBusinessCalendar()).toMatchObject({ enabled: true, selectedScheduleId: 3 });
156
+ });
157
+
158
+ test('turns the switch on by sending the whole list with the field added', async () => {
159
+ const others: FieldScheduleBinding[] = [{ fieldKey: 'other', scheduleId: 9 }];
160
+ await render({ onScheduleBindingsChange, scheduleBindings: others });
161
+
162
+ lastBusinessCalendar().onToggle(true);
163
+
164
+ expect(onScheduleBindingsChange).toHaveBeenCalledWith([
165
+ { fieldKey: 'other', scheduleId: 9 },
166
+ { fieldKey: 'f1' },
167
+ ]);
168
+ });
169
+
170
+ test('picks a schedule by sending the whole list with the field changed', async () => {
171
+ await render({
172
+ onScheduleBindingsChange,
173
+ scheduleBindings: [{ fieldKey: 'f1' }, { fieldKey: 'other', scheduleId: 9 }],
174
+ });
175
+
176
+ lastBusinessCalendar().onSelectSchedule(4);
177
+
178
+ expect(onScheduleBindingsChange).toHaveBeenCalledWith([
179
+ { fieldKey: 'other', scheduleId: 9 },
180
+ { fieldKey: 'f1', scheduleId: 4 },
181
+ ]);
182
+ });
183
+ });
184
+ });
@@ -0,0 +1,206 @@
1
+ /*
2
+ * The overlay gives the panel no schedule context when the host cannot save bindings. This checks
3
+ * the other half: the places that draw the schedule switch show it only with a context.
4
+ */
5
+ import { TextDecoder, TextEncoder } from 'util';
6
+
7
+ // jsdom has no TextEncoder; anvil2 reads it when it is loaded, so this must run before it is imported.
8
+ Object.assign(globalThis, { TextEncoder, TextDecoder });
9
+
10
+ import { act, useState } from 'react';
11
+ import { createRoot, type Root } from 'react-dom/client';
12
+ import {
13
+ type CalculatedFieldFormat,
14
+ ESignFieldType,
15
+ FieldTypeEnum,
16
+ type PdfField,
17
+ } from '../../../interface/types';
18
+ import { AdvancedSettings } from '../advanced-settings';
19
+ import { ESignOptionsModal } from '../e-sign-options-modal';
20
+ import { FieldConfigPanel } from '../field-config-panel';
21
+
22
+ // jsdom has no matchMedia, ResizeObserver, IntersectionObserver or popover API; anvil2 uses them.
23
+ Object.defineProperty(window, 'matchMedia', {
24
+ writable: true,
25
+ value: (query: string) => ({
26
+ matches: false,
27
+ media: query,
28
+ onchange: null,
29
+ addListener: () => {},
30
+ removeListener: () => {},
31
+ addEventListener: () => {},
32
+ removeEventListener: () => {},
33
+ dispatchEvent: () => false,
34
+ }),
35
+ });
36
+ class ObserverMock {
37
+ observe() {}
38
+ unobserve() {}
39
+ disconnect() {}
40
+ }
41
+ global.ResizeObserver = ObserverMock as unknown as typeof ResizeObserver;
42
+ global.IntersectionObserver = ObserverMock as unknown as typeof IntersectionObserver;
43
+ HTMLElement.prototype.showPopover ??= () => {};
44
+ HTMLElement.prototype.hidePopover ??= () => {};
45
+ HTMLElement.prototype.togglePopover ??= () => false;
46
+
47
+ const SWITCH_LABEL = 'Exclude weekends & holidays from the calculation';
48
+ const noOp = () => {};
49
+ const businessCalendar = { enabled: false, onToggle: noOp, onSelectSchedule: noOp };
50
+ const dateFormat: CalculatedFieldFormat = { resultType: 'date', dateFormat: 'MM/DD/YYYY' };
51
+ const numberFormat: CalculatedFieldFormat = {
52
+ resultType: 'number',
53
+ thousandsSeparator: false,
54
+ decimals: 2,
55
+ roundingMode: 'round',
56
+ decimalSeparatorEnabled: false,
57
+ decimalSeparator: '.',
58
+ prefixText: '',
59
+ postfixText: '',
60
+ };
61
+
62
+ const AdvancedSettingsSubject = ({
63
+ format,
64
+ withSchedules,
65
+ }: {
66
+ format: CalculatedFieldFormat;
67
+ withSchedules: boolean;
68
+ }) => {
69
+ const [current, setCurrent] = useState(format);
70
+
71
+ return (
72
+ <AdvancedSettings
73
+ format={current}
74
+ setFormat={setCurrent}
75
+ businessCalendar={withSchedules ? businessCalendar : undefined}
76
+ />
77
+ );
78
+ };
79
+
80
+ describe('the schedule switch', () => {
81
+ let container: HTMLDivElement;
82
+ let root: Root;
83
+
84
+ const render = (element: JSX.Element) =>
85
+ act(async () => {
86
+ root.render(element);
87
+ });
88
+
89
+ beforeAll(() => {
90
+ (globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
91
+ });
92
+
93
+ beforeEach(() => {
94
+ container = document.createElement('div');
95
+ document.body.appendChild(container);
96
+ root = createRoot(container);
97
+ });
98
+
99
+ afterEach(async () => {
100
+ await act(async () => root.unmount());
101
+ container.remove();
102
+ });
103
+
104
+ describe('in the advanced settings of a calculated field', () => {
105
+ test('is shown for a date field with a schedule context', async () => {
106
+ await render(<AdvancedSettingsSubject format={dateFormat} withSchedules />);
107
+
108
+ expect(container.textContent).toContain('Date format');
109
+ expect(container.textContent).toContain(SWITCH_LABEL);
110
+ });
111
+
112
+ test('is not shown for a date field without a schedule context', async () => {
113
+ await render(<AdvancedSettingsSubject format={dateFormat} withSchedules={false} />);
114
+
115
+ expect(container.textContent).toContain('Date format');
116
+ expect(container.textContent).not.toContain(SWITCH_LABEL);
117
+ });
118
+
119
+ test('is not shown for a number field', async () => {
120
+ await render(<AdvancedSettingsSubject format={numberFormat} withSchedules />);
121
+
122
+ expect(container.textContent).not.toContain(SWITCH_LABEL);
123
+ });
124
+ });
125
+
126
+ describe('in the options of an e-sign date signed offset', () => {
127
+ const renderOptions = (withSchedules: boolean) =>
128
+ render(
129
+ <ESignOptionsModal
130
+ initialState={{ rules: [{ days: 3 }] }}
131
+ onSave={() => {}}
132
+ businessCalendar={withSchedules ? businessCalendar : undefined}
133
+ />,
134
+ );
135
+
136
+ test('is shown with a schedule context', async () => {
137
+ await renderOptions(true);
138
+
139
+ expect(container.textContent).toContain(SWITCH_LABEL);
140
+ });
141
+
142
+ test('is not shown without a schedule context', async () => {
143
+ await renderOptions(false);
144
+
145
+ expect(container.textContent).not.toContain(SWITCH_LABEL);
146
+ });
147
+ });
148
+
149
+ describe('in the config panel of an e-sign date signed offset field', () => {
150
+ const field = {
151
+ id: 'e1',
152
+ type: FieldTypeEnum.eSign,
153
+ subType: ESignFieldType.dateSignedOffset,
154
+ recipient: 'customer',
155
+ path: 'esign.customer.dateSignedOffset',
156
+ data: { rules: [{ days: 3 }] },
157
+ } as unknown as PdfField;
158
+ const onFieldConfigChange = jest.fn();
159
+
160
+ const renderPanel = (context?: typeof businessCalendar) =>
161
+ render(
162
+ <FieldConfigPanel
163
+ field={field}
164
+ recipients={[{ id: 1, name: 'customer', displayName: 'Customer' }]}
165
+ forms={[]}
166
+ hideConditionalLogic
167
+ businessCalendar={context}
168
+ onDeleteField={noOp}
169
+ onFieldConfigChange={onFieldConfigChange}
170
+ onRequestFormFields={noOp}
171
+ />,
172
+ );
173
+
174
+ const findSwitch = () =>
175
+ [...container.querySelectorAll('input')].find(input =>
176
+ input.closest('label')?.textContent?.includes(SWITCH_LABEL),
177
+ );
178
+
179
+ beforeEach(() => onFieldConfigChange.mockClear());
180
+
181
+ test('is not shown without a schedule context', async () => {
182
+ await renderPanel();
183
+
184
+ expect(container.textContent).toContain('Number of days');
185
+ expect(container.textContent).not.toContain(SWITCH_LABEL);
186
+ });
187
+
188
+ test('is shown with a schedule context', async () => {
189
+ await renderPanel(businessCalendar);
190
+
191
+ expect(findSwitch()).toBeDefined();
192
+ });
193
+
194
+ test('stores the choice in the field data and does not call the context', async () => {
195
+ const onToggle = jest.fn();
196
+ await renderPanel({ ...businessCalendar, onToggle });
197
+
198
+ await act(async () => findSwitch()?.click());
199
+
200
+ expect(onFieldConfigChange).toHaveBeenCalledWith({
201
+ data: { rules: [{ days: 3 }], businessCalendarEnabled: true },
202
+ });
203
+ expect(onToggle).not.toHaveBeenCalled();
204
+ });
205
+ });
206
+ });
@@ -106,23 +106,32 @@ export const FieldConfigPanelOverlay: FC<FieldConfigPanelOverlayProps> = ({
106
106
  [scheduleBindings, selectedFieldId, onScheduleBindingsChange],
107
107
  );
108
108
 
109
- const businessCalendar: ScheduleEditorContext = useMemo(
110
- () => ({
111
- enabled: !!selectedBinding,
112
- selectedScheduleId: selectedBinding?.scheduleId,
113
- onToggle: handleToggle,
114
- onSelectSchedule: handleSelectSchedule,
115
- holidayCatalog,
116
- holidayCatalogLoading,
117
- holidayCatalogError,
118
- schedules,
119
- schedulesLoading,
120
- schedulesError,
121
- onCreateSchedule,
122
- onUpdateSchedule,
123
- onDeleteSchedule,
124
- }),
109
+ /*
110
+ * The schedule UI (the Formula Builder's switch and the e-sign day offset's schedule) is offered
111
+ * only to a host that passes `onScheduleBindingsChange`. Without it there is no context, and
112
+ * everything that renders the schedule UI checks for one.
113
+ */
114
+ const businessCalendar: ScheduleEditorContext | undefined = useMemo(
115
+ () =>
116
+ onScheduleBindingsChange
117
+ ? {
118
+ enabled: !!selectedBinding,
119
+ selectedScheduleId: selectedBinding?.scheduleId,
120
+ onToggle: handleToggle,
121
+ onSelectSchedule: handleSelectSchedule,
122
+ holidayCatalog,
123
+ holidayCatalogLoading,
124
+ holidayCatalogError,
125
+ schedules,
126
+ schedulesLoading,
127
+ schedulesError,
128
+ onCreateSchedule,
129
+ onUpdateSchedule,
130
+ onDeleteSchedule,
131
+ }
132
+ : undefined,
125
133
  [
134
+ onScheduleBindingsChange,
126
135
  selectedBinding,
127
136
  handleToggle,
128
137
  handleSelectSchedule,
@@ -46,7 +46,7 @@ export interface PdfEditorProps {
46
46
  /**
47
47
  * Date calculated fields whose custom business-day exclusion toggle is on, and the schedule
48
48
  * each uses (`PdfField.id` as `fieldKey`), as `PdfView`'s. Also drives the Formula Builder's
49
- * toggle/picker for the selected field.
49
+ * toggle/picker for the selected field, which are shown only with `onScheduleBindingsChange`.
50
50
  */
51
51
  scheduleBindings?: FieldScheduleBinding[];
52
52
  /** The tenant's known holidays, for the schedule editor's checklist. */
@@ -67,6 +67,11 @@ export interface PdfEditorProps {
67
67
  * `PUT api/holidays/templates/{id}/bindings`). `PdfEditor` does not persist this itself —
68
68
  * the host is expected to save it (and the bindings are typically saved separately from the
69
69
  * template's own fields).
70
+ *
71
+ * Passing it also turns the schedule UI on: without it the Formula Builder has no "Exclude
72
+ * weekends & holidays" switch and the e-sign day offset has no schedule. A host that cannot save
73
+ * bindings (for example one without a tenant) leaves it out. It is not called for the e-sign
74
+ * schedule, which is stored in the field's `data`.
70
75
  */
71
76
  onScheduleBindingsChange?(bindings: FieldScheduleBinding[]): void;
72
77
  /**