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

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 (263) hide show
  1. package/README.md +4 -0
  2. package/dist/plugin/dashboard.plugin.d.ts +25 -6
  3. package/dist/plugin/dashboard.plugin.js +184 -27
  4. package/dist/plugin/default-page.html +188 -0
  5. package/dist/vite/vite-plugin-config.js +13 -9
  6. package/dist/vite/vite-plugin-translations.d.ts +22 -0
  7. package/dist/vite/vite-plugin-translations.js +66 -0
  8. package/dist/vite/vite-plugin-vendure-dashboard.js +8 -6
  9. package/lingui.config.js +25 -2
  10. package/package.json +159 -156
  11. package/src/app/app-providers.tsx +0 -4
  12. package/src/app/common/delete-bulk-action.tsx +6 -5
  13. package/src/app/common/duplicate-bulk-action.tsx +4 -5
  14. package/src/app/common/duplicate-entity-dialog.tsx +1 -1
  15. package/src/app/common/set-document-direction.ts +7 -0
  16. package/src/app/main.tsx +50 -17
  17. package/src/app/routes/_authenticated/_administrators/administrators.tsx +8 -6
  18. package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +17 -6
  19. package/src/app/routes/_authenticated/_administrators/components/role-permissions-display.tsx +2 -2
  20. package/src/app/routes/_authenticated/_assets/assets.tsx +1 -1
  21. package/src/app/routes/_authenticated/_assets/assets_.$id.tsx +4 -4
  22. package/src/app/routes/_authenticated/_assets/components/asset-bulk-actions.tsx +8 -6
  23. package/src/app/routes/_authenticated/_assets/components/asset-tag-filter.tsx +1 -1
  24. package/src/app/routes/_authenticated/_assets/components/asset-tags-editor.tsx +1 -1
  25. package/src/app/routes/_authenticated/_assets/components/manage-tags-dialog.tsx +3 -8
  26. package/src/app/routes/_authenticated/_channels/channels.tsx +3 -6
  27. package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +5 -5
  28. package/src/app/routes/_authenticated/_collections/collections.tsx +3 -4
  29. package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +4 -6
  30. package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +1 -1
  31. package/src/app/routes/_authenticated/_collections/components/collection-contents-sheet.tsx +1 -1
  32. package/src/app/routes/_authenticated/_collections/components/move-collections-dialog.tsx +6 -6
  33. package/src/app/routes/_authenticated/_countries/countries.graphql.ts +2 -0
  34. package/src/app/routes/_authenticated/_countries/countries.tsx +2 -3
  35. package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +4 -4
  36. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-sheet.tsx +1 -1
  37. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-table.tsx +4 -4
  38. package/src/app/routes/_authenticated/_customer-groups/customer-groups.tsx +2 -4
  39. package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +13 -6
  40. package/src/app/routes/_authenticated/_customers/components/customer-address-card.tsx +8 -8
  41. package/src/app/routes/_authenticated/_customers/components/customer-address-form.tsx +3 -3
  42. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-container.tsx +1 -1
  43. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-utils.tsx +1 -1
  44. package/src/app/routes/_authenticated/_customers/components/customer-history/default-customer-history-components.tsx +1 -1
  45. package/src/app/routes/_authenticated/_customers/components/customer-history/use-customer-history.ts +1 -1
  46. package/src/app/routes/_authenticated/_customers/components/customer-status-badge.tsx +1 -1
  47. package/src/app/routes/_authenticated/_customers/customers.graphql.ts +4 -0
  48. package/src/app/routes/_authenticated/_customers/customers.tsx +23 -11
  49. package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +10 -8
  50. package/src/app/routes/_authenticated/_facets/components/edit-facet-value.tsx +1 -1
  51. package/src/app/routes/_authenticated/_facets/components/facet-bulk-actions.tsx +6 -5
  52. package/src/app/routes/_authenticated/_facets/components/facet-values-sheet.tsx +1 -1
  53. package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +1 -1
  54. package/src/app/routes/_authenticated/_facets/facets.tsx +5 -5
  55. package/src/app/routes/_authenticated/_facets/facets_.$facetId.values_.$id.tsx +7 -5
  56. package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +4 -4
  57. package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +5 -5
  58. package/src/app/routes/_authenticated/_orders/components/add-manual-payment-dialog.tsx +19 -21
  59. package/src/app/routes/_authenticated/_orders/components/customer-address-selector.tsx +1 -1
  60. package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +22 -22
  61. package/src/app/routes/_authenticated/_orders/components/fulfill-order-dialog.tsx +6 -6
  62. package/src/app/routes/_authenticated/_orders/components/fulfillment-details.tsx +15 -9
  63. package/src/app/routes/_authenticated/_orders/components/order-address.tsx +1 -1
  64. package/src/app/routes/_authenticated/_orders/components/order-detail-shared.tsx +11 -9
  65. package/src/app/routes/_authenticated/_orders/components/order-history/default-order-history-components.tsx +1 -1
  66. package/src/app/routes/_authenticated/_orders/components/order-history/order-history-container.tsx +1 -1
  67. package/src/app/routes/_authenticated/_orders/components/order-history/order-history-utils.tsx +1 -1
  68. package/src/app/routes/_authenticated/_orders/components/order-history/use-order-history.ts +1 -1
  69. package/src/app/routes/_authenticated/_orders/components/order-line-custom-fields-form.tsx +1 -1
  70. package/src/app/routes/_authenticated/_orders/components/order-modification-preview-dialog.tsx +4 -4
  71. package/src/app/routes/_authenticated/_orders/components/order-modification-summary.tsx +1 -1
  72. package/src/app/routes/_authenticated/_orders/components/order-table-totals.tsx +27 -27
  73. package/src/app/routes/_authenticated/_orders/components/order-table.tsx +2 -2
  74. package/src/app/routes/_authenticated/_orders/components/order-tax-summary.tsx +1 -1
  75. package/src/app/routes/_authenticated/_orders/components/payment-details.tsx +26 -20
  76. package/src/app/routes/_authenticated/_orders/components/seller-orders-card.tsx +3 -1
  77. package/src/app/routes/_authenticated/_orders/components/settle-refund-dialog.tsx +6 -6
  78. package/src/app/routes/_authenticated/_orders/components/shipping-method-selector.tsx +1 -1
  79. package/src/app/routes/_authenticated/_orders/components/state-transition-control.tsx +1 -1
  80. package/src/app/routes/_authenticated/_orders/components/use-transition-order-to-state.tsx +3 -2
  81. package/src/app/routes/_authenticated/_orders/orders.tsx +5 -9
  82. package/src/app/routes/_authenticated/_orders/orders_.$aggregateOrderId_.seller-orders.$sellerOrderId.tsx +1 -1
  83. package/src/app/routes/_authenticated/_orders/orders_.$id.tsx +1 -1
  84. package/src/app/routes/_authenticated/_orders/orders_.$id_.modify.tsx +4 -4
  85. package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +17 -17
  86. package/src/app/routes/_authenticated/_orders/utils/order-detail-loaders.tsx +1 -1
  87. package/src/app/routes/_authenticated/_payment-methods/payment-methods.tsx +5 -6
  88. package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +13 -6
  89. package/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx +1 -1
  90. package/src/app/routes/_authenticated/_product-variants/components/variant-price-detail.tsx +1 -1
  91. package/src/app/routes/_authenticated/_product-variants/product-variants.tsx +9 -2
  92. package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +13 -6
  93. package/src/app/routes/_authenticated/_products/components/add-option-group-dialog.tsx +5 -5
  94. package/src/app/routes/_authenticated/_products/components/add-product-variant-dialog.tsx +5 -5
  95. package/src/app/routes/_authenticated/_products/components/assign-facet-values-dialog.tsx +5 -4
  96. package/src/app/routes/_authenticated/_products/components/create-product-options-dialog.tsx +9 -12
  97. package/src/app/routes/_authenticated/_products/components/create-product-variants-dialog.tsx +1 -1
  98. package/src/app/routes/_authenticated/_products/components/create-product-variants.tsx +4 -4
  99. package/src/app/routes/_authenticated/_products/components/option-groups-editor.tsx +1 -1
  100. package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +1 -1
  101. package/src/app/routes/_authenticated/_products/components/product-option-select.tsx +3 -3
  102. package/src/app/routes/_authenticated/_products/components/product-options-table.tsx +9 -6
  103. package/src/app/routes/_authenticated/_products/products.graphql.ts +31 -31
  104. package/src/app/routes/_authenticated/_products/products.tsx +11 -6
  105. package/src/app/routes/_authenticated/_products/products_.$id.tsx +4 -4
  106. package/src/app/routes/_authenticated/_products/products_.$id_.variants.tsx +11 -11
  107. package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$id.tsx +8 -12
  108. package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$productOptionGroupId.options_.$id.tsx +2 -2
  109. package/src/app/routes/_authenticated/_profile/profile.tsx +4 -4
  110. package/src/app/routes/_authenticated/_promotions/promotions.tsx +2 -4
  111. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +16 -9
  112. package/src/app/routes/_authenticated/_roles/components/permissions-table-grid.tsx +1 -1
  113. package/src/app/routes/_authenticated/_roles/roles.tsx +3 -6
  114. package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +4 -6
  115. package/src/app/routes/_authenticated/_sellers/sellers.tsx +3 -4
  116. package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +4 -4
  117. package/src/app/routes/_authenticated/_shipping-methods/components/price-display.tsx +5 -5
  118. package/src/app/routes/_authenticated/_shipping-methods/components/shipping-method-test-result-wrapper.tsx +1 -1
  119. package/src/app/routes/_authenticated/_shipping-methods/components/test-address-form.tsx +4 -3
  120. package/src/app/routes/_authenticated/_shipping-methods/components/test-order-builder.tsx +4 -3
  121. package/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-methods-result.tsx +8 -8
  122. package/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-methods-sheet.tsx +1 -1
  123. package/src/app/routes/_authenticated/_shipping-methods/components/test-single-method-result.tsx +8 -8
  124. package/src/app/routes/_authenticated/_shipping-methods/components/test-single-shipping-method-sheet.tsx +4 -4
  125. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.tsx +2 -3
  126. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +2 -2
  127. package/src/app/routes/_authenticated/_stock-locations/stock-locations.tsx +3 -4
  128. package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +13 -6
  129. package/src/app/routes/_authenticated/_system/healthchecks.tsx +10 -4
  130. package/src/app/routes/_authenticated/_system/job-queue.tsx +10 -13
  131. package/src/app/routes/_authenticated/_system/scheduled-tasks.tsx +18 -16
  132. package/src/app/routes/_authenticated/_tax-categories/tax-categories.tsx +2 -4
  133. package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +13 -6
  134. package/src/app/routes/_authenticated/_tax-rates/tax-rates.tsx +8 -12
  135. package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +6 -4
  136. package/src/app/routes/_authenticated/_zones/zones.tsx +4 -4
  137. package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +8 -5
  138. package/src/app/routes/_authenticated/index.tsx +6 -2
  139. package/src/app/styles.css +4 -0
  140. package/src/i18n/common-strings.ts +111 -0
  141. package/src/i18n/locales/ar.po +4777 -0
  142. package/src/i18n/locales/cs.po +4777 -0
  143. package/src/i18n/locales/de.po +4299 -1101
  144. package/src/i18n/locales/en.po +3857 -659
  145. package/src/i18n/locales/es.po +4777 -0
  146. package/src/i18n/locales/fa.po +4777 -0
  147. package/src/i18n/locales/fr.po +4777 -0
  148. package/src/i18n/locales/he.po +4777 -0
  149. package/src/i18n/locales/hr.po +4777 -0
  150. package/src/i18n/locales/it.po +4777 -0
  151. package/src/i18n/locales/ja.po +4777 -0
  152. package/src/i18n/locales/ko.po +4628 -0
  153. package/src/i18n/locales/nb.po +4777 -0
  154. package/src/i18n/locales/ne.po +4777 -0
  155. package/src/i18n/locales/nl.po +4628 -0
  156. package/src/i18n/locales/pl.po +4777 -0
  157. package/src/i18n/locales/pt_BR.po +4777 -0
  158. package/src/i18n/locales/pt_PT.po +4777 -0
  159. package/src/i18n/locales/ru.po +4777 -0
  160. package/src/i18n/locales/sv.po +4777 -0
  161. package/src/i18n/locales/tr.po +4777 -0
  162. package/src/i18n/locales/uk.po +4777 -0
  163. package/src/i18n/locales/zh_Hans.po +4777 -0
  164. package/src/i18n/locales/zh_Hant.po +4777 -0
  165. package/src/lib/components/data-input/combination-mode-input.tsx +1 -1
  166. package/src/lib/components/data-input/custom-field-list-input.tsx +11 -7
  167. package/src/lib/components/data-input/customer-group-input.tsx +27 -33
  168. package/src/lib/components/data-input/datetime-input.tsx +40 -1
  169. package/src/lib/components/data-input/default-relation-input.tsx +5 -4
  170. package/src/lib/components/data-input/product-multi-selector-input.tsx +14 -14
  171. package/src/lib/components/data-input/relation-selector.tsx +1 -1
  172. package/src/lib/components/data-input/select-with-options.tsx +1 -1
  173. package/src/lib/components/data-input/slug-input.tsx +9 -15
  174. package/src/lib/components/data-table/add-filter-menu.tsx +4 -4
  175. package/src/lib/components/data-table/data-table-bulk-action-item.tsx +8 -8
  176. package/src/lib/components/data-table/data-table-bulk-actions.tsx +4 -4
  177. package/src/lib/components/data-table/data-table-column-header.tsx +13 -8
  178. package/src/lib/components/data-table/data-table-faceted-filter.tsx +2 -1
  179. package/src/lib/components/data-table/data-table-filter-dialog.tsx +1 -1
  180. package/src/lib/components/data-table/data-table-utils.ts +21 -4
  181. package/src/lib/components/data-table/data-table-view-options.tsx +4 -2
  182. package/src/lib/components/data-table/data-table.tsx +3 -3
  183. package/src/lib/components/data-table/filters/data-table-boolean-filter.tsx +4 -4
  184. package/src/lib/components/data-table/global-views-bar.tsx +1 -1
  185. package/src/lib/components/data-table/human-readable-operator.tsx +1 -1
  186. package/src/lib/components/data-table/manage-global-views-button.tsx +1 -1
  187. package/src/lib/components/data-table/my-views-button.tsx +13 -13
  188. package/src/lib/components/data-table/refresh-button.tsx +1 -1
  189. package/src/lib/components/data-table/save-view-button.tsx +11 -11
  190. package/src/lib/components/data-table/use-generated-columns.tsx +10 -7
  191. package/src/lib/components/data-table/views-sheet.tsx +79 -71
  192. package/src/lib/components/date-range-picker.tsx +36 -34
  193. package/src/lib/components/layout/app-sidebar.tsx +3 -1
  194. package/src/lib/components/layout/channel-switcher.tsx +8 -10
  195. package/src/lib/components/layout/dev-mode-indicator.tsx +1 -1
  196. package/src/lib/components/layout/generated-breadcrumbs.tsx +10 -8
  197. package/src/lib/components/layout/language-dialog.tsx +34 -13
  198. package/src/lib/components/layout/manage-languages-dialog.tsx +1 -1
  199. package/src/lib/components/layout/nav-main.tsx +23 -13
  200. package/src/lib/components/layout/nav-user.tsx +19 -23
  201. package/src/lib/components/login/login-form.tsx +1 -1
  202. package/src/lib/components/shared/asset/asset-bulk-actions.tsx +4 -4
  203. package/src/lib/components/shared/asset/asset-focal-point-editor.tsx +1 -1
  204. package/src/lib/components/shared/asset/asset-gallery.tsx +15 -14
  205. package/src/lib/components/shared/assign-to-channel-bulk-action.tsx +11 -11
  206. package/src/lib/components/shared/assign-to-channel-dialog.tsx +6 -5
  207. package/src/lib/components/shared/channel-code-label.tsx +1 -1
  208. package/src/lib/components/shared/channel-selector.tsx +4 -4
  209. package/src/lib/components/shared/configurable-operation-multi-selector.tsx +16 -14
  210. package/src/lib/components/shared/configurable-operation-selector.tsx +1 -1
  211. package/src/lib/components/shared/confirmation-dialog.tsx +8 -8
  212. package/src/lib/components/shared/country-selector.tsx +1 -1
  213. package/src/lib/components/shared/currency-selector.tsx +4 -4
  214. package/src/lib/components/shared/custom-fields-form.tsx +8 -24
  215. package/src/lib/components/shared/customer-address-form.tsx +3 -3
  216. package/src/lib/components/shared/customer-group-selector.tsx +1 -1
  217. package/src/lib/components/shared/customer-selector.tsx +1 -1
  218. package/src/lib/components/shared/error-page.tsx +1 -1
  219. package/src/lib/components/shared/facet-value-selector.tsx +10 -10
  220. package/src/lib/components/shared/history-timeline/history-note-checkbox.tsx +1 -1
  221. package/src/lib/components/shared/history-timeline/history-note-editor.tsx +1 -1
  222. package/src/lib/components/shared/history-timeline/history-note-entry.tsx +1 -1
  223. package/src/lib/components/shared/language-selector.tsx +4 -4
  224. package/src/lib/components/shared/navigation-confirmation.tsx +1 -1
  225. package/src/lib/components/shared/paginated-list-data-table.tsx +21 -18
  226. package/src/lib/components/shared/remove-from-channel-bulk-action.tsx +6 -5
  227. package/src/lib/components/shared/rich-text-editor/image-dialog.tsx +1 -1
  228. package/src/lib/components/shared/rich-text-editor/link-dialog.tsx +1 -1
  229. package/src/lib/components/shared/rich-text-editor/responsive-toolbar.tsx +1 -1
  230. package/src/lib/components/shared/rich-text-editor/table-edit-icons.tsx +1 -1
  231. package/src/lib/components/shared/role-code-label.tsx +1 -1
  232. package/src/lib/components/shared/role-selector.tsx +4 -4
  233. package/src/lib/components/shared/seller-selector.tsx +1 -1
  234. package/src/lib/components/shared/stock-level-label.tsx +3 -5
  235. package/src/lib/components/shared/table-cell/order-table-cell-components.tsx +3 -1
  236. package/src/lib/components/shared/tax-category-selector.tsx +1 -1
  237. package/src/lib/components/shared/translatable-form-field.tsx +15 -15
  238. package/src/lib/components/shared/zone-selector.tsx +1 -1
  239. package/src/lib/constants.ts +10 -0
  240. package/src/lib/framework/dashboard-widget/base-widget.tsx +11 -9
  241. package/src/lib/framework/dashboard-widget/latest-orders-widget/index.tsx +6 -4
  242. package/src/lib/framework/dashboard-widget/metrics-widget/index.tsx +8 -5
  243. package/src/lib/framework/dashboard-widget/orders-summary/index.tsx +7 -4
  244. package/src/lib/framework/dashboard-widget/widget-filters-context.tsx +3 -1
  245. package/src/lib/framework/defaults.ts +34 -63
  246. package/src/lib/framework/layout-engine/page-layout.tsx +36 -36
  247. package/src/lib/framework/page/detail-page.tsx +10 -10
  248. package/src/lib/framework/page/use-extended-router.tsx +48 -23
  249. package/src/lib/graphql/api.ts +22 -7
  250. package/src/lib/graphql/graphql-env.d.ts +13 -25
  251. package/src/lib/hooks/use-display-locale.ts +40 -0
  252. package/src/lib/hooks/use-dynamic-translations.ts +46 -0
  253. package/src/lib/hooks/use-extended-detail-query.ts +1 -1
  254. package/src/lib/hooks/use-extended-list-query.ts +1 -1
  255. package/src/lib/hooks/use-local-format.ts +15 -1
  256. package/src/lib/hooks/use-saved-views.ts +7 -0
  257. package/src/lib/hooks/use-ui-language-loader.ts +30 -0
  258. package/src/lib/lib/load-i18n-messages.ts +17 -0
  259. package/src/lib/lib/trans.tsx +15 -11
  260. package/src/lib/providers/auth.tsx +2 -2
  261. package/src/lib/providers/channel-provider.tsx +3 -2
  262. package/src/lib/providers/i18n-provider.tsx +7 -14
  263. package/src/lib/providers/user-settings.tsx +46 -5
