@vendure/dashboard 3.4.3-master-202509260228 → 3.5.0-minor-202510012036

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 (295) hide show
  1. package/README.md +4 -0
  2. package/dist/plugin/api/api-extensions.js +11 -14
  3. package/dist/plugin/api/metrics.resolver.d.ts +2 -2
  4. package/dist/plugin/api/metrics.resolver.js +2 -2
  5. package/dist/plugin/config/metrics-strategies.d.ts +9 -9
  6. package/dist/plugin/config/metrics-strategies.js +6 -6
  7. package/dist/plugin/constants.d.ts +2 -0
  8. package/dist/plugin/constants.js +3 -1
  9. package/dist/plugin/dashboard.plugin.js +13 -0
  10. package/dist/plugin/service/metrics.service.d.ts +3 -3
  11. package/dist/plugin/service/metrics.service.js +37 -53
  12. package/dist/plugin/types.d.ts +9 -12
  13. package/dist/plugin/types.js +7 -11
  14. package/dist/vite/vite-plugin-config.js +13 -9
  15. package/dist/vite/vite-plugin-translations.d.ts +22 -0
  16. package/dist/vite/vite-plugin-translations.js +66 -0
  17. package/dist/vite/vite-plugin-vendure-dashboard.js +10 -8
  18. package/lingui.config.js +25 -2
  19. package/package.json +159 -156
  20. package/src/app/app-providers.tsx +0 -4
  21. package/src/app/common/delete-bulk-action.tsx +6 -5
  22. package/src/app/common/duplicate-bulk-action.tsx +4 -5
  23. package/src/app/common/duplicate-entity-dialog.tsx +1 -1
  24. package/src/app/common/set-document-direction.ts +7 -0
  25. package/src/app/main.tsx +50 -17
  26. package/src/app/routes/_authenticated/_administrators/administrators.tsx +8 -6
  27. package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +17 -6
  28. package/src/app/routes/_authenticated/_administrators/components/role-permissions-display.tsx +2 -2
  29. package/src/app/routes/_authenticated/_assets/assets.tsx +1 -1
  30. package/src/app/routes/_authenticated/_assets/assets_.$id.tsx +4 -4
  31. package/src/app/routes/_authenticated/_assets/components/asset-bulk-actions.tsx +8 -6
  32. package/src/app/routes/_authenticated/_assets/components/asset-tag-filter.tsx +1 -1
  33. package/src/app/routes/_authenticated/_assets/components/asset-tags-editor.tsx +1 -1
  34. package/src/app/routes/_authenticated/_assets/components/manage-tags-dialog.tsx +3 -8
  35. package/src/app/routes/_authenticated/_channels/channels.tsx +3 -6
  36. package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +5 -5
  37. package/src/app/routes/_authenticated/_collections/collections.tsx +10 -6
  38. package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +16 -5
  39. package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +1 -1
  40. package/src/app/routes/_authenticated/_collections/components/collection-contents-sheet.tsx +1 -1
  41. package/src/app/routes/_authenticated/_collections/components/move-collections-dialog.tsx +6 -6
  42. package/src/app/routes/_authenticated/_countries/countries.graphql.ts +2 -0
  43. package/src/app/routes/_authenticated/_countries/countries.tsx +2 -3
  44. package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +4 -4
  45. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-sheet.tsx +1 -1
  46. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-table.tsx +4 -4
  47. package/src/app/routes/_authenticated/_customer-groups/customer-groups.tsx +2 -4
  48. package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +13 -6
  49. package/src/app/routes/_authenticated/_customers/components/customer-address-card.tsx +8 -8
  50. package/src/app/routes/_authenticated/_customers/components/customer-address-form.tsx +3 -3
  51. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-container.tsx +1 -1
  52. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-utils.tsx +1 -1
  53. package/src/app/routes/_authenticated/_customers/components/customer-history/default-customer-history-components.tsx +1 -1
  54. package/src/app/routes/_authenticated/_customers/components/customer-history/use-customer-history.ts +1 -1
  55. package/src/app/routes/_authenticated/_customers/components/customer-status-badge.tsx +1 -1
  56. package/src/app/routes/_authenticated/_customers/customers.graphql.ts +4 -0
  57. package/src/app/routes/_authenticated/_customers/customers.tsx +23 -11
  58. package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +10 -8
  59. package/src/app/routes/_authenticated/_facets/components/edit-facet-value.tsx +1 -1
  60. package/src/app/routes/_authenticated/_facets/components/facet-bulk-actions.tsx +6 -5
  61. package/src/app/routes/_authenticated/_facets/components/facet-values-sheet.tsx +1 -1
  62. package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +1 -1
  63. package/src/app/routes/_authenticated/_facets/facets.tsx +5 -5
  64. package/src/app/routes/_authenticated/_facets/facets_.$facetId.values_.$id.tsx +7 -5
  65. package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +18 -6
  66. package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +5 -5
  67. package/src/app/routes/_authenticated/_orders/components/add-manual-payment-dialog.tsx +19 -21
  68. package/src/app/routes/_authenticated/_orders/components/customer-address-selector.tsx +1 -1
  69. package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +22 -22
  70. package/src/app/routes/_authenticated/_orders/components/fulfill-order-dialog.tsx +6 -6
  71. package/src/app/routes/_authenticated/_orders/components/fulfillment-details.tsx +15 -9
  72. package/src/app/routes/_authenticated/_orders/components/order-address.tsx +1 -1
  73. package/src/app/routes/_authenticated/_orders/components/order-detail-shared.tsx +11 -9
  74. package/src/app/routes/_authenticated/_orders/components/order-history/default-order-history-components.tsx +1 -1
  75. package/src/app/routes/_authenticated/_orders/components/order-history/order-history-container.tsx +1 -1
  76. package/src/app/routes/_authenticated/_orders/components/order-history/order-history-utils.tsx +1 -1
  77. package/src/app/routes/_authenticated/_orders/components/order-history/use-order-history.ts +1 -1
  78. package/src/app/routes/_authenticated/_orders/components/order-line-custom-fields-form.tsx +1 -1
  79. package/src/app/routes/_authenticated/_orders/components/order-modification-preview-dialog.tsx +4 -4
  80. package/src/app/routes/_authenticated/_orders/components/order-modification-summary.tsx +1 -1
  81. package/src/app/routes/_authenticated/_orders/components/order-table-totals.tsx +27 -27
  82. package/src/app/routes/_authenticated/_orders/components/order-table.tsx +2 -2
  83. package/src/app/routes/_authenticated/_orders/components/order-tax-summary.tsx +1 -1
  84. package/src/app/routes/_authenticated/_orders/components/payment-details.tsx +26 -20
  85. package/src/app/routes/_authenticated/_orders/components/seller-orders-card.tsx +3 -1
  86. package/src/app/routes/_authenticated/_orders/components/settle-refund-dialog.tsx +6 -6
  87. package/src/app/routes/_authenticated/_orders/components/shipping-method-selector.tsx +1 -1
  88. package/src/app/routes/_authenticated/_orders/components/state-transition-control.tsx +1 -1
  89. package/src/app/routes/_authenticated/_orders/components/use-transition-order-to-state.tsx +3 -2
  90. package/src/app/routes/_authenticated/_orders/orders.tsx +5 -9
  91. package/src/app/routes/_authenticated/_orders/orders_.$aggregateOrderId_.seller-orders.$sellerOrderId.tsx +1 -1
  92. package/src/app/routes/_authenticated/_orders/orders_.$id.tsx +1 -1
  93. package/src/app/routes/_authenticated/_orders/orders_.$id_.modify.tsx +4 -4
  94. package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +17 -17
  95. package/src/app/routes/_authenticated/_orders/utils/order-detail-loaders.tsx +1 -1
  96. package/src/app/routes/_authenticated/_payment-methods/payment-methods.tsx +5 -6
  97. package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +13 -6
  98. package/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx +1 -1
  99. package/src/app/routes/_authenticated/_product-variants/components/variant-price-detail.tsx +1 -1
  100. package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +10 -0
  101. package/src/app/routes/_authenticated/_product-variants/product-variants.tsx +9 -2
  102. package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +13 -6
  103. package/src/app/routes/_authenticated/_products/components/add-option-group-dialog.tsx +5 -5
  104. package/src/app/routes/_authenticated/_products/components/add-product-variant-dialog.tsx +5 -5
  105. package/src/app/routes/_authenticated/_products/components/assign-facet-values-dialog.tsx +5 -4
  106. package/src/app/routes/_authenticated/_products/components/create-product-options-dialog.tsx +9 -12
  107. package/src/app/routes/_authenticated/_products/components/create-product-variants-dialog.tsx +1 -1
  108. package/src/app/routes/_authenticated/_products/components/create-product-variants.tsx +4 -4
  109. package/src/app/routes/_authenticated/_products/components/option-groups-editor.tsx +1 -1
  110. package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +1 -1
  111. package/src/app/routes/_authenticated/_products/components/product-option-group-badge.tsx +19 -0
  112. package/src/app/routes/_authenticated/_products/components/product-option-select.tsx +3 -3
  113. package/src/app/routes/_authenticated/_products/components/product-options-table.tsx +114 -0
  114. package/src/app/routes/_authenticated/_products/product-option-groups.graphql.ts +103 -0
  115. package/src/app/routes/_authenticated/_products/products.graphql.ts +44 -32
  116. package/src/app/routes/_authenticated/_products/products.tsx +34 -5
  117. package/src/app/routes/_authenticated/_products/products_.$id.tsx +29 -12
  118. package/src/app/routes/_authenticated/_products/products_.$id_.variants.tsx +11 -11
  119. package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$id.tsx +177 -0
  120. package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$productOptionGroupId.options_.$id.tsx +208 -0
  121. package/src/app/routes/_authenticated/_profile/profile.tsx +4 -4
  122. package/src/app/routes/_authenticated/_promotions/promotions.tsx +2 -4
  123. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +16 -9
  124. package/src/app/routes/_authenticated/_roles/components/permissions-table-grid.tsx +1 -1
  125. package/src/app/routes/_authenticated/_roles/roles.tsx +3 -6
  126. package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +4 -6
  127. package/src/app/routes/_authenticated/_sellers/sellers.tsx +3 -4
  128. package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +4 -4
  129. package/src/app/routes/_authenticated/_shipping-methods/components/price-display.tsx +5 -5
  130. package/src/app/routes/_authenticated/_shipping-methods/components/shipping-method-test-result-wrapper.tsx +1 -1
  131. package/src/app/routes/_authenticated/_shipping-methods/components/test-address-form.tsx +11 -11
  132. package/src/app/routes/_authenticated/_shipping-methods/components/test-order-builder.tsx +1 -1
  133. package/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-methods-result.tsx +8 -8
  134. package/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-methods-sheet.tsx +1 -1
  135. package/src/app/routes/_authenticated/_shipping-methods/components/test-single-method-result.tsx +8 -8
  136. package/src/app/routes/_authenticated/_shipping-methods/components/test-single-shipping-method-sheet.tsx +4 -4
  137. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.tsx +2 -3
  138. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +2 -2
  139. package/src/app/routes/_authenticated/_stock-locations/stock-locations.tsx +3 -4
  140. package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +13 -6
  141. package/src/app/routes/_authenticated/_system/healthchecks.tsx +10 -4
  142. package/src/app/routes/_authenticated/_system/job-queue.tsx +10 -13
  143. package/src/app/routes/_authenticated/_system/scheduled-tasks.tsx +18 -16
  144. package/src/app/routes/_authenticated/_tax-categories/tax-categories.tsx +2 -4
  145. package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +13 -6
  146. package/src/app/routes/_authenticated/_tax-rates/tax-rates.tsx +8 -12
  147. package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +6 -4
  148. package/src/app/routes/_authenticated/_zones/components/zone-countries-sheet.tsx +4 -1
  149. package/src/app/routes/_authenticated/_zones/zones.tsx +4 -4
  150. package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +8 -5
  151. package/src/app/routes/_authenticated/index.tsx +46 -25
  152. package/src/app/styles.css +4 -0
  153. package/src/i18n/common-strings.ts +111 -0
  154. package/src/i18n/locales/ar.po +4777 -0
  155. package/src/i18n/locales/cs.po +4777 -0
  156. package/src/i18n/locales/de.po +4299 -1101
  157. package/src/i18n/locales/en.po +3857 -659
  158. package/src/i18n/locales/es.po +4777 -0
  159. package/src/i18n/locales/fa.po +4777 -0
  160. package/src/i18n/locales/fr.po +4777 -0
  161. package/src/i18n/locales/he.po +4777 -0
  162. package/src/i18n/locales/hr.po +4777 -0
  163. package/src/i18n/locales/it.po +4777 -0
  164. package/src/i18n/locales/ja.po +4777 -0
  165. package/src/i18n/locales/ko.po +4628 -0
  166. package/src/i18n/locales/nb.po +4777 -0
  167. package/src/i18n/locales/ne.po +4777 -0
  168. package/src/i18n/locales/nl.po +4628 -0
  169. package/src/i18n/locales/pl.po +4777 -0
  170. package/src/i18n/locales/pt_BR.po +4777 -0
  171. package/src/i18n/locales/pt_PT.po +4777 -0
  172. package/src/i18n/locales/ru.po +4777 -0
  173. package/src/i18n/locales/sv.po +4777 -0
  174. package/src/i18n/locales/tr.po +4777 -0
  175. package/src/i18n/locales/uk.po +4777 -0
  176. package/src/i18n/locales/zh_Hans.po +4777 -0
  177. package/src/i18n/locales/zh_Hant.po +4777 -0
  178. package/src/lib/components/data-display/json.tsx +16 -1
  179. package/src/lib/components/data-input/combination-mode-input.tsx +1 -1
  180. package/src/lib/components/data-input/custom-field-list-input.tsx +11 -7
  181. package/src/lib/components/data-input/customer-group-input.tsx +27 -33
  182. package/src/lib/components/data-input/datetime-input.tsx +40 -1
  183. package/src/lib/components/data-input/default-relation-input.tsx +5 -4
  184. package/src/lib/components/data-input/index.ts +3 -0
  185. package/src/lib/components/data-input/product-multi-selector-input.tsx +14 -14
  186. package/src/lib/components/data-input/relation-selector.tsx +1 -1
  187. package/src/lib/components/data-input/select-with-options.tsx +1 -1
  188. package/src/lib/components/data-input/slug-input.tsx +290 -0
  189. package/src/lib/components/data-table/add-filter-menu.tsx +17 -10
  190. package/src/lib/components/data-table/data-table-bulk-action-item.tsx +45 -8
  191. package/src/lib/components/data-table/data-table-bulk-actions.tsx +4 -4
  192. package/src/lib/components/data-table/data-table-column-header.tsx +13 -8
  193. package/src/lib/components/data-table/data-table-context.tsx +91 -0
  194. package/src/lib/components/data-table/data-table-faceted-filter.tsx +2 -1
  195. package/src/lib/components/data-table/data-table-filter-badge.tsx +9 -5
  196. package/src/lib/components/data-table/data-table-filter-dialog.tsx +1 -1
  197. package/src/lib/components/data-table/data-table-utils.ts +21 -4
  198. package/src/lib/components/data-table/data-table-view-options.tsx +21 -10
  199. package/src/lib/components/data-table/data-table.tsx +146 -94
  200. package/src/lib/components/data-table/filters/data-table-boolean-filter.tsx +4 -4
  201. package/src/lib/components/data-table/global-views-bar.tsx +97 -0
  202. package/src/lib/components/data-table/global-views-sheet.tsx +11 -0
  203. package/src/lib/components/data-table/human-readable-operator.tsx +1 -1
  204. package/src/lib/components/data-table/manage-global-views-button.tsx +26 -0
  205. package/src/lib/components/data-table/my-views-button.tsx +47 -0
  206. package/src/lib/components/data-table/refresh-button.tsx +12 -3
  207. package/src/lib/components/data-table/save-view-button.tsx +41 -0
  208. package/src/lib/components/data-table/save-view-dialog.tsx +113 -0
  209. package/src/lib/components/data-table/use-generated-columns.tsx +13 -8
  210. package/src/lib/components/data-table/user-views-sheet.tsx +11 -0
  211. package/src/lib/components/data-table/views-sheet.tsx +305 -0
  212. package/src/lib/components/date-range-picker.tsx +186 -0
  213. package/src/lib/components/layout/app-sidebar.tsx +3 -1
  214. package/src/lib/components/layout/channel-switcher.tsx +8 -10
  215. package/src/lib/components/layout/dev-mode-indicator.tsx +1 -1
  216. package/src/lib/components/layout/generated-breadcrumbs.tsx +10 -8
  217. package/src/lib/components/layout/language-dialog.tsx +34 -13
  218. package/src/lib/components/layout/manage-languages-dialog.tsx +1 -1
  219. package/src/lib/components/layout/nav-main.tsx +23 -13
  220. package/src/lib/components/layout/nav-user.tsx +19 -23
  221. package/src/lib/components/login/login-form.tsx +1 -1
  222. package/src/lib/components/shared/asset/asset-bulk-actions.tsx +4 -4
  223. package/src/lib/components/shared/asset/asset-focal-point-editor.tsx +1 -1
  224. package/src/lib/components/shared/asset/asset-gallery.tsx +15 -14
  225. package/src/lib/components/shared/assign-to-channel-bulk-action.tsx +11 -11
  226. package/src/lib/components/shared/assign-to-channel-dialog.tsx +6 -5
  227. package/src/lib/components/shared/channel-code-label.tsx +1 -1
  228. package/src/lib/components/shared/channel-selector.tsx +4 -4
  229. package/src/lib/components/shared/configurable-operation-multi-selector.tsx +16 -14
  230. package/src/lib/components/shared/configurable-operation-selector.tsx +1 -1
  231. package/src/lib/components/shared/confirmation-dialog.tsx +8 -8
  232. package/src/lib/components/shared/country-selector.tsx +1 -1
  233. package/src/lib/components/shared/currency-selector.tsx +4 -4
  234. package/src/lib/components/shared/custom-fields-form.tsx +8 -24
  235. package/src/lib/components/shared/customer-address-form.tsx +3 -3
  236. package/src/lib/components/shared/customer-group-selector.tsx +1 -1
  237. package/src/lib/components/shared/customer-selector.tsx +1 -1
  238. package/src/lib/components/shared/error-page.tsx +1 -1
  239. package/src/lib/components/shared/facet-value-selector.tsx +10 -10
  240. package/src/lib/components/shared/history-timeline/history-note-checkbox.tsx +1 -1
  241. package/src/lib/components/shared/history-timeline/history-note-editor.tsx +1 -1
  242. package/src/lib/components/shared/history-timeline/history-note-entry.tsx +1 -1
  243. package/src/lib/components/shared/language-selector.tsx +4 -4
  244. package/src/lib/components/shared/navigation-confirmation.tsx +1 -1
  245. package/src/lib/components/shared/paginated-list-data-table.tsx +64 -34
  246. package/src/lib/components/shared/remove-from-channel-bulk-action.tsx +6 -5
  247. package/src/lib/components/shared/rich-text-editor/image-dialog.tsx +1 -1
  248. package/src/lib/components/shared/rich-text-editor/link-dialog.tsx +1 -1
  249. package/src/lib/components/shared/rich-text-editor/responsive-toolbar.tsx +1 -1
  250. package/src/lib/components/shared/rich-text-editor/table-edit-icons.tsx +1 -1
  251. package/src/lib/components/shared/role-code-label.tsx +1 -1
  252. package/src/lib/components/shared/role-selector.tsx +4 -4
  253. package/src/lib/components/shared/seller-selector.tsx +1 -1
  254. package/src/lib/components/shared/stock-level-label.tsx +3 -5
  255. package/src/lib/components/shared/table-cell/order-table-cell-components.tsx +3 -1
  256. package/src/lib/components/shared/tax-category-selector.tsx +1 -1
  257. package/src/lib/components/shared/translatable-form-field.tsx +15 -15
  258. package/src/lib/components/shared/zone-selector.tsx +1 -1
  259. package/src/lib/components/ui/button.tsx +1 -1
  260. package/src/lib/framework/dashboard-widget/base-widget.tsx +11 -9
  261. package/src/lib/framework/dashboard-widget/latest-orders-widget/index.tsx +35 -6
  262. package/src/lib/framework/dashboard-widget/metrics-widget/index.tsx +18 -12
  263. package/src/lib/framework/dashboard-widget/metrics-widget/metrics-widget.graphql.ts +9 -3
  264. package/src/lib/framework/dashboard-widget/orders-summary/index.tsx +26 -79
  265. package/src/lib/framework/dashboard-widget/widget-filters-context.tsx +35 -0
  266. package/src/lib/framework/defaults.ts +34 -63
  267. package/src/lib/framework/document-introspection/add-custom-fields.spec.ts +319 -9
  268. package/src/lib/framework/document-introspection/add-custom-fields.ts +60 -31
  269. package/src/lib/framework/document-introspection/get-document-structure.spec.ts +1 -159
  270. package/src/lib/framework/document-introspection/include-only-selected-list-fields.spec.ts +1840 -0
  271. package/src/lib/framework/document-introspection/include-only-selected-list-fields.ts +940 -0
  272. package/src/lib/framework/document-introspection/testing-utils.ts +161 -0
  273. package/src/lib/framework/extension-api/display-component-extensions.tsx +2 -0
  274. package/src/lib/framework/extension-api/types/data-table.ts +62 -4
  275. package/src/lib/framework/extension-api/types/navigation.ts +16 -0
  276. package/src/lib/framework/form-engine/utils.ts +34 -0
  277. package/src/lib/framework/layout-engine/page-layout.tsx +36 -36
  278. package/src/lib/framework/page/detail-page.tsx +10 -10
  279. package/src/lib/framework/page/list-page.tsx +289 -4
  280. package/src/lib/framework/page/use-extended-router.tsx +101 -34
  281. package/src/lib/graphql/api.ts +6 -2
  282. package/src/lib/graphql/graphql-env.d.ts +38 -26
  283. package/src/lib/hooks/use-display-locale.ts +40 -0
  284. package/src/lib/hooks/use-dynamic-translations.ts +46 -0
  285. package/src/lib/hooks/use-extended-detail-query.ts +1 -1
  286. package/src/lib/hooks/use-extended-list-query.ts +6 -1
  287. package/src/lib/hooks/use-local-format.ts +15 -1
  288. package/src/lib/hooks/use-saved-views.ts +230 -0
  289. package/src/lib/hooks/use-ui-language-loader.ts +30 -0
  290. package/src/lib/index.ts +15 -0
  291. package/src/lib/lib/load-i18n-messages.ts +17 -0
  292. package/src/lib/lib/trans.tsx +15 -11
  293. package/src/lib/providers/i18n-provider.tsx +7 -14
  294. package/src/lib/types/saved-views.ts +39 -0
  295. package/src/lib/utils/saved-views-utils.ts +40 -0
