@vendure/dashboard 3.3.6-master-202506290242 → 3.3.6-master-202507010731
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/package.json +4 -4
- package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_assets/assets_.$id.tsx +7 -2
- package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_collections/collections.graphql.ts +16 -0
- package/src/app/routes/_authenticated/_collections/collections.tsx +16 -2
- package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_collections/components/assign-collections-to-channel-dialog.tsx +110 -0
- package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +99 -0
- package/src/app/routes/_authenticated/_countries/countries.graphql.ts +1 -1
- package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +9 -5
- package/src/app/routes/_authenticated/_customer-groups/customer-groups.graphql.ts +1 -1
- package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +8 -5
- package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_orders/orders_.$id.tsx +5 -2
- package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx +184 -0
- package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +62 -1
- package/src/app/routes/_authenticated/_product-variants/product-variants.tsx +33 -3
- package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +14 -3
- package/src/app/routes/_authenticated/_products/components/assign-facet-values-dialog.tsx +67 -36
- package/src/app/routes/_authenticated/_products/components/assign-to-channel-dialog.tsx +28 -17
- package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +12 -2
- package/src/app/routes/_authenticated/_products/components/product-variants-table.tsx +74 -55
- package/src/app/routes/_authenticated/_products/products_.$id.tsx +6 -1
- package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +6 -2
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +5 -1
- package/src/app/routes/_authenticated/_tax-categories/tax-categories.graphql.ts +1 -1
- package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +9 -5
- package/src/app/routes/_authenticated/_tax-rates/tax-rates.graphql.ts +1 -1
- package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +8 -4
- package/src/app/routes/_authenticated/_zones/zones.graphql.ts +1 -1
- package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +8 -4
- package/src/lib/components/shared/detail-page-button.tsx +3 -1
- package/src/lib/components/shared/paginated-list-data-table.tsx +6 -4
- package/src/lib/framework/data-table/data-table-extensions.ts +14 -0
- package/src/lib/framework/document-extension/extend-detail-form-query.ts +50 -0
- package/src/lib/framework/document-extension/extend-document.spec.ts +884 -0
- package/src/lib/framework/document-extension/extend-document.ts +159 -0
- package/src/lib/framework/document-introspection/add-custom-fields.ts +48 -0
- package/src/lib/framework/extension-api/define-dashboard-extension.ts +33 -2
- package/src/lib/framework/extension-api/extension-api-types.ts +21 -2
- package/src/lib/framework/form-engine/custom-form-component-extensions.ts +13 -3
- package/src/lib/framework/layout-engine/page-layout.tsx +1 -0
- package/src/lib/framework/page/detail-page-route-loader.tsx +22 -4
- package/src/lib/framework/page/use-detail-page.ts +11 -2
- package/src/lib/framework/registry/registry-types.ts +3 -0
- package/src/lib/graphql/graphql-env.d.ts +8 -6
- package/src/lib/hooks/use-extended-detail-query.ts +37 -0
- package/src/lib/hooks/use-extended-list-query.ts +73 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { extendDetailFormQuery } from '@/framework/document-extension/extend-detail-form-query.js';
|
|
2
|
+
import { useLingui } from '@/lib/trans.js';
|
|
3
|
+
import { DocumentNode } from 'graphql';
|
|
4
|
+
import { useEffect, useMemo, useRef } from 'react';
|
|
5
|
+
import { toast } from 'sonner';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @description
|
|
9
|
+
* Extends a detail page query document with any registered extensions provided by
|
|
10
|
+
* the `extendDetailDocument` function for the given page.
|
|
11
|
+
*/
|
|
12
|
+
export function useExtendedDetailQuery<T extends DocumentNode>(detailQuery: T, pageId?: string) {
|
|
13
|
+
const hasShownError = useRef(false);
|
|
14
|
+
const { i18n } = useLingui();
|
|
15
|
+
|
|
16
|
+
const extendedDetailQuery = useMemo(() => {
|
|
17
|
+
if (!pageId || !detailQuery) {
|
|
18
|
+
return detailQuery;
|
|
19
|
+
}
|
|
20
|
+
const result = extendDetailFormQuery(detailQuery, pageId);
|
|
21
|
+
if (result.errorMessage && !hasShownError.current) {
|
|
22
|
+
// Show a user-friendly toast notification
|
|
23
|
+
toast.error(i18n.t('Query extension error'), {
|
|
24
|
+
description:
|
|
25
|
+
result.errorMessage + '. ' + i18n.t('The page will continue with the default query.'),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return result.extendedQuery;
|
|
29
|
+
}, [detailQuery, pageId]);
|
|
30
|
+
|
|
31
|
+
// Reset error flag when dependencies change
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
hasShownError.current = false;
|
|
34
|
+
}, [detailQuery, pageId]);
|
|
35
|
+
|
|
36
|
+
return extendedDetailQuery;
|
|
37
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { getListQueryDocuments } from '@/framework/data-table/data-table-extensions.js';
|
|
2
|
+
import { extendDocument } from '@/framework/document-extension/extend-document.js';
|
|
3
|
+
import { useLingui } from '@/lib/trans.js';
|
|
4
|
+
import { DocumentNode } from 'graphql';
|
|
5
|
+
import { useEffect, useMemo, useRef } from 'react';
|
|
6
|
+
import { toast } from 'sonner';
|
|
7
|
+
|
|
8
|
+
import { usePageBlock } from './use-page-block.js';
|
|
9
|
+
import { usePage } from './use-page.js';
|
|
10
|
+
|
|
11
|
+
export function useExtendedListQuery<T extends DocumentNode>(listQuery: T) {
|
|
12
|
+
const { pageId } = usePage();
|
|
13
|
+
const { blockId } = usePageBlock();
|
|
14
|
+
const { i18n } = useLingui();
|
|
15
|
+
const listQueryExtensions = pageId && blockId ? getListQueryDocuments(pageId, blockId) : [];
|
|
16
|
+
const hasShownError = useRef(false);
|
|
17
|
+
|
|
18
|
+
const extendedListQuery = useMemo(() => {
|
|
19
|
+
let result: T = listQuery;
|
|
20
|
+
let error: Error | null = null;
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
result = listQueryExtensions.reduce(
|
|
24
|
+
(acc, extension) => extendDocument(acc, extension),
|
|
25
|
+
listQuery,
|
|
26
|
+
) as T;
|
|
27
|
+
} catch (err) {
|
|
28
|
+
error = err instanceof Error ? err : new Error(String(err));
|
|
29
|
+
// Continue with the original query instead of the extended one
|
|
30
|
+
result = listQuery;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Store error for useEffect to handle
|
|
34
|
+
if (error && !hasShownError.current) {
|
|
35
|
+
hasShownError.current = true;
|
|
36
|
+
|
|
37
|
+
// Provide a helpful error message based on the error type
|
|
38
|
+
let errorMessage = i18n.t('Failed to extend query document');
|
|
39
|
+
if (error.message.includes('Extension query must have at least one top-level field')) {
|
|
40
|
+
errorMessage = i18n.t('Query extension is invalid: must have at least one top-level field');
|
|
41
|
+
} else if (error.message.includes('The query extension must extend the')) {
|
|
42
|
+
errorMessage = i18n.t('Query extension mismatch: ') + error.message;
|
|
43
|
+
} else if (error.message.includes('Syntax Error')) {
|
|
44
|
+
errorMessage = i18n.t('Query extension contains invalid GraphQL syntax');
|
|
45
|
+
} else {
|
|
46
|
+
errorMessage = i18n.t('Query extension error: ') + error.message;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Log the error and continue with the original query
|
|
50
|
+
// eslint-disable-next-line no-console
|
|
51
|
+
console.warn(`${errorMessage}. Continuing with original query.`, {
|
|
52
|
+
pageId,
|
|
53
|
+
blockId,
|
|
54
|
+
extensionsCount: listQueryExtensions.length,
|
|
55
|
+
error: error.message,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Show a user-friendly toast notification
|
|
59
|
+
toast.error(i18n.t('Query extension error'), {
|
|
60
|
+
description: errorMessage + '. ' + i18n.t('The page will continue with the default query.'),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return result;
|
|
65
|
+
}, [listQuery, listQueryExtensions, pageId, blockId]);
|
|
66
|
+
|
|
67
|
+
// Reset error flag when dependencies change
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
hasShownError.current = false;
|
|
70
|
+
}, [listQuery, listQueryExtensions, pageId, blockId]);
|
|
71
|
+
|
|
72
|
+
return extendedListQuery;
|
|
73
|
+
}
|