@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
package/dist/bundle/main.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import "react/jsx-runtime";
|
|
2
|
-
import "./chunks/use-job-queue-polling-
|
|
3
|
-
import "
|
|
2
|
+
import "./chunks/use-job-queue-polling-mUjHlukj.js";
|
|
3
|
+
import "sonner";
|
|
4
|
+
import "./chunks/main-DVt3RsH7.js";
|
|
5
|
+
import "@tanstack/react-router";
|
|
4
6
|
import "react";
|
|
5
7
|
import "react-dom";
|
|
6
8
|
import "react-dom/client";
|
|
@@ -34,7 +34,7 @@ let MetricsService = class MetricsService {
|
|
|
34
34
|
.update(JSON.stringify({
|
|
35
35
|
startDate: calculatedStartDate,
|
|
36
36
|
endDate: calculatedEndDate,
|
|
37
|
-
types: [...types].sort(),
|
|
37
|
+
types: [...types].sort((a, b) => a.localeCompare(b)),
|
|
38
38
|
channel: ctx.channel.token,
|
|
39
39
|
}))
|
|
40
40
|
.digest('base64');
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependencies kept **external** in the pre-built dashboard bundle
|
|
3
|
+
* (`dist/bundle`, produced by `vite.lib.config.mts`).
|
|
4
|
+
*
|
|
5
|
+
* Anything not listed here is frozen into the bundle's shared chunks. That is
|
|
6
|
+
* fine for leaf utilities, but a library that (a) owns a React Context or other
|
|
7
|
+
* module-level singleton AND (b) is reachable by extension code through the
|
|
8
|
+
* `@vendure/dashboard` public API MUST be external. Otherwise the consumer's
|
|
9
|
+
* separate extension build re-bundles a second copy: the two module instances
|
|
10
|
+
* each call `createContext()`, and the extension's hook reads a different
|
|
11
|
+
* context than the one the dashboard's provider populated — the "No QueryClient
|
|
12
|
+
* set" class of failure. See issue #4919.
|
|
13
|
+
*
|
|
14
|
+
* A duplication audit that turns this contract into a test lives in
|
|
15
|
+
* `vite/tests/bundle-singleton.spec.ts`.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Always-external: resolved from the consumer's own module graph at runtime
|
|
19
|
+
* (React, Lingui) or injected by the consumer's Vite plugins (`virtual:*`).
|
|
20
|
+
*/
|
|
21
|
+
export declare const runtimePeers: Array<string | RegExp>;
|
|
22
|
+
/**
|
|
23
|
+
* Context- and singleton-bearing libraries that must be **shared** between the
|
|
24
|
+
* dashboard app and extension code rather than frozen into the bundle. Keeping
|
|
25
|
+
* them external means both `main.js` (which renders the providers) and an
|
|
26
|
+
* extension's separately-built code resolve to the consumer's single instance.
|
|
27
|
+
*/
|
|
28
|
+
export declare const singletonSharedDeps: Array<string | RegExp>;
|
|
29
|
+
/**
|
|
30
|
+
* Bare specifiers of {@link singletonSharedDeps}, for the consumer dev server's
|
|
31
|
+
* dep optimizer (`optimizeDeps.include`) so every bare import — from the
|
|
32
|
+
* pre-built `main.js`, from `lib.js`, and from extension code — resolves to one
|
|
33
|
+
* pre-bundled instance.
|
|
34
|
+
*/
|
|
35
|
+
export declare const singletonSharedDepNames: string[];
|
|
36
|
+
/**
|
|
37
|
+
* The full external list for the dashboard bundle build.
|
|
38
|
+
*/
|
|
39
|
+
export declare const dashboardBundleExternals: Array<string | RegExp>;
|
|
40
|
+
/**
|
|
41
|
+
* Returns `true` if `id` is matched by any entry in `externals` (string exact
|
|
42
|
+
* match or subpath, or RegExp test).
|
|
43
|
+
*/
|
|
44
|
+
export declare function isExternalId(id: string, externals: Array<string | RegExp>): boolean;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependencies kept **external** in the pre-built dashboard bundle
|
|
3
|
+
* (`dist/bundle`, produced by `vite.lib.config.mts`).
|
|
4
|
+
*
|
|
5
|
+
* Anything not listed here is frozen into the bundle's shared chunks. That is
|
|
6
|
+
* fine for leaf utilities, but a library that (a) owns a React Context or other
|
|
7
|
+
* module-level singleton AND (b) is reachable by extension code through the
|
|
8
|
+
* `@vendure/dashboard` public API MUST be external. Otherwise the consumer's
|
|
9
|
+
* separate extension build re-bundles a second copy: the two module instances
|
|
10
|
+
* each call `createContext()`, and the extension's hook reads a different
|
|
11
|
+
* context than the one the dashboard's provider populated — the "No QueryClient
|
|
12
|
+
* set" class of failure. See issue #4919.
|
|
13
|
+
*
|
|
14
|
+
* A duplication audit that turns this contract into a test lives in
|
|
15
|
+
* `vite/tests/bundle-singleton.spec.ts`.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Always-external: resolved from the consumer's own module graph at runtime
|
|
19
|
+
* (React, Lingui) or injected by the consumer's Vite plugins (`virtual:*`).
|
|
20
|
+
*/
|
|
21
|
+
export const runtimePeers = [
|
|
22
|
+
// React core (peer deps in user projects)
|
|
23
|
+
'react',
|
|
24
|
+
'react-dom',
|
|
25
|
+
'react-dom/client',
|
|
26
|
+
'react/jsx-runtime',
|
|
27
|
+
'react/jsx-dev-runtime',
|
|
28
|
+
// Lingui — macros are transformed separately; keep the runtime external
|
|
29
|
+
/^@lingui\//,
|
|
30
|
+
// Virtual modules — resolved by the consumer's vendureDashboardPlugin
|
|
31
|
+
/^virtual:/,
|
|
32
|
+
// @vendure/common is a peer of every Vendure plugin
|
|
33
|
+
/^@vendure\/common(\/|$)/,
|
|
34
|
+
// The dashboard's own subpath exports
|
|
35
|
+
'@vendure/dashboard/plugin',
|
|
36
|
+
'@vendure/dashboard/vite',
|
|
37
|
+
];
|
|
38
|
+
/**
|
|
39
|
+
* Context- and singleton-bearing libraries that must be **shared** between the
|
|
40
|
+
* dashboard app and extension code rather than frozen into the bundle. Keeping
|
|
41
|
+
* them external means both `main.js` (which renders the providers) and an
|
|
42
|
+
* extension's separately-built code resolve to the consumer's single instance.
|
|
43
|
+
*/
|
|
44
|
+
export const singletonSharedDeps = [
|
|
45
|
+
// @tanstack/react-query — QueryClientContext
|
|
46
|
+
'@tanstack/react-query',
|
|
47
|
+
// react-hook-form — FormProvider context
|
|
48
|
+
'react-hook-form',
|
|
49
|
+
// @tanstack/react-router — RouterContext (companion packages travel with it
|
|
50
|
+
// since the whole package stays external)
|
|
51
|
+
/^@tanstack\/react-router(\/|$)/,
|
|
52
|
+
// sonner — module-level toast observer
|
|
53
|
+
'sonner',
|
|
54
|
+
];
|
|
55
|
+
/**
|
|
56
|
+
* Bare specifiers of {@link singletonSharedDeps}, for the consumer dev server's
|
|
57
|
+
* dep optimizer (`optimizeDeps.include`) so every bare import — from the
|
|
58
|
+
* pre-built `main.js`, from `lib.js`, and from extension code — resolves to one
|
|
59
|
+
* pre-bundled instance.
|
|
60
|
+
*/
|
|
61
|
+
export const singletonSharedDepNames = [
|
|
62
|
+
'@tanstack/react-query',
|
|
63
|
+
'react-hook-form',
|
|
64
|
+
'@tanstack/react-router',
|
|
65
|
+
'sonner',
|
|
66
|
+
];
|
|
67
|
+
/**
|
|
68
|
+
* The full external list for the dashboard bundle build.
|
|
69
|
+
*/
|
|
70
|
+
export const dashboardBundleExternals = [
|
|
71
|
+
...runtimePeers,
|
|
72
|
+
...singletonSharedDeps,
|
|
73
|
+
];
|
|
74
|
+
/**
|
|
75
|
+
* Returns `true` if `id` is matched by any entry in `externals` (string exact
|
|
76
|
+
* match or subpath, or RegExp test).
|
|
77
|
+
*/
|
|
78
|
+
export function isExternalId(id, externals) {
|
|
79
|
+
return externals.some(entry => typeof entry === 'string' ? id === entry || id.startsWith(`${entry}/`) : entry.test(id));
|
|
80
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
+
import { singletonSharedDepNames } from './lib-externals.js';
|
|
2
3
|
export function viteConfigPlugin({ packageRoot, useExperimentalBundle }) {
|
|
3
4
|
return {
|
|
4
5
|
name: 'vendure:vite-config-plugin',
|
|
@@ -67,6 +68,13 @@ export function viteConfigPlugin({ packageRoot, useExperimentalBundle }) {
|
|
|
67
68
|
'use-sync-external-store/shim',
|
|
68
69
|
'use-sync-external-store/shim/with-selector',
|
|
69
70
|
'@messageformat/parser',
|
|
71
|
+
// In bundle mode these context/singleton libraries are kept
|
|
72
|
+
// external from the pre-built bundle (see lib-externals.ts),
|
|
73
|
+
// so pre-bundle them here to guarantee that main.js, lib.js
|
|
74
|
+
// and extension code all resolve to ONE instance. Without
|
|
75
|
+
// this the dashboard's provider and an extension's hook can
|
|
76
|
+
// bind to different module instances — issue #4919.
|
|
77
|
+
...(useExperimentalBundle ? singletonSharedDepNames : []),
|
|
70
78
|
] });
|
|
71
79
|
return config;
|
|
72
80
|
},
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vendure/dashboard",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "3.7.1
|
|
4
|
+
"version": "3.7.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"build": "npm run check-types && npm run build:vite && npm run build:plugin && npm run build:lib",
|
|
23
23
|
"watch": "tsc --project tsconfig.vite.json --watch",
|
|
24
24
|
"test": "vitest run",
|
|
25
|
+
"audit:bundle": "cross-env RUN_BUNDLE_AUDIT=true vitest run vite/tests/bundle-singleton.spec.ts vite/tests/bundle-singleton-dev-serving.spec.ts",
|
|
25
26
|
"lint": "eslint .",
|
|
26
27
|
"preview": "vite preview",
|
|
27
28
|
"generate-index": "node scripts/generate-index.js",
|
|
@@ -138,8 +139,8 @@
|
|
|
138
139
|
"@storybook/addon-vitest": "^10.3.1",
|
|
139
140
|
"@storybook/react-vite": "^10.3.1",
|
|
140
141
|
"@types/node": "^22.19.0",
|
|
141
|
-
"@vendure/common": "
|
|
142
|
-
"@vendure/core": "
|
|
142
|
+
"@vendure/common": "3.7.1",
|
|
143
|
+
"@vendure/core": "3.7.1",
|
|
143
144
|
"@vitest/browser": "^3.2.4",
|
|
144
145
|
"@vitest/coverage-v8": "^3.2.4",
|
|
145
146
|
"eslint": "^9.39.0",
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { DataTableBulkActionItem } from '@/vdb/components/data-table/data-table-bulk-action-item.js';
|
|
2
|
+
import { BulkActionComponent } from '@/vdb/framework/extension-api/types/data-table.js';
|
|
3
|
+
import { api } from '@/vdb/graphql/api.js';
|
|
4
|
+
import { usePaginatedList } from '@/vdb/hooks/use-paginated-list.js';
|
|
5
|
+
import { plural } from '@lingui/core/macro';
|
|
6
|
+
import { Plural, Trans, useLingui } from '@lingui/react/macro';
|
|
7
|
+
import { useMutation } from '@tanstack/react-query';
|
|
8
|
+
import { UserMinus } from 'lucide-react';
|
|
9
|
+
import { toast } from 'sonner';
|
|
10
|
+
import { removeCustomersFromGroupDocument } from '../customer-groups.graphql.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The group id is only known by the parent table, so the bulk action is built as a factory rather
|
|
14
|
+
* than a plain component. Callers must memoize the result: `DataTableBulkActions` renders the
|
|
15
|
+
* component by identity, so a fresh one each render would remount it and discard the confirmation
|
|
16
|
+
* dialog's open state mid-interaction.
|
|
17
|
+
*/
|
|
18
|
+
export function createRemoveFromGroupBulkAction(customerGroupId: string): BulkActionComponent<any> {
|
|
19
|
+
return function RemoveFromGroupBulkAction({ selection, table }) {
|
|
20
|
+
const { refetchPaginatedList } = usePaginatedList();
|
|
21
|
+
const { t } = useLingui();
|
|
22
|
+
const count = selection.length;
|
|
23
|
+
|
|
24
|
+
const { mutate, isPending } = useMutation({
|
|
25
|
+
mutationFn: api.mutate(removeCustomersFromGroupDocument),
|
|
26
|
+
onSuccess: () => {
|
|
27
|
+
// `plural` from @lingui/core/macro is used (not useLingui's `t`) because this is a
|
|
28
|
+
// non-JSX message: it compiles to an i18n._() call against the same global instance
|
|
29
|
+
// the I18nProvider activates. Do NOT nest t`...` inside the arms — that breaks extraction.
|
|
30
|
+
toast.success(
|
|
31
|
+
plural(count, {
|
|
32
|
+
one: `Removed ${count} customer from group`,
|
|
33
|
+
other: `Removed ${count} customers from group`,
|
|
34
|
+
}),
|
|
35
|
+
);
|
|
36
|
+
refetchPaginatedList();
|
|
37
|
+
table.resetRowSelection();
|
|
38
|
+
},
|
|
39
|
+
onError: error => {
|
|
40
|
+
toast.error(t`Failed to remove customers from group`, {
|
|
41
|
+
description: error.message,
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<DataTableBulkActionItem
|
|
48
|
+
requiresPermission={['UpdateCustomerGroup']}
|
|
49
|
+
onClick={() =>
|
|
50
|
+
mutate({
|
|
51
|
+
customerGroupId,
|
|
52
|
+
customerIds: selection.map(s => s.id),
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
disabled={isPending}
|
|
56
|
+
label={<Trans>Remove from group</Trans>}
|
|
57
|
+
confirmationText={
|
|
58
|
+
<Plural
|
|
59
|
+
value={count}
|
|
60
|
+
one={`Are you sure you want to remove ${count} customer from this group?`}
|
|
61
|
+
other={`Are you sure you want to remove ${count} customers from this group?`}
|
|
62
|
+
/>
|
|
63
|
+
}
|
|
64
|
+
icon={UserMinus}
|
|
65
|
+
className="text-destructive"
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
}
|
package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-table.tsx
CHANGED
|
@@ -11,9 +11,10 @@ import { Trans, useLingui } from '@lingui/react/macro';
|
|
|
11
11
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
12
12
|
import { Link } from '@tanstack/react-router';
|
|
13
13
|
import { ColumnFiltersState, SortingState } from '@tanstack/react-table';
|
|
14
|
-
import { useState } from 'react';
|
|
14
|
+
import { useMemo, useState } from 'react';
|
|
15
15
|
import { toast } from 'sonner';
|
|
16
16
|
import { addCustomerToGroupDocument } from '../../_customers/customers.graphql.js';
|
|
17
|
+
import { createRemoveFromGroupBulkAction } from './customer-group-members-bulk-actions.js';
|
|
17
18
|
|
|
18
19
|
export const customerGroupMemberListDocument = graphql(`
|
|
19
20
|
query CustomerGroupMemberList($id: ID!, $options: CustomerListOptions) {
|
|
@@ -49,6 +50,11 @@ export function CustomerGroupMembersTable({
|
|
|
49
50
|
const { t } = useLingui();
|
|
50
51
|
const queryClient = useQueryClient();
|
|
51
52
|
|
|
53
|
+
const bulkActions = useMemo(
|
|
54
|
+
() => [{ component: createRemoveFromGroupBulkAction(customerGroupId) }],
|
|
55
|
+
[customerGroupId],
|
|
56
|
+
);
|
|
57
|
+
|
|
52
58
|
const { mutate: addCustomerToGroup } = useMutation({
|
|
53
59
|
mutationFn: api.mutate(addCustomerToGroupDocument),
|
|
54
60
|
onSuccess: () => {
|
|
@@ -70,6 +76,7 @@ export function CustomerGroupMembersTable({
|
|
|
70
76
|
...variables,
|
|
71
77
|
id: customerGroupId,
|
|
72
78
|
})}
|
|
79
|
+
bulkActions={bulkActions}
|
|
73
80
|
page={page}
|
|
74
81
|
itemsPerPage={pageSize}
|
|
75
82
|
sorting={sorting}
|
|
@@ -100,7 +107,10 @@ export function CustomerGroupMembersTable({
|
|
|
100
107
|
cell: ({ row }) => {
|
|
101
108
|
const value = `${row.original.firstName} ${row.original.lastName}`;
|
|
102
109
|
return (
|
|
103
|
-
<Button
|
|
110
|
+
<Button
|
|
111
|
+
render={<Link to="/customers/$id" params={{ id: row.original.id }} />}
|
|
112
|
+
variant="ghost"
|
|
113
|
+
>
|
|
104
114
|
{value}
|
|
105
115
|
</Button>
|
|
106
116
|
);
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
VisibilityState,
|
|
15
15
|
} from '@tanstack/react-table';
|
|
16
16
|
import { Trash2 } from 'lucide-react';
|
|
17
|
-
import { useMemo, useState } from 'react';
|
|
17
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
18
18
|
import {
|
|
19
19
|
couponCodeSelectorPromotionListDocument,
|
|
20
20
|
draftOrderEligibleShippingMethodsDocument,
|
|
@@ -27,6 +27,77 @@ import { OrderTableTotals } from './order-table-totals.js';
|
|
|
27
27
|
import { ShippingMethodSelector } from './shipping-method-selector.js';
|
|
28
28
|
|
|
29
29
|
type OrderFragment = NonNullable<ResultOf<typeof orderDetailDocument>['order']>;
|
|
30
|
+
|
|
31
|
+
function QuantityCell({
|
|
32
|
+
line,
|
|
33
|
+
onAdjustLine,
|
|
34
|
+
onRemoveLine,
|
|
35
|
+
}: {
|
|
36
|
+
line: OrderLineFragment & { customFields?: Record<string, any> };
|
|
37
|
+
onAdjustLine: OrderTableProps['onAdjustLine'];
|
|
38
|
+
onRemoveLine: OrderTableProps['onRemoveLine'];
|
|
39
|
+
}) {
|
|
40
|
+
const [localValue, setLocalValue] = useState<string>(String(line.quantity));
|
|
41
|
+
|
|
42
|
+
// Sync local value when server state changes (e.g. after mutation completes)
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
setLocalValue(String(line.quantity));
|
|
45
|
+
}, [line.quantity]);
|
|
46
|
+
|
|
47
|
+
const commitValue = (removeOnZero: boolean) => {
|
|
48
|
+
const numValue = localValue === '' ? 0 : Number(localValue);
|
|
49
|
+
if (numValue <= 0 || Number.isNaN(numValue)) {
|
|
50
|
+
if (removeOnZero) {
|
|
51
|
+
onRemoveLine({ lineId: line.id });
|
|
52
|
+
} else {
|
|
53
|
+
// Revert to the server value on blur
|
|
54
|
+
setLocalValue(String(line.quantity));
|
|
55
|
+
}
|
|
56
|
+
} else if (numValue !== line.quantity) {
|
|
57
|
+
onAdjustLine({ lineId: line.id, quantity: numValue, customFields: line.customFields });
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div className="flex gap-2">
|
|
63
|
+
<Input
|
|
64
|
+
type="number"
|
|
65
|
+
value={localValue}
|
|
66
|
+
min={0}
|
|
67
|
+
placeholder="0"
|
|
68
|
+
data-testid="order-line-quantity"
|
|
69
|
+
onChange={e => setLocalValue(e.target.value)}
|
|
70
|
+
onKeyDown={e => {
|
|
71
|
+
if (e.key === 'Enter') {
|
|
72
|
+
e.preventDefault();
|
|
73
|
+
commitValue(true);
|
|
74
|
+
}
|
|
75
|
+
}}
|
|
76
|
+
onBlur={() => commitValue(false)}
|
|
77
|
+
/>
|
|
78
|
+
<Button
|
|
79
|
+
variant="outline"
|
|
80
|
+
type="button"
|
|
81
|
+
size="icon"
|
|
82
|
+
onClick={() => onRemoveLine({ lineId: line.id })}
|
|
83
|
+
>
|
|
84
|
+
<Trash2 />
|
|
85
|
+
</Button>
|
|
86
|
+
{line.customFields && (
|
|
87
|
+
<OrderLineCustomFieldsForm
|
|
88
|
+
onUpdate={customFields => {
|
|
89
|
+
onAdjustLine({
|
|
90
|
+
lineId: line.id,
|
|
91
|
+
quantity: line.quantity,
|
|
92
|
+
customFields: customFields,
|
|
93
|
+
});
|
|
94
|
+
}}
|
|
95
|
+
value={line.customFields}
|
|
96
|
+
/>
|
|
97
|
+
)}
|
|
98
|
+
</div>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
30
101
|
type OrderLineFragment = ResultOf<typeof orderLineFragment>;
|
|
31
102
|
|
|
32
103
|
type ShippingMethodQuote = ResultOf<
|
|
@@ -110,49 +181,13 @@ export function EditOrderTable({
|
|
|
110
181
|
{
|
|
111
182
|
header: t`Quantity`,
|
|
112
183
|
accessorKey: 'quantity',
|
|
113
|
-
cell: ({ row }) =>
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
data-testid="order-line-quantity"
|
|
121
|
-
onChange={e => {
|
|
122
|
-
const value = Number.isNaN(e.target.valueAsNumber)
|
|
123
|
-
? 0
|
|
124
|
-
: e.target.valueAsNumber;
|
|
125
|
-
onAdjustLine({
|
|
126
|
-
lineId: row.original.id,
|
|
127
|
-
quantity: value,
|
|
128
|
-
customFields: row.original.customFields,
|
|
129
|
-
});
|
|
130
|
-
}}
|
|
131
|
-
/>
|
|
132
|
-
<Button
|
|
133
|
-
variant="outline"
|
|
134
|
-
type="button"
|
|
135
|
-
size="icon"
|
|
136
|
-
disabled={row.original.quantity === 0}
|
|
137
|
-
onClick={() => onRemoveLine({ lineId: row.original.id })}
|
|
138
|
-
>
|
|
139
|
-
<Trash2 />
|
|
140
|
-
</Button>
|
|
141
|
-
{row.original.customFields && (
|
|
142
|
-
<OrderLineCustomFieldsForm
|
|
143
|
-
onUpdate={customFields => {
|
|
144
|
-
onAdjustLine({
|
|
145
|
-
lineId: row.original.id,
|
|
146
|
-
quantity: row.original.quantity,
|
|
147
|
-
customFields: customFields,
|
|
148
|
-
});
|
|
149
|
-
}}
|
|
150
|
-
value={row.original.customFields}
|
|
151
|
-
/>
|
|
152
|
-
)}
|
|
153
|
-
</div>
|
|
154
|
-
);
|
|
155
|
-
},
|
|
184
|
+
cell: ({ row }) => (
|
|
185
|
+
<QuantityCell
|
|
186
|
+
line={row.original}
|
|
187
|
+
onAdjustLine={onAdjustLine}
|
|
188
|
+
onRemoveLine={onRemoveLine}
|
|
189
|
+
/>
|
|
190
|
+
),
|
|
156
191
|
},
|
|
157
192
|
{
|
|
158
193
|
header: t`Total`,
|
package/src/app/routes/_authenticated/_products/components/force-remove-option-group-dialog.tsx
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AlertDialog,
|
|
3
|
+
AlertDialogAction,
|
|
4
|
+
AlertDialogCancel,
|
|
5
|
+
AlertDialogContent,
|
|
6
|
+
AlertDialogDescription,
|
|
7
|
+
AlertDialogFooter,
|
|
8
|
+
AlertDialogHeader,
|
|
9
|
+
AlertDialogTitle,
|
|
10
|
+
} from '@/vdb/components/ui/alert-dialog.js';
|
|
11
|
+
import { Trans } from '@lingui/react/macro';
|
|
12
|
+
|
|
13
|
+
interface ForceRemoveOptionGroupDialogProps {
|
|
14
|
+
open: boolean;
|
|
15
|
+
onOpenChange: (open: boolean) => void;
|
|
16
|
+
onConfirm: () => void;
|
|
17
|
+
isPending?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Confirmation shown when an option group cannot be removed normally because it is
|
|
22
|
+
* still in use by existing variants (`ProductOptionInUseError`). Shared by the
|
|
23
|
+
* product-detail badge and the Manage Variants page so the copy and behaviour stay
|
|
24
|
+
* in one place.
|
|
25
|
+
*/
|
|
26
|
+
export function ForceRemoveOptionGroupDialog({
|
|
27
|
+
open,
|
|
28
|
+
onOpenChange,
|
|
29
|
+
onConfirm,
|
|
30
|
+
isPending,
|
|
31
|
+
}: Readonly<ForceRemoveOptionGroupDialogProps>) {
|
|
32
|
+
return (
|
|
33
|
+
<AlertDialog open={open} onOpenChange={onOpenChange}>
|
|
34
|
+
<AlertDialogContent>
|
|
35
|
+
<AlertDialogHeader>
|
|
36
|
+
<AlertDialogTitle>
|
|
37
|
+
<Trans>Force remove option group</Trans>
|
|
38
|
+
</AlertDialogTitle>
|
|
39
|
+
<AlertDialogDescription>
|
|
40
|
+
<Trans>
|
|
41
|
+
This option group is in use by existing variants. Force removing it may affect
|
|
42
|
+
those variants. Are you sure?
|
|
43
|
+
</Trans>
|
|
44
|
+
</AlertDialogDescription>
|
|
45
|
+
</AlertDialogHeader>
|
|
46
|
+
<AlertDialogFooter>
|
|
47
|
+
<AlertDialogCancel disabled={isPending}>
|
|
48
|
+
<Trans>Cancel</Trans>
|
|
49
|
+
</AlertDialogCancel>
|
|
50
|
+
<AlertDialogAction
|
|
51
|
+
disabled={isPending}
|
|
52
|
+
// preventDefault keeps the dialog open while the mutation is in
|
|
53
|
+
// flight so the disabled state can block a double-submit; the hook
|
|
54
|
+
// closes it on success.
|
|
55
|
+
onClick={event => {
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
onConfirm();
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
<Trans>Force remove</Trans>
|
|
61
|
+
</AlertDialogAction>
|
|
62
|
+
</AlertDialogFooter>
|
|
63
|
+
</AlertDialogContent>
|
|
64
|
+
</AlertDialog>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
@@ -1,24 +1,78 @@
|
|
|
1
|
+
import { ConfirmationDialog } from '@/vdb/components/shared/confirmation-dialog.js';
|
|
2
|
+
import { PermissionGuard } from '@/vdb/components/shared/permission-guard.js';
|
|
1
3
|
import { Badge } from '@/vdb/components/ui/badge.js';
|
|
4
|
+
import { useLingui } from '@lingui/react/macro';
|
|
2
5
|
import { Link } from '@tanstack/react-router';
|
|
3
|
-
import { Edit2 } from 'lucide-react';
|
|
6
|
+
import { Edit2, Trash2 } from 'lucide-react';
|
|
7
|
+
|
|
8
|
+
import { useRemoveOptionGroup } from '../hooks/use-remove-option-group.js';
|
|
9
|
+
import { ForceRemoveOptionGroupDialog } from './force-remove-option-group-dialog.js';
|
|
4
10
|
|
|
5
11
|
interface ProductOptionGroupBadgeProps {
|
|
6
12
|
id: string;
|
|
7
13
|
name: string;
|
|
8
14
|
productId: string;
|
|
15
|
+
/**
|
|
16
|
+
* When provided, the badge renders a remove control that detaches the option
|
|
17
|
+
* group from the product (issue #4703 — a wrongly-added option group could
|
|
18
|
+
* not be removed from the product detail page). Called after a successful
|
|
19
|
+
* removal so the parent can refresh.
|
|
20
|
+
*/
|
|
21
|
+
onRemoved?: () => void;
|
|
9
22
|
}
|
|
10
23
|
|
|
11
|
-
export function ProductOptionGroupBadge({
|
|
24
|
+
export function ProductOptionGroupBadge({
|
|
25
|
+
id,
|
|
26
|
+
name,
|
|
27
|
+
productId,
|
|
28
|
+
onRemoved,
|
|
29
|
+
}: Readonly<ProductOptionGroupBadgeProps>) {
|
|
30
|
+
const { t } = useLingui();
|
|
31
|
+
const { remove, forceRemove, inUseGroupId, clearInUseGroup, isPending } = useRemoveOptionGroup(
|
|
32
|
+
productId,
|
|
33
|
+
{ onRemoved },
|
|
34
|
+
);
|
|
35
|
+
|
|
12
36
|
return (
|
|
13
|
-
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
37
|
+
<>
|
|
38
|
+
<Badge variant="secondary" className="text-xs">
|
|
39
|
+
<span>{name}</span>
|
|
40
|
+
<Link
|
|
41
|
+
to={`/option-groups/${id}`}
|
|
42
|
+
search={{ from: 'product', productId }}
|
|
43
|
+
className="ml-1.5 inline-flex"
|
|
44
|
+
>
|
|
45
|
+
<Edit2 className="h-3 w-3" />
|
|
46
|
+
</Link>
|
|
47
|
+
{onRemoved && (
|
|
48
|
+
<PermissionGuard requires={['UpdateProduct', 'UpdateCatalog']}>
|
|
49
|
+
<ConfirmationDialog
|
|
50
|
+
title={t`Remove option group`}
|
|
51
|
+
description={t`Are you sure you want to remove this option group from the product?`}
|
|
52
|
+
onConfirm={() => remove(id)}
|
|
53
|
+
>
|
|
54
|
+
<button
|
|
55
|
+
type="button"
|
|
56
|
+
aria-label={t`Remove option group`}
|
|
57
|
+
disabled={isPending}
|
|
58
|
+
className="ml-1 inline-flex"
|
|
59
|
+
>
|
|
60
|
+
<Trash2 className="h-3 w-3 text-destructive" />
|
|
61
|
+
</button>
|
|
62
|
+
</ConfirmationDialog>
|
|
63
|
+
</PermissionGuard>
|
|
64
|
+
)}
|
|
65
|
+
</Badge>
|
|
66
|
+
<ForceRemoveOptionGroupDialog
|
|
67
|
+
open={inUseGroupId === id}
|
|
68
|
+
onOpenChange={open => {
|
|
69
|
+
if (!open) {
|
|
70
|
+
clearInUseGroup();
|
|
71
|
+
}
|
|
72
|
+
}}
|
|
73
|
+
onConfirm={forceRemove}
|
|
74
|
+
isPending={isPending}
|
|
75
|
+
/>
|
|
76
|
+
</>
|
|
23
77
|
);
|
|
24
78
|
}
|