@vendure/dashboard 3.5.0-minor-202510031341 → 3.5.0-minor-202510161257

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 (220) hide show
  1. package/dist/plugin/dashboard.plugin.js +1 -1
  2. package/dist/plugin/default-page.html +1 -1
  3. package/dist/vite/utils/ast-utils.spec.js +3 -3
  4. package/dist/vite/utils/tsconfig-utils.js +2 -1
  5. package/dist/vite/vite-plugin-hmr.d.ts +8 -0
  6. package/dist/vite/vite-plugin-hmr.js +34 -0
  7. package/dist/vite/vite-plugin-theme.js +6 -6
  8. package/dist/vite/vite-plugin-transform-index.js +6 -1
  9. package/dist/vite/vite-plugin-vendure-dashboard.d.ts +31 -4
  10. package/dist/vite/vite-plugin-vendure-dashboard.js +89 -34
  11. package/package.json +18 -5
  12. package/src/app/app-providers.tsx +4 -1
  13. package/src/app/common/map-faceted-filter-fields.ts +21 -0
  14. package/src/app/main.tsx +3 -1
  15. package/src/app/routes/_authenticated/_administrators/administrators.graphql.ts +2 -2
  16. package/src/app/routes/_authenticated/_administrators/administrators.tsx +13 -3
  17. package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +6 -13
  18. package/src/app/routes/_authenticated/_administrators/components/role-permissions-display.tsx +1 -1
  19. package/src/app/routes/_authenticated/_assets/assets.tsx +17 -1
  20. package/src/app/routes/_authenticated/_collections/collections.graphql.ts +1 -0
  21. package/src/app/routes/_authenticated/_collections/collections.tsx +5 -0
  22. package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +0 -1
  23. package/src/app/routes/_authenticated/_customers/customers.tsx +9 -5
  24. package/src/app/routes/_authenticated/_facets/components/facet-bulk-actions.tsx +0 -6
  25. package/src/app/routes/_authenticated/_facets/components/facet-value-bulk-actions.tsx +16 -0
  26. package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +43 -12
  27. package/src/app/routes/_authenticated/_facets/facets_.$facetId.values_.$id.tsx +14 -5
  28. package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +4 -8
  29. package/src/app/routes/_authenticated/_global-settings/utils/global-languages.ts +268 -0
  30. package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +117 -92
  31. package/src/app/routes/_authenticated/_orders/components/order-address.tsx +15 -15
  32. package/src/app/routes/_authenticated/_orders/components/order-detail-shared.tsx +5 -5
  33. package/src/app/routes/_authenticated/_orders/components/order-modification-summary.tsx +2 -1
  34. package/src/app/routes/_authenticated/_orders/components/order-table-totals.tsx +26 -27
  35. package/src/app/routes/_authenticated/_orders/components/order-table.tsx +5 -3
  36. package/src/app/routes/_authenticated/_orders/components/state-transition-control.tsx +6 -9
  37. package/src/app/routes/_authenticated/_orders/orders.graphql.ts +17 -1
  38. package/src/app/routes/_authenticated/_orders/orders_.$id_.modify.tsx +48 -281
  39. package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +59 -40
  40. package/src/app/routes/_authenticated/_orders/utils/order-utils.ts +73 -0
  41. package/src/app/routes/_authenticated/_orders/utils/use-modify-order.ts +312 -0
  42. package/src/app/routes/_authenticated/_payment-methods/payment-methods.graphql.ts +2 -2
  43. package/src/app/routes/_authenticated/_payment-methods/payment-methods.tsx +4 -0
  44. package/src/app/routes/_authenticated/_product-variants/components/add-currency-dropdown.tsx +49 -0
  45. package/src/app/routes/_authenticated/_product-variants/components/add-stock-location-dropdown.tsx +56 -0
  46. package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +12 -0
  47. package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +178 -50
  48. package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +0 -6
  49. package/src/app/routes/_authenticated/_products/components/product-variants-table.tsx +0 -11
  50. package/src/app/routes/_authenticated/_products/products.tsx +6 -2
  51. package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$productOptionGroupId.options_.$id.tsx +4 -8
  52. package/src/app/routes/_authenticated/_promotions/components/promotion-bulk-actions.tsx +0 -10
  53. package/src/app/routes/_authenticated/_promotions/promotions.graphql.ts +2 -2
  54. package/src/app/routes/_authenticated/_promotions/promotions.tsx +12 -0
  55. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +3 -10
  56. package/src/app/routes/_authenticated/_sellers/sellers.graphql.ts +2 -2
  57. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.graphql.ts +2 -2
  58. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.tsx +4 -0
  59. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +4 -10
  60. package/src/app/routes/_authenticated/_stock-locations/stock-locations.graphql.ts +2 -2
  61. package/src/app/routes/_authenticated/_tax-categories/tax-categories.graphql.ts +2 -2
  62. package/src/app/routes/_authenticated/_tax-rates/tax-rates.tsx +9 -0
  63. package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +1 -0
  64. package/src/app/routes/_authenticated/_zones/zones.graphql.ts +2 -2
  65. package/src/app/routes/login.tsx +2 -2
  66. package/src/i18n/locales/ar.po +420 -289
  67. package/src/i18n/locales/cs.po +420 -289
  68. package/src/i18n/locales/de.po +420 -289
  69. package/src/i18n/locales/en.po +420 -289
  70. package/src/i18n/locales/es.po +420 -289
  71. package/src/i18n/locales/fa.po +420 -289
  72. package/src/i18n/locales/fr.po +468 -337
  73. package/src/i18n/locales/he.po +420 -289
  74. package/src/i18n/locales/hr.po +420 -289
  75. package/src/i18n/locales/it.po +420 -289
  76. package/src/i18n/locales/ja.po +420 -289
  77. package/src/i18n/locales/nb.po +420 -289
  78. package/src/i18n/locales/ne.po +420 -289
  79. package/src/i18n/locales/pl.po +420 -289
  80. package/src/i18n/locales/pt_BR.po +420 -289
  81. package/src/i18n/locales/pt_PT.po +420 -289
  82. package/src/i18n/locales/ru.po +420 -289
  83. package/src/i18n/locales/sv.po +420 -289
  84. package/src/i18n/locales/tr.po +420 -289
  85. package/src/i18n/locales/uk.po +420 -289
  86. package/src/i18n/locales/zh_Hans.po +420 -289
  87. package/src/i18n/locales/zh_Hant.po +420 -289
  88. package/src/lib/components/data-input/affixed-input.stories.tsx +93 -0
  89. package/src/lib/components/data-input/affixed-input.tsx +5 -2
  90. package/src/lib/components/data-input/boolean-input.stories.tsx +102 -0
  91. package/src/lib/components/data-input/checkbox-input.stories.tsx +61 -0
  92. package/src/lib/components/data-input/customer-group-input.tsx +0 -1
  93. package/src/lib/components/data-input/datetime-input.stories.tsx +62 -0
  94. package/src/lib/components/data-input/datetime-input.tsx +27 -13
  95. package/src/lib/components/data-input/default-relation-input.tsx +18 -12
  96. package/src/lib/components/data-input/money-input.stories.tsx +88 -0
  97. package/src/lib/components/data-input/money-input.tsx +7 -11
  98. package/src/lib/components/data-input/number-input.stories.tsx +103 -0
  99. package/src/lib/components/data-input/number-input.tsx +16 -5
  100. package/src/lib/components/data-input/password-input.stories.tsx +65 -0
  101. package/src/lib/components/data-input/rich-text-input.stories.tsx +92 -0
  102. package/src/lib/components/data-input/slug-input.stories.tsx +232 -0
  103. package/src/lib/components/data-input/slug-input.tsx +9 -10
  104. package/src/lib/components/data-input/text-input.stories.tsx +52 -0
  105. package/src/lib/components/data-input/textarea-input.stories.tsx +55 -0
  106. package/src/lib/components/data-table/add-filter-menu.tsx +6 -1
  107. package/src/lib/components/data-table/column-header-wrapper.tsx +106 -0
  108. package/src/lib/components/data-table/data-table-bulk-action-item.tsx +11 -9
  109. package/src/lib/components/data-table/data-table-bulk-actions.tsx +4 -4
  110. package/src/lib/components/data-table/data-table-column-header.tsx +17 -14
  111. package/src/lib/components/data-table/data-table-faceted-filter.tsx +33 -11
  112. package/src/lib/components/data-table/data-table-filter-badge-editable.tsx +35 -0
  113. package/src/lib/components/data-table/data-table-filter-badge.tsx +28 -14
  114. package/src/lib/components/data-table/data-table-filter-dialog.tsx +28 -8
  115. package/src/lib/components/data-table/data-table-pagination.tsx +23 -7
  116. package/src/lib/components/data-table/data-table.stories.tsx +249 -0
  117. package/src/lib/components/data-table/data-table.tsx +39 -11
  118. package/src/lib/components/data-table/filters/data-table-datetime-filter.tsx +79 -34
  119. package/src/lib/components/data-table/use-generated-columns.tsx +55 -27
  120. package/src/lib/components/layout/generated-breadcrumbs.tsx +4 -12
  121. package/src/lib/components/layout/nav-user.tsx +19 -13
  122. package/src/lib/components/login/login-form.tsx +39 -123
  123. package/src/lib/components/shared/alerts.tsx +29 -17
  124. package/src/lib/components/shared/asset/asset-bulk-actions.tsx +3 -3
  125. package/src/lib/components/shared/asset/asset-gallery.stories.tsx +76 -0
  126. package/src/lib/components/shared/asset/asset-gallery.tsx +147 -113
  127. package/src/lib/components/shared/asset/asset-picker-dialog.stories.tsx +58 -0
  128. package/src/lib/components/shared/configurable-operation-input.tsx +1 -1
  129. package/src/lib/components/shared/customer-group-selector.tsx +5 -2
  130. package/src/lib/components/shared/detail-page-button.stories.tsx +52 -0
  131. package/src/lib/components/shared/facet-value-selector.stories.tsx +48 -0
  132. package/src/lib/components/shared/facet-value-selector.tsx +130 -34
  133. package/src/lib/components/shared/paginated-list-data-table.stories.tsx +212 -0
  134. package/src/lib/components/shared/paginated-list-data-table.tsx +12 -12
  135. package/src/lib/components/shared/permission-guard.stories.tsx +46 -0
  136. package/src/lib/components/shared/remove-from-channel-bulk-action.tsx +2 -0
  137. package/src/lib/components/shared/rich-text-editor/responsive-toolbar.tsx +8 -4
  138. package/src/lib/components/shared/rich-text-editor/rich-text-editor.tsx +1 -0
  139. package/src/lib/components/shared/table-cell/order-table-cell-components.tsx +40 -0
  140. package/src/lib/components/shared/vendure-image.stories.tsx +167 -0
  141. package/src/lib/components/shared/vendure-image.tsx +6 -7
  142. package/src/lib/components/ui/accordion.stories.tsx +33 -0
  143. package/src/lib/components/ui/alert-dialog.stories.tsx +48 -0
  144. package/src/lib/components/ui/alert.stories.tsx +35 -0
  145. package/src/lib/components/ui/aspect-ratio.stories.tsx +28 -0
  146. package/src/lib/components/ui/badge.stories.tsx +28 -0
  147. package/src/lib/components/ui/breadcrumb.stories.tsx +41 -0
  148. package/src/lib/components/ui/button.stories.tsx +38 -0
  149. package/src/lib/components/ui/calendar.stories.tsx +22 -0
  150. package/src/lib/components/ui/card.stories.tsx +28 -0
  151. package/src/lib/components/ui/carousel.stories.tsx +34 -0
  152. package/src/lib/components/ui/checkbox.stories.tsx +31 -0
  153. package/src/lib/components/ui/collapsible.stories.tsx +39 -0
  154. package/src/lib/components/ui/command.stories.tsx +44 -0
  155. package/src/lib/components/ui/context-menu.stories.tsx +38 -0
  156. package/src/lib/components/ui/dialog.stories.tsx +52 -0
  157. package/src/lib/components/ui/drawer.stories.tsx +50 -0
  158. package/src/lib/components/ui/dropdown-menu.stories.tsx +41 -0
  159. package/src/lib/components/ui/hover-card.stories.tsx +38 -0
  160. package/src/lib/components/ui/input-group.tsx +148 -0
  161. package/src/lib/components/ui/input-otp.stories.tsx +30 -0
  162. package/src/lib/components/ui/input.stories.tsx +38 -0
  163. package/src/lib/components/ui/label.stories.tsx +24 -0
  164. package/src/lib/components/ui/menubar.stories.tsx +53 -0
  165. package/src/lib/components/ui/navigation-menu.stories.tsx +54 -0
  166. package/src/lib/components/ui/pagination.stories.tsx +51 -0
  167. package/src/lib/components/ui/password-input.stories.tsx +32 -0
  168. package/src/lib/components/ui/password-input.tsx +33 -0
  169. package/src/lib/components/ui/popover.stories.tsx +33 -0
  170. package/src/lib/components/ui/progress.stories.tsx +27 -0
  171. package/src/lib/components/ui/radio-group.stories.tsx +34 -0
  172. package/src/lib/components/ui/resizable.stories.tsx +32 -0
  173. package/src/lib/components/ui/scroll-area.stories.tsx +31 -0
  174. package/src/lib/components/ui/select.stories.tsx +36 -0
  175. package/src/lib/components/ui/separator.stories.tsx +35 -0
  176. package/src/lib/components/ui/sheet.stories.tsx +50 -0
  177. package/src/lib/components/ui/sidebar-context.ts +16 -0
  178. package/src/lib/components/ui/sidebar.tsx +2 -13
  179. package/src/lib/components/ui/skeleton.stories.tsx +26 -0
  180. package/src/lib/components/ui/slider.stories.tsx +37 -0
  181. package/src/lib/components/ui/switch.stories.tsx +31 -0
  182. package/src/lib/components/ui/table.stories.tsx +52 -0
  183. package/src/lib/components/ui/tabs.stories.tsx +29 -0
  184. package/src/lib/components/ui/textarea.stories.tsx +32 -0
  185. package/src/lib/components/ui/toggle-group.stories.tsx +31 -0
  186. package/src/lib/components/ui/toggle.stories.tsx +39 -0
  187. package/src/lib/components/ui/tooltip.stories.tsx +30 -0
  188. package/src/lib/components/ui/tooltip.tsx +2 -2
  189. package/src/lib/framework/alert/alert-extensions.tsx +0 -11
  190. package/src/lib/framework/alert/alert-item.tsx +14 -19
  191. package/src/lib/framework/alert/alerts-indicator.tsx +14 -15
  192. package/src/lib/framework/alert/search-index-buffer-alert/search-index-buffer-alert.ts +41 -0
  193. package/src/lib/framework/component-registry/component-registry.tsx +3 -14
  194. package/src/lib/framework/dashboard-widget/base-widget.tsx +18 -9
  195. package/src/lib/framework/dashboard-widget/latest-orders-widget/index.tsx +0 -2
  196. package/src/lib/framework/dashboard-widget/widget-filters-context.tsx +12 -11
  197. package/src/lib/framework/defaults.ts +9 -13
  198. package/src/lib/framework/extension-api/input-component-extensions.tsx +6 -1
  199. package/src/lib/framework/extension-api/logic/alerts.ts +3 -2
  200. package/src/lib/framework/extension-api/types/alerts.ts +12 -6
  201. package/src/lib/framework/extension-api/types/data-table.ts +5 -2
  202. package/src/lib/framework/extension-api/types/layout.ts +41 -1
  203. package/src/lib/framework/extension-api/types/login.ts +0 -21
  204. package/src/lib/framework/form-engine/value-transformers.ts +8 -1
  205. package/src/lib/framework/layout-engine/custom-form-page.stories.tsx +344 -0
  206. package/src/lib/framework/layout-engine/page-layout.tsx +69 -57
  207. package/src/lib/framework/layout-engine/page.stories.tsx +275 -0
  208. package/src/lib/framework/nav-menu/nav-menu-extensions.ts +32 -19
  209. package/src/lib/framework/page/detail-page.stories.tsx +151 -0
  210. package/src/lib/framework/page/detail-page.tsx +12 -15
  211. package/src/lib/framework/page/list-page.stories.tsx +217 -0
  212. package/src/lib/framework/page/list-page.tsx +8 -1
  213. package/src/lib/graphql/api.ts +18 -1
  214. package/src/lib/graphql/graphql-env.d.ts +1 -1
  215. package/src/lib/hooks/use-alerts.ts +84 -0
  216. package/src/lib/hooks/use-floating-bulk-actions.ts +2 -3
  217. package/src/lib/index.ts +12 -5
  218. package/src/lib/providers/alerts-provider.tsx +60 -0
  219. package/src/lib/providers/channel-provider.tsx +1 -0
  220. package/src/lib/providers/theme-provider.tsx +6 -3
