@vendure/dashboard 3.3.6-master-202507030648 → 3.3.6-master-202507030835

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.
Files changed (67) hide show
  1. package/dist/plugin/vite-plugin-vendure-dashboard.js +1 -1
  2. package/package.json +40 -27
  3. package/src/app/routes/_authenticated/_collections/collections.graphql.ts +32 -0
  4. package/src/app/routes/_authenticated/_collections/collections.tsx +153 -133
  5. package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +1 -1
  6. package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +34 -1
  7. package/src/app/routes/_authenticated/_collections/components/move-collections-dialog.tsx +430 -0
  8. package/src/app/routes/_authenticated/_collections/components/move-single-collection.tsx +33 -0
  9. package/src/app/routes/_authenticated/_customers/components/customer-address-card.tsx +8 -3
  10. package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +1 -1
  11. package/src/app/routes/_authenticated/_products/products_.$id.tsx +1 -1
  12. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +1 -1
  13. package/src/lib/components/data-input/money-input.tsx +2 -9
  14. package/src/lib/components/data-table/data-table.tsx +1 -1
  15. package/src/lib/components/shared/form-field-wrapper.tsx +22 -13
  16. package/src/lib/components/shared/paginated-list-data-table.tsx +1 -1
  17. package/src/lib/components/ui/accordion.tsx +50 -45
  18. package/src/lib/components/ui/alert-dialog.tsx +122 -93
  19. package/src/lib/components/ui/alert.tsx +54 -48
  20. package/src/lib/components/ui/aspect-ratio.tsx +9 -0
  21. package/src/lib/components/ui/avatar.tsx +53 -0
  22. package/src/lib/components/ui/badge.tsx +37 -29
  23. package/src/lib/components/ui/breadcrumb.tsx +89 -82
  24. package/src/lib/components/ui/button.tsx +52 -51
  25. package/src/lib/components/ui/calendar.tsx +196 -435
  26. package/src/lib/components/ui/card.tsx +78 -33
  27. package/src/lib/components/ui/carousel.tsx +241 -0
  28. package/src/lib/components/ui/chart.tsx +351 -0
  29. package/src/lib/components/ui/checkbox.tsx +28 -23
  30. package/src/lib/components/ui/collapsible.tsx +0 -2
  31. package/src/lib/components/ui/command.tsx +159 -114
  32. package/src/lib/components/ui/context-menu.tsx +252 -0
  33. package/src/lib/components/ui/dialog.tsx +115 -90
  34. package/src/lib/components/ui/drawer.tsx +133 -0
  35. package/src/lib/components/ui/dropdown-menu.tsx +207 -170
  36. package/src/lib/components/ui/form.tsx +138 -114
  37. package/src/lib/components/ui/hover-card.tsx +32 -26
  38. package/src/lib/components/ui/input-otp.tsx +77 -0
  39. package/src/lib/components/ui/input.tsx +17 -15
  40. package/src/lib/components/ui/label.tsx +19 -16
  41. package/src/lib/components/ui/menubar.tsx +274 -0
  42. package/src/lib/components/ui/navigation-menu.tsx +168 -0
  43. package/src/lib/components/ui/pagination.tsx +108 -87
  44. package/src/lib/components/ui/popover.tsx +36 -28
  45. package/src/lib/components/ui/progress.tsx +29 -0
  46. package/src/lib/components/ui/radio-group.tsx +45 -0
  47. package/src/lib/components/ui/resizable.tsx +54 -0
  48. package/src/lib/components/ui/scroll-area.tsx +48 -40
  49. package/src/lib/components/ui/select.tsx +151 -129
  50. package/src/lib/components/ui/separator.tsx +22 -20
  51. package/src/lib/components/ui/sheet.tsx +110 -91
  52. package/src/lib/components/ui/sidebar.tsx +652 -622
  53. package/src/lib/components/ui/skeleton.tsx +10 -10
  54. package/src/lib/components/ui/slider.tsx +63 -0
  55. package/src/lib/components/ui/sonner.tsx +7 -11
  56. package/src/lib/components/ui/switch.tsx +27 -22
  57. package/src/lib/components/ui/table.tsx +96 -64
  58. package/src/lib/components/ui/tabs.tsx +56 -38
  59. package/src/lib/components/ui/textarea.tsx +14 -14
  60. package/src/lib/components/ui/toggle-group.tsx +73 -0
  61. package/src/lib/components/ui/toggle.tsx +45 -0
  62. package/src/lib/components/ui/tooltip.tsx +45 -37
  63. package/src/lib/framework/component-registry/component-registry.tsx +5 -3
  64. package/src/lib/framework/page/detail-page.tsx +28 -17
  65. package/src/lib/framework/page/list-page.tsx +1 -1
  66. package/src/lib/index.ts +5 -6
  67. package/vite/vite-plugin-vendure-dashboard.ts +1 -1
