@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
package/README.md CHANGED
@@ -110,3 +110,7 @@ when developing dashboard extensions.
110
110
  ## Testing
111
111
 
112
112
  Run `npm run test` to run tests once, or `npx vitest` to run tests in watch mode
113
+
114
+ ## Translations
115
+
116
+ See [./scripts/translate/README.md](./scripts/translate/README.md)
@@ -6,33 +6,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.adminApiExtensions = void 0;
7
7
  const graphql_tag_1 = __importDefault(require("graphql-tag"));
8
8
  exports.adminApiExtensions = (0, graphql_tag_1.default) `
9
- type MetricSummary {
10
- interval: MetricInterval!
11
- type: MetricType!
9
+ type DashboardMetricSummary {
10
+ type: DashboardMetricType!
12
11
  title: String!
13
- entries: [MetricSummaryEntry!]!
12
+ entries: [DashboardMetricSummaryEntry!]!
14
13
  }
15
- enum MetricInterval {
16
- Daily
17
- }
18
- enum MetricType {
14
+ enum DashboardMetricType {
19
15
  OrderCount
20
16
  OrderTotal
21
17
  AverageOrderValue
22
18
  }
23
- type MetricSummaryEntry {
19
+ type DashboardMetricSummaryEntry {
24
20
  label: String!
25
21
  value: Float!
26
22
  }
27
- input MetricSummaryInput {
28
- interval: MetricInterval!
29
- types: [MetricType!]!
23
+ input DashboardMetricSummaryInput {
24
+ types: [DashboardMetricType!]!
30
25
  refresh: Boolean
26
+ startDate: DateTime!
27
+ endDate: DateTime!
31
28
  }
32
29
  extend type Query {
33
30
  """
34
- Get metrics for the given interval and metric types.
31
+ Get metrics for the given date range and metric types.
35
32
  """
36
- metricSummary(input: MetricSummaryInput): [MetricSummary!]!
33
+ dashboardMetricSummary(input: DashboardMetricSummaryInput): [DashboardMetricSummary!]!
37
34
  }
38
35
  `;
@@ -1,8 +1,8 @@
1
1
  import { RequestContext } from '@vendure/core';
2
2
  import { MetricsService } from '../service/metrics.service.js';
3
- import { MetricSummary, MetricSummaryInput } from '../types.js';
3
+ import { DashboardMetricSummary, DashboardMetricSummaryInput } from '../types.js';
4
4
  export declare class MetricsResolver {
5
5
  private service;
6
6
  constructor(service: MetricsService);
7
- metricSummary(ctx: RequestContext, input: MetricSummaryInput): Promise<MetricSummary[]>;
7
+ dashboardMetricSummary(ctx: RequestContext, input: DashboardMetricSummaryInput): Promise<DashboardMetricSummary[]>;
8
8
  }