package/src/app/main.tsx CHANGED
@@ -7,40 +7,66 @@ import { useExtendedRouter } from '@/vdb/framework/page/use-extended-router.js';
7
7
  import { useAuth } from '@/vdb/hooks/use-auth.js';
8
8
  import { useServerConfig } from '@/vdb/hooks/use-server-config.js';
9
9
  import { defaultLocale, dynamicActivate } from '@/vdb/providers/i18n-provider.js';
10
- import { createRouter, RouterProvider } from '@tanstack/react-router';
10
+ import { AnyRoute, createRouter, RouterOptions, RouterProvider } from '@tanstack/react-router';
11
11
  import React, { useEffect } from 'react';
12
12
  import ReactDOM from 'react-dom/client';
13
13
 
14
+ import { useDisplayLocale } from '@/vdb/hooks/use-display-locale.js';
15
+ import { useUiLanguageLoader } from '@/vdb/hooks/use-ui-language-loader.js';
16
+ import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
17
+ import { DirectionProvider } from '@radix-ui/react-direction';
18
+ import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
14
19
  import { AppProviders, queryClient } from './app-providers.js';
20
+ import { setDocumentDirection } from './common/set-document-direction.js';
15
21
  import { routeTree } from './routeTree.gen.js';
16
22
  import './styles.css';