@@ -151,7 +151,7 @@ let DashboardPlugin = DashboardPlugin_1 = class DashboardPlugin {
151
151
  createStaticServer(dashboardPath) {
152
152
  const limiter = (0, express_rate_limit_1.rateLimit)({
153
153
  windowMs: 60 * 1000,
154
- limit: process.env.NODE_ENV === 'production' ? 500 : 2000,
154
+ limit: process.env.NODE_ENV === 'production' ? 500 : 10000,
155
155
  standardHeaders: true,
156
156
  legacyHeaders: false,
157
157
  });
@@ -108,7 +108,7 @@
108
108
  </head>
109
109
  <body>
110
110
  <div class="container">
111
- <svg viewBox="0 0 539 100" fill="none" xmlns="http://www.w3.org/2000/svg">
111
+ <svg class="logo" viewBox="0 0 539 100" fill="none" xmlns="http://www.w3.org/2000/svg">
112
112
  <path d="M198.715 29.7044C198.311 29.1369 197.638 28.7809 196.916 28.7809H189.317C188.393 28.7809 187.547 29.3774 187.239 30.2431L174.3 67.6252L161.16 30.2239C160.862 29.3581 160.034 28.7617 159.082 28.7617H151.261C150.54 28.7617 149.886 29.108 149.462 29.6852C149.058 30.2527 148.962 31.0031 149.183 31.6764L167.817 82.9974C168.115 83.8632 168.942 84.4404 169.866 84.4404H178.139C179.062 84.4404 179.889 83.8728 180.188 82.9974L198.927 31.6764C199.177 31.0031 199.081 30.2623 198.648 29.6852L198.696 29.714L198.715 29.7044Z" fill="#17C1FF"/>
113
113
  <path d="M252.778 58.3518C252.855 57.5342 252.903 56.4086 252.903 54.9465C252.903 49.7807 251.729 45.0286 249.43 40.8055C247.131 36.5825 243.88 33.1771 239.839 30.7145C235.77 28.2518 231.143 26.982 226.15 26.982C220.85 26.982 216.031 28.2711 211.836 30.8107C207.642 33.3503 204.343 36.9288 201.995 41.4212C199.667 45.8655 198.494 50.9639 198.494 56.553C198.494 62.142 199.696 67.2404 202.044 71.7135C204.42 76.2156 207.767 79.7941 211.99 82.3241C216.213 84.8636 221.081 86.1527 226.458 86.1527C232.23 86.1527 237.329 84.9887 241.619 82.6511C245.89 80.3135 249.392 77.0621 252.008 72.9834C252.633 71.9925 252.354 70.6746 251.383 70.0012L245.438 66.0476C244.938 65.7205 244.341 65.5955 243.735 65.7205C243.158 65.8456 242.639 66.2207 242.34 66.7113C240.792 69.299 238.695 71.3384 236.145 72.8006C233.596 74.2435 230.277 74.9842 226.256 74.9842C221.456 74.9842 217.791 73.4162 215.04 70.1648C212.644 67.327 211.163 64.0755 210.595 60.2469H250.613C251.739 60.2469 252.691 59.4004 252.787 58.2845V58.3326L252.778 58.3518ZM211.355 49.8288C212.25 46.7986 213.78 44.2397 215.925 42.0753C218.57 39.4395 221.899 38.1505 226.122 38.1505C230.345 38.1505 233.846 39.2664 236.318 41.5558C238.339 43.4413 239.791 46.231 240.59 49.8095H211.336L211.365 49.8384L211.355 49.8288Z" fill="#17C1FF"/>
114
114
  <path d="M305.417 36.6883C303.396 33.5042 300.645 31.0512 297.25 29.4062C293.931 27.819 290.227 26.9917 286.331 26.9917C282.108 26.9917 278.337 28.0114 275.086 30.0026C273.758 30.8203 272.537 31.7919 271.44 32.8885V30.9261C271.44 29.7333 270.468 28.7425 269.237 28.7425H261.743C260.541 28.7425 259.54 29.714 259.54 30.9261V82.2471C259.54 83.4399 260.512 84.4308 261.743 84.4308H269.237C270.439 84.4308 271.44 83.4592 271.44 82.2471V56.5722C271.44 50.7811 272.642 46.1348 275.009 42.8064C277.231 39.6704 280.559 38.1312 285.129 38.1312C292.978 38.1312 296.624 42.2773 296.624 51.2044V82.2471C296.624 83.4399 297.596 84.4308 298.827 84.4308H306.321C307.523 84.4308 308.524 83.4592 308.524 82.2471V47.9241C308.524 43.653 307.504 39.8724 305.503 36.6883H305.426H305.417Z" fill="#17C1FF"/>
@@ -2,7 +2,7 @@ import ts from 'typescript';
2
2
  import { describe, expect, it } from 'vitest';
3
3
  import { findConfigExport } from './ast-utils.js';
4
4
  describe('findConfigExport', () => {
5
- it('should return undefined when no VendureConfig export is found', () => {
5
+ it('should return undefined when no VendureConfig export is found', { timeout: 30000 }, () => {
6
6
  const sourceText = `
7
7
  export const notConfig = {
8
8
  some: 'value'
@@ -12,7 +12,7 @@ describe('findConfigExport', () => {
12
12
  const result = findConfigExport(sourceFile);
13
13
  expect(result).toBeUndefined();
14
14
  });
15
- it('should find exported variable with VendureConfig type', () => {
15
+ it('should find exported variable with VendureConfig type', { timeout: 30000 }, () => {
16
16
  const sourceText = `
17
17
  import { VendureConfig } from '@vendure/core';
18
18
 
@@ -26,7 +26,7 @@ describe('findConfigExport', () => {
26
26
  const result = findConfigExport(sourceFile);
27
27
  expect(result).toBe('config');
28
28
  });
29
- it('should find exported variable with VendureConfig type among other exports', () => {
29
+ it('should find exported variable with VendureConfig type among other exports', { timeout: 30000 }, () => {
30
30
  const sourceText = `
31
31
  import { VendureConfig } from '@vendure/core';
32
32
 
@@ -1,5 +1,6 @@
1
1
  import fs from 'fs-extra';
2
2
  import path from 'path';
3
+ import stripJsonComments from 'strip-json-comments';
3
4
  /**
4
5
  * Finds and parses tsconfig files in the given directory and its parent directories.
5
6
  */
@@ -33,7 +34,7 @@ export async function findTsConfigPaths(configPath, logger, phase, transformTsCo
33
34
  }
34
35
  async function getCompilerOptionsFromFile(tsConfigFilePath) {
35
36
  const tsConfigContent = await fs.readFile(tsConfigFilePath, 'utf-8');
36
- const tsConfig = JSON.parse(tsConfigContent);
37
+ const tsConfig = JSON.parse(stripJsonComments(tsConfigContent));
37
38
  return tsConfig.compilerOptions || {};
38
39
  }
39
40
  function getTransformedPathMappings(paths, phase, transformTsConfigPathMappings) {
@@ -0,0 +1,8 @@
1
+ import { Plugin } from 'vite';
2
+ /**
3
+ * @description
4
+ * This plugin enables kind-of HMR for when dashboard extension files change.
5
+ * It is not true HMR because it triggers a page reload. Making real HMR work is very
6
+ * tricky in this case due to the way we load extension files via virtual modules.
7
+ */
8
+ export declare function hmrPlugin(): Plugin;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @description
3
+ * This plugin enables kind-of HMR for when dashboard extension files change.
4
+ * It is not true HMR because it triggers a page reload. Making real HMR work is very
5
+ * tricky in this case due to the way we load extension files via virtual modules.
6
+ */
7
+ export function hmrPlugin() {
8
+ let viteRoot;
9
+ return {
10
+ name: 'vendure:hmr',
11
+ configResolved(config) {
12
+ viteRoot = config.root;
13
+ },
14
+ handleHotUpdate({ server, modules, timestamp, file }) {
15
+ const invalidatedModules = new Set();
16
+ for (const mod of modules) {
17
+ server.moduleGraph.invalidateModule(mod, invalidatedModules, timestamp, true);
18
+ // Check if this is a file outside the Vite root (e.g., dashboard extensions)
19
+ const isOutsideRoot = mod.file && !mod.file.startsWith(viteRoot);
20
+ if (isOutsideRoot) {
21
+ // For files outside root, trigger a full page reload
22
+ // This ensures all extension code is fresh
23
+ server.ws.send({
24
+ type: 'full-reload',
25
+ path: '*',
26
+ });
27
+ return [];
28
+ }
29
+ }
30
+ // Let Vite handle normal HMR for files inside root
31
+ return undefined;
32
+ },
33
+ };
34
+ }
@@ -7,16 +7,16 @@ const defaultVariables = {
7
7
  popover: 'oklch(1.0000 0 0)',
8
8
  'popover-foreground': 'oklch(0.2103 0.0059 285.8852)',
9
9
  primary: 'oklch(0.7613 0.1503 231.1314)',
10
- 'primary-foreground': 'oklch(0.1408 0.0044 285.8229)',
10
+ 'primary-foreground': 'oklch(0.261 0.043 218.379)',
11
11
  secondary: 'oklch(0.9674 0.0013 286.3752)',
12
12
  'secondary-foreground': 'oklch(0.2103 0.0059 285.8852)',
13
13
  muted: 'oklch(0.9674 0.0013 286.3752)',
14
14
  'muted-foreground': 'oklch(0.5517 0.0138 285.9385)',
15
15
  accent: 'oklch(0.9674 0.0013 286.3752)',
16
16
  'accent-foreground': 'oklch(0.2103 0.0059 285.8852)',
17
- destructive: 'oklch(0.5771 0.2152 27.3250)',
17
+ destructive: 'oklch(0.505 0.188 27.325)',
18
18
  'destructive-foreground': 'oklch(0.9851 0 0)',
19
- success: 'hsl(100, 81%, 35%)',
19
+ success: 'hsl(99deg 67.25% 33.2%)',
20
20
  'success-foreground': 'hsl(0 0% 98%)',
21
21
  'dev-mode': 'hsl(204, 76%, 62%)',
22
22
  'dev-mode-foreground': 'hsl(0 0% 98%)',
@@ -58,9 +58,9 @@ const defaultVariables = {
58
58
  'muted-foreground': 'oklch(0.7118 0.0129 286.0665)',
59
59
  accent: 'oklch(0.2739 0.0055 286.0326)',
60
60
  'accent-foreground': 'oklch(0.9851 0 0)',
61
- destructive: 'oklch(0.6368 0.2078 25.3313)',
61
+ destructive: 'oklch(0.4 0.15 27.11)',
62
62
  'destructive-foreground': 'oklch(0.9851 0 0)',
63
- success: 'hsl(100, 100%, 35%)',
63
+ success: 'hsl(100 76.42% 22.21%)',
64
64
  'success-foreground': 'hsl(0 0% 98%)',
65
65
  'dev-mode': 'hsl(204, 86%, 53%)',
66
66
  'dev-mode-foreground': 'hsl(0 0% 98%)',
@@ -72,7 +72,7 @@ const defaultVariables = {
72
72
  'chart-3': 'oklch(0.6450 0.2154 16.4393)',
73
73
  'chart-4': 'oklch(0.7686 0.1647 70.0804)',
74
74
  'chart-5': 'oklch(0.7227 0.1920 149.5793)',
75
- sidebar: 'oklch(0.1408 0.0044 285.8229)',
75
+ sidebar: 'oklch(0.2 0 0)',
76
76
  'sidebar-foreground': 'oklch(0.9851 0 0)',
77
77
  'sidebar-primary': 'oklch(0.7613 0.1503 231.1314)',
78
78
  'sidebar-primary-foreground': 'oklch(0.1408 0.0044 285.8229)',
@@ -17,7 +17,12 @@ export function transformIndexHtmlPlugin() {
17
17
  },
18
18
  // Only apply this plugin during the build phase
19
19
  apply: 'build',
20
- transformIndexHtml(html) {
20
+ transformIndexHtml(html, ctx) {
21
+ // Don't transform Storybook HTML files
22
+ if (ctx.filename &&
23
+ (ctx.filename.includes('iframe.html') || ctx.filename.includes('storybook'))) {
24
+ return html;
25
+ }
21
26
  if (config.base && config.base !== '/') {
22
27
  // Remove the base path from hrefs and srcs
23
28
  const basePath = config.base.replace(/\/$/, ''); // Remove trailing slash
@@ -73,11 +73,38 @@ export type VitePluginVendureDashboardOptions = {
73
73
  * the location based on the location of the `@vendure/core` package.
74
74
  */
75
75
  pluginPackageScanner?: PackageScannerConfig;
76
+ /**
77
+ * @description
78
+ * Allows you to selectively disable individual plugins.
79
+ * @example
80
+ * ```ts
81
+ * vendureDashboardPlugin({
82
+ * vendureConfigPath: './config.ts',
83
+ * disablePlugins: {
84
+ * react: true,
85
+ * lingui: true,
86
+ * }
87
+ * })
88
+ * ```
89
+ */
90
+ disablePlugins?: {
91
+ tanstackRouter?: boolean;
92
+ react?: boolean;
93
+ lingui?: boolean;
94
+ themeVariables?: boolean;
95
+ tailwindSource?: boolean;
96
+ tailwindcss?: boolean;
97
+ configLoader?: boolean;
98
+ viteConfig?: boolean;
99
+ adminApiSchema?: boolean;
100
+ dashboardMetadata?: boolean;
101
+ uiConfig?: boolean;
102
+ gqlTada?: boolean;
103
+ transformIndexHtml?: boolean;
104
+ translations?: boolean;
105
+ hmr?: boolean;
106
+ };
76
107
  } & UiConfigPluginOptions & ThemeVariablesPluginOptions;
77
- /**
78
- * @description
79
- * This is a Vite plugin which configures a set of plugins required to build the Vendure Dashboard.
80
- */
81
108
  export declare function vendureDashboardPlugin(options: VitePluginVendureDashboardOptions): PluginOption[];
82
109
  /**
83
110
  * Get the normalized path to the Vendure config file given either a string or URL.
@@ -8,60 +8,115 @@ import { configLoaderPlugin } from './vite-plugin-config-loader.js';
8
8
  import { viteConfigPlugin } from './vite-plugin-config.js';
9
9
  import { dashboardMetadataPlugin } from './vite-plugin-dashboard-metadata.js';
10
10
  import { gqlTadaPlugin } from './vite-plugin-gql-tada.js';
11
+ import { hmrPlugin } from './vite-plugin-hmr.js';
11
12
  import { dashboardTailwindSourcePlugin } from './vite-plugin-tailwind-source.js';
12
13
  import { themeVariablesPlugin } from './vite-plugin-theme.js';
13
14
  import { transformIndexHtmlPlugin } from './vite-plugin-transform-index.js';
14
15
  import { translationsPlugin } from './vite-plugin-translations.js';
15
16
  import { uiConfigPlugin } from './vite-plugin-ui-config.js';
16
- /**
17
- * @description
18
- * This is a Vite plugin which configures a set of plugins required to build the Vendure Dashboard.
19
- */
20
17
  export function vendureDashboardPlugin(options) {
21
- var _a;
18
+ var _a, _b;
22
19
  const tempDir = (_a = options.tempCompilationDir) !== null && _a !== void 0 ? _a : path.join(import.meta.dirname, './.vendure-dashboard-temp');
23
20
  const normalizedVendureConfigPath = getNormalizedVendureConfigPath(options.vendureConfigPath);
24
21
  const packageRoot = getDashboardPackageRoot();
25
22
  const linguiConfigPath = path.join(packageRoot, 'lingui.config.js');
23
+ const disabled = (_b = options.disablePlugins) !== null && _b !== void 0 ? _b : {};
26
24
  if (process.env.IS_LOCAL_DEV !== 'true') {
27
25
  process.env.LINGUI_CONFIG = linguiConfigPath;
28
26
  }
29
- return [
30
- ...(options.disableTansStackRouterPlugin
31
- ? []
32
- : [
27
+ const pluginMap = [
28
+ {
29
+ key: 'tanstackRouter',
30
+ plugin: () => !options.disableTansStackRouterPlugin &&
33
31
  tanstackRouter({
34
32
  autoCodeSplitting: true,
35
33
  routeFileIgnorePattern: '.graphql.ts|components|hooks|utils',
36
34
  routesDirectory: path.join(packageRoot, 'src/app/routes'),
37
35
  generatedRouteTree: path.join(packageRoot, 'src/app/routeTree.gen.ts'),
38
36
  }),
39
- ]),
40
- react({
41
- plugins: [['@lingui/swc-plugin', {}]],
42
- }),
43
- lingui({}),
44
- themeVariablesPlugin({ theme: options.theme }),
45
- dashboardTailwindSourcePlugin(),
46
- tailwindcss(),
47
- configLoaderPlugin({
48
- vendureConfigPath: normalizedVendureConfigPath,
49
- outputPath: tempDir,
50
- pathAdapter: options.pathAdapter,
51
- pluginPackageScanner: options.pluginPackageScanner,
52
- }),
53
- viteConfigPlugin({ packageRoot }),
54
- adminApiSchemaPlugin(),
55
- dashboardMetadataPlugin(),
56
- uiConfigPlugin(options),
57
- ...(options.gqlOutputPath
58
- ? [gqlTadaPlugin({ gqlTadaOutputPath: options.gqlOutputPath, tempDir, packageRoot })]
59
- : []),
60
- transformIndexHtmlPlugin(),
61
- translationsPlugin({
62
- packageRoot,
63
- }),
37
+ },
38
+ {
39
+ key: 'react',
40
+ plugin: () => react({
41
+ plugins: [['@lingui/swc-plugin', {}]],
42
+ }),
43
+ },
44
+ {
45
+ key: 'lingui',
46
+ plugin: () => lingui({}),
47
+ },
48
+ {
49
+ key: 'themeVariables',
50
+ plugin: () => themeVariablesPlugin({ theme: options.theme }),
51
+ },
52
+ {
53
+ key: 'tailwindSource',
54
+ plugin: () => dashboardTailwindSourcePlugin(),
55
+ },
56
+ {
57
+ key: 'tailwindcss',
58
+ plugin: () => tailwindcss(),
59
+ },
60
+ {
61
+ key: 'configLoader',
62
+ plugin: () => configLoaderPlugin({
63
+ vendureConfigPath: normalizedVendureConfigPath,
64
+ outputPath: tempDir,
65
+ pathAdapter: options.pathAdapter,
66
+ pluginPackageScanner: options.pluginPackageScanner,
67
+ }),
68
+ },
69
+ {
70
+ key: 'viteConfig',
71
+ plugin: () => viteConfigPlugin({ packageRoot }),
72
+ },
73
+ {
74
+ key: 'adminApiSchema',
75
+ plugin: () => adminApiSchemaPlugin(),
76
+ },
77
+ {
78
+ key: 'dashboardMetadata',
79
+ plugin: () => dashboardMetadataPlugin(),
80
+ },
81
+ {
82
+ key: 'uiConfig',
83
+ plugin: () => uiConfigPlugin(options),
84
+ },
85
+ {
86
+ key: 'gqlTada',
87
+ plugin: () => options.gqlOutputPath &&
88
+ gqlTadaPlugin({ gqlTadaOutputPath: options.gqlOutputPath, tempDir, packageRoot }),
89
+ },
90
+ {
91
+ key: 'transformIndexHtml',
92
+ plugin: () => transformIndexHtmlPlugin(),
93
+ },
94
+ {
95
+ key: 'translations',
96
+ plugin: () => translationsPlugin({
97
+ packageRoot,
98
+ }),
99
+ },
100
+ {
101
+ key: 'hmr',
102
+ plugin: () => hmrPlugin(),
103
+ },
64
104
  ];
105
+ const plugins = [];
106
+ for (const entry of pluginMap) {
107
+ if (!disabled[entry.key]) {
108
+ const plugin = entry.plugin();
109
+ if (plugin) {
110
+ if (Array.isArray(plugin)) {
111
+ plugins.push(...plugin);
112
+ }
113
+ else {
114
+ plugins.push(plugin);
115
+ }
116
+ }
117
+ }
118
+ }
119
+ return plugins;
65
120
  }
66
121
  /**
67
122
  * @description
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vendure/dashboard",
3
3
  "private": false,
4
- "version": "3.5.0-minor-202510031341",
4
+ "version": "3.5.0-minor-202510161257",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -24,7 +24,10 @@
24
24
  "preview": "vite preview",
25
25
  "generate-index": "node scripts/generate-index.js",
26
26
  "i18n:extract": "lingui extract && node ./scripts/translate/i18n-tool.js extract",
27
- "i18n:apply": "node ./scripts/translate/i18n-tool.js apply"
27
+ "i18n:apply": "node ./scripts/translate/i18n-tool.js apply",
28
+ "storybook": "storybook dev -p 6006",
29
+ "storybook:build": "storybook build",
30
+ "storybook:deploy": "npm run build --prefix ../common && npm run build --prefix ../core && npm run build:vite && storybook build"
28
31
  },
29
32
  "module": "./src/lib/index.ts",
30
33
  "main": "./src/lib/index.ts",
@@ -134,6 +137,7 @@
134
137
  "react-resizable-panels": "^3.0.3",
135
138
  "recharts": "^2.15.4",
136
139
  "sonner": "^2.0.6",
140
+ "strip-json-comments": "^5.0.3",
137
141
  "tailwind-merge": "^3.2.0",
138
142
  "tailwindcss": "^4.1.5",
139
143
  "tailwindcss-animate": "^1.0.7",
@@ -145,19 +149,28 @@
145
149
  },
146
150
  "devDependencies": {
147
151
  "@eslint/js": "^9.19.0",
152
+ "@storybook/addon-a11y": "^10.0.0-beta.9",
153
+ "@storybook/addon-docs": "^10.0.0-beta.9",
154
+ "@storybook/addon-vitest": "^10.0.0-beta.9",
155
+ "@storybook/react-vite": "^10.0.0-beta.9",
148
156
  "@types/node": "^22.13.4",
149
- "@vendure/common": "^3.5.0-minor-202510031341",
150
- "@vendure/core": "^3.5.0-minor-202510031341",
157
+ "@vendure/common": "^3.5.0-minor-202510161257",
158
+ "@vendure/core": "^3.5.0-minor-202510161257",
159
+ "@vitest/browser": "^3.2.4",
160
+ "@vitest/coverage-v8": "^3.2.4",
151
161
  "eslint": "^9.19.0",
152
162
  "eslint-plugin-react": "^7.37.4",
153
163
  "eslint-plugin-react-hooks": "^5.0.0",
154
164
  "eslint-plugin-react-refresh": "^0.4.18",
165
+ "eslint-plugin-storybook": "^10.0.0-beta.9",
155
166
  "globals": "^15.14.0",
167
+ "playwright": "^1.55.1",
168
+ "storybook": "^10.0.0-beta.9",
156
169
  "vite-plugin-dts": "^4.5.4"
157
170
  },
158
171
  "optionalDependencies": {
159
172
  "lightningcss-linux-arm64-musl": "^1.29.3",
160
173
  "lightningcss-linux-x64-musl": "^1.29.1"
161
174
  },
162
- "gitHead": "ffe957ddc6b419f17fced0b4b94fe66fc42528f8"
175
+ "gitHead": "7567509a55b94070b741cf44e432533a12233369"
163
176
  }
@@ -1,3 +1,4 @@
1
+ import { AlertsProvider } from '@/vdb/providers/alerts-provider.js';
1
2
  import { AuthProvider } from '@/vdb/providers/auth.js';
2
3
  import { ChannelProvider } from '@/vdb/providers/channel-provider.js';
3
4
  import { I18nProvider } from '@/vdb/providers/i18n-provider.js';
@@ -17,7 +18,9 @@ export function AppProviders({ children }: { children: React.ReactNode }) {
17
18
  <ThemeProvider defaultTheme="system">
18
19
  <AuthProvider>
19
20
  <ServerConfigProvider>
20
- <ChannelProvider>{children}</ChannelProvider>
21
+ <ChannelProvider>
22
+ <AlertsProvider>{children}</AlertsProvider>
23
+ </ChannelProvider>
21
24
  </ServerConfigProvider>
22
25
  </AuthProvider>
23
26
  </ThemeProvider>
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Maps filter fields to their corresponding ID fields in faceted filters.
3
+ * For example, transforms { category: '5' } to { categoryId: { eq: '5' } }
4
+ *
5
+ * @param facetedFilters - Array of filter objects to transform
6
+ * @param fieldMapping - Record mapping source field names to target field names
7
+ */
8
+ export function mapFacetedFilterFields(
9
+ facetedFilters: Array<Record<string, any>>,
10
+ fieldMapping: Record<string, string>,
11
+ ) {
12
+ for (const [index, filter] of Object.entries(facetedFilters)) {
13
+ for (const [sourceField, targetField] of Object.entries(fieldMapping)) {
14
+ if (filter[sourceField]) {
15
+ facetedFilters[index as unknown as number] = {
16
+ [targetField]: filter[sourceField],
17
+ };
18
+ }
19
+ }
20
+ }
21
+ }
package/src/app/main.tsx CHANGED
@@ -38,7 +38,9 @@ const routerOptions: RouterOptions<AnyRoute, any> = {
38
38
  auth: undefined!, // This will be set after we wrap the app in an AuthProvider
39
39
  queryClient,
40
40
  },
41
- defaultErrorComponent: ({ error }: { error: Error }) => <div>Uh Oh!!! {error.message}</div>,
41
+ defaultErrorComponent: ({ error }: { error: Error }) => (
42
+ <div className="text-destructive p-6">An error occurred: {error.message}</div>
43
+ ),
42
44
  };
43
45
 
44
46
  // Create a type-only router instance for TypeScript type registration
@@ -29,8 +29,8 @@ export const administratorItemFragment = graphql(`
29
29
 
30
30
  export const administratorListDocument = graphql(
31
31
  `
32
- query AdministratorList {
33
- administrators {
32
+ query AdministratorList($options: AdministratorListOptions) {
33
+ administrators(options: $options) {
34
34
  items {
35
35
  ...AdministratorItem
36
36
  }
@@ -24,10 +24,20 @@ function AdministratorListPage() {
24
24
  listQuery={administratorListDocument}
25
25
  route={Route}
26
26
  onSearchTermChange={searchTerm => {
27
+ return searchTerm
28
+ ? {
29
+ firstName: { contains: searchTerm },
30
+ lastName: { contains: searchTerm },
31
+ emailAddress: { contains: searchTerm },
32
+ }
33
+ : {};
34
+ }}
35
+ transformVariables={variables => {
27
36
  return {
28
- firstName: { contains: searchTerm },
29
- lastName: { contains: searchTerm },
30
- emailAddress: { contains: searchTerm },
37
+ options: {
38
+ ...variables.options,
39
+ filterOperator: 'OR',
40
+ },
31
41
  };
32
42
  }}
33
43
  additionalColumns={{
@@ -75,11 +75,9 @@ function AdministratorDetailPage() {
75
75
  params: { id: params.id },
76
76
  onSuccess: async data => {
77
77
  toast(
78
- i18n.t(
79
- creatingNewEntity
80
- ? 'Successfully created administrator'
81
- : 'Successfully updated administrator',
82
- ),
78
+ creatingNewEntity
79
+ ? t`Successfully created administrator`
80
+ : t`Successfully updated administrator`,
83
81
  );
84
82
  resetForm();
85
83
  if (creatingNewEntity) {
@@ -87,14 +85,9 @@ function AdministratorDetailPage() {
87
85
  }
88
86
  },
89
87
  onError: err => {
90
- toast(
91
- i18n.t(
92
- creatingNewEntity ? 'Failed to create administrator' : 'Failed to update administrator',
93
- ),
94
- {
95
- description: err instanceof Error ? err.message : 'Unknown error',
96
- },
97
- );
88
+ toast(creatingNewEntity ? t`Failed to create administrator` : t`Failed to update administrator`, {
89
+ description: err instanceof Error ? err.message : 'Unknown error',
90
+ });
98
91
  },
99
92
  });
100
93
 
@@ -29,7 +29,7 @@ interface RolePermissionsDisplayProps {
29
29
  }
30
30
 
31
31
  export function RolePermissionsDisplay({ value = [] }: Readonly<RolePermissionsDisplayProps>) {
32
- const { t } = useLingui();
32
+ const { i18n } = useLingui();
33
33
  const groupedPermissions = useGroupedPermissions();
34
34
 
35
35
  const { data } = useQuery({
@@ -1,15 +1,29 @@
1
1
  import { AssetGallery } from '@/vdb/components/shared/asset/asset-gallery.js';
2
2
  import { Page, PageBlock, PageTitle } from '@/vdb/framework/layout-engine/page-layout.js';
3
3
  import { Trans } from '@lingui/react/macro';
4
- import { createFileRoute } from '@tanstack/react-router';
4
+ import { createFileRoute, useNavigate } from '@tanstack/react-router';
5
5
  import { DeleteAssetsBulkAction } from './components/asset-bulk-actions.js';
6
6
 
7
7
  export const Route = createFileRoute('/_authenticated/_assets/assets')({
8
8
  component: RouteComponent,
9
9
  loader: () => ({ breadcrumb: () => <Trans>Assets</Trans> }),
10
+ validateSearch: (search: Record<string, unknown>) => {
11
+ return {
12
+ perPage: (search.perPage as number) || 24,
13
+ };
14
+ },
10
15
  });
11
16
 
12
17
  function RouteComponent() {
18
+ const navigate = useNavigate({ from: Route.fullPath });
19
+ const { perPage } = Route.useSearch();
20
+
21
+ const handlePageSizeChange = (newPageSize: number) => {
22
+ navigate({
23
+ search: (prev: any) => ({ ...prev, perPage: newPageSize }),
24
+ });
25
+ };
26
+
13
27
  return (
14
28
  <Page pageId="asset-list">
15
29
  <PageTitle>
@@ -19,6 +33,8 @@ function RouteComponent() {
19
33
  <AssetGallery
20
34
  selectable={true}
21
35
  multiSelect="manual"
36
+ pageSize={perPage}
37
+ onPageSizeChange={handlePageSizeChange}
22
38
  bulkActions={[
23
39
  {
24
40
  order: 10,
@@ -20,6 +20,7 @@ export const collectionListDocument = graphql(
20
20
  }
21
21
  name
22
22
  slug
23
+ description
23
24
  breadcrumbs {
24
25
  id
25
26
  name
@@ -13,6 +13,7 @@ import { ResultOf } from 'gql.tada';
13
13
  import { Folder, FolderOpen, PlusIcon } from 'lucide-react';
14
14
  import { useState } from 'react';
15
15
 
16
+ import { RichTextDescriptionCell } from '@/vdb/components/shared/table-cell/order-table-cell-components.js';
16
17
  import { Badge } from '@/vdb/components/ui/badge.js';
17
18
  import { collectionListDocument } from './collections.graphql.js';
18
19
  import {
@@ -123,6 +124,9 @@ function CollectionListPage() {
123
124
  );
124
125
  },
125
126
  },
127
+ description: {
128
+ cell: RichTextDescriptionCell,
129
+ },
126
130
  breadcrumbs: {
127
131
  cell: ({ cell }) => {
128
132
  const value = cell.getValue();
@@ -204,6 +208,7 @@ function CollectionListPage() {
204
208
  position: false,
205
209
  parentId: false,
206
210
  children: false,
211
+ description: false,
207
212
  }}
208
213
  onSearchTermChange={searchTerm => {
209
214
  return {
@@ -68,7 +68,6 @@ export const DuplicateCollectionsBulkAction: BulkActionComponent<any> = ({ selec
68
68
  <DuplicateBulkAction
69
69
  entityType="Collection"
70
70
  duplicatorCode="collection-duplicator"
71
- duplicatorArguments={[]}
72
71
  requiredPermissions={['UpdateCatalog', 'UpdateCollection']}
73
72
  entityName="Collection"
74
73
  selection={selection}