@open-mercato/core 0.6.6-develop.6205.1.109e4b6a84 → 0.6.6-develop.6227.1.2695efff30
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/.turbo/turbo-build.log +1 -1
- package/dist/modules/currencies/backend/currencies/[id]/page.js +33 -8
- package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/page.js +63 -27
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +35 -14
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/currencies/components/CurrencyFetchingConfig.js +104 -41
- package/dist/modules/currencies/components/CurrencyFetchingConfig.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/roles/[id]/acl.js +57 -8
- package/dist/modules/customer_accounts/api/admin/roles/[id]/acl.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +5 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +30 -14
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +29 -19
- package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js +166 -64
- package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js.map +2 -2
- package/dist/modules/customers/components/AddressFormatSettings.js +31 -16
- package/dist/modules/customers/components/AddressFormatSettings.js.map +2 -2
- package/dist/modules/customers/components/DictionarySettings.js +57 -31
- package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
- package/dist/modules/customers/components/PipelineSettings.js +156 -76
- package/dist/modules/customers/components/PipelineSettings.js.map +2 -2
- package/dist/modules/customers/components/calendar/AgendaList.js +10 -4
- package/dist/modules/customers/components/calendar/AgendaList.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js +18 -2
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js.map +2 -2
- package/dist/modules/customers/components/calendar/MonthGrid.js +5 -2
- package/dist/modules/customers/components/calendar/MonthGrid.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/PeopleField.js +6 -0
- package/dist/modules/customers/components/calendar/editor/PeopleField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/RelatedToField.js +2 -0
- package/dist/modules/customers/components/calendar/editor/RelatedToField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/ScheduleSection.js +4 -1
- package/dist/modules/customers/components/calendar/editor/ScheduleSection.js.map +2 -2
- package/dist/modules/customers/lib/calendar/labels.js +33 -0
- package/dist/modules/customers/lib/calendar/labels.js.map +7 -0
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +32 -11
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
- package/dist/modules/data_sync/api/mappings/[id]/route.js +59 -0
- package/dist/modules/data_sync/api/mappings/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/mappings/route.js +44 -0
- package/dist/modules/data_sync/api/mappings/route.js.map +2 -2
- package/dist/modules/data_sync/api/run.js +31 -0
- package/dist/modules/data_sync/api/run.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/cancel.js +31 -0
- package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/retry.js +31 -0
- package/dist/modules/data_sync/api/runs/[id]/retry.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/[id]/route.js +59 -3
- package/dist/modules/data_sync/api/schedules/[id]/route.js.map +2 -2
- package/dist/modules/data_sync/api/schedules/route.js +33 -4
- package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
- package/dist/modules/directory/api/organization-branding/route.js +54 -2
- package/dist/modules/directory/api/organization-branding/route.js.map +2 -2
- package/dist/modules/directory/backend/directory/branding/page.js +15 -9
- package/dist/modules/directory/backend/directory/branding/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/organizations/page.js +28 -9
- package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js +29 -13
- package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
- package/dist/modules/entities/api/definitions.batch.js +15 -0
- package/dist/modules/entities/api/definitions.batch.js.map +2 -2
- package/dist/modules/entities/api/definitions.js +26 -0
- package/dist/modules/entities/api/definitions.js.map +2 -2
- package/dist/modules/entities/api/definitions.mutation-guard.js +57 -0
- package/dist/modules/entities/api/definitions.mutation-guard.js.map +7 -0
- package/dist/modules/entities/api/definitions.restore.js +15 -0
- package/dist/modules/entities/api/definitions.restore.js.map +2 -2
- package/dist/modules/entities/api/entities.js +31 -3
- package/dist/modules/entities/api/entities.js.map +2 -2
- package/dist/modules/entities/api/records.js +18 -0
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +28 -10
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
- package/dist/modules/feature_toggles/api/overrides/route.js +38 -1
- package/dist/modules/feature_toggles/api/overrides/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/emails/[id]/route.js +30 -0
- package/dist/modules/inbox_ops/api/emails/[id]/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/[id]/accept-all/route.js +30 -0
- package/dist/modules/inbox_ops/api/proposals/[id]/accept-all/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js +31 -0
- package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/[id]/categorize/route.js +31 -0
- package/dist/modules/inbox_ops/api/proposals/[id]/categorize/route.js.map +2 -2
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js +68 -39
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js.map +2 -2
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +14 -4
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +2 -2
- package/dist/modules/payment_gateways/api/cancel/route.js +37 -0
- package/dist/modules/payment_gateways/api/cancel/route.js.map +2 -2
- package/dist/modules/payment_gateways/api/capture/route.js +37 -0
- package/dist/modules/payment_gateways/api/capture/route.js.map +2 -2
- package/dist/modules/payment_gateways/api/guards.js +31 -0
- package/dist/modules/payment_gateways/api/guards.js.map +7 -0
- package/dist/modules/payment_gateways/api/refund/route.js +37 -0
- package/dist/modules/payment_gateways/api/refund/route.js.map +2 -2
- package/dist/modules/payment_gateways/api/sessions/route.js +37 -0
- package/dist/modules/payment_gateways/api/sessions/route.js.map +2 -2
- package/dist/modules/planner/api/availability-date-specific.js +11 -1
- package/dist/modules/planner/api/availability-date-specific.js.map +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js +20 -3
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
- package/dist/modules/planner/commands/availability-date-specific.js +16 -0
- package/dist/modules/planner/commands/availability-date-specific.js.map +2 -2
- package/dist/modules/planner/components/AvailabilityRulesEditor.js +109 -40
- package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
- package/dist/modules/query_index/api/purge.js +35 -3
- package/dist/modules/query_index/api/purge.js.map +2 -2
- package/dist/modules/query_index/api/reindex.js +41 -3
- package/dist/modules/query_index/api/reindex.js.map +2 -2
- package/dist/modules/query_index/components/QueryIndexesTable.js +57 -24
- package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
- package/dist/modules/shipping_carriers/api/shipments/route.js +31 -0
- package/dist/modules/shipping_carriers/api/shipments/route.js.map +2 -2
- package/dist/modules/shipping_carriers/api/tracking/refresh/route.js +55 -0
- package/dist/modules/shipping_carriers/api/tracking/refresh/route.js.map +7 -0
- package/dist/modules/shipping_carriers/data/validators.js +6 -1
- package/dist/modules/shipping_carriers/data/validators.js.map +2 -2
- package/dist/modules/shipping_carriers/lib/shipment-wizard/hooks/useShipmentWizard.js +28 -8
- package/dist/modules/shipping_carriers/lib/shipment-wizard/hooks/useShipmentWizard.js.map +2 -2
- package/dist/modules/shipping_carriers/lib/shipping-service.js +37 -7
- package/dist/modules/shipping_carriers/lib/shipping-service.js.map +2 -2
- package/dist/modules/shipping_carriers/workers/status-poller.js +1 -1
- package/dist/modules/shipping_carriers/workers/status-poller.js.map +2 -2
- package/dist/modules/translations/components/TranslationManager.js +49 -20
- package/dist/modules/translations/components/TranslationManager.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/currencies/backend/currencies/[id]/page.tsx +40 -10
- package/src/modules/currencies/backend/currencies/page.tsx +68 -29
- package/src/modules/currencies/backend/exchange-rates/page.tsx +40 -15
- package/src/modules/currencies/components/CurrencyFetchingConfig.tsx +110 -41
- package/src/modules/customer_accounts/api/admin/roles/[id]/acl.ts +69 -7
- package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +16 -8
- package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +32 -14
- package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +32 -20
- package/src/modules/customers/backend/config/customers/pipeline-stages/page.tsx +171 -64
- package/src/modules/customers/components/AddressFormatSettings.tsx +39 -19
- package/src/modules/customers/components/DictionarySettings.tsx +63 -29
- package/src/modules/customers/components/PipelineSettings.tsx +165 -80
- package/src/modules/customers/components/calendar/AgendaList.tsx +13 -8
- package/src/modules/customers/components/calendar/CalendarSettingsModal.tsx +16 -2
- package/src/modules/customers/components/calendar/MonthGrid.tsx +5 -2
- package/src/modules/customers/components/calendar/editor/PeopleField.tsx +6 -0
- package/src/modules/customers/components/calendar/editor/RelatedToField.tsx +2 -0
- package/src/modules/customers/components/calendar/editor/ScheduleSection.tsx +7 -0
- package/src/modules/customers/i18n/de.json +11 -7
- package/src/modules/customers/i18n/en.json +6 -2
- package/src/modules/customers/i18n/es.json +11 -7
- package/src/modules/customers/i18n/pl.json +11 -7
- package/src/modules/customers/lib/calendar/labels.ts +42 -0
- package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +39 -11
- package/src/modules/data_sync/api/mappings/[id]/route.ts +63 -0
- package/src/modules/data_sync/api/mappings/route.ts +48 -0
- package/src/modules/data_sync/api/run.ts +33 -0
- package/src/modules/data_sync/api/runs/[id]/cancel.ts +34 -0
- package/src/modules/data_sync/api/runs/[id]/retry.ts +33 -0
- package/src/modules/data_sync/api/schedules/[id]/route.ts +64 -2
- package/src/modules/data_sync/api/schedules/route.ts +36 -4
- package/src/modules/directory/api/organization-branding/route.ts +61 -0
- package/src/modules/directory/backend/directory/branding/page.tsx +16 -10
- package/src/modules/directory/backend/directory/organizations/page.tsx +35 -8
- package/src/modules/directory/backend/directory/tenants/page.tsx +37 -13
- package/src/modules/entities/api/definitions.batch.ts +17 -0
- package/src/modules/entities/api/definitions.mutation-guard.ts +80 -0
- package/src/modules/entities/api/definitions.restore.ts +17 -0
- package/src/modules/entities/api/definitions.ts +30 -0
- package/src/modules/entities/api/entities.ts +35 -3
- package/src/modules/entities/api/records.ts +20 -0
- package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +33 -10
- package/src/modules/feature_toggles/api/overrides/route.ts +44 -1
- package/src/modules/inbox_ops/api/emails/[id]/route.ts +32 -0
- package/src/modules/inbox_ops/api/proposals/[id]/accept-all/route.ts +32 -0
- package/src/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.ts +33 -0
- package/src/modules/inbox_ops/api/proposals/[id]/categorize/route.ts +33 -0
- package/src/modules/messages/components/message-detail/hooks/useMessageDetailsActions.ts +80 -42
- package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +21 -4
- package/src/modules/payment_gateways/api/cancel/route.ts +39 -0
- package/src/modules/payment_gateways/api/capture/route.ts +39 -0
- package/src/modules/payment_gateways/api/guards.ts +59 -0
- package/src/modules/payment_gateways/api/refund/route.ts +39 -0
- package/src/modules/payment_gateways/api/sessions/route.ts +40 -0
- package/src/modules/planner/api/availability-date-specific.ts +10 -0
- package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +26 -5
- package/src/modules/planner/commands/availability-date-specific.ts +24 -0
- package/src/modules/planner/components/AvailabilityRulesEditor.tsx +122 -41
- package/src/modules/query_index/api/purge.ts +37 -3
- package/src/modules/query_index/api/reindex.ts +43 -3
- package/src/modules/query_index/components/QueryIndexesTable.tsx +66 -24
- package/src/modules/shipping_carriers/api/shipments/route.ts +31 -0
- package/src/modules/shipping_carriers/api/tracking/refresh/route.ts +53 -0
- package/src/modules/shipping_carriers/data/validators.ts +5 -0
- package/src/modules/shipping_carriers/lib/shipment-wizard/hooks/useShipmentWizard.ts +29 -8
- package/src/modules/shipping_carriers/lib/shipping-service.ts +43 -7
- package/src/modules/shipping_carriers/workers/status-poller.ts +1 -1
- package/src/modules/translations/components/TranslationManager.tsx +65 -21
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import { LoadingMessage, ErrorMessage } from "@open-mercato/ui/backend/detail";
|
|
17
17
|
import { apiCall, apiCallOrThrow, withScopedApiRequestHeaders } from "@open-mercato/ui/backend/utils/apiCall";
|
|
18
18
|
import { createCrud, deleteCrud, updateCrud } from "@open-mercato/ui/backend/utils/crud";
|
|
19
|
+
import { useGuardedMutation } from "@open-mercato/ui/backend/injection/useGuardedMutation";
|
|
19
20
|
import { buildOptimisticLockHeader } from "@open-mercato/ui/backend/utils/optimisticLock";
|
|
20
21
|
import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
21
22
|
import { Spinner } from "@open-mercato/ui/primitives/spinner";
|
|
@@ -28,6 +29,7 @@ import {
|
|
|
28
29
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
29
30
|
import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
|
|
30
31
|
import { normalizeCrudServerError } from "@open-mercato/ui/backend/utils/serverErrors";
|
|
32
|
+
import { surfaceRecordConflict } from "@open-mercato/ui/backend/conflicts";
|
|
31
33
|
import { parseAvailabilityRuleWindow } from "@open-mercato/core/modules/planner/lib/availabilitySchedule";
|
|
32
34
|
import { deleteAvailabilityRuleSet } from "@open-mercato/core/modules/planner/lib/deleteAvailabilityRuleSet";
|
|
33
35
|
import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
|
|
@@ -43,6 +45,22 @@ function withOptimisticLockForRule(rule, mutation) {
|
|
|
43
45
|
function withOptimisticLockForRuleSet(ruleSet, mutation) {
|
|
44
46
|
return withScopedApiRequestHeaders(buildOptimisticLockHeader(ruleSet?.updatedAt ?? ruleSet?.updated_at ?? null), mutation);
|
|
45
47
|
}
|
|
48
|
+
function resolveDateSpecificLockToken(rules) {
|
|
49
|
+
let latestMs = Number.NEGATIVE_INFINITY;
|
|
50
|
+
let latestIso = null;
|
|
51
|
+
for (const rule of rules) {
|
|
52
|
+
const raw = rule.updatedAt ?? rule.updated_at ?? null;
|
|
53
|
+
if (!raw) continue;
|
|
54
|
+
const ms = Date.parse(raw);
|
|
55
|
+
if (!Number.isFinite(ms) || ms <= latestMs) continue;
|
|
56
|
+
latestMs = ms;
|
|
57
|
+
latestIso = raw;
|
|
58
|
+
}
|
|
59
|
+
return latestIso;
|
|
60
|
+
}
|
|
61
|
+
function withOptimisticLockForDateSpecific(rules, mutation) {
|
|
62
|
+
return withScopedApiRequestHeaders(buildOptimisticLockHeader(resolveDateSpecificLockToken(rules)), mutation);
|
|
63
|
+
}
|
|
46
64
|
const DAY_LABELS = [
|
|
47
65
|
{ code: "SU", short: "S", nameKey: "schedule.weekday.sunday", fallback: "Sunday" },
|
|
48
66
|
{ code: "MO", short: "M", nameKey: "schedule.weekday.monday", fallback: "Monday" },
|
|
@@ -289,6 +307,19 @@ function AvailabilityRulesEditor({
|
|
|
289
307
|
}) {
|
|
290
308
|
const t = useT();
|
|
291
309
|
const { confirm, ConfirmDialogElement } = useConfirmDialog();
|
|
310
|
+
const mutationContextId = "planner-availability-rules-editor";
|
|
311
|
+
const { runMutation, retryLastMutation } = useGuardedMutation({
|
|
312
|
+
contextId: mutationContextId,
|
|
313
|
+
blockedMessage: t("ui.forms.flash.saveBlocked", "Save blocked by validation")
|
|
314
|
+
});
|
|
315
|
+
const mutationContext = React.useMemo(
|
|
316
|
+
() => ({
|
|
317
|
+
formId: mutationContextId,
|
|
318
|
+
resourceKind: "planner.availability",
|
|
319
|
+
retryLastMutation
|
|
320
|
+
}),
|
|
321
|
+
[mutationContextId, retryLastMutation]
|
|
322
|
+
);
|
|
292
323
|
const isReadOnly = Boolean(readOnly);
|
|
293
324
|
const canManageUnavailability = allowUnavailability ?? true;
|
|
294
325
|
const dialogRef = React.useRef(null);
|
|
@@ -692,16 +723,20 @@ function AvailabilityRulesEditor({
|
|
|
692
723
|
setIsWeeklyAutoSaving(options?.silentSuccess === true);
|
|
693
724
|
try {
|
|
694
725
|
const windows = buildWeeklyPayload(normalizeWeeklyWindows(weeklyWindowsRef.current));
|
|
695
|
-
await
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
726
|
+
await runMutation({
|
|
727
|
+
operation: () => apiCallOrThrow("/api/planner/availability-weekly", {
|
|
728
|
+
method: "POST",
|
|
729
|
+
headers: { "Content-Type": "application/json" },
|
|
730
|
+
body: JSON.stringify({
|
|
731
|
+
subjectType: subjectForRules,
|
|
732
|
+
subjectId: subjectIdForRules,
|
|
733
|
+
timezone,
|
|
734
|
+
windows
|
|
735
|
+
})
|
|
736
|
+
}, { errorMessage: listLabels.saveWeeklyError }),
|
|
737
|
+
context: mutationContext,
|
|
738
|
+
mutationPayload: { action: "save-weekly", subjectType: subjectForRules, subjectId: subjectIdForRules }
|
|
739
|
+
});
|
|
705
740
|
lastSavedWeeklyKeyRef.current = weeklyKey;
|
|
706
741
|
weeklyDirtyRef.current = false;
|
|
707
742
|
if (!options?.silentSuccess) {
|
|
@@ -729,7 +764,9 @@ function AvailabilityRulesEditor({
|
|
|
729
764
|
usingRuleSet,
|
|
730
765
|
weeklyHasErrors,
|
|
731
766
|
weeklyKey,
|
|
732
|
-
isReadOnly
|
|
767
|
+
isReadOnly,
|
|
768
|
+
mutationContext,
|
|
769
|
+
runMutation
|
|
733
770
|
]);
|
|
734
771
|
React.useEffect(() => {
|
|
735
772
|
saveWeeklyRef.current = saveWeeklyHours;
|
|
@@ -795,7 +832,11 @@ function AvailabilityRulesEditor({
|
|
|
795
832
|
})));
|
|
796
833
|
}
|
|
797
834
|
if (updates.length) {
|
|
798
|
-
await
|
|
835
|
+
await runMutation({
|
|
836
|
+
operation: () => Promise.all(updates),
|
|
837
|
+
context: mutationContext,
|
|
838
|
+
mutationPayload: { action: "update-timezone", timezone: trimmedTimezone }
|
|
839
|
+
});
|
|
799
840
|
await refreshAvailability();
|
|
800
841
|
await refreshRuleSetRules();
|
|
801
842
|
}
|
|
@@ -816,7 +857,9 @@ function AvailabilityRulesEditor({
|
|
|
816
857
|
effectiveRulesetId,
|
|
817
858
|
subjectId,
|
|
818
859
|
subjectType,
|
|
819
|
-
isReadOnly
|
|
860
|
+
isReadOnly,
|
|
861
|
+
mutationContext,
|
|
862
|
+
runMutation
|
|
820
863
|
]);
|
|
821
864
|
React.useEffect(() => {
|
|
822
865
|
if (!timezoneDirty) return;
|
|
@@ -853,14 +896,18 @@ function AvailabilityRulesEditor({
|
|
|
853
896
|
kind: rule.kind ?? "availability",
|
|
854
897
|
note: rule.note ?? null
|
|
855
898
|
}));
|
|
856
|
-
await
|
|
899
|
+
await runMutation({
|
|
900
|
+
operation: () => Promise.all(creations),
|
|
901
|
+
context: mutationContext,
|
|
902
|
+
mutationPayload: { action: "customize", count: creations.length }
|
|
903
|
+
});
|
|
857
904
|
setCustomOverridesEnabled(true);
|
|
858
905
|
await refreshAvailability();
|
|
859
906
|
} catch (error2) {
|
|
860
907
|
const message = error2 instanceof Error ? error2.message : listLabels.saveWeeklyError;
|
|
861
908
|
flash(message, "error");
|
|
862
909
|
}
|
|
863
|
-
}, [effectiveRulesetId, listLabels.saveWeeklyError, refreshAvailability, rulesetRules, subjectId, subjectType, isReadOnly]);
|
|
910
|
+
}, [effectiveRulesetId, listLabels.saveWeeklyError, refreshAvailability, rulesetRules, subjectId, subjectType, isReadOnly, mutationContext, runMutation]);
|
|
864
911
|
const handleResetToRuleSet = React.useCallback(async () => {
|
|
865
912
|
if (isReadOnly) return;
|
|
866
913
|
if (!effectiveRulesetId) return;
|
|
@@ -874,31 +921,39 @@ function AvailabilityRulesEditor({
|
|
|
874
921
|
try {
|
|
875
922
|
const idsToDelete = selectCustomRuleIdsToDelete("reset", availabilityRules);
|
|
876
923
|
const idsToDeleteSet = new Set(idsToDelete);
|
|
877
|
-
await
|
|
878
|
-
|
|
879
|
-
rule
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
924
|
+
await runMutation({
|
|
925
|
+
operation: () => Promise.all(
|
|
926
|
+
availabilityRules.filter((rule) => idsToDeleteSet.has(rule.id)).map((rule) => withOptimisticLockForRule(
|
|
927
|
+
rule,
|
|
928
|
+
() => deleteCrud("planner/availability", rule.id, { errorMessage: listLabels.saveWeeklyError })
|
|
929
|
+
))
|
|
930
|
+
),
|
|
931
|
+
context: mutationContext,
|
|
932
|
+
mutationPayload: { action: "reset-to-ruleset", ids: idsToDelete }
|
|
933
|
+
});
|
|
883
934
|
setCustomOverridesEnabled(false);
|
|
884
935
|
await refreshAvailability();
|
|
885
936
|
} catch (error2) {
|
|
886
937
|
const message = error2 instanceof Error ? error2.message : listLabels.saveWeeklyError;
|
|
887
938
|
flash(message, "error");
|
|
888
939
|
}
|
|
889
|
-
}, [availabilityRules, confirm, effectiveRulesetId, listLabels.ruleSetConfirm, listLabels.saveWeeklyError, refreshAvailability, isReadOnly]);
|
|
940
|
+
}, [availabilityRules, confirm, effectiveRulesetId, listLabels.ruleSetConfirm, listLabels.saveWeeklyError, refreshAvailability, isReadOnly, mutationContext, runMutation]);
|
|
890
941
|
const handleRuleSetChange = React.useCallback(async (nextId) => {
|
|
891
942
|
if (isReadOnly) return;
|
|
892
943
|
if (!onRulesetChange) return;
|
|
893
944
|
const idsToDelete = selectCustomRuleIdsToDelete("switch", availabilityRules);
|
|
894
945
|
if (idsToDelete.length) {
|
|
895
946
|
const idsToDeleteSet = new Set(idsToDelete);
|
|
896
|
-
await
|
|
897
|
-
|
|
898
|
-
rule
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
947
|
+
await runMutation({
|
|
948
|
+
operation: () => Promise.all(
|
|
949
|
+
availabilityRules.filter((rule) => idsToDeleteSet.has(rule.id)).map((rule) => withOptimisticLockForRule(
|
|
950
|
+
rule,
|
|
951
|
+
() => deleteCrud("planner/availability", rule.id, { errorMessage: listLabels.saveWeeklyError })
|
|
952
|
+
))
|
|
953
|
+
),
|
|
954
|
+
context: mutationContext,
|
|
955
|
+
mutationPayload: { action: "switch-ruleset", ids: idsToDelete }
|
|
956
|
+
});
|
|
902
957
|
}
|
|
903
958
|
setSelectedRulesetId(nextId);
|
|
904
959
|
setCustomOverridesEnabled(false);
|
|
@@ -915,7 +970,9 @@ function AvailabilityRulesEditor({
|
|
|
915
970
|
listLabels.saveWeeklyError,
|
|
916
971
|
onRulesetChange,
|
|
917
972
|
refreshAvailability,
|
|
918
|
-
isReadOnly
|
|
973
|
+
isReadOnly,
|
|
974
|
+
mutationContext,
|
|
975
|
+
runMutation
|
|
919
976
|
]);
|
|
920
977
|
const handleDeleteRuleSet = React.useCallback(async () => {
|
|
921
978
|
if (isReadOnly || !onRulesetChange || !rulesetId) return;
|
|
@@ -929,7 +986,11 @@ function AvailabilityRulesEditor({
|
|
|
929
986
|
variant: "destructive"
|
|
930
987
|
}),
|
|
931
988
|
deleteRuleSet: async (id) => {
|
|
932
|
-
await
|
|
989
|
+
await runMutation({
|
|
990
|
+
operation: () => withOptimisticLockForRuleSet(selected, () => deleteCrud("planner/availability-rule-sets", id, { errorMessage: listLabels.ruleSetDeleteError })),
|
|
991
|
+
context: mutationContext,
|
|
992
|
+
mutationPayload: { action: "delete-ruleset", id }
|
|
993
|
+
});
|
|
933
994
|
},
|
|
934
995
|
clearAssignment: async () => {
|
|
935
996
|
setCustomOverridesEnabled(false);
|
|
@@ -955,7 +1016,9 @@ function AvailabilityRulesEditor({
|
|
|
955
1016
|
refreshAvailability,
|
|
956
1017
|
refreshRuleSets,
|
|
957
1018
|
ruleSets,
|
|
958
|
-
rulesetId
|
|
1019
|
+
rulesetId,
|
|
1020
|
+
mutationContext,
|
|
1021
|
+
runMutation
|
|
959
1022
|
]);
|
|
960
1023
|
const ruleSetFormSchema = React.useMemo(
|
|
961
1024
|
() => z.object({
|
|
@@ -1134,11 +1197,11 @@ function AvailabilityRulesEditor({
|
|
|
1134
1197
|
unavailabilityReasonEntryId: editorUnavailable ? reasonEntryId : null,
|
|
1135
1198
|
unavailabilityReasonValue: editorUnavailable ? reasonValue : null
|
|
1136
1199
|
};
|
|
1137
|
-
await apiCallOrThrow("/api/planner/availability-date-specific", {
|
|
1200
|
+
await withOptimisticLockForDateSpecific(editorRules, () => apiCallOrThrow("/api/planner/availability-date-specific", {
|
|
1138
1201
|
method: "POST",
|
|
1139
1202
|
headers: { "Content-Type": "application/json" },
|
|
1140
1203
|
body: JSON.stringify(payload)
|
|
1141
|
-
}, { errorMessage: listLabels.saveDateError });
|
|
1204
|
+
}, { errorMessage: listLabels.saveDateError }));
|
|
1142
1205
|
} else {
|
|
1143
1206
|
const rulesToDelete = editorRules;
|
|
1144
1207
|
const uniqueRulesById = new Map(rulesToDelete.map((rule) => [rule.id, rule]));
|
|
@@ -1172,6 +1235,7 @@ function AvailabilityRulesEditor({
|
|
|
1172
1235
|
await refreshAvailability();
|
|
1173
1236
|
await refreshRuleSetRules();
|
|
1174
1237
|
} catch (error2) {
|
|
1238
|
+
if (surfaceRecordConflict(error2, t)) return;
|
|
1175
1239
|
const message = error2 instanceof Error ? error2.message : listLabels.saveDateError;
|
|
1176
1240
|
flash(message, "error");
|
|
1177
1241
|
}
|
|
@@ -1197,7 +1261,8 @@ function AvailabilityRulesEditor({
|
|
|
1197
1261
|
timezone,
|
|
1198
1262
|
usingRuleSet,
|
|
1199
1263
|
canManageUnavailability,
|
|
1200
|
-
isReadOnly
|
|
1264
|
+
isReadOnly,
|
|
1265
|
+
t
|
|
1201
1266
|
]);
|
|
1202
1267
|
const handleSlotClick = React.useCallback((slot) => {
|
|
1203
1268
|
if (usingRuleSet || isReadOnly) return;
|
|
@@ -1453,12 +1518,16 @@ function AvailabilityRulesEditor({
|
|
|
1453
1518
|
variant: "outline",
|
|
1454
1519
|
size: "icon",
|
|
1455
1520
|
onClick: async () => {
|
|
1456
|
-
await
|
|
1457
|
-
|
|
1458
|
-
rule
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1521
|
+
await runMutation({
|
|
1522
|
+
operation: () => Promise.all(
|
|
1523
|
+
rules.map((rule) => withOptimisticLockForRule(
|
|
1524
|
+
rule,
|
|
1525
|
+
() => deleteCrud("planner/availability", rule.id)
|
|
1526
|
+
))
|
|
1527
|
+
),
|
|
1528
|
+
context: mutationContext,
|
|
1529
|
+
mutationPayload: { action: "delete-date-rules", count: rules.length }
|
|
1530
|
+
});
|
|
1462
1531
|
await refreshAvailability();
|
|
1463
1532
|
await refreshRuleSetRules();
|
|
1464
1533
|
},
|