@@ -32,7 +32,7 @@ export function vendureDashboardPlugin(options) {
32
32
  : [
33
33
  TanStackRouterVite({
34
34
  autoCodeSplitting: true,
35
- routeFileIgnorePattern: '.graphql.ts|components',
35
+ routeFileIgnorePattern: '.graphql.ts|components|hooks',
36
36
  routesDirectory: path.join(packageRoot, 'src/app/routes'),
37
37
  generatedRouteTree: path.join(packageRoot, 'src/app/routeTree.gen.ts'),
38
38
  }),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vendure/dashboard",
3
3
  "private": false,
4
- "version": "3.3.6-master-202507030648",
4
+ "version": "3.3.6-master-202507030835",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -54,23 +54,32 @@
54
54
  "@lingui/core": "^5.2.0",
55
55
  "@lingui/react": "^5.2.0",
56
56
  "@lingui/vite-plugin": "^5.2.0",
57
- "@radix-ui/react-accordion": "^1.2.3",
58
- "@radix-ui/react-alert-dialog": "^1.1.6",
59
- "@radix-ui/react-avatar": "^1.1.3",
60
- "@radix-ui/react-checkbox": "^1.1.4",
61
- "@radix-ui/react-collapsible": "^1.1.3",
62
- "@radix-ui/react-dialog": "^1.1.6",
63
- "@radix-ui/react-dropdown-menu": "^2.1.6",
64
- "@radix-ui/react-hover-card": "^1.1.6",
65
- "@radix-ui/react-label": "^2.1.2",
66
- "@radix-ui/react-popover": "^1.1.6",
67
- "@radix-ui/react-scroll-area": "^1.2.3",
68
- "@radix-ui/react-select": "^2.1.6",
69
- "@radix-ui/react-separator": "^1.1.2",
70
- "@radix-ui/react-slot": "^1.1.2",
71
- "@radix-ui/react-switch": "^1.1.3",
72
- "@radix-ui/react-tabs": "^1.1.3",
73
- "@radix-ui/react-tooltip": "^1.1.8",
57
+ "@radix-ui/react-accordion": "^1.2.11",
58
+ "@radix-ui/react-alert-dialog": "^1.1.14",
59
+ "@radix-ui/react-aspect-ratio": "^1.1.7",
60
+ "@radix-ui/react-avatar": "^1.1.10",
61
+ "@radix-ui/react-checkbox": "^1.3.2",
62
+ "@radix-ui/react-collapsible": "^1.1.11",
63
+ "@radix-ui/react-context-menu": "^2.2.15",
64
+ "@radix-ui/react-dialog": "^1.1.14",
65
+ "@radix-ui/react-dropdown-menu": "^2.1.15",
66
+ "@radix-ui/react-hover-card": "^1.1.14",
67
+ "@radix-ui/react-label": "^2.1.7",
68
+ "@radix-ui/react-menubar": "^1.1.15",
69
+ "@radix-ui/react-navigation-menu": "^1.2.13",
70
+ "@radix-ui/react-popover": "^1.1.14",
71
+ "@radix-ui/react-progress": "^1.1.7",
72
+ "@radix-ui/react-radio-group": "^1.3.7",
73
+ "@radix-ui/react-scroll-area": "^1.2.9",
74
+ "@radix-ui/react-select": "^2.2.5",
75
+ "@radix-ui/react-separator": "^1.1.7",
76
+ "@radix-ui/react-slider": "^1.3.5",
77
+ "@radix-ui/react-slot": "^1.2.3",
78
+ "@radix-ui/react-switch": "^1.2.5",
79
+ "@radix-ui/react-tabs": "^1.1.12",
80
+ "@radix-ui/react-toggle": "^1.1.9",
81
+ "@radix-ui/react-toggle-group": "^1.1.10",
82
+ "@radix-ui/react-tooltip": "^1.2.7",
74
83
  "@tailwindcss/vite": "^4.1.5",
75
84
  "@tanstack/eslint-plugin-query": "^5.66.1",
76
85
  "@tanstack/react-query": "^5.66.7",
@@ -86,35 +95,39 @@
86
95
  "@types/react-dom": "^19.0.4",
87
96
  "@types/react-grid-layout": "^1.3.5",
88
97
  "@uidotdev/usehooks": "^2.4.1",
89
- "@vendure/common": "^3.3.6-master-202507030648",
90
- "@vendure/core": "^3.3.6-master-202507030648",
98
+ "@vendure/common": "^3.3.6-master-202507030835",
99
+ "@vendure/core": "^3.3.6-master-202507030835",
91
100
  "@vitejs/plugin-react": "^4.3.4",
92
101
  "awesome-graphql-client": "^2.1.0",
93
102
  "class-variance-authority": "^0.7.1",
94
103
  "clsx": "^2.1.1",
95
- "cmdk": "^1.0.0",
104
+ "cmdk": "^1.1.1",
96
105
  "date-fns": "^3.6.0",
106
+ "embla-carousel-react": "^8.6.0",
97
107
  "gql.tada": "^1.8.10",
98
108
  "graphql": "^16.10.0",
109
+ "input-otp": "^1.4.2",
99
110
  "json-edit-react": "^1.23.1",
100
111
  "lucide-react": "^0.475.0",
101
112
  "motion": "^12.6.2",
102
113
  "next-themes": "^0.4.6",
103
114
  "react": "^19.0.0",
104
- "react-day-picker": "^9.6.7",
115
+ "react-day-picker": "^9.7.0",
105
116
  "react-dom": "^19.0.0",
106
117
  "react-dropzone": "^14.3.8",
107
118
  "react-grid-layout": "^1.5.1",
108
- "react-hook-form": "^7.54.2",
109
- "recharts": "^2.15.1",
110
- "sonner": "^2.0.1",
119
+ "react-hook-form": "^7.59.0",
120
+ "react-resizable-panels": "^3.0.3",
121
+ "recharts": "^2.15.4",
122
+ "sonner": "^2.0.5",
111
123
  "tailwind-merge": "^3.2.0",
112
124
  "tailwindcss": "^4.1.5",
113
125
  "tailwindcss-animate": "^1.0.7",
114
126
  "tsconfig-paths": "^4.2.0",
115
127
  "tw-animate-css": "^1.2.9",
128
+ "vaul": "^1.1.2",
116
129
  "vite": "^6.3.5",
117
- "zod": "^3.24.2"
130
+ "zod": "^3.25.71"
118
131
  },
119
132
  "devDependencies": {
120
133
  "@eslint/js": "^9.19.0",
@@ -130,5 +143,5 @@
130
143
  "lightningcss-linux-arm64-musl": "^1.29.3",
131
144
  "lightningcss-linux-x64-musl": "^1.29.1"
132
145
  },
133
- "gitHead": "04f25e9d0bd06d8031d2f5dbc4373ec0e322f535"
146
+ "gitHead": "d79942fa16b812acfb665834088b0416dfde4670"
134
147
  }
