@vendure/dashboard 3.7.1-master-202607110305 → 3.7.1
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/bundle/chunks/{2SSKDMRQ-BXz8vjrT.js → 2SSKDMRQ-CGPzX7ok.js} +2 -2
- package/dist/bundle/chunks/{AP7HFJJL-BcewBvAf.js → AP7HFJJL-BANaC6nc.js} +1 -1
- package/dist/bundle/chunks/{WDYDFRGG-Cd364FN_.js → WDYDFRGG-DWwEqh2h.js} +2 -2
- package/dist/bundle/chunks/ar-DCEbHB2w.js +4 -0
- package/dist/bundle/chunks/bg-Dfcm3H-7.js +4 -0
- package/dist/bundle/chunks/cs-CAXaYQpr.js +4 -0
- package/dist/bundle/chunks/de-2rMAToGI.js +4 -0
- package/dist/bundle/chunks/en-CBy7m12i.js +4 -0
- package/dist/bundle/chunks/es-DhcrnvxO.js +4 -0
- package/dist/bundle/chunks/fa-BvgI8zZ5.js +4 -0
- package/dist/bundle/chunks/fr-B1Aw3cxh.js +4 -0
- package/dist/bundle/chunks/he-Dvum09Nk.js +4 -0
- package/dist/bundle/chunks/hr-CiUxzJsU.js +4 -0
- package/dist/bundle/chunks/hu-nmofxtH_.js +4 -0
- package/dist/bundle/chunks/it-CHi8ynGm.js +4 -0
- package/dist/bundle/chunks/ja-zasGFj1j.js +4 -0
- package/dist/bundle/chunks/ko-CBy7m12i.js +4 -0
- package/dist/bundle/chunks/{locale-YfvnivAQ.js → locale--aauL66m.js} +1 -1
- package/dist/bundle/chunks/{main-CG6JVORh.js → main-DVt3RsH7.js} +385 -1076
- package/dist/bundle/chunks/nb-DL1AcZeO.js +4 -0
- package/dist/bundle/chunks/ne-4aOoOw2J.js +4 -0
- package/dist/bundle/chunks/nl-Bf1kuLeC.js +4 -0
- package/dist/bundle/chunks/pl-Ak_kyBWq.js +4 -0
- package/dist/bundle/chunks/pt_BR-DS-J3yJI.js +4 -0
- package/dist/bundle/chunks/pt_PT-CQT5peF9.js +4 -0
- package/dist/bundle/chunks/ro-BJ2PuiOl.js +4 -0
- package/dist/bundle/chunks/ru-Bc_E807P.js +4 -0
- package/dist/bundle/chunks/sv-CZhEzelP.js +4 -0
- package/dist/bundle/chunks/tr-mdPJPyeZ.js +4 -0
- package/dist/bundle/chunks/uk-fAchGf1H.js +4 -0
- package/dist/bundle/chunks/{use-job-queue-polling-BESJ2s1g.js → use-job-queue-polling-mUjHlukj.js} +1329 -12523
- package/dist/bundle/chunks/uz-B5L-lMAZ.js +4 -0
- package/dist/bundle/chunks/zh_Hans-C8s-LcKM.js +4 -0
- package/dist/bundle/chunks/zh_Hant-CGwnZIiO.js +4 -0
- package/dist/bundle/lib.js +584 -577
- package/dist/bundle/main.js +4 -2
- package/dist/plugin/service/metrics.service.js +1 -1
- package/dist/vite/lib-externals.d.ts +44 -0
- package/dist/vite/lib-externals.js +80 -0
- package/dist/vite/vite-plugin-config.js +8 -0
- package/package.json +4 -3
- package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-bulk-actions.tsx +69 -0
- package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-table.tsx +12 -2
- package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +79 -44
- package/src/app/routes/_authenticated/_products/components/force-remove-option-group-dialog.tsx +66 -0
- package/src/app/routes/_authenticated/_products/components/product-option-group-badge.tsx +66 -12
- package/src/app/routes/_authenticated/_products/hooks/use-remove-option-group.ts +90 -0
- package/src/app/routes/_authenticated/_products/products_.$id.tsx +15 -21
- package/src/app/routes/_authenticated/_products/products_.$id_.variants.tsx +34 -75
- package/src/i18n/locales/ar.po +89 -63
- package/src/i18n/locales/bg.po +89 -63
- package/src/i18n/locales/cs.po +89 -63
- package/src/i18n/locales/de.po +89 -63
- package/src/i18n/locales/en.po +89 -63
- package/src/i18n/locales/es.po +89 -63
- package/src/i18n/locales/fa.po +89 -63
- package/src/i18n/locales/fr.po +89 -63
- package/src/i18n/locales/he.po +89 -63
- package/src/i18n/locales/hr.po +89 -63
- package/src/i18n/locales/hu.po +89 -63
- package/src/i18n/locales/it.po +89 -63
- package/src/i18n/locales/ja.po +89 -63
- package/src/i18n/locales/ko.po +16 -0
- package/src/i18n/locales/nb.po +89 -63
- package/src/i18n/locales/ne.po +89 -63
- package/src/i18n/locales/nl.po +89 -63
- package/src/i18n/locales/pl.po +89 -63
- package/src/i18n/locales/pt_BR.po +89 -63
- package/src/i18n/locales/pt_PT.po +89 -63
- package/src/i18n/locales/ro.po +89 -63
- package/src/i18n/locales/ru.po +89 -63
- package/src/i18n/locales/sv.po +89 -63
- package/src/i18n/locales/tr.po +89 -63
- package/src/i18n/locales/uk.po +89 -63
- package/src/i18n/locales/uz.po +89 -63
- package/src/i18n/locales/zh_Hans.po +89 -63
- package/src/i18n/locales/zh_Hant.po +89 -63
- package/src/lib/components/layout/nav-main.tsx +3 -1
- package/src/lib/framework/document-introspection/add-custom-fields.ts +2 -2
- package/src/lib/framework/document-introspection/include-only-selected-list-fields.ts +4 -1
- package/src/lib/framework/extension-api/custom-providers.ts +1 -1
- package/dist/bundle/chunks/ar-BGF27StW.js +0 -4
- package/dist/bundle/chunks/bg-DkqOGEvG.js +0 -4
- package/dist/bundle/chunks/cs-CKnEitnA.js +0 -4
- package/dist/bundle/chunks/de-B-hSTdcF.js +0 -4
- package/dist/bundle/chunks/en-4EbLSxP4.js +0 -4
- package/dist/bundle/chunks/es-BJr_pTZZ.js +0 -4
- package/dist/bundle/chunks/fa-NHk9jRAC.js +0 -4
- package/dist/bundle/chunks/fr-gP2g5_ht.js +0 -4
- package/dist/bundle/chunks/he-Xr8Cx_mh.js +0 -4
- package/dist/bundle/chunks/hr-DzjCNMEU.js +0 -4
- package/dist/bundle/chunks/hu-CXOlSiP6.js +0 -4
- package/dist/bundle/chunks/it-DYujYua2.js +0 -4
- package/dist/bundle/chunks/ja-ZaE7h4EQ.js +0 -4
- package/dist/bundle/chunks/ko-4EbLSxP4.js +0 -4
- package/dist/bundle/chunks/nb-BGkcDLkm.js +0 -4
- package/dist/bundle/chunks/ne-DDJwrpmB.js +0 -4
- package/dist/bundle/chunks/nl-DaJt2O1a.js +0 -4
- package/dist/bundle/chunks/pl-DQ-xjSLt.js +0 -4
- package/dist/bundle/chunks/pt_BR-Bv3fwQyM.js +0 -4
- package/dist/bundle/chunks/pt_PT-DdlVuwFg.js +0 -4
- package/dist/bundle/chunks/ro-CsBx1KAe.js +0 -4
- package/dist/bundle/chunks/ru-CfK8XmB-.js +0 -4
- package/dist/bundle/chunks/sv-DpW1nyx4.js +0 -4
- package/dist/bundle/chunks/tr-iM7XvP3W.js +0 -4
- package/dist/bundle/chunks/uk-Cc2aTucO.js +0 -4
- package/dist/bundle/chunks/uz-Bp06aVxW.js +0 -4
- package/dist/bundle/chunks/zh_Hans-D1qOG21m.js +0 -4
- package/dist/bundle/chunks/zh_Hant-C2Tj1zDP.js +0 -4
- package/dist/vite/.vendure-dashboard-temp/compiler/4346-7f116ae5-e526-4aad-b671-b514921c7c92/dev-config.js +0 -251
- package/dist/vite/.vendure-dashboard-temp/compiler/4346-7f116ae5-e526-4aad-b671-b514921c7c92/package.json +0 -4
- package/dist/vite/.vendure-dashboard-temp/compiler/4346-7f116ae5-e526-4aad-b671-b514921c7c92/test-plugins/nav-modifier-plugin/nav-modifier-plugin.js +0 -23
- package/dist/vite/.vendure-dashboard-temp/compiler/4346-7f116ae5-e526-4aad-b671-b514921c7c92/test-plugins/reviews/api/api-extensions.js +0 -99
- package/dist/vite/.vendure-dashboard-temp/compiler/4346-7f116ae5-e526-4aad-b671-b514921c7c92/test-plugins/reviews/api/product-entity.resolver.js +0 -73
- package/dist/vite/.vendure-dashboard-temp/compiler/4346-7f116ae5-e526-4aad-b671-b514921c7c92/test-plugins/reviews/api/product-review-admin.resolver.js +0 -146
- package/dist/vite/.vendure-dashboard-temp/compiler/4346-7f116ae5-e526-4aad-b671-b514921c7c92/test-plugins/reviews/api/product-review-entity.resolver.js +0 -79
- package/dist/vite/.vendure-dashboard-temp/compiler/4346-7f116ae5-e526-4aad-b671-b514921c7c92/test-plugins/reviews/api/product-review-shop.resolver.js +0 -79
- package/dist/vite/.vendure-dashboard-temp/compiler/4346-7f116ae5-e526-4aad-b671-b514921c7c92/test-plugins/reviews/entities/product-review-translation.entity.js +0 -47
- package/dist/vite/.vendure-dashboard-temp/compiler/4346-7f116ae5-e526-4aad-b671-b514921c7c92/test-plugins/reviews/entities/product-review.entity.js +0 -90
- package/dist/vite/.vendure-dashboard-temp/compiler/4346-7f116ae5-e526-4aad-b671-b514921c7c92/test-plugins/reviews/generated-admin-types.js +0 -1021
- package/dist/vite/.vendure-dashboard-temp/compiler/4346-7f116ae5-e526-4aad-b671-b514921c7c92/test-plugins/reviews/generated-shop-types.js +0 -974
- package/dist/vite/.vendure-dashboard-temp/compiler/4346-7f116ae5-e526-4aad-b671-b514921c7c92/test-plugins/reviews/reviews-plugin.js +0 -46
- package/dist/vite/.vendure-dashboard-temp/compiler/4346-7f116ae5-e526-4aad-b671-b514921c7c92/test-plugins/reviews/types.js +0 -2
- package/dist/vite/.vendure-dashboard-temp/gql-tada/4346-7f116ae5-e526-4aad-b671-b514921c7c92/schema.graphql +0 -6844
- package/dist/vite/.vendure-dashboard-temp/gql-tada/4346-7f116ae5-e526-4aad-b671-b514921c7c92/tsconfig.json +0 -10
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/dev-config.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/package.json +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/test-plugins/nav-modifier-plugin/nav-modifier-plugin.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/test-plugins/reviews/api/api-extensions.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/test-plugins/reviews/api/product-entity.resolver.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/test-plugins/reviews/api/product-review-admin.resolver.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/test-plugins/reviews/api/product-review-entity.resolver.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/test-plugins/reviews/api/product-review-shop.resolver.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/test-plugins/reviews/entities/product-review-translation.entity.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/test-plugins/reviews/entities/product-review.entity.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/test-plugins/reviews/generated-admin-types.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/test-plugins/reviews/generated-shop-types.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/test-plugins/reviews/reviews-plugin.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/test-plugins/reviews/types.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/gql-tada/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/schema.graphql +0 -0
- /package/dist/vite/.vendure-dashboard-temp/gql-tada/{3392-6cc5883f-d536-4750-80a8-e56ef4d1f34c → 3313-17d5f23c-1ffd-4e86-b905-7235d2fbfa10}/tsconfig.json +0 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { api } from '@/vdb/graphql/api.js';
|
|
2
|
+
import { ResultOf } from '@/vdb/graphql/graphql.js';
|
|
3
|
+
import { useLingui } from '@lingui/react/macro';
|
|
4
|
+
import { useMutation } from '@tanstack/react-query';
|
|
5
|
+
import { useState } from 'react';
|
|
6
|
+
import { toast } from 'sonner';
|
|
7
|
+
|
|
8
|
+
import { removeOptionGroupFromProductDocument } from '../products.graphql.js';
|
|
9
|
+
|
|
10
|
+
type RemoveOptionGroupResult = ResultOf<
|
|
11
|
+
typeof removeOptionGroupFromProductDocument
|
|
12
|
+
>['removeOptionGroupFromProduct'];
|
|
13
|
+
|
|
14
|
+
export interface UseRemoveOptionGroupOptions {
|
|
15
|
+
/** Called after a group is successfully (force-)removed, e.g. to refetch. */
|
|
16
|
+
onRemoved?: () => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @description
|
|
21
|
+
* Shared logic for removing an option group from a product (issue #4703). Owns the
|
|
22
|
+
* single mutation, the typed `ProductOptionInUseError` discrimination, the toasts,
|
|
23
|
+
* and the "in use" state that drives the force-remove confirmation. Consumers own
|
|
24
|
+
* only their trigger UI and the {@link ForceRemoveOptionGroupDialog} placement.
|
|
25
|
+
*
|
|
26
|
+
* `remove` handles the interactive single-group flow (surfacing the force dialog on
|
|
27
|
+
* `ProductOptionInUseError`); `removeOptionGroupAsync` is the low-level typed
|
|
28
|
+
* primitive for batch callers that inspect the result themselves.
|
|
29
|
+
*/
|
|
30
|
+
export function useRemoveOptionGroup(productId: string, options?: UseRemoveOptionGroupOptions) {
|
|
31
|
+
const { t } = useLingui();
|
|
32
|
+
// The group that hit ProductOptionInUseError and is awaiting force confirmation.
|
|
33
|
+
// When a single hook instance is shared across many groups (the Manage Variants
|
|
34
|
+
// page), this also identifies which group's force dialog is open. Per-instance
|
|
35
|
+
// callers (the detail-page badge) only ever see null or their own group id.
|
|
36
|
+
const [inUseGroupId, setInUseGroupId] = useState<string | null>(null);
|
|
37
|
+
const mutation = useMutation({ mutationFn: api.mutate(removeOptionGroupFromProductDocument) });
|
|
38
|
+
|
|
39
|
+
const removeOptionGroupAsync = (optionGroupId: string, force = false): Promise<RemoveOptionGroupResult> =>
|
|
40
|
+
mutation
|
|
41
|
+
.mutateAsync({ productId, optionGroupId, force })
|
|
42
|
+
.then(result => result.removeOptionGroupFromProduct);
|
|
43
|
+
|
|
44
|
+
const remove = async (optionGroupId: string) => {
|
|
45
|
+
try {
|
|
46
|
+
const result = await removeOptionGroupAsync(optionGroupId);
|
|
47
|
+
if (result.__typename === 'ProductOptionInUseError') {
|
|
48
|
+
setInUseGroupId(optionGroupId);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
toast.success(t`Option group removed`);
|
|
52
|
+
options?.onRemoved?.();
|
|
53
|
+
} catch (error) {
|
|
54
|
+
toast.error(t`Failed to remove option group`, {
|
|
55
|
+
description: error instanceof Error ? error.message : t`Unknown error`,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const forceRemove = async () => {
|
|
61
|
+
if (!inUseGroupId) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
await removeOptionGroupAsync(inUseGroupId, true);
|
|
66
|
+
setInUseGroupId(null);
|
|
67
|
+
toast.success(t`Option group removed`);
|
|
68
|
+
options?.onRemoved?.();
|
|
69
|
+
} catch (error) {
|
|
70
|
+
// Keep the dialog open on failure so the user can retry the force-remove
|
|
71
|
+
// without restarting the whole flow; only a success clears `inUseGroupId`.
|
|
72
|
+
toast.error(t`Failed to remove option group`, {
|
|
73
|
+
description: error instanceof Error ? error.message : t`Unknown error`,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
/** Remove a single group, surfacing the force dialog if it is in use. */
|
|
80
|
+
remove,
|
|
81
|
+
/** Confirm force-removal of the group currently in `inUseGroupId`. */
|
|
82
|
+
forceRemove,
|
|
83
|
+
/** Typed remove primitive for batch callers that inspect the result. */
|
|
84
|
+
removeOptionGroupAsync,
|
|
85
|
+
/** Non-null while the force-remove dialog should be shown for that group. */
|
|
86
|
+
inUseGroupId,
|
|
87
|
+
clearInUseGroup: () => setInUseGroupId(null),
|
|
88
|
+
isPending: mutation.isPending,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -23,7 +23,6 @@ import { detailPageRouteLoader } from '@/vdb/framework/page/detail-page-route-lo
|
|
|
23
23
|
import { useDetailPage } from '@/vdb/framework/page/use-detail-page.js';
|
|
24
24
|
import { Trans, useLingui } from '@lingui/react/macro';
|
|
25
25
|
import { createFileRoute, Link, useNavigate } from '@tanstack/react-router';
|
|
26
|
-
import { useMutation } from '@tanstack/react-query';
|
|
27
26
|
import { Layers, Package, PlusIcon } from 'lucide-react';
|
|
28
27
|
import { useRef, useState } from 'react';
|
|
29
28
|
import { toast } from 'sonner';
|
|
@@ -31,11 +30,11 @@ import { AddOptionGroupDialog } from './components/add-option-group-dialog.js';
|
|
|
31
30
|
import { GenerateVariantsPanel } from './components/generate-variants-panel.js';
|
|
32
31
|
import { ProductOptionGroupBadge } from './components/product-option-group-badge.js';
|
|
33
32
|
import { ProductVariantsTable } from './components/product-variants-table.js';
|
|
33
|
+
import { useRemoveOptionGroup } from './hooks/use-remove-option-group.js';
|
|
34
34
|
import {
|
|
35
35
|
assignProductsToChannelDocument,
|
|
36
36
|
createProductDocument,
|
|
37
37
|
productDetailDocument,
|
|
38
|
-
removeOptionGroupFromProductDocument,
|
|
39
38
|
removeProductsFromChannelDocument,
|
|
40
39
|
updateProductDocument,
|
|
41
40
|
} from './products.graphql.js';
|
|
@@ -171,28 +170,22 @@ function ProductDetailPage() {
|
|
|
171
170
|
},
|
|
172
171
|
});
|
|
173
172
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
173
|
+
// The empty-string fallback only ever applies before `entity` has loaded;
|
|
174
|
+
// `removeAllOptionGroups` is reachable exclusively from the onBack handler below,
|
|
175
|
+
// which is rendered only once `entity` exists, so the real id is always used.
|
|
176
|
+
const { removeOptionGroupAsync } = useRemoveOptionGroup(entity?.id ?? '');
|
|
177
177
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
178
|
+
// Batch-removes every option group when the user backs out of variant setup. This is
|
|
179
|
+
// reached only while the product has zero variants, so ProductOptionInUseError cannot
|
|
180
|
+
// realistically fire here — the branch is kept as a defensive guard. Note the loop is
|
|
181
|
+
// not transactional: a mid-list failure leaves earlier groups already removed.
|
|
182
|
+
const removeAllOptionGroups = async (optionGroups: Array<{ id: string }>) => {
|
|
182
183
|
try {
|
|
183
184
|
for (const group of optionGroups) {
|
|
184
|
-
const result = await
|
|
185
|
-
|
|
186
|
-
optionGroupId: group.id,
|
|
187
|
-
});
|
|
188
|
-
const removeResult = result?.removeOptionGroupFromProduct;
|
|
189
|
-
if (
|
|
190
|
-
removeResult &&
|
|
191
|
-
'__typename' in removeResult &&
|
|
192
|
-
removeResult.__typename === 'ProductOptionInUseError'
|
|
193
|
-
) {
|
|
185
|
+
const result = await removeOptionGroupAsync(group.id);
|
|
186
|
+
if (result.__typename === 'ProductOptionInUseError') {
|
|
194
187
|
toast.error(t`Could not remove option group`, {
|
|
195
|
-
description:
|
|
188
|
+
description: result.message,
|
|
196
189
|
});
|
|
197
190
|
refreshEntity();
|
|
198
191
|
return;
|
|
@@ -301,7 +294,7 @@ function ProductDetailPage() {
|
|
|
301
294
|
optionGroups={entity.optionGroups}
|
|
302
295
|
onSuccess={() => refreshEntity()}
|
|
303
296
|
onBack={{
|
|
304
|
-
handler: () => removeAllOptionGroups(entity.
|
|
297
|
+
handler: () => removeAllOptionGroups(entity.optionGroups),
|
|
305
298
|
confirmation: {
|
|
306
299
|
title: t`Remove option groups?`,
|
|
307
300
|
description: t`This will remove all option groups from this product and return to the variant setup choice.`,
|
|
@@ -320,6 +313,7 @@ function ProductDetailPage() {
|
|
|
320
313
|
id={g.id}
|
|
321
314
|
name={g.name}
|
|
322
315
|
productId={entity.id}
|
|
316
|
+
onRemoved={() => refreshEntity()}
|
|
323
317
|
/>
|
|
324
318
|
))}
|
|
325
319
|
</div>
|
|
@@ -1,16 +1,7 @@
|
|
|
1
1
|
import { ConfirmationDialog } from '@/vdb/components/shared/confirmation-dialog.js';
|
|
2
2
|
import { ErrorPage } from '@/vdb/components/shared/error-page.js';
|
|
3
3
|
import { FormFieldWrapper } from '@/vdb/components/shared/form-field-wrapper.js';
|
|
4
|
-
import {
|
|
5
|
-
AlertDialog,
|
|
6
|
-
AlertDialogAction,
|
|
7
|
-
AlertDialogCancel,
|
|
8
|
-
AlertDialogContent,
|
|
9
|
-
AlertDialogDescription,
|
|
10
|
-
AlertDialogFooter,
|
|
11
|
-
AlertDialogHeader,
|
|
12
|
-
AlertDialogTitle,
|
|
13
|
-
} from '@/vdb/components/ui/alert-dialog.js';
|
|
4
|
+
import { PermissionGuard } from '@/vdb/components/shared/permission-guard.js';
|
|
14
5
|
import { Badge } from '@/vdb/components/ui/badge.js';
|
|
15
6
|
import { Button } from '@/vdb/components/ui/button.js';
|
|
16
7
|
import {
|
|
@@ -41,11 +32,12 @@ import { useForm } from 'react-hook-form';
|
|
|
41
32
|
import { toast } from 'sonner';
|
|
42
33
|
import { AddOptionGroupDialog } from './components/add-option-group-dialog.js';
|
|
43
34
|
import { AddProductVariantDialog } from './components/add-product-variant-dialog.js';
|
|
35
|
+
import { ForceRemoveOptionGroupDialog } from './components/force-remove-option-group-dialog.js';
|
|
36
|
+
import { useRemoveOptionGroup } from './hooks/use-remove-option-group.js';
|
|
44
37
|
import {
|
|
45
38
|
createProductOptionDocument,
|
|
46
39
|
deleteProductVariantDocument,
|
|
47
40
|
productDetailWithVariantsDocument,
|
|
48
|
-
removeOptionGroupFromProductDocument,
|
|
49
41
|
updateProductVariantDocument,
|
|
50
42
|
} from './products.graphql.js';
|
|
51
43
|
|
|
@@ -198,29 +190,13 @@ function ManageProductVariants() {
|
|
|
198
190
|
},
|
|
199
191
|
});
|
|
200
192
|
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
setForceRemoveGroupId(variables.optionGroupId);
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
toast.success(t`Option group removed`);
|
|
212
|
-
refetch();
|
|
213
|
-
},
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
const forceRemoveOptionGroupMutation = useMutation({
|
|
217
|
-
mutationFn: api.mutate(removeOptionGroupFromProductDocument),
|
|
218
|
-
onSuccess: () => {
|
|
219
|
-
setForceRemoveGroupId(null);
|
|
220
|
-
toast.success(t`Option group removed`);
|
|
221
|
-
refetch();
|
|
222
|
-
},
|
|
223
|
-
});
|
|
193
|
+
const {
|
|
194
|
+
remove: removeOptionGroup,
|
|
195
|
+
forceRemove: forceRemoveOptionGroup,
|
|
196
|
+
inUseGroupId: forceRemoveGroupId,
|
|
197
|
+
clearInUseGroup,
|
|
198
|
+
isPending: isRemovingOptionGroup,
|
|
199
|
+
} = useRemoveOptionGroup(id, { onRemoved: refetch });
|
|
224
200
|
|
|
225
201
|
const setOptionToAddToVariant = (variantId: string, groupId: string, optionId: string | undefined) => {
|
|
226
202
|
if (!optionId) {
|
|
@@ -316,22 +292,21 @@ function ManageProductVariants() {
|
|
|
316
292
|
</div>
|
|
317
293
|
</div>
|
|
318
294
|
<div className="col-span-1 flex items-end justify-end">
|
|
319
|
-
<
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
optionGroupId: group.id,
|
|
325
|
-
})}
|
|
326
|
-
>
|
|
327
|
-
<Button
|
|
328
|
-
size="icon"
|
|
329
|
-
variant="ghost"
|
|
330
|
-
disabled={removeOptionGroupMutation.isPending}
|
|
295
|
+
<PermissionGuard requires={['UpdateProduct', 'UpdateCatalog']}>
|
|
296
|
+
<ConfirmationDialog
|
|
297
|
+
title={t`Remove option group`}
|
|
298
|
+
description={t`Are you sure you want to remove this option group from the product?`}
|
|
299
|
+
onConfirm={() => removeOptionGroup(group.id)}
|
|
331
300
|
>
|
|
332
|
-
<
|
|
333
|
-
|
|
334
|
-
|
|
301
|
+
<Button
|
|
302
|
+
size="icon"
|
|
303
|
+
variant="ghost"
|
|
304
|
+
disabled={isRemovingOptionGroup}
|
|
305
|
+
>
|
|
306
|
+
<Trash2 className="h-4 w-4 text-destructive" />
|
|
307
|
+
</Button>
|
|
308
|
+
</ConfirmationDialog>
|
|
309
|
+
</PermissionGuard>
|
|
335
310
|
</div>
|
|
336
311
|
</div>
|
|
337
312
|
))
|
|
@@ -485,32 +460,16 @@ function ManageProductVariants() {
|
|
|
485
460
|
)}
|
|
486
461
|
</PageBlock>
|
|
487
462
|
</PageLayout>
|
|
488
|
-
<
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
<Trans>Cancel</Trans>
|
|
499
|
-
</AlertDialogCancel>
|
|
500
|
-
<AlertDialogAction onClick={() => {
|
|
501
|
-
if (forceRemoveGroupId) {
|
|
502
|
-
forceRemoveOptionGroupMutation.mutate({
|
|
503
|
-
productId: id,
|
|
504
|
-
optionGroupId: forceRemoveGroupId,
|
|
505
|
-
force: true,
|
|
506
|
-
});
|
|
507
|
-
}
|
|
508
|
-
}}>
|
|
509
|
-
<Trans>Force remove</Trans>
|
|
510
|
-
</AlertDialogAction>
|
|
511
|
-
</AlertDialogFooter>
|
|
512
|
-
</AlertDialogContent>
|
|
513
|
-
</AlertDialog>
|
|
463
|
+
<ForceRemoveOptionGroupDialog
|
|
464
|
+
open={!!forceRemoveGroupId}
|
|
465
|
+
onOpenChange={open => {
|
|
466
|
+
if (!open) {
|
|
467
|
+
clearInUseGroup();
|
|
468
|
+
}
|
|
469
|
+
}}
|
|
470
|
+
onConfirm={forceRemoveOptionGroup}
|
|
471
|
+
isPending={isRemovingOptionGroup}
|
|
472
|
+
/>
|
|
514
473
|
</Page>
|
|
515
474
|
);
|
|
516
475
|
}
|