@@ -19,7 +19,7 @@ export function registerDefaults() {
19
19
  sections: [
20
20
  {
21
21
  id: 'insights',
22
- title: 'Insights',
22
+ title: /* i18n*/ 'Insights',
23
23
  placement: 'top',
24
24
  icon: LayoutDashboardIcon,
25
25
  url: '/',
@@ -27,42 +27,42 @@ export function registerDefaults() {
27
27
  },
28
28
  {
29
29
  id: 'catalog',
30
- title: 'Catalog',
30
+ title: /* i18n*/ 'Catalog',
31
31
  icon: SquareTerminal,
32
32
  placement: 'top',
33
33
  order: 200,
34
34
  items: [
35
35
  {
36
36
  id: 'products',
37
- title: 'Products',
37
+ title: /* i18n*/ 'Products',
38
38
  url: '/products',
39
39
  order: 100,
40
40
  requiresPermission: ['ReadProduct', 'ReadCatalog'],
41
41
  },
42
42
  {
43
43
  id: 'product-variants',
44
- title: 'Product Variants',
44
+ title: /* i18n*/ 'Product Variants',
45
45
  url: '/product-variants',
46
46
  order: 200,
47
47
  requiresPermission: ['ReadProduct', 'ReadCatalog'],
48
48
  },
49
49
  {
50
50
  id: 'facets',
51
- title: 'Facets',
51
+ title: /* i18n*/ 'Facets',
52
52
  url: '/facets',
53
53
  order: 300,
54
54
  requiresPermission: ['ReadProduct', 'ReadCatalog'],
55
55
  },
56
56
  {
57
57
  id: 'collections',
58
- title: 'Collections',
58
+ title: /* i18n*/ 'Collections',
59
59
  url: '/collections',
60
60
  order: 400,
61
61
  requiresPermission: ['ReadCollection', 'ReadCatalog'],
62
62
  },
63
63
  {
64
64
  id: 'assets',
65
- title: 'Assets',
65
+ title: /* i18n*/ 'Assets',
66
66
  url: '/assets',
67
67
  order: 500,
68
68
  requiresPermission: ['ReadAsset', 'ReadCatalog'],
@@ -71,14 +71,14 @@ export function registerDefaults() {
71
71
  },
72
72
  {
73
73
  id: 'sales',
74
- title: 'Sales',
74
+ title: /* i18n*/ 'Sales',
75
75
  icon: ShoppingCart,
76
76
  placement: 'top',
77
77
  order: 300,
78
78
  items: [
79
79
  {
80
80
  id: 'orders',
81
- title: 'Orders',
81
+ title: /* i18n*/ 'Orders',
82
82
  url: '/orders',
83
83
  order: 100,
84
84
  requiresPermission: ['ReadOrder'],
@@ -87,21 +87,21 @@ export function registerDefaults() {
87
87
  },
88
88
  {
89
89
  id: 'customers',
90
- title: 'Customers',
90
+ title: /* i18n*/ 'Customers',
91
91
  icon: Users,
92
92
  placement: 'top',
93
93
  order: 400,
94
94
  items: [
95
95
  {
96
96
  id: 'customers',
97
- title: 'Customers',
97
+ title: /* i18n*/ 'Customers',
98
98
  url: '/customers',
99
99
  order: 100,
100
100
  requiresPermission: ['ReadCustomer'],
101
101
  },
102
102
  {
103
103
  id: 'customer-groups',
104
- title: 'Customer Groups',
104
+ title: /* i18n*/ 'Customer Groups',
105
105
  url: '/customer-groups',
106
106
  order: 200,
107
107
  requiresPermission: ['ReadCustomerGroup'],
@@ -110,14 +110,14 @@ export function registerDefaults() {
110
110
  },
111
111
  {
112
112
  id: 'marketing',
113
- title: 'Marketing',
113
+ title: /* i18n*/ 'Marketing',
114
114
  icon: Mail,
115
115
  placement: 'top',
116
116
  order: 500,
117
117
  items: [
118
118
  {
119
119
  id: 'promotions',
120
- title: 'Promotions',
120
+ title: /* i18n*/ 'Promotions',
121
121
  url: '/promotions',
122
122
  order: 100,
123
123
  requiresPermission: ['ReadPromotion'],
@@ -126,28 +126,28 @@ export function registerDefaults() {
126
126
  },
127
127
  {
128
128
  id: 'system',
129
- title: 'System',
129
+ title: /* i18n*/ 'System',
130
130
  icon: Terminal,
131
131
  placement: 'bottom',
132
132
  order: 200,
133
133
  items: [
134
134
  {
135
135
  id: 'job-queue',
136
- title: 'Job Queue',
136
+ title: /* i18n*/ 'Job Queue',
137
137
  url: '/job-queue',
138
138
  order: 100,
139
139
  requiresPermission: ['ReadSystem'],
140
140
  },
141
141
  {
142
142
  id: 'healthchecks',
143
- title: 'Healthchecks',
143
+ title: /* i18n*/ 'Healthchecks',
144
144
  url: '/healthchecks',
145
145
  order: 200,
146
146
  requiresPermission: ['ReadSystem'],
147
147
  },
148
148
  {
149
149
  id: 'scheduled-tasks',
150
- title: 'Scheduled Tasks',
150
+ title: /* i18n*/ 'Scheduled Tasks',
151
151
  url: '/scheduled-tasks',
152
152
  order: 300,
153
153
  requiresPermission: ['ReadSystem'],
@@ -156,91 +156,91 @@ export function registerDefaults() {
156
156
  },
157
157
  {
158
158
  id: 'settings',
159
- title: 'Settings',
159
+ title: /* i18n*/ 'Settings',
160
160
  icon: Settings2,
161
161
  placement: 'bottom',
162
162
  order: 100,
163
163
  items: [
164
164
  {
165
165
  id: 'sellers',
166
- title: 'Sellers',
166
+ title: /* i18n*/ 'Sellers',
167
167
  url: '/sellers',
168
168
  order: 100,
169
169
  requiresPermission: ['ReadSeller'],
170
170
  },
171
171
  {
172
172
  id: 'channels',
173
- title: 'Channels',
173
+ title: /* i18n*/ 'Channels',
174
174
  url: '/channels',
175
175
  order: 200,
176
176
  requiresPermission: ['ReadChannel'],
177
177
  },
178
178
  {
179
179
  id: 'stock-locations',
180
- title: 'Stock Locations',
180
+ title: /* i18n*/ 'Stock Locations',
181
181
  url: '/stock-locations',
182
182
  order: 300,
183
183
  requiresPermission: ['ReadStockLocation'],
184
184
  },
185
185
  {
186
186
  id: 'administrators',
187
- title: 'Administrators',
187
+ title: /* i18n*/ 'Administrators',
188
188
  url: '/administrators',
189
189
  order: 400,
190
190
  requiresPermission: ['ReadAdministrator'],
191
191
  },
192
192
  {
193
193
  id: 'roles',
194
- title: 'Roles',
194
+ title: /* i18n*/ 'Roles',
195
195
  url: '/roles',
196
196
  order: 500,
197
197
  requiresPermission: ['ReadAdministrator'],
198
198
  },
199
199
  {
200
200
  id: 'shipping-methods',
201
- title: 'Shipping Methods',
201
+ title: /* i18n*/ 'Shipping Methods',
202
202
  url: '/shipping-methods',
203
203
  order: 600,
204
204
  requiresPermission: ['ReadShippingMethod'],
205
205
  },
206
206
  {
207
207
  id: 'payment-methods',
208
- title: 'Payment Methods',
208
+ title: /* i18n*/ 'Payment Methods',
209
209
  url: '/payment-methods',
210
210
  order: 700,
211
211
  requiresPermission: ['ReadPaymentMethod'],
212
212
  },
213
213
  {
214
214
  id: 'tax-categories',
215
- title: 'Tax Categories',
215
+ title: /* i18n*/ 'Tax Categories',
216
216
  url: '/tax-categories',
217
217
  order: 800,
218
218
  requiresPermission: ['ReadTaxCategory'],
219
219
  },
220
220
  {
221
221
  id: 'tax-rates',
222
- title: 'Tax Rates',
222
+ title: /* i18n*/ 'Tax Rates',
223
223
  url: '/tax-rates',
224
224
  order: 900,
225
225
  requiresPermission: ['ReadTaxRate'],
226
226
  },
227
227
  {
228
228
  id: 'countries',
229
- title: 'Countries',
229
+ title: /* i18n*/ 'Countries',
230
230
  url: '/countries',
231
231
  order: 1000,
232
232
  requiresPermission: ['ReadCountry'],
233
233
  },
234
234
  {
235
235
  id: 'zones',
236
- title: 'Zones',
236
+ title: /* i18n*/ 'Zones',
237
237
  url: '/zones',
238
238
  order: 1100,
239
239
  requiresPermission: ['ReadZone'],
240
240
  },
241
241
  {
242
242
  id: 'global-settings',
243
- title: 'Global Settings',
243
+ title: /* i18n*/ 'Global Settings',
244
244
  url: '/global-settings',
245
245
  order: 1200,
246
246
  requiresPermission: ['UpdateGlobalSettings'],
@@ -252,7 +252,7 @@ export function registerDefaults() {
252
252
 
253
253
  registerDashboardWidget({
254
254
  id: 'metrics-widget',
255
- name: 'Metrics Widget',
255
+ name: /* i18n*/ 'Metrics Widget',
256
256
  component: MetricsWidget,
257
257
  defaultSize: { w: 12, h: 6, x: 0, y: 0 },
258
258
  minSize: { w: 6, h: 4 },
@@ -260,44 +260,15 @@ export function registerDefaults() {
260
260
 
261
261
  registerDashboardWidget({
262
262
  id: 'latest-orders-widget',
263
- name: 'Latest Orders Widget',
263
+ name: /* i18n*/ 'Latest Orders Widget',
264
264
  component: LatestOrdersWidget,
265
265
  defaultSize: { w: 6, h: 7, x: 0, y: 0 },
266
266
  });
267
267
 
268
268
  registerDashboardWidget({
269
269
  id: 'orders-summary-widget',
270
- name: 'Orders Summary Widget',
270
+ name: /* i18n*/ 'Orders Summary Widget',
271
271
  component: OrdersSummaryWidget,
272
272
  defaultSize: { w: 6, h: 3, x: 6, y: 0 },
273
273
  });
274
-
275
- // registerAlert<boolean>({
276
- // id: 'test-alert',
277
- // title: data => `Test Alert ${String(data)}`,
278
- // description: 'This is a test alert',
279
- // severity: 'info',
280
- // check: () => Promise.resolve(true),
281
- // actions: [
282
- // {
283
- // label: 'Test Action',
284
- // onClick: () => console.log('Test Action'),
285
- // },
286
- // ],
287
- // });
288
-
289
- // registerAlert<boolean>({
290
- // id: 'test-alert-2',
291
- // title: 'Test Alert 2',
292
- // description: 'This is a test alert 2',
293
- // severity: 'info',
294
- // check: () => Promise.resolve(true),
295
- // shouldShow: data => data === true,
296
- // actions: [
297
- // {
298
- // label: 'Test Action',
299
- // onClick: () => console.log('Test Action'),
300
- // },
301
- // ],
302
- // });
303
274
  }
@@ -1,14 +1,7 @@
1
1
  import { CustomFieldConfig, CustomFields } from '@vendure/common/lib/generated-types';
2
2
  import { graphql } from 'gql.tada';
3
- import {
4
- DocumentNode,
5
- FieldNode,
6
- FragmentDefinitionNode,
7
- Kind,
8
- OperationDefinitionNode,
9
- print,
10
- } from 'graphql';
11
- import { describe, it, expect, beforeEach } from 'vitest';
3
+ import { DocumentNode, FieldNode, FragmentDefinitionNode, Kind, print } from 'graphql';
4
+ import { beforeEach, describe, expect, it } from 'vitest';
12
5
 
13
6
  import { addCustomFields } from './add-custom-fields.js';
14
7
 
@@ -239,4 +232,321 @@ describe('addCustomFields()', () => {
239
232
  addsCustomFieldsToType('Address', addressFragment);
240
233
  });
241
234
  });
235
+
236
+ describe('Nested entity handling', () => {
237
+ it('User example: Should not add custom fields to Asset fragment used in nested featuredAsset', () => {
238
+ const assetFragment = graphql(`
239
+ fragment Asset on Asset {
240
+ id
241
+ createdAt
242
+ updatedAt
243
+ name
244
+ fileSize
245
+ mimeType
246
+ type
247
+ preview
248
+ source
249
+ width
250
+ height
251
+ focalPoint {
252
+ x
253
+ y
254
+ }
255
+ }
256
+ `);
257
+
258
+ const documentNode = graphql(
259
+ `
260
+ query CollectionList($options: CollectionListOptions) {
261
+ collections(options: $options) {
262
+ items {
263
+ id
264
+ createdAt
265
+ updatedAt
266
+ featuredAsset {
267
+ ...Asset
268
+ }
269
+ name
270
+ slug
271
+ breadcrumbs {
272
+ id
273
+ name
274
+ slug
275
+ }
276
+ children {
277
+ id
278
+ name
279
+ }
280
+ position
281
+ isPrivate
282
+ parentId
283
+ productVariants {
284
+ totalItems
285
+ }
286
+ }
287
+ totalItems
288
+ }
289
+ }
290
+ `,
291
+ [assetFragment],
292
+ );
293
+
294
+ const customFieldsConfig = new Map<string, CustomFieldConfig[]>();
295
+ customFieldsConfig.set('Collection', [
296
+ { name: 'featuredProducts', type: 'relation', list: true, scalarFields: ['id', 'name'] },
297
+ { name: 'alternativeAsset', type: 'relation', list: false, scalarFields: ['id', 'name'] },
298
+ ]);
299
+ customFieldsConfig.set('Asset', [
300
+ { name: 'assetCustomField1', type: 'string', list: false },
301
+ { name: 'assetCustomField2', type: 'string', list: false },
302
+ { name: 'assetCustomField3', type: 'string', list: false },
303
+ ]);
304
+
305
+ const result = addCustomFields(documentNode, { customFieldsMap: customFieldsConfig });
306
+ const printed = print(result);
307
+
308
+ // Should add customFields ONLY to Collection items (top-level entity)
309
+ expect(printed).toContain('customFields {');
310
+ expect(printed).toContain('featuredProducts {');
311
+ expect(printed).toContain('alternativeAsset {');
312
+
313
+ // Should NOT add customFields to Asset fragment (only used in nested context)
314
+ const fragmentMatch = printed.match(/fragment Asset on Asset\s*\{[^}]*\}/s);
315
+ expect(fragmentMatch).toBeTruthy();
316
+ expect(fragmentMatch![0]).not.toContain('customFields');
317
+ expect(fragmentMatch![0]).not.toContain('assetCustomField1');
318
+
319
+ // Should NOT add customFields to children (nested Collection entities)
320
+ const childrenMatch = printed.match(/children\s*\{[^}]+\}/s);
321
+ expect(childrenMatch).toBeTruthy();
322
+ expect(childrenMatch![0]).not.toContain('customFields');
323
+
324
+ // Should NOT add customFields to breadcrumbs
325
+ const breadcrumbsMatch = printed.match(/breadcrumbs\s*\{[^}]+\}/s);
326
+ expect(breadcrumbsMatch).toBeTruthy();
327
+ expect(breadcrumbsMatch![0]).not.toContain('customFields');
328
+ });
329
+
330
+ it('Should only add custom fields to top-level entity, not nested related entities', () => {
331
+ const documentNode = graphql(`
332
+ query CollectionList($options: CollectionListOptions) {
333
+ collections(options: $options) {
334
+ items {
335
+ id
336
+ name
337
+ slug
338
+ featuredAsset {
339
+ id
340
+ preview
341
+ }
342
+ children {
343
+ id
344
+ name
345
+ slug
346
+ }
347
+ breadcrumbs {
348
+ id
349
+ name
350
+ slug
351
+ }
352
+ }
353
+ totalItems
354
+ }
355
+ }
356
+ `);
357
+
358
+ const customFieldsConfig = new Map<string, CustomFieldConfig[]>();
359
+ customFieldsConfig.set('Collection', [
360
+ { name: 'featuredProducts', type: 'relation', list: true, scalarFields: ['id', 'name'] },
361
+ { name: 'alternativeAsset', type: 'relation', list: false, scalarFields: ['id', 'name'] },
362
+ ]);
363
+ customFieldsConfig.set('Asset', [
364
+ { name: 'assetCustomField1', type: 'string', list: false },
365
+ { name: 'assetCustomField2', type: 'string', list: false },
366
+ ]);
367
+
368
+ const result = addCustomFields(documentNode, { customFieldsMap: customFieldsConfig });
369
+ const printed = print(result);
370
+
371
+ // Should add customFields to top-level Collection (items)
372
+ expect(printed).toContain('customFields {');
373
+ expect(printed).toContain('featuredProducts {');
374
+ expect(printed).toContain('alternativeAsset {');
375
+
376
+ // Should NOT add customFields to nested Collection entities (children, breadcrumbs)
377
+ const childrenMatch = printed.match(/children\s*\{[^}]+\}/s);
378
+ const breadcrumbsMatch = printed.match(/breadcrumbs\s*\{[^}]+\}/s);
379
+
380
+ expect(childrenMatch).toBeTruthy();
381
+ expect(breadcrumbsMatch).toBeTruthy();
382
+ expect(childrenMatch![0]).not.toContain('customFields');
383
+ expect(breadcrumbsMatch![0]).not.toContain('customFields');
384
+
385
+ // Should NOT add customFields to nested Asset entity (featuredAsset)
386
+ const featuredAssetMatch = printed.match(/featuredAsset\s*\{[^}]+\}/s);
387
+ expect(featuredAssetMatch).toBeTruthy();
388
+ expect(featuredAssetMatch![0]).not.toContain('customFields');
389
+ expect(featuredAssetMatch![0]).not.toContain('assetCustomField1');
390
+ });
391
+
392
+ it('Should NOT add custom fields to fragments that are only used in nested contexts', () => {
393
+ const assetFragment = graphql(`
394
+ fragment Asset on Asset {
395
+ id
396
+ name
397
+ preview
398
+ }
399
+ `);
400
+
401
+ const documentNode = graphql(
402
+ `
403
+ query ProductList($options: ProductListOptions) {
404
+ products(options: $options) {
405
+ items {
406
+ id
407
+ name
408
+ featuredAsset {
409
+ ...Asset
410
+ }
411
+ variants {
412
+ id
413
+ name
414
+ assets {
415
+ ...Asset
416
+ }
417
+ }
418
+ }
419
+ totalItems
420
+ }
421
+ }
422
+ `,
423
+ [assetFragment],
424
+ );
425
+
426
+ const customFieldsConfig = new Map<string, CustomFieldConfig[]>();
427
+ customFieldsConfig.set('Product', [{ name: 'productCustomField', type: 'string', list: false }]);
428
+ customFieldsConfig.set('Asset', [{ name: 'assetCustomField', type: 'string', list: false }]);
429
+ customFieldsConfig.set('ProductVariant', [
430
+ { name: 'variantCustomField', type: 'string', list: false },
431
+ ]);
432
+
433
+ const result = addCustomFields(documentNode, { customFieldsMap: customFieldsConfig });
434
+ const printed = print(result);
435
+
436
+ // Should add customFields to Product (top-level query entity)
437
+ expect(printed).toContain('customFields {');
438
+ expect(printed).toContain('productCustomField');
439
+
440
+ // Should NOT add customFields to Asset fragment (only used in nested contexts)
441
+ expect(printed).not.toMatch(/fragment Asset on Asset\s*\{[^}]*customFields/s);
442
+
443
+ // Should NOT add customFields to nested ProductVariant entities
444
+ const variantsMatch = printed.match(/variants\s*\{[^}]+\}/s);
445
+ expect(variantsMatch).toBeTruthy();
446
+ expect(variantsMatch![0]).not.toContain('customFields');
447
+ expect(variantsMatch![0]).not.toContain('variantCustomField');
448
+ });
449
+
450
+ it('Should add custom fields to fragments used at top level', () => {
451
+ const productFragment = graphql(`
452
+ fragment ProductDetails on Product {
453
+ id
454
+ name
455
+ slug
456
+ }
457
+ `);
458
+
459
+ const documentNode = graphql(
460
+ `
461
+ query ProductList($options: ProductListOptions) {
462
+ products(options: $options) {
463
+ items {
464
+ ...ProductDetails
465
+ featuredAsset {
466
+ id
467
+ preview
468
+ }
469
+ }
470
+ totalItems
471
+ }
472
+ }
473
+ `,
474
+ [productFragment],
475
+ );
476
+
477
+ const customFieldsConfig = new Map<string, CustomFieldConfig[]>();
478
+ customFieldsConfig.set('Product', [{ name: 'productCustomField', type: 'string', list: false }]);
479
+ customFieldsConfig.set('Asset', [{ name: 'assetCustomField', type: 'string', list: false }]);
480
+
481
+ const result = addCustomFields(documentNode, { customFieldsMap: customFieldsConfig });
482
+ const printed = print(result);
483
+
484
+ // Should add customFields to ProductDetails fragment (used at top level in items)
485
+ expect(printed).toContain('fragment ProductDetails on Product');
486
+ expect(printed).toContain('productCustomField');
487
+
488
+ // Should NOT add customFields to featuredAsset (nested entity)
489
+ const featuredAssetMatch = printed.match(/featuredAsset\s*\{[^}]+\}/s);
490
+ expect(featuredAssetMatch).toBeTruthy();
491
+ expect(featuredAssetMatch![0]).not.toContain('customFields');
492
+ });
493
+
494
+ it('Should handle complex nested structure with multiple entity types', () => {
495
+ const documentNode = graphql(`
496
+ query ComplexQuery {
497
+ orders {
498
+ items {
499
+ id
500
+ code
501
+ customer {
502
+ id
503
+ firstName
504
+ addresses {
505
+ id
506
+ streetLine1
507
+ country {
508
+ id
509
+ name
510
+ }
511
+ }
512
+ }
513
+ lines {
514
+ id
515
+ productVariant {
516
+ id
517
+ name
518
+ product {
519
+ id
520
+ name
521
+ }
522
+ }
523
+ }
524
+ }
525
+ }
526
+ }
527
+ `);
528
+
529
+ const customFieldsConfig = new Map<string, CustomFieldConfig[]>();
530
+ customFieldsConfig.set('Order', [{ name: 'orderCustomField', type: 'string', list: false }]);
531
+ customFieldsConfig.set('Customer', [
532
+ { name: 'customerCustomField', type: 'string', list: false },
533
+ ]);
534
+ customFieldsConfig.set('Address', [{ name: 'addressCustomField', type: 'string', list: false }]);
535
+ customFieldsConfig.set('Product', [{ name: 'productCustomField', type: 'string', list: false }]);
536
+
537
+ const result = addCustomFields(documentNode, { customFieldsMap: customFieldsConfig });
538
+ const printed = print(result);
539
+
540
+ // Should only add customFields to top-level Order entity
541
+ expect(printed).toContain('customFields {');
542
+ expect(printed).toContain('orderCustomField');
543
+
544
+ // Should NOT add customFields to any nested entities
545
+ expect(printed).not.toMatch(/customer\s*\{[^}]*customFields/s);
546
+ expect(printed).not.toMatch(/addresses\s*\{[^}]*customFields/s);
547
+ expect(printed).not.toMatch(/country\s*\{[^}]*customFields/s);
548
+ expect(printed).not.toMatch(/productVariant\s*\{[^}]*customFields/s);
549
+ expect(printed).not.toMatch(/product\s*\{[^}]*customFields/s);
550
+ });
551
+ });
242
552
  });