@vendure/dashboard 3.3.6-master-202507100236 → 3.3.6-master-202507110238
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/plugin/tests/barrel-exports.spec.js +1 -1
- package/package.json +4 -4
- package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +30 -37
- package/src/app/routes/_authenticated/_orders/components/fulfillment-details.tsx +33 -53
- package/src/app/routes/_authenticated/_orders/components/order-address.tsx +14 -7
- package/src/app/routes/_authenticated/_orders/components/order-line-custom-fields-form.tsx +23 -12
- package/src/app/routes/_authenticated/_orders/components/order-modification-preview-dialog.tsx +364 -0
- package/src/app/routes/_authenticated/_orders/components/order-modification-summary.tsx +222 -0
- package/src/app/routes/_authenticated/_orders/components/order-table.tsx +146 -85
- package/src/app/routes/_authenticated/_orders/components/payment-details.tsx +268 -31
- package/src/app/routes/_authenticated/_orders/components/settle-refund-dialog.tsx +80 -0
- package/src/app/routes/_authenticated/_orders/components/state-transition-control.tsx +102 -0
- package/src/app/routes/_authenticated/_orders/components/use-transition-order-to-state.tsx +144 -0
- package/src/app/routes/_authenticated/_orders/orders.graphql.ts +118 -2
- package/src/app/routes/_authenticated/_orders/orders_.$id.tsx +144 -52
- package/src/app/routes/_authenticated/_orders/orders_.$id_.modify.tsx +550 -0
- package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +0 -17
- package/src/app/routes/_authenticated/_orders/utils/order-types.ts +5 -2
- package/src/app/routes/_authenticated/_orders/utils/order-utils.ts +4 -3
- package/src/app/routes/_authenticated/_products/products_.$id.tsx +0 -1
- package/src/lib/components/data-display/date-time.tsx +7 -1
- package/src/lib/components/data-input/relation-input.tsx +11 -0
- package/src/lib/components/data-input/relation-selector.tsx +9 -2
- package/src/lib/components/data-table/data-table-utils.ts +34 -0
- package/src/lib/components/data-table/data-table-view-options.tsx +2 -2
- package/src/lib/components/data-table/data-table.tsx +5 -2
- package/src/lib/components/data-table/use-generated-columns.tsx +307 -0
- package/src/lib/components/shared/paginated-list-data-table.tsx +15 -286
- package/src/lib/components/shared/product-variant-selector.tsx +28 -4
- package/src/lib/framework/component-registry/dynamic-component.tsx +3 -3
- package/src/lib/framework/document-introspection/get-document-structure.spec.ts +321 -2
- package/src/lib/framework/document-introspection/get-document-structure.ts +149 -31
- package/src/lib/framework/extension-api/types/layout.ts +21 -6
- package/src/lib/framework/layout-engine/layout-extensions.ts +1 -4
- package/src/lib/framework/layout-engine/page-layout.tsx +61 -10
- package/src/lib/framework/page/use-detail-page.ts +10 -7
- package/vite/tests/barrel-exports.spec.ts +1 -1
|
@@ -7,11 +7,14 @@ import { useCustomFieldConfig } from '@/vdb/hooks/use-custom-field-config.js';
|
|
|
7
7
|
import { usePage } from '@/vdb/hooks/use-page.js';
|
|
8
8
|
import { cn } from '@/vdb/lib/utils.js';
|
|
9
9
|
import { useMediaQuery } from '@uidotdev/usehooks';
|
|
10
|
-
import
|
|
10
|
+
import { EllipsisVerticalIcon } from 'lucide-react';
|
|
11
|
+
import React, { ComponentProps, useMemo } from 'react';
|
|
11
12
|
import { Control, UseFormReturn } from 'react-hook-form';
|
|
12
13
|
|
|
13
14
|
import { DashboardActionBarItem } from '../extension-api/types/layout.js';
|
|
14
15
|
|
|
16
|
+
import { Button } from '@/vdb/components/ui/button.js';
|
|
17
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from '@/vdb/components/ui/dropdown-menu.js';
|
|
15
18
|
import { PageBlockContext } from '@/vdb/framework/layout-engine/page-block-provider.js';
|
|
16
19
|
import { PageContext, PageContextValue } from '@/vdb/framework/layout-engine/page-provider.js';
|
|
17
20
|
import { getDashboardActionBarItems, getDashboardPageBlocks } from './layout-extensions.js';
|
|
@@ -295,6 +298,8 @@ export function PageActionBarLeft({ children }: Readonly<{ children: React.React
|
|
|
295
298
|
return <div className="flex justify-start gap-2">{children}</div>;
|
|
296
299
|
}
|
|
297
300
|
|
|
301
|
+
type InlineDropdownItem = Omit<DashboardActionBarItem, 'type' | 'pageId'>;
|
|
302
|
+
|
|
298
303
|
/**
|
|
299
304
|
* @description
|
|
300
305
|
* **Status: Developer Preview**
|
|
@@ -303,20 +308,42 @@ export function PageActionBarLeft({ children }: Readonly<{ children: React.React
|
|
|
303
308
|
* @docsPage PageActionBar
|
|
304
309
|
* @since 3.3.0
|
|
305
310
|
*/
|
|
306
|
-
export function PageActionBarRight({
|
|
311
|
+
export function PageActionBarRight({
|
|
312
|
+
children,
|
|
313
|
+
dropdownMenuItems,
|
|
314
|
+
}: Readonly<{
|
|
315
|
+
children: React.ReactNode;
|
|
316
|
+
dropdownMenuItems?: InlineDropdownItem[];
|
|
317
|
+
}>) {
|
|
307
318
|
const page = usePage();
|
|
308
319
|
const actionBarItems = page.pageId ? getDashboardActionBarItems(page.pageId) : [];
|
|
320
|
+
const actionBarButtonItems = actionBarItems.filter(item => item.type !== 'dropdown');
|
|
321
|
+
const actionBarDropdownItems = [
|
|
322
|
+
...(dropdownMenuItems ?? []).map(item => ({
|
|
323
|
+
...item,
|
|
324
|
+
pageId: page.pageId ?? '',
|
|
325
|
+
type: 'dropdown' as const,
|
|
326
|
+
})),
|
|
327
|
+
...actionBarItems.filter(item => item.type === 'dropdown'),
|
|
328
|
+
];
|
|
329
|
+
|
|
309
330
|
return (
|
|
310
331
|
<div className="flex justify-end gap-2">
|
|
311
|
-
{
|
|
312
|
-
<PageActionBarItem key={index} item={item} page={page} />
|
|
332
|
+
{actionBarButtonItems.map((item, index) => (
|
|
333
|
+
<PageActionBarItem key={item.pageId + index} item={item} page={page} />
|
|
313
334
|
))}
|
|
314
335
|
{children}
|
|
336
|
+
{actionBarDropdownItems.length > 0 && (
|
|
337
|
+
<PageActionBarDropdown items={actionBarDropdownItems} page={page} />
|
|
338
|
+
)}
|
|
315
339
|
</div>
|
|
316
340
|
);
|
|
317
341
|
}
|
|
318
342
|
|
|
319
|
-
function PageActionBarItem({
|
|
343
|
+
function PageActionBarItem({
|
|
344
|
+
item,
|
|
345
|
+
page,
|
|
346
|
+
}: Readonly<{ item: DashboardActionBarItem; page: PageContextValue }>) {
|
|
320
347
|
return (
|
|
321
348
|
<PermissionGuard requires={item.requiresPermission ?? []}>
|
|
322
349
|
<item.component context={page} />
|
|
@@ -324,6 +351,28 @@ function PageActionBarItem({ item, page }: { item: DashboardActionBarItem; page:
|
|
|
324
351
|
);
|
|
325
352
|
}
|
|
326
353
|
|
|
354
|
+
function PageActionBarDropdown({
|
|
355
|
+
items,
|
|
356
|
+
page,
|
|
357
|
+
}: Readonly<{ items: DashboardActionBarItem[]; page: PageContextValue }>) {
|
|
358
|
+
return (
|
|
359
|
+
<DropdownMenu>
|
|
360
|
+
<DropdownMenuTrigger asChild>
|
|
361
|
+
<Button variant="ghost" size="icon">
|
|
362
|
+
<EllipsisVerticalIcon className="w-4 h-4" />
|
|
363
|
+
</Button>
|
|
364
|
+
</DropdownMenuTrigger>
|
|
365
|
+
<DropdownMenuContent>
|
|
366
|
+
{items.map((item, index) => (
|
|
367
|
+
<PermissionGuard key={item.pageId + index} requires={item.requiresPermission ?? []}>
|
|
368
|
+
<item.component context={page} />
|
|
369
|
+
</PermissionGuard>
|
|
370
|
+
))}
|
|
371
|
+
</DropdownMenuContent>
|
|
372
|
+
</DropdownMenu>
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
|
|
327
376
|
/**
|
|
328
377
|
* @description
|
|
329
378
|
* **Status: Developer Preview**
|
|
@@ -363,8 +412,9 @@ export function PageBlock({
|
|
|
363
412
|
blockId,
|
|
364
413
|
column,
|
|
365
414
|
}: Readonly<PageBlockProps>) {
|
|
415
|
+
const contextValue = useMemo(() => ({ blockId, title, description, column }), [blockId, title, description, column]);
|
|
366
416
|
return (
|
|
367
|
-
<PageBlockContext.Provider value={
|
|
417
|
+
<PageBlockContext.Provider value={contextValue}>
|
|
368
418
|
<LocationWrapper>
|
|
369
419
|
<Card className={cn('w-full', className)}>
|
|
370
420
|
{title || description ? (
|
|
@@ -395,9 +445,10 @@ export function FullWidthPageBlock({
|
|
|
395
445
|
children,
|
|
396
446
|
className,
|
|
397
447
|
blockId,
|
|
398
|
-
}: Pick<PageBlockProps, 'children' | 'className' | 'blockId'
|
|
448
|
+
}: Readonly<Pick<PageBlockProps, 'children' | 'className' | 'blockId'>>) {
|
|
449
|
+
const contextValue = useMemo(() => ({ blockId, column: 'main' as const }), [blockId]);
|
|
399
450
|
return (
|
|
400
|
-
<PageBlockContext.Provider value={
|
|
451
|
+
<PageBlockContext.Provider value={contextValue}>
|
|
401
452
|
<LocationWrapper>
|
|
402
453
|
<div className={cn('w-full', className)}>{children}</div>
|
|
403
454
|
</LocationWrapper>
|
|
@@ -419,11 +470,11 @@ export function CustomFieldsPageBlock({
|
|
|
419
470
|
column,
|
|
420
471
|
entityType,
|
|
421
472
|
control,
|
|
422
|
-
}: {
|
|
473
|
+
}: Readonly<{
|
|
423
474
|
column: 'main' | 'side';
|
|
424
475
|
entityType: string;
|
|
425
476
|
control: Control<any, any>;
|
|
426
|
-
}) {
|
|
477
|
+
}>) {
|
|
427
478
|
const customFieldConfig = useCustomFieldConfig(entityType);
|
|
428
479
|
if (!customFieldConfig || customFieldConfig.length === 0) {
|
|
429
480
|
return null;
|
|
@@ -13,7 +13,7 @@ import { FormEvent } from 'react';
|
|
|
13
13
|
import { UseFormReturn } from 'react-hook-form';
|
|
14
14
|
|
|
15
15
|
import { NEW_ENTITY_PATH } from '../../constants.js';
|
|
16
|
-
import { api
|
|
16
|
+
import { api } from '../../graphql/api.js';
|
|
17
17
|
import { useCustomFieldConfig } from '../../hooks/use-custom-field-config.js';
|
|
18
18
|
import { useExtendedDetailQuery } from '../../hooks/use-extended-detail-query.js';
|
|
19
19
|
import { addCustomFields } from '../document-introspection/add-custom-fields.js';
|
|
@@ -33,6 +33,8 @@ type RemoveNullFields<T> = {
|
|
|
33
33
|
[K in keyof T]: RemoveNull<T[K]>;
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
+
const NEW_ENTITY_ID = '__NEW__';
|
|
37
|
+
|
|
36
38
|
/**
|
|
37
39
|
* @description
|
|
38
40
|
* **Status: Developer Preview**
|
|
@@ -108,14 +110,16 @@ export interface DetailPageOptions<
|
|
|
108
110
|
onError?: (error: unknown) => void;
|
|
109
111
|
}
|
|
110
112
|
|
|
111
|
-
export function getDetailQueryOptions<T, V extends
|
|
113
|
+
export function getDetailQueryOptions<T, V extends { id: string }>(
|
|
112
114
|
document: TypedDocumentNode<T, V> | DocumentNode,
|
|
113
115
|
variables: V,
|
|
116
|
+
options: Partial<Parameters<typeof queryOptions>[0]> = {},
|
|
114
117
|
): DefinedInitialDataOptions {
|
|
115
118
|
const queryName = getQueryName(document);
|
|
116
119
|
return queryOptions({
|
|
117
120
|
queryKey: ['DetailPage', queryName, variables],
|
|
118
|
-
queryFn: () => api.query(document, variables),
|
|
121
|
+
queryFn: () => (variables.id === NEW_ENTITY_ID ? null : api.query(document, variables)),
|
|
122
|
+
...options,
|
|
119
123
|
}) as DefinedInitialDataOptions;
|
|
120
124
|
}
|
|
121
125
|
|
|
@@ -152,7 +156,6 @@ export type DetailPageEntity<
|
|
|
152
156
|
*/
|
|
153
157
|
export interface UseDetailPageResult<
|
|
154
158
|
T extends TypedDocumentNode<any, any>,
|
|
155
|
-
C extends TypedDocumentNode<any, any>,
|
|
156
159
|
U extends TypedDocumentNode<any, any>,
|
|
157
160
|
EntityField extends keyof ResultOf<T>,
|
|
158
161
|
> {
|
|
@@ -242,7 +245,7 @@ export function useDetailPage<
|
|
|
242
245
|
VarNameCreate extends keyof VariablesOf<C> = 'input',
|
|
243
246
|
>(
|
|
244
247
|
options: DetailPageOptions<T, C, U, EntityField, VarNameCreate, VarNameUpdate>,
|
|
245
|
-
): UseDetailPageResult<T,
|
|
248
|
+
): UseDetailPageResult<T, U, EntityField> {
|
|
246
249
|
const {
|
|
247
250
|
pageId,
|
|
248
251
|
queryDocument,
|
|
@@ -263,12 +266,12 @@ export function useDetailPage<
|
|
|
263
266
|
const customFieldConfig = useCustomFieldConfig(returnEntityName);
|
|
264
267
|
const extendedDetailQuery = useExtendedDetailQuery(addCustomFields(queryDocument), pageId);
|
|
265
268
|
const detailQueryOptions = getDetailQueryOptions(extendedDetailQuery, {
|
|
266
|
-
id: isNew ?
|
|
269
|
+
id: isNew ? NEW_ENTITY_ID : params.id,
|
|
267
270
|
});
|
|
268
271
|
const detailQuery = useSuspenseQuery(detailQueryOptions);
|
|
269
272
|
const entityQueryField = entityField ?? getQueryName(extendedDetailQuery);
|
|
270
273
|
|
|
271
|
-
const entity = (detailQuery?.data as any)[entityQueryField] as
|
|
274
|
+
const entity = (detailQuery?.data as any)?.[entityQueryField] as
|
|
272
275
|
| DetailPageEntity<T, EntityField>
|
|
273
276
|
| undefined;
|
|
274
277
|
|