@@ -156,3 +156,35 @@ export const deleteCollectionsDocument = graphql(`
156
156
  }
157
157
  }
158
158
  `);
159
+
160
+ export const moveCollectionDocument = graphql(`
161
+ mutation MoveCollection($input: MoveCollectionInput!) {
162
+ moveCollection(input: $input) {
163
+ id
164
+ }
165
+ }
166
+ `);
167
+
168
+ export const collectionListForMoveDocument = graphql(`
169
+ query CollectionListForMove($options: CollectionListOptions) {
170
+ collections(options: $options) {
171
+ items {
172
+ id
173
+ name
174
+ slug
175
+ breadcrumbs {
176
+ id
177
+ name
178
+ slug
179
+ }
180
+ children {
181
+ id
182
+ }
183
+ position
184
+ isPrivate
185
+ parentId
186
+ }
187
+ totalItems
188
+ }
189
+ }
190
+ `);
@@ -10,7 +10,7 @@ import { createFileRoute, Link } from '@tanstack/react-router';
10
10
  import { ExpandedState, getExpandedRowModel } from '@tanstack/react-table';
11
11
  import { TableOptions } from '@tanstack/table-core';
12
12
  import { ResultOf } from 'gql.tada';
13
- import { Folder, FolderOpen, PlusIcon } from 'lucide-react';
13
+ import { Folder, FolderOpen, FolderTreeIcon, PlusIcon } from 'lucide-react';
14
14
  import { useState } from 'react';
15
15
 
16
16
  import { collectionListDocument, deleteCollectionDocument } from './collections.graphql.js';