17
23
 
18
- // Register things for typesafety
19
- declare module '@tanstack/react-router' {
20
- interface Register {
21
- router: typeof router;
22
- }
23
- }
24
+ const processedBaseUrl = (() => {
25
+ const baseUrl = import.meta.env.BASE_URL;
26
+ if (!baseUrl || baseUrl === '/') return undefined;
27
+ // Ensure leading slash, remove trailing slash
28
+ const normalized = baseUrl.startsWith('/') ? baseUrl : '/' + baseUrl;
29
+ return normalized.endsWith('/') ? normalized.slice(0, -1) : normalized;
30
+ })();
24
31
 
25
- export const router = createRouter({
26
- routeTree,
27
- defaultPreload: 'intent',
32
+ const routerOptions: RouterOptions<AnyRoute, any> = {
33
+ defaultPreload: 'intent' as const,
28
34
  scrollRestoration: true,
29
- // In case the dashboard gets served from a subpath, we need to set the basepath based on the environment variable
30
- ...(import.meta.env.BASE_URL ? { basepath: import.meta.env.BASE_URL } : {}),
35
+ basepath: processedBaseUrl,
31
36
  context: {
32
37
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
33
38
  auth: undefined!, // This will be set after we wrap the app in an AuthProvider
34
39
  queryClient,
35
40
  },
36
41
  defaultErrorComponent: ({ error }: { error: Error }) => <div>Uh Oh!!! {error.message}</div>,
42
+ };
43
+
44
+ // Create a type-only router instance for TypeScript type registration
45
+ // The actual runtime router is created in InnerApp component
46
+ const typeRouter = createRouter({
47
+ ...routerOptions,
48
+ routeTree,
37
49
  });
38
50
 
51
+ // Register the router type for TypeScript
52
+ declare module '@tanstack/react-router' {
53
+ interface Register {
54
+ router: typeof typeRouter;
55
+ }
56
+ }
57
+
39
58
  function InnerApp() {
40
59
  const auth = useAuth();
41
- const extendedRouter = useExtendedRouter(router);
60
+ const router = useExtendedRouter(routeTree, routerOptions);
42
61
  const serverConfig = useServerConfig();
62
+ const { isRTL } = useDisplayLocale();
43
63
  const [hasSetCustomFieldsMap, setHasSetCustomFieldsMap] = React.useState(false);
64
+ const { settings } = useUserSettings();
65
+ const { loadAndActivateLocale } = useUiLanguageLoader();
66
+
67
+ useEffect(() => {
68
+ void loadAndActivateLocale(settings.displayLanguage);
69
+ }, [settings.displayLanguage]);
44
70
 
45
71
  useEffect(() => {
46
72
  if (!serverConfig) {
@@ -50,11 +76,18 @@ function InnerApp() {
50
76
  setHasSetCustomFieldsMap(true);
51
77
  }, [serverConfig?.entityCustomFields.length]);
52
78
 
79
+ useEffect(() => {
80
+ setDocumentDirection(isRTL ? 'rtl' : 'ltr');
81
+ }, [isRTL]);
82
+
53
83
  return (
54
84
  <>
55
- {(hasSetCustomFieldsMap || auth.status === 'unauthenticated') && (
56
- <RouterProvider router={extendedRouter} context={{ auth, queryClient }} />
57
- )}
85
+ <DirectionProvider dir={isRTL ? 'rtl' : 'ltr'}>
86
+ {(hasSetCustomFieldsMap || auth.status === 'unauthenticated') && (
87
+ <RouterProvider router={router} context={{ auth, queryClient }} />
88
+ )}
89
+ {settings.devMode ? <ReactQueryDevtools /> : null}
90
+ </DirectionProvider>
58
91
  </>
59
92
  );
60
93
  }
@@ -64,7 +97,7 @@ function App() {
64
97
  const { extensionsLoaded } = useDashboardExtensions();
65
98
  useEffect(() => {
66
99
  // With this method we dynamically load the catalogs
67
- dynamicActivate(defaultLocale, () => {
100
+ void dynamicActivate(defaultLocale, () => {
68
101
  setI18nLoaded(true);
69
102
  });
70
103
  registerDefaults();
@@ -5,7 +5,7 @@ import { Badge } from '@/vdb/components/ui/badge.js';
5
5
  import { Button } from '@/vdb/components/ui/button.js';
6
6
  import { PageActionBarRight } from '@/vdb/framework/layout-engine/page-layout.js';
7
7
  import { ListPage } from '@/vdb/framework/page/list-page.js';
8
- import { Trans } from '@/vdb/lib/trans.js';
8
+ import { Trans } from '@lingui/react/macro';
9
9
  import { createFileRoute, Link } from '@tanstack/react-router';
10
10
  import { PlusIcon } from 'lucide-react';
11
11
  import { administratorListDocument } from './administrators.graphql.js';
@@ -20,7 +20,7 @@ function AdministratorListPage() {
20
20
  return (
21
21
  <ListPage
22
22
  pageId="administrator-list"
23
- title="Administrators"
23
+ title={<Trans>Administrators</Trans>}
24
24
  listQuery={administratorListDocument}
25
25
  route={Route}
26
26
  onSearchTermChange={searchTerm => {
@@ -32,7 +32,8 @@ function AdministratorListPage() {
32
32
  }}
33
33
  additionalColumns={{
34
34
  name: {
35
- header: 'Name',
35
+ meta: { dependencies: ['id', 'firstName', 'lastName'] },
36
+ header: () => <Trans>Name</Trans>,
36
37
  cell: ({ row }) => (
37
38
  <DetailPageButton
38
39
  id={row.original.id}
@@ -41,11 +42,12 @@ function AdministratorListPage() {
41
42
  ),
42
43
  },
43
44
  roles: {
44
- header: 'Roles',
45
+ meta: { dependencies: ['user'] },
46
+ header: () => <Trans>Roles</Trans>,
45
47
  cell: ({ row }) => {
46
48
  return (
47
49
  <div className="flex flex-wrap gap-2">
48
- {row.original.user.roles.map(role => {
50
+ {row.original.user?.roles.map(role => {
49
51
  return (
50
52
  <Badge variant="secondary" key={role.id}>
51
53
  <RoleCodeLabel code={role.code} />
@@ -59,7 +61,6 @@ function AdministratorListPage() {
59
61
  }}
60
62
  customizeColumns={{
61
63
  emailAddress: {
62
- id: 'Identifier',
63
64
  header: () => <Trans>Identifier</Trans>,
64
65
  cell: ({ row }) => {
65
66
  return <div>{row.original.emailAddress}</div>;
@@ -68,6 +69,7 @@ function AdministratorListPage() {
68
69
  }}
69
70
  defaultVisibility={{
70
71
  emailAddress: true,
72
+ name: true,
71
73
  }}
72
74
  defaultColumnOrder={['name', 'emailAddress', 'roles']}
73
75
  bulkActions={[
@@ -16,7 +16,7 @@ import {
16
16
  } from '@/vdb/framework/layout-engine/page-layout.js';
17
17
  import { detailPageRouteLoader } from '@/vdb/framework/page/detail-page-route-loader.js';
18
18
  import { useDetailPage } from '@/vdb/framework/page/use-detail-page.js';
19
- import { Trans, useLingui } from '@/vdb/lib/trans.js';
19
+ import { Trans, useLingui } from '@lingui/react/macro';
20
20
  import { createFileRoute, useNavigate } from '@tanstack/react-router';
21
21
  import { toast } from 'sonner';
22
22
  import {
@@ -48,7 +48,7 @@ function AdministratorDetailPage() {
48
48
  const params = Route.useParams();
49
49
  const navigate = useNavigate();
50
50
  const creatingNewEntity = params.id === NEW_ENTITY_PATH;
51
- const { i18n } = useLingui();
51
+ const { t } = useLingui();
52
52
 
53
53
  const { form, submitHandler, entity, isPending, resetForm } = useDetailPage({
54
54
  pageId,
@@ -74,16 +74,27 @@ function AdministratorDetailPage() {
74
74
  },
75
75
  params: { id: params.id },
76
76
  onSuccess: async data => {
77
- toast(i18n.t(creatingNewEntity ? 'Successfully created administrator' : 'Successfully updated administrator'));
77
+ toast(
78
+ i18n.t(
79
+ creatingNewEntity
80
+ ? 'Successfully created administrator'
81
+ : 'Successfully updated administrator',
82
+ ),
83
+ );
78
84
  resetForm();
79
85
  if (creatingNewEntity) {
80
86
  await navigate({ to: `../$id`, params: { id: data.id } });
81
87
  }
82
88
  },
83
89
  onError: err => {
84
- toast(i18n.t(creatingNewEntity ? 'Failed to create administrator' : 'Failed to update administrator'), {
85
- description: err instanceof Error ? err.message : 'Unknown error',
86
- });
90
+ toast(
91
+ i18n.t(
92
+ creatingNewEntity ? 'Failed to create administrator' : 'Failed to update administrator',
93
+ ),
94
+ {
95
+ description: err instanceof Error ? err.message : 'Unknown error',
96
+ },
97
+ );
87
98
  },
88
99
  });
89
100
 
@@ -5,7 +5,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/vdb/
5
5
  import { api } from '@/vdb/graphql/api.js';
6
6
  import { graphql } from '@/vdb/graphql/graphql.js';
7
7
  import { useGroupedPermissions } from '@/vdb/hooks/use-grouped-permissions.js';
8
- import { useLingui } from '@/vdb/lib/trans.js';
8
+ import { useLingui } from '@lingui/react/macro';
9
9
  import { useQuery } from '@tanstack/react-query';
10
10
 
11
11
  const rolesByIdDocument = graphql(`
@@ -29,7 +29,7 @@ interface RolePermissionsDisplayProps {
29
29
  }
30
30
 
31
31
  export function RolePermissionsDisplay({ value = [] }: Readonly<RolePermissionsDisplayProps>) {
32
- const { i18n } = useLingui();
32
+ const { t } = useLingui();
33
33
  const groupedPermissions = useGroupedPermissions();
34
34
 
35
35
  const { data } = useQuery({
@@ -1,6 +1,6 @@
1
1
  import { AssetGallery } from '@/vdb/components/shared/asset/asset-gallery.js';
2
2
  import { Page, PageBlock, PageTitle } from '@/vdb/framework/layout-engine/page-layout.js';
3
- import { Trans } from '@/vdb/lib/trans.js';
3
+ import { Trans } from '@lingui/react/macro';
4
4
  import { createFileRoute } from '@tanstack/react-router';
5
5
  import { DeleteAssetsBulkAction } from './components/asset-bulk-actions.js';
6
6
 
@@ -18,7 +18,7 @@ import {
18
18
  } from '@/vdb/framework/layout-engine/page-layout.js';
19
19
  import { detailPageRouteLoader } from '@/vdb/framework/page/detail-page-route-loader.js';
20
20
  import { useDetailPage } from '@/vdb/framework/page/use-detail-page.js';
21
- import { Trans, useLingui } from '@/vdb/lib/trans.js';
21
+ import { Trans, useLingui } from '@lingui/react/macro';
22
22
  import { createFileRoute } from '@tanstack/react-router';
23
23
  import { FocusIcon } from 'lucide-react';
24
24
  import { useRef, useState } from 'react';
@@ -45,7 +45,7 @@ export const Route = createFileRoute('/_authenticated/_assets/assets_/$id')({
45
45
 
46
46
  function AssetDetailPage() {
47
47
  const params = Route.useParams();
48
- const { i18n } = useLingui();
48
+ const { t } = useLingui();
49
49
 
50
50
  const imageRef = useRef<HTMLImageElement>(null);
51
51
  const [size, setSize] = useState<PreviewPreset>('medium');
@@ -67,11 +67,11 @@ function AssetDetailPage() {
67
67
  },
68
68
  params: { id: params.id },
69
69
  onSuccess: async () => {
70
- toast(i18n.t('Successfully updated asset'));
70
+ toast(t`Successfully updated asset`);
71
71
  form.reset(form.getValues());
72
72
  },
73
73
  onError: err => {
74
- toast(i18n.t('Failed to update asset'), {
74
+ toast(t`Failed to update asset`, {
75
75
  description: err instanceof Error ? err.message : 'Unknown error',
76
76
  });
77
77
  },
@@ -6,7 +6,7 @@ import { DataTableBulkActionItem } from '@/vdb/components/data-table/data-table-
6
6
  import { api } from '@/vdb/graphql/api.js';
7
7
  import { AssetFragment } from '@/vdb/graphql/fragments.js';
8
8
  import { ResultOf } from '@/vdb/graphql/graphql.js';
9
- import { Trans, useLingui } from '@/vdb/lib/trans.js';
9
+ import { Trans, useLingui } from '@lingui/react/macro';
10
10
  import { deleteAssetsDocument } from '../assets.graphql.js';
11
11
 
12
12
  export const DeleteAssetsBulkAction = ({
@@ -16,19 +16,21 @@ export const DeleteAssetsBulkAction = ({
16
16
  selection: AssetFragment[];
17
17
  refetch: () => void;
18
18
  }) => {
19
- const { i18n } = useLingui();
19
+ const { t } = useLingui();
20
+ const selectionLength = selection.length;
20
21
  const { mutate } = useMutation({
21
22
  mutationFn: api.mutate(deleteAssetsDocument),
22
23
  onSuccess: (result: ResultOf<typeof deleteAssetsDocument>) => {
23
24
  if (result.deleteAssets.result === 'DELETED') {
24
- toast.success(i18n.t(`Deleted ${selection.length} assets`));
25
+ toast.success(t`Deleted ${selectionLength} assets`);
25
26
  } else {
26
- toast.error(i18n.t(`Failed to delete assets: ${result.deleteAssets.message}`));
27
+ const message = result.deleteAssets.message;
28
+ toast.error(t`Failed to delete assets: ${message}`);
27
29
  }
28
30
  refetch();
29
31
  },
30
32
  onError: () => {
31
- toast.error(`Failed to delete ${selection.length} assets`);
33
+ toast.error(`Failed to delete ${selectionLength} assets`);
32
34
  },
33
35
  });
34
36
 
@@ -37,7 +39,7 @@ export const DeleteAssetsBulkAction = ({
37
39
  requiresPermission={['DeleteCatalog', 'DeleteAsset']}
38
40
  onClick={() => mutate({ input: { assetIds: selection.map(s => s.id) } })}
39
41
  label={<Trans>Delete</Trans>}
40
- confirmationText={<Trans>Are you sure you want to delete {selection.length} assets?</Trans>}
42
+ confirmationText={<Trans>Are you sure you want to delete {selectionLength} assets?</Trans>}
41
43
  icon={TrashIcon}
42
44
  className="text-destructive"
43
45
  />
@@ -10,8 +10,8 @@ import {
10
10
  } from '@/vdb/components/ui/command.js';
11
11
  import { Popover, PopoverContent, PopoverTrigger } from '@/vdb/components/ui/popover.js';
12
12
  import { api } from '@/vdb/graphql/api.js';
13
- import { Trans } from '@/vdb/lib/trans.js';
14
13
  import { cn } from '@/vdb/lib/utils.js';
14
+ import { Trans } from '@lingui/react/macro';
15
15
  import { useInfiniteQuery } from '@tanstack/react-query';
16
16
  import { useDebounce } from '@uidotdev/usehooks';
17
17
  import { Check, Filter, Loader2, X } from 'lucide-react';
@@ -10,8 +10,8 @@ import {
10
10
  import { Label } from '@/vdb/components/ui/label.js';
11
11
  import { Popover, PopoverContent, PopoverTrigger } from '@/vdb/components/ui/popover.js';
12
12
  import { api } from '@/vdb/graphql/api.js';
13
- import { Trans } from '@/vdb/lib/trans.js';
14
13
  import { cn } from '@/vdb/lib/utils.js';
14
+ import { Trans } from '@lingui/react/macro';
15
15
  import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
16
16
  import { Check, ChevronsUpDown, Settings2, X } from 'lucide-react';
17
17
  import { useCallback, useState } from 'react';
@@ -9,8 +9,8 @@ import {
9
9
  } from '@/vdb/components/ui/dialog.js';
10
10
  import { Input } from '@/vdb/components/ui/input.js';
11
11
  import { api } from '@/vdb/graphql/api.js';
12
- import { Trans } from '@/vdb/lib/trans.js';
13
12
  import { cn } from '@/vdb/lib/utils.js';
13
+ import { Trans } from '@lingui/react/macro';
14
14
  import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
15
15
  import { Trash2 } from 'lucide-react';
16
16
  import { useState } from 'react';
@@ -108,10 +108,7 @@ export function ManageTagsDialog({ open, onOpenChange, onTagsUpdated }: Readonly
108
108
  return (
109
109
  <div
110
110
  key={tag.id}
111
- className={cn(
112
- 'flex items-center gap-2 p-2 rounded-md',
113
- isDeleted && 'opacity-50',
114
- )}
111
+ className={cn('flex items-center gap-2 p-2 rounded-md', isDeleted && 'opacity-50')}
115
112
  >
116
113
  <Input
117
114
  value={getDisplayValue(tag.id)}
@@ -199,9 +196,7 @@ export function ManageTagsDialog({ open, onOpenChange, onTagsUpdated }: Readonly
199
196
  </DialogDescription>
200
197
  </DialogHeader>
201
198
 
202
- <div className="max-h-[400px] overflow-y-auto space-y-2 py-4">
203
- {renderTagsList()}
204
- </div>
199
+ <div className="max-h-[400px] overflow-y-auto space-y-2 py-4">{renderTagsList()}</div>
205
200
 
206
201
  <DialogFooter>
207
202
  <Button variant="outline" onClick={handleCancel} disabled={isSaving}>
@@ -5,7 +5,7 @@ import { Button } from '@/vdb/components/ui/button.js';
5
5
  import { PageActionBarRight } from '@/vdb/framework/layout-engine/page-layout.js';
6
6
  import { ListPage } from '@/vdb/framework/page/list-page.js';
7
7
  import { useLocalFormat } from '@/vdb/hooks/use-local-format.js';
8
- import { Trans } from '@/vdb/lib/trans.js';
8
+ import { Trans } from '@lingui/react/macro';
9
9
  import { createFileRoute, Link } from '@tanstack/react-router';
10
10
  import { PlusIcon } from 'lucide-react';
11
11
  import { channelListQuery } from './channels.graphql.js';
@@ -21,7 +21,7 @@ function ChannelListPage() {
21
21
  return (
22
22
  <ListPage
23
23
  pageId="channel-list"
24
- title="Channels"
24
+ title={<Trans>Channels</Trans>}
25
25
  listQuery={channelListQuery}
26
26
  route={Route}
27
27
  defaultVisibility={{
@@ -39,7 +39,6 @@ function ChannelListPage() {
39
39
  }}
40
40
  customizeColumns={{
41
41
  code: {
42
- header: 'Code',
43
42
  cell: ({ row }) => {
44
43
  return (
45
44
  <DetailPageButton
@@ -50,13 +49,11 @@ function ChannelListPage() {
50
49
  },
51
50
  },
52
51
  seller: {
53
- header: 'Seller',
54
52
  cell: ({ row }) => {
55
53
  return row.original.seller?.name;
56
54
  },
57
55
  },
58
56
  defaultLanguageCode: {
59
- header: 'Default Language',
60
57
  cell: ({ row }) => {
61
58
  return formatLanguageName(row.original.defaultLanguageCode);
62
59
  },
@@ -74,7 +71,7 @@ function ChannelListPage() {
74
71
  <Button asChild>
75
72
  <Link to="./new">
76
73
  <PlusIcon className="mr-2 h-4 w-4" />
77
- New Channel
74
+ <Trans>New Channel</Trans>
78
75
  </Link>
79
76
  </Button>
80
77
  </PermissionGuard>
@@ -23,7 +23,7 @@ import {
23
23
  import { detailPageRouteLoader } from '@/vdb/framework/page/detail-page-route-loader.js';
24
24
  import { useDetailPage } from '@/vdb/framework/page/use-detail-page.js';
25
25
  import { useChannel } from '@/vdb/hooks/use-channel.js';
26
- import { Trans, useLingui } from '@/vdb/lib/trans.js';
26
+ import { Trans, useLingui } from '@lingui/react/macro';
27
27
  import { createFileRoute, useNavigate } from '@tanstack/react-router';
28
28
  import { toast } from 'sonner';
29
29
  import { channelDetailDocument, createChannelDocument, updateChannelDocument } from './channels.graphql.js';
@@ -49,7 +49,7 @@ function ChannelDetailPage() {
49
49
  const params = Route.useParams();
50
50
  const navigate = useNavigate();
51
51
  const creatingNewEntity = params.id === NEW_ENTITY_PATH;
52
- const { i18n } = useLingui();
52
+ const { t } = useLingui();
53
53
  const { refreshChannels } = useChannel();
54
54
 
55
55
  const { form, submitHandler, entity, isPending, resetForm } = useDetailPage({
@@ -82,20 +82,20 @@ function ChannelDetailPage() {
82
82
  params: { id: params.id },
83
83
  onSuccess: async data => {
84
84
  if (data.__typename === 'Channel') {
85
- toast(i18n.t(creatingNewEntity ? 'Successfully created channel' : 'Successfully updated channel'));
85
+ toast(creatingNewEntity ? t`Successfully created channel` : t`Successfully updated channel`);
86
86
  refreshChannels();
87
87
  resetForm();
88
88
  if (creatingNewEntity) {
89
89
  await navigate({ to: `../$id`, params: { id: data.id } });
90
90
  }
91
91
  } else {
92
- toast(i18n.t(creatingNewEntity ? 'Failed to create channel' : 'Failed to update channel'), {
92
+ toast(creatingNewEntity ? t`Failed to create channel` : t`Failed to update channel`, {
93
93
  description: data.message,
94
94
  });
95
95
  }
96
96
  },
97
97
  onError: err => {
98
- toast(i18n.t(creatingNewEntity ? 'Failed to create channel' : 'Failed to update channel'), {
98
+ toast(creatingNewEntity ? t`Failed to create channel` : t`Failed to update channel`, {
99
99
  description: err instanceof Error ? err.message : 'Unknown error',
100
100
  });
101
101
  },
@@ -4,7 +4,7 @@ import { Button } from '@/vdb/components/ui/button.js';
4
4
  import { PageActionBarRight } from '@/vdb/framework/layout-engine/page-layout.js';
5
5
  import { ListPage } from '@/vdb/framework/page/list-page.js';
6
6
  import { api } from '@/vdb/graphql/api.js';
7
- import { Trans } from '@/vdb/lib/trans.js';
7
+ import { Trans } from '@lingui/react/macro';
8
8
  import { FetchQueryOptions, useQueries } from '@tanstack/react-query';
9
9
  import { createFileRoute, Link } from '@tanstack/react-router';
10
10
  import { ExpandedState, getExpandedRowModel } from '@tanstack/react-table';
@@ -82,7 +82,7 @@ function CollectionListPage() {
82
82
  <>
83
83
  <ListPage
84
84
  pageId="collection-list"
85
- title="Collections"
85
+ title={<Trans>Collections</Trans>}
86
86
  listQuery={collectionListDocument}
87
87
  transformVariables={input => {
88
88
  const filterTerm = input.options?.filter?.name?.contains;
@@ -101,7 +101,6 @@ function CollectionListPage() {
101
101
  // in order to correctly render.
102
102
  dependencies: ['children', 'breadcrumbs'],
103
103
  },
104
- header: 'Collection Name',
105
104
  cell: ({ row }) => {
106
105
  const isExpanded = row.getIsExpanded();
107
106
  const hasChildren = !!row.original.children?.length;
@@ -141,7 +140,7 @@ function CollectionListPage() {
141
140
  },
142
141
  },
143
142
  productVariants: {
144
- header: 'Contents',
143
+ header: () => <Trans>Contents</Trans>,
145
144
  cell: ({ row }) => {
146
145
  return (
147
146
  <CollectionContentsSheet
@@ -22,7 +22,7 @@ import {
22
22
  } from '@/vdb/framework/layout-engine/page-layout.js';
23
23
  import { detailPageRouteLoader } from '@/vdb/framework/page/detail-page-route-loader.js';
24
24
  import { useDetailPage } from '@/vdb/framework/page/use-detail-page.js';
25
- import { Trans, useLingui } from '@/vdb/lib/trans.js';
25
+ import { Trans, useLingui } from '@lingui/react/macro';
26
26
  import { createFileRoute, useNavigate } from '@tanstack/react-router';
27
27
  import { toast } from 'sonner';
28
28
  import {
@@ -53,7 +53,7 @@ function CollectionDetailPage() {
53
53
  const params = Route.useParams();
54
54
  const navigate = useNavigate();
55
55
  const creatingNewEntity = params.id === NEW_ENTITY_PATH;
56
- const { i18n } = useLingui();
56
+ const { t } = useLingui();
57
57
 
58
58
  const { form, submitHandler, entity, isPending, resetForm } = useDetailPage({
59
59
  pageId,
@@ -91,9 +91,7 @@ function CollectionDetailPage() {
91
91
  params: { id: params.id },
92
92
  onSuccess: async data => {
93
93
  toast(
94
- i18n.t(
95
- creatingNewEntity ? 'Successfully created collection' : 'Successfully updated collection',
96
- ),
94
+ creatingNewEntity ? t`Successfully created collection` : t`Successfully updated collection`,
97
95
  );
98
96
  resetForm();
99
97
  if (creatingNewEntity) {
@@ -101,7 +99,7 @@ function CollectionDetailPage() {
101
99
  }
102
100
  },
103
101
  onError: err => {
104
- toast(i18n.t(creatingNewEntity ? 'Failed to create collection' : 'Failed to update collection'), {
102
+ toast(creatingNewEntity ? t`Failed to create collection` : t`Failed to update collection`, {
105
103
  description: err instanceof Error ? err.message : 'Unknown error',
106
104
  });
107
105
  },
@@ -9,7 +9,7 @@ import { RemoveFromChannelBulkAction } from '@/vdb/components/shared/remove-from
9
9
  import { BulkActionComponent } from '@/vdb/framework/extension-api/types/data-table.js';
10
10
  import { api } from '@/vdb/graphql/api.js';
11
11
  import { useChannel } from '@/vdb/hooks/use-channel.js';
12
- import { Trans } from '@/vdb/lib/trans.js';
12
+ import { Trans } from '@lingui/react/macro';
13
13
  import { DeleteBulkAction } from '../../../../common/delete-bulk-action.js';
14
14
  import { DuplicateBulkAction } from '../../../../common/duplicate-bulk-action.js';
15
15
  import {
@@ -7,7 +7,7 @@ import {
7
7
  SheetTitle,
8
8
  SheetTrigger,
9
9
  } from '@/vdb/components/ui/sheet.js';
10
- import { Trans } from '@/vdb/lib/trans.js';
10
+ import { Trans } from '@lingui/react/macro';
11
11
  import { PanelLeftOpen } from 'lucide-react';
12
12
  import { CollectionContentsTable } from './collection-contents-table.js';
13
13
 
@@ -16,7 +16,7 @@ import {
16
16
  import { Input } from '@/vdb/components/ui/input.js';
17
17
  import { ScrollArea } from '@/vdb/components/ui/scroll-area.js';
18
18
  import { api } from '@/vdb/graphql/api.js';
19
- import { Trans, useLingui } from '@/vdb/lib/trans.js';
19
+ import { Trans, useLingui } from '@lingui/react/macro';
20
20
  import { ChevronRight, Folder, FolderOpen, Search } from 'lucide-react';
21
21
 
22
22
  import { collectionListForMoveDocument, moveCollectionDocument } from '../collections.graphql.js';
@@ -217,7 +217,7 @@ export function MoveCollectionsDialog({
217
217
  const debouncedSearchTerm = useDebounce(searchTerm, 300);
218
218
  const collectionNameCache = useRef<Map<string, string>>(new Map());
219
219
  const queryClient = useQueryClient();
220
- const { i18n } = useLingui();
220
+ const { t } = useLingui();
221
221
  const collectionForMoveKey = ['collectionsForMove', debouncedSearchTerm];
222
222
  const childCollectionsForMoveKey = (collectionId?: string) =>
223
223
  collectionId ? ['childCollectionsForMove', collectionId] : ['childCollectionsForMove'];
@@ -280,14 +280,14 @@ export function MoveCollectionsDialog({
280
280
  const moveCollectionsMutation = useMutation({
281
281
  mutationFn: api.mutate(moveCollectionDocument),
282
282
  onSuccess: () => {
283
- toast.success(i18n.t('Collections moved successfully'));
283
+ toast.success(t`Collections moved successfully`);
284
284
  queryClient.invalidateQueries({ queryKey: collectionForMoveKey });
285
285
  queryClient.invalidateQueries({ queryKey: childCollectionsForMoveKey() });
286
286
  onSuccess?.();
287
287
  onOpenChange(false);
288
288
  },
289
289
  onError: error => {
290
- toast.error(i18n.t('Failed to move collections'));
290
+ toast.error(t`Failed to move collections`);
291
291
  console.error('Move collections error:', error);
292
292
  },
293
293
  });
@@ -305,7 +305,7 @@ export function MoveCollectionsDialog({
305
305
 
306
306
  const handleMove = () => {
307
307
  if (!selectedCollectionId) {
308
- toast.error(i18n.t('Please select a target collection'));
308
+ toast.error(t`Please select a target collection`);
309
309
  return;
310
310
  }
311
311
  // Move to a specific parent using moveCollection
@@ -363,7 +363,7 @@ export function MoveCollectionsDialog({
363
363
  <div className="relative mb-3">
364
364
  <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
365
365
  <Input
366
- placeholder={i18n.t('Filter by collection name')}
366
+ placeholder={t`Filter by collection name`}
367
367
  value={searchTerm}
368
368
  onChange={e => setSearchTerm(e.target.value)}
369
369
  className="pl-10"
@@ -3,6 +3,8 @@ import { graphql } from '@/vdb/graphql/graphql.js';
3
3
  export const countryItemFragment = graphql(`
4
4
  fragment CountryItem on Country {
5
5
  id
6
+ createdAt
7
+ updatedAt
6
8
  name
7
9
  code
8
10
  enabled