@@ -20,7 +20,7 @@ let MetricsResolver = class MetricsResolver {
20
20
  constructor(service) {
21
21
  this.service = service;
22
22
  }
23
- async metricSummary(ctx, input) {
23
+ async dashboardMetricSummary(ctx, input) {
24
24
  return this.service.getMetrics(ctx, input);
25
25
  }
26
26
  };
@@ -33,7 +33,7 @@ __decorate([
33
33
  __metadata("design:type", Function),
34
34
  __metadata("design:paramtypes", [core_1.RequestContext, Object]),
35
35
  __metadata("design:returntype", Promise)
36
- ], MetricsResolver.prototype, "metricSummary", null);
36
+ ], MetricsResolver.prototype, "dashboardMetricSummary", null);
37
37
  exports.MetricsResolver = MetricsResolver = __decorate([
38
38
  (0, graphql_1.Resolver)(),
39
39
  __metadata("design:paramtypes", [metrics_service_js_1.MetricsService])
@@ -1,6 +1,6 @@
1
1
  import { RequestContext } from '@vendure/core';
2
2
  import { MetricData } from '../service/metrics.service.js';
3
- import { MetricInterval, MetricSummaryEntry, MetricType } from '../types.js';
3
+ import { DashboardMetricSummaryEntry, DashboardMetricType } from '../types.js';
4
4
  /**
5
5
  * Calculate your metric data based on the given input.
6
6
  * Be careful with heavy queries and calculations,
@@ -8,32 +8,32 @@ import { MetricInterval, MetricSummaryEntry, MetricType } from '../types.js';
8
8
  *
9
9
  */
10
10
  export interface MetricCalculation {
11
- type: MetricType;
11
+ type: DashboardMetricType;
12
12
  getTitle(ctx: RequestContext): string;
13
- calculateEntry(ctx: RequestContext, interval: MetricInterval, data: MetricData): MetricSummaryEntry;
13
+ calculateEntry(ctx: RequestContext, data: MetricData): DashboardMetricSummaryEntry;
14
14
  }
15
15
  export declare function getMonthName(monthNr: number): string;
16
16
  /**
17
17
  * Calculates the average order value per month/week
18
18
  */
19
19
  export declare class AverageOrderValueMetric implements MetricCalculation {
20
- readonly type = MetricType.AverageOrderValue;
20
+ readonly type = DashboardMetricType.AverageOrderValue;
21
21
  getTitle(ctx: RequestContext): string;
22
- calculateEntry(ctx: RequestContext, interval: MetricInterval, data: MetricData): MetricSummaryEntry;
22
+ calculateEntry(ctx: RequestContext, data: MetricData): DashboardMetricSummaryEntry;
23
23
  }
24
24
  /**
25
25
  * Calculates number of orders
26
26
  */
27
27
  export declare class OrderCountMetric implements MetricCalculation {
28
- readonly type = MetricType.OrderCount;
28
+ readonly type = DashboardMetricType.OrderCount;
29
29
  getTitle(ctx: RequestContext): string;
30
- calculateEntry(ctx: RequestContext, interval: MetricInterval, data: MetricData): MetricSummaryEntry;
30
+ calculateEntry(ctx: RequestContext, data: MetricData): DashboardMetricSummaryEntry;
31
31
  }
32
32
  /**
33
33
  * Calculates order total
34
34
  */
35
35
  export declare class OrderTotalMetric implements MetricCalculation {
36
- readonly type = MetricType.OrderTotal;
36
+ readonly type = DashboardMetricType.OrderTotal;
37
37
  getTitle(ctx: RequestContext): string;
38
- calculateEntry(ctx: RequestContext, interval: MetricInterval, data: MetricData): MetricSummaryEntry;
38
+ calculateEntry(ctx: RequestContext, data: MetricData): DashboardMetricSummaryEntry;
39
39
  }
@@ -12,12 +12,12 @@ function getMonthName(monthNr) {
12
12
  */
13
13
  class AverageOrderValueMetric {
14
14
  constructor() {
15
- this.type = types_js_1.MetricType.AverageOrderValue;
15
+ this.type = types_js_1.DashboardMetricType.AverageOrderValue;
16
16
  }
17
17
  getTitle(ctx) {
18
18
  return 'average-order-value';
19
19
  }
20
- calculateEntry(ctx, interval, data) {
20
+ calculateEntry(ctx, data) {
21
21
  const label = data.date.toISOString();
22
22
  if (!data.orders.length) {
23
23
  return {
@@ -39,12 +39,12 @@ exports.AverageOrderValueMetric = AverageOrderValueMetric;
39
39
  */
40
40
  class OrderCountMetric {
41
41
  constructor() {
42
- this.type = types_js_1.MetricType.OrderCount;
42
+ this.type = types_js_1.DashboardMetricType.OrderCount;
43
43
  }
44
44
  getTitle(ctx) {
45
45
  return 'order-count';
46
46
  }
47
- calculateEntry(ctx, interval, data) {
47
+ calculateEntry(ctx, data) {
48
48
  const label = data.date.toISOString();
49
49
  return {
50
50
  label,
@@ -58,12 +58,12 @@ exports.OrderCountMetric = OrderCountMetric;
58
58
  */
59
59
  class OrderTotalMetric {
60
60
  constructor() {
61
- this.type = types_js_1.MetricType.OrderTotal;
61
+ this.type = types_js_1.DashboardMetricType.OrderTotal;
62
62
  }
63
63
  getTitle(ctx) {
64
64
  return 'order-totals';
65
65
  }
66
- calculateEntry(ctx, interval, data) {
66
+ calculateEntry(ctx, data) {
67
67
  const label = data.date.toISOString();
68
68
  return {
69
69
  label,
@@ -1,6 +1,8 @@
1
+ import { RwPermissionDefinition } from '@vendure/core';
1
2
  export declare const DEFAULT_APP_PATH: string;
2
3
  export declare const loggerCtx = "DashboardPlugin";
3
4
  export declare const defaultLanguage = "en";
4
5
  export declare const defaultLocale: undefined;
5
6
  export declare const defaultAvailableLanguages: string[];
6
7
  export declare const defaultAvailableLocales: string[];
8
+ export declare const manageDashboardGlobalViews: RwPermissionDefinition;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.defaultAvailableLocales = exports.defaultAvailableLanguages = exports.defaultLocale = exports.defaultLanguage = exports.loggerCtx = exports.DEFAULT_APP_PATH = void 0;
3
+ exports.manageDashboardGlobalViews = exports.defaultAvailableLocales = exports.defaultAvailableLanguages = exports.defaultLocale = exports.defaultLanguage = exports.loggerCtx = exports.DEFAULT_APP_PATH = void 0;
4
+ const core_1 = require("@vendure/core");
4
5
  const path_1 = require("path");
5
6
  exports.DEFAULT_APP_PATH = (0, path_1.join)(__dirname, 'dist');
6
7
  exports.loggerCtx = 'DashboardPlugin';
@@ -8,3 +9,4 @@ exports.defaultLanguage = 'en';
8
9
  exports.defaultLocale = undefined;
9
10
  exports.defaultAvailableLanguages = ['en', 'de', 'es', 'cs', 'zh_Hans', 'pt_BR', 'pt_PT', 'zh_Hant'];
10
11
  exports.defaultAvailableLocales = ['en-US', 'de-DE', 'es-ES', 'zh-CN', 'zh-TW', 'pt-BR', 'pt-PT'];
12
+ exports.manageDashboardGlobalViews = new core_1.RwPermissionDefinition('DashboardGlobalViews');
@@ -154,11 +154,24 @@ exports.DashboardPlugin = DashboardPlugin = DashboardPlugin_1 = __decorate([
154
154
  },
155
155
  providers: [metrics_service_js_1.MetricsService],
156
156
  configuration: config => {
157
+ config.authOptions.customPermissions.push(constants_js_1.manageDashboardGlobalViews);
157
158
  config.settingsStoreFields['vendure.dashboard'] = [
158
159
  {
159
160
  name: 'userSettings',
160
161
  scope: core_1.SettingsStoreScopes.user,
161
162
  },
163
+ {
164
+ name: 'globalSavedViews',
165
+ scope: core_1.SettingsStoreScopes.global,
166
+ requiresPermission: {
167
+ read: constants_js_1.manageDashboardGlobalViews.Read,
168
+ write: constants_js_1.manageDashboardGlobalViews.Write,
169
+ },
170
+ },
171
+ {
172
+ name: 'userSavedViews',
173
+ scope: core_1.SettingsStoreScopes.user,
174
+ },
162
175
  ];
163
176
  return config;
164
177
  },
@@ -1,6 +1,6 @@
1
1
  import { CacheService, Order, RequestContext, TransactionalConnection } from '@vendure/core';
2
2
  import { MetricCalculation } from '../config/metrics-strategies.js';
3
- import { MetricInterval, MetricSummary, MetricSummaryInput } from '../types.js';
3
+ import { DashboardMetricSummary, DashboardMetricSummaryInput } from '../types.js';
4
4
  export type MetricData = {
5
5
  date: Date;
6
6
  orders: Order[];
@@ -10,6 +10,6 @@ export declare class MetricsService {
10
10
  private cacheService;
11
11
  metricCalculations: MetricCalculation[];
12
12
  constructor(connection: TransactionalConnection, cacheService: CacheService);
13
- getMetrics(ctx: RequestContext, { interval, types, refresh }: MetricSummaryInput): Promise<MetricSummary[]>;
14
- loadData(ctx: RequestContext, interval: MetricInterval, endDate: Date): Promise<Map<number, MetricData>>;
13
+ getMetrics(ctx: RequestContext, { types, refresh, startDate, endDate }: DashboardMetricSummaryInput): Promise<DashboardMetricSummary[]>;
14
+ loadData(ctx: RequestContext, startDate: Date, endDate: Date): Promise<Map<string, MetricData>>;
15
15
  }
@@ -11,13 +11,11 @@ var __metadata = (this && this.__metadata) || function (k, v) {
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.MetricsService = void 0;
13
13
  const common_1 = require("@nestjs/common");
14
- const shared_utils_1 = require("@vendure/common/lib/shared-utils");
15
14
  const core_1 = require("@vendure/core");
16
15
  const crypto_1 = require("crypto");
17
16
  const date_fns_1 = require("date-fns");
18
17
  const metrics_strategies_js_1 = require("../config/metrics-strategies.js");
19
18
  const constants_js_1 = require("../constants.js");
20
- const types_js_1 = require("../types.js");
21
19
  let MetricsService = class MetricsService {
22
20
  constructor(connection, cacheService) {
23
21
  this.connection = connection;
@@ -28,15 +26,15 @@ let MetricsService = class MetricsService {
28
26
  new metrics_strategies_js_1.OrderTotalMetric(),
29
27
  ];
30
28
  }
31
- async getMetrics(ctx, { interval, types, refresh }) {
32
- // Set 23:59:59.999 as endDate
33
- const endDate = (0, date_fns_1.endOfDay)(new Date());
29
+ async getMetrics(ctx, { types, refresh, startDate, endDate }) {
30
+ const calculatedStartDate = (0, date_fns_1.startOfDay)(new Date(startDate));
31
+ const calculatedEndDate = (0, date_fns_1.endOfDay)(new Date(endDate));
34
32
  // Check if we have cached result
35
33
  const hash = (0, crypto_1.createHash)('sha1')
36
34
  .update(JSON.stringify({
37
- endDate,
35
+ startDate: calculatedStartDate,
36
+ endDate: calculatedEndDate,
38
37
  types: types.sort(),
39
- interval,
40
38
  channel: ctx.channel.token,
41
39
  }))
42
40
  .digest('base64');
@@ -47,22 +45,21 @@ let MetricsService = class MetricsService {
47
45
  return cachedMetricList;
48
46
  }
49
47
  // No cache, calculating new metrics
50
- core_1.Logger.verbose(`No cache hit, calculating ${interval} metrics until ${endDate.toISOString()} for channel ${ctx.channel.token} for all orders`, constants_js_1.loggerCtx);
51
- const data = await this.loadData(ctx, interval, endDate);
48
+ core_1.Logger.verbose(`No cache hit, calculating metrics from ${calculatedStartDate.toISOString()} to ${calculatedEndDate.toISOString()} for channel ${ctx.channel.token} for all orders`, constants_js_1.loggerCtx);
49
+ const data = await this.loadData(ctx, calculatedStartDate, calculatedEndDate);
52
50
  const metrics = [];
53
51
  for (const type of types) {
54
52
  const metric = this.metricCalculations.find(m => m.type === type);
55
53
  if (!metric) {
56
54
  continue;
57
55
  }
58
- // Calculate entry (month or week)
56
+ // Calculate entries for each day
59
57
  const entries = [];
60
- data.forEach(dataPerTick => {
61
- entries.push(metric.calculateEntry(ctx, interval, dataPerTick));
58
+ data.forEach(dataPerDay => {
59
+ entries.push(metric.calculateEntry(ctx, dataPerDay));
62
60
  });
63
61
  // Create metric with calculated entries
64
62
  metrics.push({
65
- interval,
66
63
  title: metric.getTitle(ctx),
67
64
  type: metric.type,
68
65
  entries,
@@ -71,26 +68,11 @@ let MetricsService = class MetricsService {
71
68
  await this.cacheService.set(cacheKey, metrics, { ttl: 1000 * 60 * 60 * 2 }); // 2 hours
72
69
  return metrics;
73
70
  }
74
- async loadData(ctx, interval, endDate) {
75
- let nrOfEntries;
76
- let backInTimeAmount;
71
+ async loadData(ctx, startDate, endDate) {
77
72
  const orderRepo = this.connection.getRepository(ctx, core_1.Order);
78
- // What function to use to get the current Tick of a date (i.e. the week or month number)
79
- let getTickNrFn;
80
- let maxTick;
81
- switch (interval) {
82
- case types_js_1.MetricInterval.Daily: {
83
- nrOfEntries = 30;
84
- backInTimeAmount = { days: nrOfEntries };
85
- getTickNrFn = date_fns_1.getDayOfYear;
86
- maxTick = 365;
87
- break;
88
- }
89
- default:
90
- (0, shared_utils_1.assertNever)(interval);
91
- }
92
- const startDate = (0, date_fns_1.startOfDay)((0, date_fns_1.sub)(endDate, backInTimeAmount));
93
- const startTick = getTickNrFn(startDate);
73
+ // Calculate number of days between start and end
74
+ const diffTime = Math.abs(endDate.getTime() - startDate.getTime());
75
+ const nrOfDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1;
94
76
  // Get orders in a loop until we have all
95
77
  let skip = 0;
96
78
  const take = 1000;
@@ -103,38 +85,40 @@ let MetricsService = class MetricsService {
103
85
  .where('orderChannel.id=:channelId', { channelId: ctx.channelId })
104
86
  .andWhere('order.orderPlacedAt >= :startDate', {
105
87
  startDate: startDate.toISOString(),
88
+ })
89
+ .andWhere('order.orderPlacedAt <= :endDate', {
90
+ endDate: endDate.toISOString(),
106
91
  })
107
92
  .skip(skip)
108
93
  .take(take);
109
94
  const [items, nrOfOrders] = await query.getManyAndCount();
110
95
  orders.push(...items);
111
- core_1.Logger.verbose(`Fetched orders ${skip}-${skip + take} for channel ${ctx.channel.token} for ${interval} metrics`, constants_js_1.loggerCtx);
96
+ core_1.Logger.verbose(`Fetched orders ${skip}-${skip + take} for channel ${ctx.channel.token} for date range metrics`, constants_js_1.loggerCtx);
112
97
  skip += items.length;
113
98
  if (orders.length >= nrOfOrders) {
114
99
  hasMoreOrders = false;
115
100
  }
116
101
  }
117
- core_1.Logger.verbose(`Finished fetching all ${orders.length} orders for channel ${ctx.channel.token} for ${interval} metrics`, constants_js_1.loggerCtx);
118
- const dataPerInterval = new Map();
119
- const ticks = [];
120
- for (let i = 1; i <= nrOfEntries; i++) {
121
- if (startTick + i >= maxTick) {
122
- // make sure we don't go over month 12 or week 52
123
- ticks.push(startTick + i - maxTick);
124
- }
125
- else {
126
- ticks.push(startTick + i);
127
- }
128
- }
129
- ticks.forEach(tick => {
130
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
131
- const ordersInCurrentTick = orders.filter(order => getTickNrFn(order.orderPlacedAt) === tick);
132
- dataPerInterval.set(tick, {
133
- orders: ordersInCurrentTick,
134
- date: (0, date_fns_1.setDayOfYear)(endDate, tick),
102
+ core_1.Logger.verbose(`Finished fetching all ${orders.length} orders for channel ${ctx.channel.token} for date range metrics`, constants_js_1.loggerCtx);
103
+ const dataPerDay = new Map();
104
+ // Create a map entry for each day in the range
105
+ for (let i = 0; i < nrOfDays; i++) {
106
+ const currentDate = new Date(startDate);
107
+ currentDate.setDate(startDate.getDate() + i);
108
+ const dateKey = currentDate.toISOString().split('T')[0]; // YYYY-MM-DD format
109
+ // Filter orders for this specific day
110
+ const ordersForDay = orders.filter(order => {
111
+ if (!order.orderPlacedAt)
112
+ return false;
113
+ const orderDate = new Date(order.orderPlacedAt).toISOString().split('T')[0];
114
+ return orderDate === dateKey;
135
115
  });
136
- });
137
- return dataPerInterval;
116
+ dataPerDay.set(dateKey, {
117
+ orders: ordersForDay,
118
+ date: currentDate,
119
+ });
120
+ }
121
+ return dataPerDay;
138
122
  }
139
123
  };
140
124
  exports.MetricsService = MetricsService;
@@ -1,23 +1,20 @@
1
- export type MetricSummary = {
2
- interval: MetricInterval;
3
- type: MetricType;
1
+ export type DashboardMetricSummary = {
2
+ type: DashboardMetricType;
4
3
  title: string;
5
- entries: MetricSummaryEntry[];
4
+ entries: DashboardMetricSummaryEntry[];
6
5
  };
7
- export declare enum MetricType {
6
+ export declare enum DashboardMetricType {
8
7
  OrderCount = "OrderCount",
9
8
  OrderTotal = "OrderTotal",
10
9
  AverageOrderValue = "AverageOrderValue"
11
10
  }
12
- export declare enum MetricInterval {
13
- Daily = "Daily"
14
- }
15
- export type MetricSummaryEntry = {
11
+ export type DashboardMetricSummaryEntry = {
16
12
  label: string;
17
13
  value: number;
18
14
  };
19
- export interface MetricSummaryInput {
20
- interval: MetricInterval;
21
- types: MetricType[];
15
+ export interface DashboardMetricSummaryInput {
16
+ types: DashboardMetricType[];
22
17
  refresh?: boolean;
18
+ startDate: string;
19
+ endDate: string;
23
20
  }
@@ -1,13 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MetricInterval = exports.MetricType = void 0;
4
- var MetricType;
5
- (function (MetricType) {
6
- MetricType["OrderCount"] = "OrderCount";
7
- MetricType["OrderTotal"] = "OrderTotal";
8
- MetricType["AverageOrderValue"] = "AverageOrderValue";
9
- })(MetricType || (exports.MetricType = MetricType = {}));
10
- var MetricInterval;
11
- (function (MetricInterval) {
12
- MetricInterval["Daily"] = "Daily";
13
- })(MetricInterval || (exports.MetricInterval = MetricInterval = {}));
3
+ exports.DashboardMetricType = void 0;
4
+ var DashboardMetricType;
5
+ (function (DashboardMetricType) {
6
+ DashboardMetricType["OrderCount"] = "OrderCount";
7
+ DashboardMetricType["OrderTotal"] = "OrderTotal";
8
+ DashboardMetricType["AverageOrderValue"] = "AverageOrderValue";
9
+ })(DashboardMetricType || (exports.DashboardMetricType = DashboardMetricType = {}));
@@ -3,7 +3,7 @@ export function viteConfigPlugin({ packageRoot }) {
3
3
  return {
4
4
  name: 'vendure:vite-config-plugin',
5
5
  config: (config, env) => {
6
- var _a, _b, _c, _d, _e;
6
+ var _a, _b, _c, _d, _e, _f;
7
7
  // Only set the vite `root` to the dashboard package when running the dev server.
8
8
  // During a production build we still need to reference the dashboard source which
9
9
  // lives in `node_modules`, but we don't want the build output to be emitted in there.
@@ -11,29 +11,31 @@ export function viteConfigPlugin({ packageRoot }) {
11
11
  // an `outDir` **outside** of `node_modules` is used (defaulting to the current working
12
12
  // directory if the user did not provide one already).
13
13
  config.root = packageRoot;
14
+ config.publicDir = (_a = config.publicDir) !== null && _a !== void 0 ? _a : path.join(packageRoot, 'public');
14
15
  // If we are building and no explicit outDir has been provided (or it is a relative path),
15
16
  // set it to an **absolute** path relative to the cwd so that the output never ends up in
16
17
  // `node_modules`.
17
18
  if (env.command === 'build') {
18
- const buildConfig = (_a = config.build) !== null && _a !== void 0 ? _a : {};
19
- const hasOutDir = typeof buildConfig.outDir === 'string' && buildConfig.outDir.length > 0;
20
- const outDirIsAbsolute = hasOutDir && path.isAbsolute(buildConfig.outDir);
19
+ const buildConfig = (_b = config.build) !== null && _b !== void 0 ? _b : {};
20
+ const outDir = buildConfig.outDir;
21
+ const hasOutDir = typeof outDir === 'string' && outDir.length > 0;
22
+ const outDirIsAbsolute = hasOutDir && path.isAbsolute(outDir);
21
23
  const normalizedOutDir = hasOutDir
22
24
  ? outDirIsAbsolute
23
- ? buildConfig.outDir
24
- : path.resolve(process.cwd(), buildConfig.outDir)
25
+ ? outDir
26
+ : path.resolve(process.cwd(), outDir)
25
27
  : path.resolve(process.cwd(), 'dist');
26
28
  config.build = Object.assign(Object.assign({}, buildConfig), { outDir: normalizedOutDir });
27
29
  }
28
30
  config.resolve = {
29
- alias: Object.assign(Object.assign({}, ((_c = (_b = config.resolve) === null || _b === void 0 ? void 0 : _b.alias) !== null && _c !== void 0 ? _c : {})), {
31
+ alias: Object.assign(Object.assign({}, ((_d = (_c = config.resolve) === null || _c === void 0 ? void 0 : _c.alias) !== null && _d !== void 0 ? _d : {})), {
30
32
  // See the readme for an explanation of this alias.
31
33
  '@/vdb': path.resolve(packageRoot, './src/lib'), '@/graphql': path.resolve(packageRoot, './src/lib/graphql') }),
32
34
  };
33
35
  // This is required to prevent Vite from pre-bundling the
34
36
  // dashboard source when it resides in node_modules.
35
37
  config.optimizeDeps = Object.assign(Object.assign({}, config.optimizeDeps), { exclude: [
36
- ...(((_d = config.optimizeDeps) === null || _d === void 0 ? void 0 : _d.exclude) || []),
38
+ ...(((_e = config.optimizeDeps) === null || _e === void 0 ? void 0 : _e.exclude) || []),
37
39
  '@vendure/dashboard',
38
40
  '@/vdb',
39
41
  'virtual:vendure-ui-config',
@@ -44,11 +46,13 @@ export function viteConfigPlugin({ packageRoot }) {
44
46
  // on lodash which is a CJS packages and _does_ require
45
47
  // pre-bundling.
46
48
  include: [
47
- ...(((_e = config.optimizeDeps) === null || _e === void 0 ? void 0 : _e.include) || []),
49
+ ...(((_f = config.optimizeDeps) === null || _f === void 0 ? void 0 : _f.include) || []),
48
50
  '@/components > recharts',
49
51
  '@/components > react-dropzone',
50
52
  '@/components > @tiptap/react', // https://github.com/fawmi/vue-google-maps/issues/148#issuecomment-1235143844
51
53
  '@vendure/common/lib/generated-types',
54
+ '@radix-ui/react-portal > react-dom',
55
+ '@messageformat/parser',
52
56
  ] });
53
57
  return config;
54
58
  },
@@ -0,0 +1,22 @@
1
+ import type { Plugin } from 'vite';
2
+ export interface TranslationsPluginOptions {
3
+ /**
4
+ * Array of paths to .po files to merge with built-in translations
5
+ */
6
+ externalPoFiles?: string[];
7
+ /**
8
+ * Path to the built-in locales directory
9
+ */
10
+ localesDir?: string;
11
+ /**
12
+ * Output path for merged translations within the build output (e.g., 'i18n')
13
+ */
14
+ outputPath?: string;
15
+ packageRoot: string;
16
+ }
17
+ /**
18
+ * @description
19
+ * This Vite plugin compiles
20
+ * @param options
21
+ */
22
+ export declare function translationsPlugin(options: TranslationsPluginOptions): Plugin;
@@ -0,0 +1,66 @@
1
+ import { createCompilationErrorMessage, createCompiledCatalog, getCatalogForFile, getCatalogs, } from '@lingui/cli/api';
2
+ import { getConfig } from '@lingui/conf';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ /**
6
+ * @description
7
+ * This Vite plugin compiles
8
+ * @param options
9
+ */
10
+ export function translationsPlugin(options) {
11
+ const { externalPoFiles = [], localesDir = 'src/i18n/locales', outputPath = 'assets/i18n' } = options;
12
+ const linguiConfig = getConfig({ configPath: path.join(options.packageRoot, 'lingui.config.js') });
13
+ const catalogsPromise = getCatalogs(linguiConfig);
14
+ async function compileTranslations(files, emitFile) {
15
+ const catalogs = await catalogsPromise;
16
+ for (const file of files) {
17
+ const catalogRelativePath = path.relative(options.packageRoot, file.path);
18
+ const fileCatalog = getCatalogForFile(catalogRelativePath, catalogs);
19
+ const { locale, catalog } = fileCatalog;
20
+ const { messages } = await catalog.getTranslations(locale, {
21
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
22
+ fallbackLocales: { default: linguiConfig.sourceLocale },
23
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
24
+ sourceLocale: linguiConfig.sourceLocale,
25
+ });
26
+ const { source: code, errors } = createCompiledCatalog(locale, messages, {
27
+ namespace: 'es',
28
+ pseudoLocale: linguiConfig.pseudoLocale,
29
+ });
30
+ if (errors.length) {
31
+ const message = createCompilationErrorMessage(locale, errors);
32
+ throw new Error(message +
33
+ `These errors fail build because \`failOnCompileError=true\` in Lingui Vite plugin configuration.`);
34
+ }
35
+ // Emit the compiled JavaScript file to the build output
36
+ const outputFileName = path.posix.join(outputPath, `${locale}.js`);
37
+ emitFile({
38
+ type: 'asset',
39
+ fileName: outputFileName,
40
+ source: code,
41
+ });
42
+ }
43
+ }
44
+ return {
45
+ name: 'vendure:compile-translations',
46
+ async generateBundle() {
47
+ // This runs during the bundle generation phase - emit files directly to build output
48
+ try {
49
+ const resolvedLocalesDir = path.resolve(options.packageRoot, localesDir);
50
+ // Get all built-in .po files
51
+ const builtInFiles = fs
52
+ .readdirSync(resolvedLocalesDir)
53
+ .filter(file => file.endsWith('.po'))
54
+ .map(file => ({
55
+ name: file,
56
+ path: path.join(resolvedLocalesDir, file),
57
+ }));
58
+ await compileTranslations(builtInFiles, this.emitFile);
59
+ this.info(`✓ Processed ${builtInFiles.length} translation files to ${outputPath}`);
60
+ }
61
+ catch (error) {
62
+ this.error(`Translation plugin error: ${error instanceof Error ? error.message : String(error)}`);
63
+ }
64
+ },
65
+ };
66
+ }