@@ -18,9 +18,11 @@ import {
18
18
  AssignCollectionsToChannelBulkAction,
19
19
  DeleteCollectionsBulkAction,
20
20
  DuplicateCollectionsBulkAction,
21
+ MoveCollectionsBulkAction,
21
22
  RemoveCollectionsFromChannelBulkAction,
22
23
  } from './components/collection-bulk-actions.js';
23
24
  import { CollectionContentsSheet } from './components/collection-contents-sheet.js';
25
+ import { useMoveSingleCollection } from './components/move-single-collection.js';
24
26
 
25
27
  export const Route = createFileRoute('/_authenticated/_collections/collections')({
26
28
  component: CollectionListPage,
@@ -31,6 +33,7 @@ type Collection = ResultOf<typeof collectionListDocument>['collections']['items'
31
33
 
32
34
  function CollectionListPage() {
33
35
  const [expanded, setExpanded] = useState<ExpandedState>({});
36
+ const { handleMoveClick, MoveDialog } = useMoveSingleCollection();
34
37
  const childrenQueries = useQueries({
35
38
  queries: Object.entries(expanded).map(([collectionId, isExpanded]) => {
36
39
  return {
@@ -77,143 +80,160 @@ function CollectionListPage() {
77
80
  };
78
81
 
79
82
  return (
80
- <ListPage
81
- pageId="collection-list"
82
- title="Collections"
83
- listQuery={collectionListDocument}
84
- transformVariables={input => {
85
- const filterTerm = input.options?.filter?.name?.contains;
86
- const isFiltering = !!filterTerm;
87
- return {
88
- options: {
89
- ...input.options,
90
- topLevelOnly: !isFiltering,
83
+ <>
84
+ <ListPage
85
+ pageId="collection-list"
86
+ title="Collections"
87
+ listQuery={collectionListDocument}
88
+ transformVariables={input => {
89
+ const filterTerm = input.options?.filter?.name?.contains;
90
+ const isFiltering = !!filterTerm;
91
+ return {
92
+ options: {
93
+ ...input.options,
94
+ topLevelOnly: !isFiltering,
95
+ },
96
+ };
97
+ }}
98
+ deleteMutation={deleteCollectionDocument}
99
+ customizeColumns={{
100
+ name: {
101
+ header: 'Collection Name',
102
+ cell: ({ row }) => {
103
+ const isExpanded = row.getIsExpanded();
104
+ const hasChildren = !!row.original.children?.length;
105
+ return (
106
+ <div
107
+ style={{ marginLeft: (row.original.breadcrumbs.length - 2) * 20 + 'px' }}
108
+ className="flex gap-2 items-center"
109
+ >
110
+ <Button
111
+ size="icon"
112
+ variant="secondary"
113
+ onClick={row.getToggleExpandedHandler()}
114
+ disabled={!hasChildren}
115
+ className={!hasChildren ? 'opacity-20' : ''}
116
+ >
117
+ {isExpanded ? <FolderOpen /> : <Folder />}
118
+ </Button>
119
+ <DetailPageButton id={row.original.id} label={row.original.name} />
120
+ </div>
121
+ );
122
+ },
123
+ },
124
+ breadcrumbs: {
125
+ cell: ({ cell }) => {
126
+ const value = cell.getValue();
127
+ if (!Array.isArray(value)) {
128
+ return null;
129
+ }
130
+ return (
131
+ <div>
132
+ {value
133
+ .slice(1)
134
+ .map(breadcrumb => breadcrumb.name)
135
+ .join(' / ')}
136
+ </div>
137
+ );
138
+ },
91
139
  },
92
- };
93
- }}
94
- deleteMutation={deleteCollectionDocument}
95
- customizeColumns={{
96
- name: {
97
- header: 'Collection Name',
98
- cell: ({ row }) => {
99
- const isExpanded = row.getIsExpanded();
100
- const hasChildren = !!row.original.children?.length;
101
- return (
102
- <div
103
- style={{ marginLeft: (row.original.breadcrumbs.length - 2) * 20 + 'px' }}
104
- className="flex gap-2 items-center"
105
- >
106
- <Button
107
- size="icon"
108
- variant="secondary"
109
- onClick={row.getToggleExpandedHandler()}
110
- disabled={!hasChildren}
111
- className={!hasChildren ? 'opacity-20' : ''}
140
+ productVariants: {
141
+ header: 'Contents',
142
+ cell: ({ row }) => {
143
+ return (
144
+ <CollectionContentsSheet
145
+ collectionId={row.original.id}
146
+ collectionName={row.original.name}
112
147
  >
113
- {isExpanded ? <FolderOpen /> : <Folder />}
114
- </Button>
115
- <DetailPageButton id={row.original.id} label={row.original.name} />
116
- </div>
117
- );
148
+ <Trans>{row.original.productVariants.totalItems} variants</Trans>
149
+ </CollectionContentsSheet>
150
+ );
151
+ },
118
152
  },
119
- },
120
- breadcrumbs: {
121
- cell: ({ cell }) => {
122
- const value = cell.getValue();
123
- if (!Array.isArray(value)) {
124
- return null;
125
- }
126
- return (
127
- <div>
128
- {value
129
- .slice(1)
130
- .map(breadcrumb => breadcrumb.name)
131
- .join(' / ')}
153
+ }}
154
+ defaultColumnOrder={[
155
+ 'featuredAsset',
156
+ 'children',
157
+ 'name',
158
+ 'slug',
159
+ 'breadcrumbs',
160
+ 'productVariants',
161
+ ]}
162
+ transformData={data => {
163
+ return addSubCollections(data);
164
+ }}
165
+ setTableOptions={(options: TableOptions<any>) => {
166
+ options.state = {
167
+ ...options.state,
168
+ expanded: expanded,
169
+ };
170
+ options.onExpandedChange = setExpanded;
171
+ options.getExpandedRowModel = getExpandedRowModel();
172
+ options.getRowCanExpand = () => true;
173
+ options.getRowId = row => {
174
+ return row.id;
175
+ };
176
+ return options;
177
+ }}
178
+ defaultVisibility={{
179
+ id: false,
180
+ createdAt: false,
181
+ updatedAt: false,
182
+ position: false,
183
+ parentId: false,
184
+ children: false,
185
+ }}
186
+ onSearchTermChange={searchTerm => {
187
+ return {
188
+ name: { contains: searchTerm },
189
+ };
190
+ }}
191
+ route={Route}
192
+ rowActions={[
193
+ {
194
+ label: (
195
+ <div className="flex items-center gap-2">
196
+ <FolderTreeIcon className="w-4 h-4" /> <Trans>Move</Trans>
132
197
  </div>
133
- );
198
+ ),
199
+ onClick: row => handleMoveClick(row.original),
200
+ },
201
+ ]}
202
+ bulkActions={[
203
+ {
204
+ component: AssignCollectionsToChannelBulkAction,
205
+ order: 100,
206
+ },
207
+ {
208
+ component: RemoveCollectionsFromChannelBulkAction,
209
+ order: 200,
210
+ },
211
+ {
212
+ component: DuplicateCollectionsBulkAction,
213
+ order: 300,
214
+ },
215
+ {
216
+ component: MoveCollectionsBulkAction,
217
+ order: 400,
134
218
  },
135
- },
136
- productVariants: {
137
- header: 'Contents',
138
- cell: ({ row }) => {
139
- return (
140
- <CollectionContentsSheet
141
- collectionId={row.original.id}
142
- collectionName={row.original.name}
143
- >
144
- <Trans>{row.original.productVariants.totalItems} variants</Trans>
145
- </CollectionContentsSheet>
146
- );
219
+ {
220
+ component: DeleteCollectionsBulkAction,
221
+ order: 500,
147
222
  },
148
- },
149
- }}
150
- defaultColumnOrder={[
151
- 'featuredAsset',
152
- 'children',
153
- 'name',
154
- 'slug',
155
- 'breadcrumbs',
156
- 'productVariants',
157
- ]}
158
- transformData={data => {
159
- return addSubCollections(data);
160
- }}
161
- setTableOptions={(options: TableOptions<any>) => {
162
- options.state = {
163
- ...options.state,
164
- expanded: expanded,
165
- };
166
- options.onExpandedChange = setExpanded;
167
- options.getExpandedRowModel = getExpandedRowModel();
168
- options.getRowCanExpand = () => true;
169
- options.getRowId = row => {
170
- return row.id;
171
- };
172
- return options;
173
- }}
174
- defaultVisibility={{
175
- id: false,
176
- createdAt: false,
177
- updatedAt: false,
178
- position: false,
179
- parentId: false,
180
- children: false,
181
- }}
182
- onSearchTermChange={searchTerm => {
183
- return {
184
- name: { contains: searchTerm },
185
- };
186
- }}
187
- route={Route}
188
- bulkActions={[
189
- {
190
- component: AssignCollectionsToChannelBulkAction,
191
- order: 100,
192
- },
193
- {
194
- component: RemoveCollectionsFromChannelBulkAction,
195
- order: 200,
196
- },
197
- {
198
- component: DuplicateCollectionsBulkAction,
199
- order: 300,
200
- },
201
- {
202
- component: DeleteCollectionsBulkAction,
203
- order: 400,
204
- },
205
- ]}
206
- >
207
- <PageActionBarRight>
208
- <PermissionGuard requires={['CreateCollection', 'CreateCatalog']}>
209
- <Button asChild>
210
- <Link to="./new">
211
- <PlusIcon className="mr-2 h-4 w-4" />
212
- <Trans>New Collection</Trans>
213
- </Link>
214
- </Button>
215
- </PermissionGuard>
216
- </PageActionBarRight>
217
- </ListPage>
223
+ ]}
224
+ >
225
+ <PageActionBarRight>
226
+ <PermissionGuard requires={['CreateCollection', 'CreateCatalog']}>
227
+ <Button asChild>
228
+ <Link to="./new">
229
+ <PlusIcon className="mr-2 h-4 w-4" />
230
+ <Trans>New Collection</Trans>
231
+ </Link>
232
+ </Button>
233
+ </PermissionGuard>
234
+ </PageActionBarRight>
235
+ </ListPage>
236
+ <MoveDialog />
237
+ </>
218
238
  );
219
239
  }
@@ -1,4 +1,4 @@
1
- import { RichTextInput } from '@/vdb/components/data-input/richt-text-input.js';
1
+ import { RichTextInput } from '@/vdb/components/data-input/rich-text-input.js';
2
2
  import { EntityAssets } from '@/vdb/components/shared/entity-assets.js';
3
3
  import { ErrorPage } from '@/vdb/components/shared/error-page.js';
4
4
  import { FormFieldWrapper } from '@/vdb/components/shared/form-field-wrapper.js';
@@ -1,9 +1,12 @@
1
1
  import { useQueryClient } from '@tanstack/react-query';
2
+ import { useState } from 'react';
3
+ import { FolderTree } from 'lucide-react';
2
4
 
5
+ import { Trans } from '@/vdb/lib/trans.js';
3
6
  import { AssignToChannelBulkAction } from '@/vdb/components/shared/assign-to-channel-bulk-action.js';
4
7
  import { RemoveFromChannelBulkAction } from '@/vdb/components/shared/remove-from-channel-bulk-action.js';
5
8
  import { api } from '@/vdb/graphql/api.js';
6
- import { BulkActionComponent, useChannel } from '@/vdb/index.js';
9
+ import { BulkActionComponent, useChannel, DataTableBulkActionItem, usePaginatedList } from '@/vdb/index.js';
7
10
  import { DeleteBulkAction } from '../../../../common/delete-bulk-action.js';
8
11
  import { DuplicateBulkAction } from '../../../../common/duplicate-bulk-action.js';
9
12
  import {
@@ -11,6 +14,7 @@ import {
11
14
  deleteCollectionsDocument,
12
15
  removeCollectionFromChannelDocument,
13
16
  } from '../collections.graphql.js';
17
+ import { MoveCollectionsDialog } from './move-collections-dialog.js';
14
18
 
15
19
  export const AssignCollectionsToChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
16
20
  const queryClient = useQueryClient();
@@ -85,3 +89,32 @@ export const DeleteCollectionsBulkAction: BulkActionComponent<any> = ({ selectio
85
89
  />
86
90
  );
87
91
  };
92
+
93
+ export const MoveCollectionsBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
94
+ const [dialogOpen, setDialogOpen] = useState(false);
95
+ const queryClient = useQueryClient();
96
+ const { refetchPaginatedList } = usePaginatedList();
97
+
98
+ const handleSuccess = () => {
99
+ queryClient.invalidateQueries({ queryKey: ['childCollections'] });
100
+ refetchPaginatedList();
101
+ table.resetRowSelection();
102
+ };
103
+
104
+ return (
105
+ <>
106
+ <DataTableBulkActionItem
107
+ requiresPermission={['UpdateCatalog', 'UpdateCollection']}
108
+ onClick={() => setDialogOpen(true)}
109
+ label={<Trans>Move</Trans>}
110
+ icon={FolderTree}
111
+ />
112
+ <MoveCollectionsDialog
113
+ open={dialogOpen}
114
+ onOpenChange={setDialogOpen}
115
+ collectionsToMove={selection}
116
+ onSuccess={handleSuccess}
117
+ />
118
+ </>
119
+ );
120
+ };