@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.
- package/README.md +4 -0
- package/dist/plugin/api/api-extensions.js +11 -14
- package/dist/plugin/api/metrics.resolver.d.ts +2 -2
- package/dist/plugin/api/metrics.resolver.js +2 -2
- package/dist/plugin/config/metrics-strategies.d.ts +9 -9
- package/dist/plugin/config/metrics-strategies.js +6 -6
- package/dist/plugin/constants.d.ts +2 -0
- package/dist/plugin/constants.js +3 -1
- package/dist/plugin/dashboard.plugin.js +13 -0
- package/dist/plugin/service/metrics.service.d.ts +3 -3
- package/dist/plugin/service/metrics.service.js +37 -53
- package/dist/plugin/types.d.ts +9 -12
- package/dist/plugin/types.js +7 -11
- package/dist/vite/vite-plugin-config.js +13 -9
- package/dist/vite/vite-plugin-translations.d.ts +22 -0
- package/dist/vite/vite-plugin-translations.js +66 -0
- package/dist/vite/vite-plugin-vendure-dashboard.js +10 -8
- package/lingui.config.js +25 -2
- package/package.json +159 -156
- package/src/app/app-providers.tsx +0 -4
- package/src/app/common/delete-bulk-action.tsx +6 -5
- package/src/app/common/duplicate-bulk-action.tsx +4 -5
- package/src/app/common/duplicate-entity-dialog.tsx +1 -1
- package/src/app/common/set-document-direction.ts +7 -0
- package/src/app/main.tsx +50 -17
- package/src/app/routes/_authenticated/_administrators/administrators.tsx +8 -6
- package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +17 -6
- package/src/app/routes/_authenticated/_administrators/components/role-permissions-display.tsx +2 -2
- package/src/app/routes/_authenticated/_assets/assets.tsx +1 -1
- package/src/app/routes/_authenticated/_assets/assets_.$id.tsx +4 -4
- package/src/app/routes/_authenticated/_assets/components/asset-bulk-actions.tsx +8 -6
- package/src/app/routes/_authenticated/_assets/components/asset-tag-filter.tsx +1 -1
- package/src/app/routes/_authenticated/_assets/components/asset-tags-editor.tsx +1 -1
- package/src/app/routes/_authenticated/_assets/components/manage-tags-dialog.tsx +3 -8
- package/src/app/routes/_authenticated/_channels/channels.tsx +3 -6
- package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +5 -5
- package/src/app/routes/_authenticated/_collections/collections.tsx +10 -6
- package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +16 -5
- package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +1 -1
- package/src/app/routes/_authenticated/_collections/components/collection-contents-sheet.tsx +1 -1
- package/src/app/routes/_authenticated/_collections/components/move-collections-dialog.tsx +6 -6
- package/src/app/routes/_authenticated/_countries/countries.graphql.ts +2 -0
- package/src/app/routes/_authenticated/_countries/countries.tsx +2 -3
- package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +4 -4
- package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-sheet.tsx +1 -1
- package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-table.tsx +4 -4
- package/src/app/routes/_authenticated/_customer-groups/customer-groups.tsx +2 -4
- package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +13 -6
- package/src/app/routes/_authenticated/_customers/components/customer-address-card.tsx +8 -8
- package/src/app/routes/_authenticated/_customers/components/customer-address-form.tsx +3 -3
- package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-container.tsx +1 -1
- package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-utils.tsx +1 -1
- package/src/app/routes/_authenticated/_customers/components/customer-history/default-customer-history-components.tsx +1 -1
- package/src/app/routes/_authenticated/_customers/components/customer-history/use-customer-history.ts +1 -1
- package/src/app/routes/_authenticated/_customers/components/customer-status-badge.tsx +1 -1
- package/src/app/routes/_authenticated/_customers/customers.graphql.ts +4 -0
- package/src/app/routes/_authenticated/_customers/customers.tsx +23 -11
- package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +10 -8
- package/src/app/routes/_authenticated/_facets/components/edit-facet-value.tsx +1 -1
- package/src/app/routes/_authenticated/_facets/components/facet-bulk-actions.tsx +6 -5
- package/src/app/routes/_authenticated/_facets/components/facet-values-sheet.tsx +1 -1
- package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +1 -1
- package/src/app/routes/_authenticated/_facets/facets.tsx +5 -5
- package/src/app/routes/_authenticated/_facets/facets_.$facetId.values_.$id.tsx +7 -5
- package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +18 -6
- package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +5 -5
- package/src/app/routes/_authenticated/_orders/components/add-manual-payment-dialog.tsx +19 -21
- package/src/app/routes/_authenticated/_orders/components/customer-address-selector.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +22 -22
- package/src/app/routes/_authenticated/_orders/components/fulfill-order-dialog.tsx +6 -6
- package/src/app/routes/_authenticated/_orders/components/fulfillment-details.tsx +15 -9
- package/src/app/routes/_authenticated/_orders/components/order-address.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-detail-shared.tsx +11 -9
- package/src/app/routes/_authenticated/_orders/components/order-history/default-order-history-components.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-history/order-history-container.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-history/order-history-utils.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-history/use-order-history.ts +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-line-custom-fields-form.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-modification-preview-dialog.tsx +4 -4
- package/src/app/routes/_authenticated/_orders/components/order-modification-summary.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-table-totals.tsx +27 -27
- package/src/app/routes/_authenticated/_orders/components/order-table.tsx +2 -2
- package/src/app/routes/_authenticated/_orders/components/order-tax-summary.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/payment-details.tsx +26 -20
- package/src/app/routes/_authenticated/_orders/components/seller-orders-card.tsx +3 -1
- package/src/app/routes/_authenticated/_orders/components/settle-refund-dialog.tsx +6 -6
- package/src/app/routes/_authenticated/_orders/components/shipping-method-selector.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/state-transition-control.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/use-transition-order-to-state.tsx +3 -2
- package/src/app/routes/_authenticated/_orders/orders.tsx +5 -9
- package/src/app/routes/_authenticated/_orders/orders_.$aggregateOrderId_.seller-orders.$sellerOrderId.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/orders_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/orders_.$id_.modify.tsx +4 -4
- package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +17 -17
- package/src/app/routes/_authenticated/_orders/utils/order-detail-loaders.tsx +1 -1
- package/src/app/routes/_authenticated/_payment-methods/payment-methods.tsx +5 -6
- package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +13 -6
- package/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx +1 -1
- package/src/app/routes/_authenticated/_product-variants/components/variant-price-detail.tsx +1 -1
- package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +10 -0
- package/src/app/routes/_authenticated/_product-variants/product-variants.tsx +9 -2
- package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +13 -6
- package/src/app/routes/_authenticated/_products/components/add-option-group-dialog.tsx +5 -5
- package/src/app/routes/_authenticated/_products/components/add-product-variant-dialog.tsx +5 -5
- package/src/app/routes/_authenticated/_products/components/assign-facet-values-dialog.tsx +5 -4
- package/src/app/routes/_authenticated/_products/components/create-product-options-dialog.tsx +9 -12
- package/src/app/routes/_authenticated/_products/components/create-product-variants-dialog.tsx +1 -1
- package/src/app/routes/_authenticated/_products/components/create-product-variants.tsx +4 -4
- package/src/app/routes/_authenticated/_products/components/option-groups-editor.tsx +1 -1
- package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +1 -1
- package/src/app/routes/_authenticated/_products/components/product-option-group-badge.tsx +19 -0
- package/src/app/routes/_authenticated/_products/components/product-option-select.tsx +3 -3
- package/src/app/routes/_authenticated/_products/components/product-options-table.tsx +114 -0
- package/src/app/routes/_authenticated/_products/product-option-groups.graphql.ts +103 -0
- package/src/app/routes/_authenticated/_products/products.graphql.ts +44 -32
- package/src/app/routes/_authenticated/_products/products.tsx +34 -5
- package/src/app/routes/_authenticated/_products/products_.$id.tsx +29 -12
- package/src/app/routes/_authenticated/_products/products_.$id_.variants.tsx +11 -11
- package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$id.tsx +177 -0
- package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$productOptionGroupId.options_.$id.tsx +208 -0
- package/src/app/routes/_authenticated/_profile/profile.tsx +4 -4
- package/src/app/routes/_authenticated/_promotions/promotions.tsx +2 -4
- package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +16 -9
- package/src/app/routes/_authenticated/_roles/components/permissions-table-grid.tsx +1 -1
- package/src/app/routes/_authenticated/_roles/roles.tsx +3 -6
- package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +4 -6
- package/src/app/routes/_authenticated/_sellers/sellers.tsx +3 -4
- package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +4 -4
- package/src/app/routes/_authenticated/_shipping-methods/components/price-display.tsx +5 -5
- package/src/app/routes/_authenticated/_shipping-methods/components/shipping-method-test-result-wrapper.tsx +1 -1
- package/src/app/routes/_authenticated/_shipping-methods/components/test-address-form.tsx +11 -11
- package/src/app/routes/_authenticated/_shipping-methods/components/test-order-builder.tsx +1 -1
- package/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-methods-result.tsx +8 -8
- package/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-methods-sheet.tsx +1 -1
- package/src/app/routes/_authenticated/_shipping-methods/components/test-single-method-result.tsx +8 -8
- package/src/app/routes/_authenticated/_shipping-methods/components/test-single-shipping-method-sheet.tsx +4 -4
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.tsx +2 -3
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +2 -2
- package/src/app/routes/_authenticated/_stock-locations/stock-locations.tsx +3 -4
- package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +13 -6
- package/src/app/routes/_authenticated/_system/healthchecks.tsx +10 -4
- package/src/app/routes/_authenticated/_system/job-queue.tsx +10 -13
- package/src/app/routes/_authenticated/_system/scheduled-tasks.tsx +18 -16
- package/src/app/routes/_authenticated/_tax-categories/tax-categories.tsx +2 -4
- package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +13 -6
- package/src/app/routes/_authenticated/_tax-rates/tax-rates.tsx +8 -12
- package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +6 -4
- package/src/app/routes/_authenticated/_zones/components/zone-countries-sheet.tsx +4 -1
- package/src/app/routes/_authenticated/_zones/zones.tsx +4 -4
- package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +8 -5
- package/src/app/routes/_authenticated/index.tsx +46 -25
- package/src/app/styles.css +4 -0
- package/src/i18n/common-strings.ts +111 -0
- package/src/i18n/locales/ar.po +4777 -0
- package/src/i18n/locales/cs.po +4777 -0
- package/src/i18n/locales/de.po +4299 -1101
- package/src/i18n/locales/en.po +3857 -659
- package/src/i18n/locales/es.po +4777 -0
- package/src/i18n/locales/fa.po +4777 -0
- package/src/i18n/locales/fr.po +4777 -0
- package/src/i18n/locales/he.po +4777 -0
- package/src/i18n/locales/hr.po +4777 -0
- package/src/i18n/locales/it.po +4777 -0
- package/src/i18n/locales/ja.po +4777 -0
- package/src/i18n/locales/ko.po +4628 -0
- package/src/i18n/locales/nb.po +4777 -0
- package/src/i18n/locales/ne.po +4777 -0
- package/src/i18n/locales/nl.po +4628 -0
- package/src/i18n/locales/pl.po +4777 -0
- package/src/i18n/locales/pt_BR.po +4777 -0
- package/src/i18n/locales/pt_PT.po +4777 -0
- package/src/i18n/locales/ru.po +4777 -0
- package/src/i18n/locales/sv.po +4777 -0
- package/src/i18n/locales/tr.po +4777 -0
- package/src/i18n/locales/uk.po +4777 -0
- package/src/i18n/locales/zh_Hans.po +4777 -0
- package/src/i18n/locales/zh_Hant.po +4777 -0
- package/src/lib/components/data-display/json.tsx +16 -1
- package/src/lib/components/data-input/combination-mode-input.tsx +1 -1
- package/src/lib/components/data-input/custom-field-list-input.tsx +11 -7
- package/src/lib/components/data-input/customer-group-input.tsx +27 -33
- package/src/lib/components/data-input/datetime-input.tsx +40 -1
- package/src/lib/components/data-input/default-relation-input.tsx +5 -4
- package/src/lib/components/data-input/index.ts +3 -0
- package/src/lib/components/data-input/product-multi-selector-input.tsx +14 -14
- package/src/lib/components/data-input/relation-selector.tsx +1 -1
- package/src/lib/components/data-input/select-with-options.tsx +1 -1
- package/src/lib/components/data-input/slug-input.tsx +290 -0
- package/src/lib/components/data-table/add-filter-menu.tsx +17 -10
- package/src/lib/components/data-table/data-table-bulk-action-item.tsx +45 -8
- package/src/lib/components/data-table/data-table-bulk-actions.tsx +4 -4
- package/src/lib/components/data-table/data-table-column-header.tsx +13 -8
- package/src/lib/components/data-table/data-table-context.tsx +91 -0
- package/src/lib/components/data-table/data-table-faceted-filter.tsx +2 -1
- package/src/lib/components/data-table/data-table-filter-badge.tsx +9 -5
- package/src/lib/components/data-table/data-table-filter-dialog.tsx +1 -1
- package/src/lib/components/data-table/data-table-utils.ts +21 -4
- package/src/lib/components/data-table/data-table-view-options.tsx +21 -10
- package/src/lib/components/data-table/data-table.tsx +146 -94
- package/src/lib/components/data-table/filters/data-table-boolean-filter.tsx +4 -4
- package/src/lib/components/data-table/global-views-bar.tsx +97 -0
- package/src/lib/components/data-table/global-views-sheet.tsx +11 -0
- package/src/lib/components/data-table/human-readable-operator.tsx +1 -1
- package/src/lib/components/data-table/manage-global-views-button.tsx +26 -0
- package/src/lib/components/data-table/my-views-button.tsx +47 -0
- package/src/lib/components/data-table/refresh-button.tsx +12 -3
- package/src/lib/components/data-table/save-view-button.tsx +41 -0
- package/src/lib/components/data-table/save-view-dialog.tsx +113 -0
- package/src/lib/components/data-table/use-generated-columns.tsx +13 -8
- package/src/lib/components/data-table/user-views-sheet.tsx +11 -0
- package/src/lib/components/data-table/views-sheet.tsx +305 -0
- package/src/lib/components/date-range-picker.tsx +186 -0
- package/src/lib/components/layout/app-sidebar.tsx +3 -1
- package/src/lib/components/layout/channel-switcher.tsx +8 -10
- package/src/lib/components/layout/dev-mode-indicator.tsx +1 -1
- package/src/lib/components/layout/generated-breadcrumbs.tsx +10 -8
- package/src/lib/components/layout/language-dialog.tsx +34 -13
- package/src/lib/components/layout/manage-languages-dialog.tsx +1 -1
- package/src/lib/components/layout/nav-main.tsx +23 -13
- package/src/lib/components/layout/nav-user.tsx +19 -23
- package/src/lib/components/login/login-form.tsx +1 -1
- package/src/lib/components/shared/asset/asset-bulk-actions.tsx +4 -4
- package/src/lib/components/shared/asset/asset-focal-point-editor.tsx +1 -1
- package/src/lib/components/shared/asset/asset-gallery.tsx +15 -14
- package/src/lib/components/shared/assign-to-channel-bulk-action.tsx +11 -11
- package/src/lib/components/shared/assign-to-channel-dialog.tsx +6 -5
- package/src/lib/components/shared/channel-code-label.tsx +1 -1
- package/src/lib/components/shared/channel-selector.tsx +4 -4
- package/src/lib/components/shared/configurable-operation-multi-selector.tsx +16 -14
- package/src/lib/components/shared/configurable-operation-selector.tsx +1 -1
- package/src/lib/components/shared/confirmation-dialog.tsx +8 -8
- package/src/lib/components/shared/country-selector.tsx +1 -1
- package/src/lib/components/shared/currency-selector.tsx +4 -4
- package/src/lib/components/shared/custom-fields-form.tsx +8 -24
- package/src/lib/components/shared/customer-address-form.tsx +3 -3
- package/src/lib/components/shared/customer-group-selector.tsx +1 -1
- package/src/lib/components/shared/customer-selector.tsx +1 -1
- package/src/lib/components/shared/error-page.tsx +1 -1
- package/src/lib/components/shared/facet-value-selector.tsx +10 -10
- package/src/lib/components/shared/history-timeline/history-note-checkbox.tsx +1 -1
- package/src/lib/components/shared/history-timeline/history-note-editor.tsx +1 -1
- package/src/lib/components/shared/history-timeline/history-note-entry.tsx +1 -1
- package/src/lib/components/shared/language-selector.tsx +4 -4
- package/src/lib/components/shared/navigation-confirmation.tsx +1 -1
- package/src/lib/components/shared/paginated-list-data-table.tsx +64 -34
- package/src/lib/components/shared/remove-from-channel-bulk-action.tsx +6 -5
- package/src/lib/components/shared/rich-text-editor/image-dialog.tsx +1 -1
- package/src/lib/components/shared/rich-text-editor/link-dialog.tsx +1 -1
- package/src/lib/components/shared/rich-text-editor/responsive-toolbar.tsx +1 -1
- package/src/lib/components/shared/rich-text-editor/table-edit-icons.tsx +1 -1
- package/src/lib/components/shared/role-code-label.tsx +1 -1
- package/src/lib/components/shared/role-selector.tsx +4 -4
- package/src/lib/components/shared/seller-selector.tsx +1 -1
- package/src/lib/components/shared/stock-level-label.tsx +3 -5
- package/src/lib/components/shared/table-cell/order-table-cell-components.tsx +3 -1
- package/src/lib/components/shared/tax-category-selector.tsx +1 -1
- package/src/lib/components/shared/translatable-form-field.tsx +15 -15
- package/src/lib/components/shared/zone-selector.tsx +1 -1
- package/src/lib/components/ui/button.tsx +1 -1
- package/src/lib/framework/dashboard-widget/base-widget.tsx +11 -9
- package/src/lib/framework/dashboard-widget/latest-orders-widget/index.tsx +35 -6
- package/src/lib/framework/dashboard-widget/metrics-widget/index.tsx +18 -12
- package/src/lib/framework/dashboard-widget/metrics-widget/metrics-widget.graphql.ts +9 -3
- package/src/lib/framework/dashboard-widget/orders-summary/index.tsx +26 -79
- package/src/lib/framework/dashboard-widget/widget-filters-context.tsx +35 -0
- package/src/lib/framework/defaults.ts +34 -63
- package/src/lib/framework/document-introspection/add-custom-fields.spec.ts +319 -9
- package/src/lib/framework/document-introspection/add-custom-fields.ts +60 -31
- package/src/lib/framework/document-introspection/get-document-structure.spec.ts +1 -159
- package/src/lib/framework/document-introspection/include-only-selected-list-fields.spec.ts +1840 -0
- package/src/lib/framework/document-introspection/include-only-selected-list-fields.ts +940 -0
- package/src/lib/framework/document-introspection/testing-utils.ts +161 -0
- package/src/lib/framework/extension-api/display-component-extensions.tsx +2 -0
- package/src/lib/framework/extension-api/types/data-table.ts +62 -4
- package/src/lib/framework/extension-api/types/navigation.ts +16 -0
- package/src/lib/framework/form-engine/utils.ts +34 -0
- package/src/lib/framework/layout-engine/page-layout.tsx +36 -36
- package/src/lib/framework/page/detail-page.tsx +10 -10
- package/src/lib/framework/page/list-page.tsx +289 -4
- package/src/lib/framework/page/use-extended-router.tsx +101 -34
- package/src/lib/graphql/api.ts +6 -2
- package/src/lib/graphql/graphql-env.d.ts +38 -26
- package/src/lib/hooks/use-display-locale.ts +40 -0
- package/src/lib/hooks/use-dynamic-translations.ts +46 -0
- package/src/lib/hooks/use-extended-detail-query.ts +1 -1
- package/src/lib/hooks/use-extended-list-query.ts +6 -1
- package/src/lib/hooks/use-local-format.ts +15 -1
- package/src/lib/hooks/use-saved-views.ts +230 -0
- package/src/lib/hooks/use-ui-language-loader.ts +30 -0
- package/src/lib/index.ts +15 -0
- package/src/lib/lib/load-i18n-messages.ts +17 -0
- package/src/lib/lib/trans.tsx +15 -11
- package/src/lib/providers/i18n-provider.tsx +7 -14
- package/src/lib/types/saved-views.ts +39 -0
- package/src/lib/utils/saved-views-utils.ts +40 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useUserSettings } from './use-user-settings.js';
|
|
2
|
+
|
|
3
|
+
const rtlLanguageCodes = ['ar', 'he', 'fa', 'ur', 'ps'];
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* Returns information about the current display language & region.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* const {
|
|
12
|
+
* bcp47Tag,
|
|
13
|
+
* humanReadableLanguageAndLocale,
|
|
14
|
+
* humanReadableLanguage,
|
|
15
|
+
* isRTL,
|
|
16
|
+
* } = useDisplayLocale();
|
|
17
|
+
*
|
|
18
|
+
* console.log(bcp47Tag) // "en-GB"
|
|
19
|
+
* console.log(humanReadableLanguage) // "English"
|
|
20
|
+
* console.log(humanReadableLanguageAndLocale) // "British English"
|
|
21
|
+
* console.log(isRTL) // false
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @docsCategory hooks
|
|
25
|
+
* @docsPage useDisplayLocale
|
|
26
|
+
*/
|
|
27
|
+
export function useDisplayLocale() {
|
|
28
|
+
const { settings } = useUserSettings();
|
|
29
|
+
const language = settings.displayLanguage.replace(/[_-]/, '-');
|
|
30
|
+
const locale = settings.displayLocale;
|
|
31
|
+
const bcp47Tag = language.match(/[_-]/)
|
|
32
|
+
? language.replace(/[_-]/, '-')
|
|
33
|
+
: [language, locale].filter(x => !!x).join('-');
|
|
34
|
+
const humanReadableLanguageAndLocale = new Intl.DisplayNames([bcp47Tag], { type: 'language' }).of(
|
|
35
|
+
bcp47Tag,
|
|
36
|
+
);
|
|
37
|
+
const isRTL = rtlLanguageCodes.includes(language);
|
|
38
|
+
const humanReadableLanguage = new Intl.DisplayNames([bcp47Tag], { type: 'language' }).of(language);
|
|
39
|
+
return { bcp47Tag, humanReadableLanguageAndLocale, humanReadableLanguage, isRTL };
|
|
40
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { camelCaseToTitleCase } from '@/vdb/lib/utils.js';
|
|
2
|
+
import { useLingui } from '@lingui/react';
|
|
3
|
+
|
|
4
|
+
export function useDynamicTranslations() {
|
|
5
|
+
const { i18n } = useLingui();
|
|
6
|
+
|
|
7
|
+
const getTranslatedFieldName = (fieldId: string) => {
|
|
8
|
+
const fieldNameTranslationId = `fieldName.${fieldId}`;
|
|
9
|
+
const translatedDisplay = i18n.t(fieldNameTranslationId);
|
|
10
|
+
return translatedDisplay !== fieldNameTranslationId
|
|
11
|
+
? translatedDisplay
|
|
12
|
+
: camelCaseToTitleCase(fieldId);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const getTranslatedOrderState = (state: string) => {
|
|
16
|
+
const stateTranslationId = `orderState.${state}`;
|
|
17
|
+
const translatedDisplay = i18n.t(stateTranslationId);
|
|
18
|
+
return translatedDisplay !== stateTranslationId ? translatedDisplay : camelCaseToTitleCase(state);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const getTranslatedFulfillmentState = (state: string) => {
|
|
22
|
+
const stateTranslationId = `fulfillmentState.${state}`;
|
|
23
|
+
const translatedDisplay = i18n.t(stateTranslationId);
|
|
24
|
+
return translatedDisplay !== stateTranslationId ? translatedDisplay : camelCaseToTitleCase(state);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const getTranslatedPaymentState = (state: string) => {
|
|
28
|
+
const stateTranslationId = `paymentState.${state}`;
|
|
29
|
+
const translatedDisplay = i18n.t(stateTranslationId);
|
|
30
|
+
return translatedDisplay !== stateTranslationId ? translatedDisplay : camelCaseToTitleCase(state);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const getTranslatedRefundState = (state: string) => {
|
|
34
|
+
const stateTranslationId = `refundState.${state}`;
|
|
35
|
+
const translatedDisplay = i18n.t(stateTranslationId);
|
|
36
|
+
return translatedDisplay !== stateTranslationId ? translatedDisplay : camelCaseToTitleCase(state);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
getTranslatedFieldName,
|
|
41
|
+
getTranslatedOrderState,
|
|
42
|
+
getTranslatedFulfillmentState,
|
|
43
|
+
getTranslatedPaymentState,
|
|
44
|
+
getTranslatedRefundState,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { extendDetailFormQuery } from '@/vdb/framework/document-extension/extend-detail-form-query.js';
|
|
2
|
-
import { useLingui } from '
|
|
2
|
+
import { useLingui } from '@lingui/react/macro';
|
|
3
3
|
import { DocumentNode } from 'graphql';
|
|
4
4
|
import { useEffect, useMemo, useRef } from 'react';
|
|
5
5
|
import { toast } from 'sonner';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getListQueryDocuments } from '@/vdb/framework/data-table/data-table-extensions.js';
|
|
2
2
|
import { extendDocument } from '@/vdb/framework/document-extension/extend-document.js';
|
|
3
|
-
import { useLingui } from '
|
|
3
|
+
import { useLingui } from '@lingui/react/macro';
|
|
4
4
|
import { DocumentNode } from 'graphql';
|
|
5
5
|
import { useEffect, useMemo, useRef } from 'react';
|
|
6
6
|
import { toast } from 'sonner';
|
|
@@ -8,6 +8,11 @@ import { toast } from 'sonner';
|
|
|
8
8
|
import { usePageBlock } from './use-page-block.js';
|
|
9
9
|
import { usePage } from './use-page.js';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* @description
|
|
13
|
+
* Extends the given list query document with additional fields that can be
|
|
14
|
+
* supplied via the Dashboard Extension API.
|
|
15
|
+
*/
|
|
11
16
|
export function useExtendedListQuery<T extends DocumentNode>(listQuery: T) {
|
|
12
17
|
const { pageId } = usePage();
|
|
13
18
|
const { blockId } = usePageBlock() ?? {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback, useMemo } from 'react';
|
|
2
2
|
|
|
3
|
+
import { useDisplayLocale } from './use-display-locale.js';
|
|
3
4
|
import { useServerConfig } from './use-server-config.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -26,7 +27,8 @@ import { useServerConfig } from './use-server-config.js';
|
|
|
26
27
|
export function useLocalFormat() {
|
|
27
28
|
const { moneyStrategyPrecision } = useServerConfig() ?? { moneyStrategyPrecision: 2 };
|
|
28
29
|
const precisionFactor = useMemo(() => Math.pow(10, moneyStrategyPrecision), [moneyStrategyPrecision]);
|
|
29
|
-
const
|
|
30
|
+
const { bcp47Tag } = useDisplayLocale();
|
|
31
|
+
const locale = bcp47Tag;
|
|
30
32
|
|
|
31
33
|
const toMajorUnits = useCallback(
|
|
32
34
|
(value: number): number => {
|
|
@@ -119,6 +121,17 @@ export function useLocalFormat() {
|
|
|
119
121
|
[locale],
|
|
120
122
|
);
|
|
121
123
|
|
|
124
|
+
const formatRegionName = useCallback(
|
|
125
|
+
(value: string): string => {
|
|
126
|
+
try {
|
|
127
|
+
return new Intl.DisplayNames([locale], { type: 'region' }).of(value) ?? value;
|
|
128
|
+
} catch (e: any) {
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
[locale],
|
|
133
|
+
);
|
|
134
|
+
|
|
122
135
|
const formatCurrencyName = useCallback(
|
|
123
136
|
(currencyCode: string, display: 'full' | 'symbol' | 'name' = 'full'): string => {
|
|
124
137
|
if (!currencyCode) return '';
|
|
@@ -154,6 +167,7 @@ export function useLocalFormat() {
|
|
|
154
167
|
formatDate,
|
|
155
168
|
formatRelativeDate,
|
|
156
169
|
formatLanguageName,
|
|
170
|
+
formatRegionName,
|
|
157
171
|
formatCurrencyName,
|
|
158
172
|
toMajorUnits,
|
|
159
173
|
toMinorUnits,
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { api } from '@/vdb/graphql/api.js';
|
|
2
|
+
import {
|
|
3
|
+
getSettingsStoreValueDocument,
|
|
4
|
+
setSettingsStoreValueDocument,
|
|
5
|
+
} from '@/vdb/graphql/settings-store-operations.js';
|
|
6
|
+
import { SavedView, SavedViewsStore, SaveViewInput, UpdateViewInput } from '@/vdb/types/saved-views.js';
|
|
7
|
+
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
8
|
+
import { ColumnFiltersState } from '@tanstack/react-table';
|
|
9
|
+
|
|
10
|
+
import { usePageBlock } from './use-page-block.js';
|
|
11
|
+
import { usePage } from './use-page.js';
|
|
12
|
+
import { usePermissions } from './use-permissions.js';
|
|
13
|
+
|
|
14
|
+
const generateId = () => {
|
|
15
|
+
const array = new Uint32Array(2);
|
|
16
|
+
crypto.getRandomValues(array);
|
|
17
|
+
return array[0].toString(36) + array[1].toString(36);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export function useSavedViews() {
|
|
21
|
+
const queryClient = useQueryClient();
|
|
22
|
+
const { pageId } = usePage();
|
|
23
|
+
const pageBlock = usePageBlock({ optional: true });
|
|
24
|
+
const blockId = pageBlock?.blockId || 'default';
|
|
25
|
+
|
|
26
|
+
if (!pageId) {
|
|
27
|
+
throw new Error('useSavedViews must be used within a Page context');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const userViewsKey = 'vendure.dashboard.userSavedViews';
|
|
31
|
+
const globalViewsKey = 'vendure.dashboard.globalSavedViews';
|
|
32
|
+
|
|
33
|
+
// Query for user views
|
|
34
|
+
const { data: userViewsData, isLoading: userViewsLoading } = useQuery({
|
|
35
|
+
queryKey: ['saved-views-user', pageId, blockId],
|
|
36
|
+
queryFn: async () => {
|
|
37
|
+
const result = await api.query(getSettingsStoreValueDocument, { key: userViewsKey });
|
|
38
|
+
const allUserViews = (result?.getSettingsStoreValue as SavedViewsStore) || {};
|
|
39
|
+
return allUserViews[pageId]?.[blockId] || [];
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Query for global views
|
|
44
|
+
const { data: globalViewsData, isLoading: globalViewsLoading } = useQuery({
|
|
45
|
+
queryKey: ['saved-views-global', pageId, blockId],
|
|
46
|
+
queryFn: async () => {
|
|
47
|
+
const result = await api.query(getSettingsStoreValueDocument, { key: globalViewsKey });
|
|
48
|
+
const allGlobalViews = (result?.getSettingsStoreValue as SavedViewsStore) || {};
|
|
49
|
+
return allGlobalViews[pageId]?.[blockId] || [];
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Save user view mutation
|
|
54
|
+
const saveUserViewMutation = useMutation({
|
|
55
|
+
mutationFn: async (views: SavedView[]) => {
|
|
56
|
+
// Get current data first
|
|
57
|
+
const result = await api.query(getSettingsStoreValueDocument, { key: userViewsKey });
|
|
58
|
+
const allUserViews = (result?.getSettingsStoreValue as SavedViewsStore) || {};
|
|
59
|
+
|
|
60
|
+
// Update the specific page and block
|
|
61
|
+
const updatedViews = {
|
|
62
|
+
...allUserViews,
|
|
63
|
+
[pageId]: {
|
|
64
|
+
...allUserViews[pageId],
|
|
65
|
+
[blockId]: views,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return api.mutate(setSettingsStoreValueDocument, {
|
|
70
|
+
input: { key: userViewsKey, value: updatedViews },
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
onSuccess: () => {
|
|
74
|
+
void queryClient.invalidateQueries({ queryKey: ['saved-views-user', pageId, blockId] });
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Save global view mutation
|
|
79
|
+
const saveGlobalViewMutation = useMutation({
|
|
80
|
+
mutationFn: async (views: SavedView[]) => {
|
|
81
|
+
// Get current data first
|
|
82
|
+
const result = await api.query(getSettingsStoreValueDocument, { key: globalViewsKey });
|
|
83
|
+
const allGlobalViews = (result?.getSettingsStoreValue as SavedViewsStore) || {};
|
|
84
|
+
|
|
85
|
+
// Update the specific page and block
|
|
86
|
+
const updatedViews = {
|
|
87
|
+
...allGlobalViews,
|
|
88
|
+
[pageId]: {
|
|
89
|
+
...allGlobalViews[pageId],
|
|
90
|
+
[blockId]: views,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
return api.mutate(setSettingsStoreValueDocument, {
|
|
95
|
+
input: { key: globalViewsKey, value: updatedViews },
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
onSuccess: () => {
|
|
99
|
+
void queryClient.invalidateQueries({ queryKey: ['saved-views-global', pageId, blockId] });
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const saveView = async (input: SaveViewInput) => {
|
|
104
|
+
const newView: SavedView = {
|
|
105
|
+
id: generateId(),
|
|
106
|
+
name: input.name,
|
|
107
|
+
scope: input.scope,
|
|
108
|
+
filters: input.filters,
|
|
109
|
+
searchTerm: input.searchTerm,
|
|
110
|
+
pageId,
|
|
111
|
+
blockId: blockId === 'default' ? undefined : blockId,
|
|
112
|
+
createdAt: new Date().toISOString(),
|
|
113
|
+
updatedAt: new Date().toISOString(),
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
if (input.scope === 'user') {
|
|
117
|
+
const currentViews = userViewsData || [];
|
|
118
|
+
await saveUserViewMutation.mutateAsync([...currentViews, newView]);
|
|
119
|
+
} else {
|
|
120
|
+
const currentViews = globalViewsData || [];
|
|
121
|
+
await saveGlobalViewMutation.mutateAsync([...currentViews, newView]);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return newView;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const updateView = async (input: UpdateViewInput) => {
|
|
128
|
+
const userViews = userViewsData || [];
|
|
129
|
+
const globalViews = globalViewsData || [];
|
|
130
|
+
|
|
131
|
+
const viewInUserViews = userViews.find(v => v.id === input.id);
|
|
132
|
+
const viewInGlobalViews = globalViews.find(v => v.id === input.id);
|
|
133
|
+
|
|
134
|
+
if (viewInUserViews) {
|
|
135
|
+
const updatedViews = userViews.map(v =>
|
|
136
|
+
v.id === input.id
|
|
137
|
+
? {
|
|
138
|
+
...v,
|
|
139
|
+
name: input.name ?? v.name,
|
|
140
|
+
filters: input.filters ?? v.filters,
|
|
141
|
+
searchTerm: input.searchTerm !== undefined ? input.searchTerm : v.searchTerm,
|
|
142
|
+
updatedAt: new Date().toISOString(),
|
|
143
|
+
}
|
|
144
|
+
: v,
|
|
145
|
+
);
|
|
146
|
+
await saveUserViewMutation.mutateAsync(updatedViews);
|
|
147
|
+
} else if (viewInGlobalViews) {
|
|
148
|
+
const updatedViews = globalViews.map(v =>
|
|
149
|
+
v.id === input.id
|
|
150
|
+
? {
|
|
151
|
+
...v,
|
|
152
|
+
name: input.name ?? v.name,
|
|
153
|
+
filters: input.filters ?? v.filters,
|
|
154
|
+
searchTerm: input.searchTerm !== undefined ? input.searchTerm : v.searchTerm,
|
|
155
|
+
updatedAt: new Date().toISOString(),
|
|
156
|
+
}
|
|
157
|
+
: v,
|
|
158
|
+
);
|
|
159
|
+
await saveGlobalViewMutation.mutateAsync(updatedViews);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const deleteView = async (viewId: string) => {
|
|
164
|
+
const userViews = userViewsData || [];
|
|
165
|
+
const globalViews = globalViewsData || [];
|
|
166
|
+
|
|
167
|
+
if (userViews.some(v => v.id === viewId)) {
|
|
168
|
+
const updatedViews = userViews.filter(v => v.id !== viewId);
|
|
169
|
+
await saveUserViewMutation.mutateAsync(updatedViews);
|
|
170
|
+
} else if (globalViews.some(v => v.id === viewId)) {
|
|
171
|
+
const updatedViews = globalViews.filter(v => v.id !== viewId);
|
|
172
|
+
await saveGlobalViewMutation.mutateAsync(updatedViews);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const duplicateView = async (viewId: string, newScope: 'user' | 'global') => {
|
|
177
|
+
const allViews = [...(userViewsData || []), ...(globalViewsData || [])];
|
|
178
|
+
const viewToDuplicate = allViews.find(v => v.id === viewId);
|
|
179
|
+
|
|
180
|
+
if (viewToDuplicate) {
|
|
181
|
+
const newView: SavedView = {
|
|
182
|
+
...viewToDuplicate,
|
|
183
|
+
id: generateId(),
|
|
184
|
+
name: `${viewToDuplicate.name} (Copy)`,
|
|
185
|
+
scope: newScope,
|
|
186
|
+
pageId,
|
|
187
|
+
blockId: blockId === 'default' ? undefined : blockId,
|
|
188
|
+
createdAt: new Date().toISOString(),
|
|
189
|
+
updatedAt: new Date().toISOString(),
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
if (newScope === 'user') {
|
|
193
|
+
const currentViews = userViewsData || [];
|
|
194
|
+
await saveUserViewMutation.mutateAsync([...currentViews, newView]);
|
|
195
|
+
} else {
|
|
196
|
+
const currentViews = globalViewsData || [];
|
|
197
|
+
await saveGlobalViewMutation.mutateAsync([...currentViews, newView]);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return newView;
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const applyView = (
|
|
205
|
+
view: SavedView,
|
|
206
|
+
setFilters: (filters: ColumnFiltersState) => void,
|
|
207
|
+
setSearchTerm?: (term: string) => void,
|
|
208
|
+
) => {
|
|
209
|
+
setFilters(view.filters);
|
|
210
|
+
if (setSearchTerm && view.searchTerm !== undefined) {
|
|
211
|
+
setSearchTerm(view.searchTerm);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// Use UpdateSettings permission for managing global views
|
|
216
|
+
const { hasPermissions } = usePermissions();
|
|
217
|
+
const canManageGlobalViews = hasPermissions(['WriteDashboardGlobalViews']);
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
userViews: userViewsData || [],
|
|
221
|
+
globalViews: globalViewsData || [],
|
|
222
|
+
isLoading: userViewsLoading || globalViewsLoading,
|
|
223
|
+
saveView,
|
|
224
|
+
updateView,
|
|
225
|
+
deleteView,
|
|
226
|
+
duplicateView,
|
|
227
|
+
applyView,
|
|
228
|
+
canManageGlobalViews,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { loadI18nMessages } from '@/vdb/lib/load-i18n-messages.js';
|
|
2
|
+
import { useLingui } from '@lingui/react/macro';
|
|
3
|
+
|
|
4
|
+
let currentlyLoading: string | null = null;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @description
|
|
8
|
+
* Loads the UI translations for the given locale and activates it
|
|
9
|
+
* with the Lingui I18nProvider. Generally this is used internally
|
|
10
|
+
* when the display language is set via the user > language dialog.
|
|
11
|
+
*
|
|
12
|
+
* @docsCategory hooks
|
|
13
|
+
* @docsPage useUiLanguageLoader
|
|
14
|
+
*/
|
|
15
|
+
export function useUiLanguageLoader() {
|
|
16
|
+
const { i18n } = useLingui();
|
|
17
|
+
|
|
18
|
+
async function loadAndActivateLocale(locale: string) {
|
|
19
|
+
if (currentlyLoading === locale) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
currentlyLoading = locale;
|
|
23
|
+
const messages = await loadI18nMessages(locale);
|
|
24
|
+
i18n.load(locale, messages);
|
|
25
|
+
i18n.activate(locale);
|
|
26
|
+
currentlyLoading = null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return { loadAndActivateLocale };
|
|
30
|
+
}
|
package/src/lib/index.ts
CHANGED
|
@@ -22,6 +22,7 @@ export * from './components/data-input/relation-input.js';
|
|
|
22
22
|
export * from './components/data-input/relation-selector.js';
|
|
23
23
|
export * from './components/data-input/rich-text-input.js';
|
|
24
24
|
export * from './components/data-input/select-with-options.js';
|
|
25
|
+
export * from './components/data-input/slug-input.js';
|
|
25
26
|
export * from './components/data-input/struct-form-input.js';
|
|
26
27
|
export * from './components/data-input/text-input.js';
|
|
27
28
|
export * from './components/data-input/textarea-input.js';
|
|
@@ -29,6 +30,7 @@ export * from './components/data-table/add-filter-menu.js';
|
|
|
29
30
|
export * from './components/data-table/data-table-bulk-action-item.js';
|
|
30
31
|
export * from './components/data-table/data-table-bulk-actions.js';
|
|
31
32
|
export * from './components/data-table/data-table-column-header.js';
|
|
33
|
+
export * from './components/data-table/data-table-context.js';
|
|
32
34
|
export * from './components/data-table/data-table-faceted-filter.js';
|
|
33
35
|
export * from './components/data-table/data-table-filter-badge.js';
|
|
34
36
|
export * from './components/data-table/data-table-filter-dialog.js';
|
|
@@ -41,11 +43,20 @@ export * from './components/data-table/filters/data-table-datetime-filter.js';
|
|
|
41
43
|
export * from './components/data-table/filters/data-table-id-filter.js';
|
|
42
44
|
export * from './components/data-table/filters/data-table-number-filter.js';
|
|
43
45
|
export * from './components/data-table/filters/data-table-string-filter.js';
|
|
46
|
+
export * from './components/data-table/global-views-bar.js';
|
|
47
|
+
export * from './components/data-table/global-views-sheet.js';
|
|
44
48
|
export * from './components/data-table/human-readable-operator.js';
|
|
49
|
+
export * from './components/data-table/manage-global-views-button.js';
|
|
50
|
+
export * from './components/data-table/my-views-button.js';
|
|
45
51
|
export * from './components/data-table/refresh-button.js';
|
|
52
|
+
export * from './components/data-table/save-view-button.js';
|
|
53
|
+
export * from './components/data-table/save-view-dialog.js';
|
|
46
54
|
export * from './components/data-table/types.js';
|
|
47
55
|
export * from './components/data-table/use-all-bulk-actions.js';
|
|
48
56
|
export * from './components/data-table/use-generated-columns.js';
|
|
57
|
+
export * from './components/data-table/user-views-sheet.js';
|
|
58
|
+
export * from './components/data-table/views-sheet.js';
|
|
59
|
+
export * from './components/date-range-picker.js';
|
|
49
60
|
export * from './components/labeled-data.js';
|
|
50
61
|
export * from './components/layout/app-layout.js';
|
|
51
62
|
export * from './components/layout/app-sidebar.js';
|
|
@@ -98,9 +109,11 @@ export * from './components/shared/form-field-wrapper.js';
|
|
|
98
109
|
export * from './components/shared/history-timeline/history-entry-date.js';
|
|
99
110
|
export * from './components/shared/history-timeline/history-note-checkbox.js';
|
|
100
111
|
export * from './components/shared/history-timeline/history-note-editor.js';
|
|
112
|
+
export * from './components/shared/history-timeline/history-note-entry.js';
|
|
101
113
|
export * from './components/shared/history-timeline/history-note-input.js';
|
|
102
114
|
export * from './components/shared/history-timeline/history-timeline-with-grouping.js';
|
|
103
115
|
export * from './components/shared/history-timeline/history-timeline.js';
|
|
116
|
+
export * from './components/shared/history-timeline/use-history-note-editor.js';
|
|
104
117
|
export * from './components/shared/icon-mark.js';
|
|
105
118
|
export * from './components/shared/language-selector.js';
|
|
106
119
|
export * from './components/shared/logo-mark.js';
|
|
@@ -183,6 +196,7 @@ export * from './framework/dashboard-widget/metrics-widget/chart.js';
|
|
|
183
196
|
export * from './framework/dashboard-widget/metrics-widget/metrics-widget.graphql.js';
|
|
184
197
|
export * from './framework/dashboard-widget/orders-summary/order-summary-widget.graphql.js';
|
|
185
198
|
export * from './framework/dashboard-widget/widget-extensions.js';
|
|
199
|
+
export * from './framework/dashboard-widget/widget-filters-context.js';
|
|
186
200
|
export * from './framework/data-table/data-table-extensions.js';
|
|
187
201
|
export * from './framework/defaults.js';
|
|
188
202
|
export * from './framework/document-extension/extend-detail-form-query.js';
|
|
@@ -259,6 +273,7 @@ export * from './hooks/use-mobile.js';
|
|
|
259
273
|
export * from './hooks/use-page-block.js';
|
|
260
274
|
export * from './hooks/use-page.js';
|
|
261
275
|
export * from './hooks/use-permissions.js';
|
|
276
|
+
export * from './hooks/use-saved-views.js';
|
|
262
277
|
export * from './hooks/use-server-config.js';
|
|
263
278
|
export * from './hooks/use-theme.js';
|
|
264
279
|
export * from './hooks/use-user-settings.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Messages } from '@lingui/core';
|
|
2
|
+
|
|
3
|
+
export async function loadI18nMessages(locale: string): Promise<Messages> {
|
|
4
|
+
if (import.meta.env.PROD) {
|
|
5
|
+
// We add the vite-ignore directive because we do not want to transform and
|
|
6
|
+
// bundle this dynamic import. Instead, we actually want to load it at runtime
|
|
7
|
+
// as a normal dynamic JS import.
|
|
8
|
+
// These i18n JS files are generated during build by the `translationsPlugin` in the
|
|
9
|
+
// vite-plugin-translations.ts file.
|
|
10
|
+
const { messages } = await import(/* @vite-ignore */ `./i18n/${locale}.js`);
|
|
11
|
+
return messages;
|
|
12
|
+
} else {
|
|
13
|
+
// In dev mode we allow the dynamic import behaviour
|
|
14
|
+
const { messages } = await import(`../../i18n/locales/${locale}.po`);
|
|
15
|
+
return messages;
|
|
16
|
+
}
|
|
17
|
+
}
|
package/src/lib/lib/trans.tsx
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
|
+
// export { Trans } from '@lingui/react/macro';
|
|
2
|
+
// export { useLingui } from '@lingui/react';
|
|
3
|
+
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
6
|
* This is a temporary work-around because the Lingui macros do not
|
|
3
7
|
* currently work when the dashboard is packaged in an npm
|
|
4
8
|
* module. Related issue: https://github.com/kentcdodds/babel-plugin-macros/issues/87
|
|
5
9
|
*/
|
|
6
|
-
export function Trans({ children }: Readonly<{ children: React.ReactNode; context?: string }>) {
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function useLingui() {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
10
|
+
// export function Trans({ children }: Readonly<{ children: React.ReactNode; context?: string }>) {
|
|
11
|
+
// return <>{children}</>;
|
|
12
|
+
// }
|
|
13
|
+
//
|
|
14
|
+
// export function useLingui() {
|
|
15
|
+
// return {
|
|
16
|
+
// i18n: {
|
|
17
|
+
// t: (key: string) => key,
|
|
18
|
+
// },
|
|
19
|
+
// };
|
|
20
|
+
// }
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
+
import { loadI18nMessages } from '@/vdb/lib/load-i18n-messages.js';
|
|
2
|
+
import { i18n } from '@lingui/core';
|
|
3
|
+
import { I18nProvider as LinguiI18nProvider } from '@lingui/react';
|
|
1
4
|
import React from 'react';
|
|
2
|
-
// import { i18n } from '@lingui/core';
|
|
3
|
-
// import { I18nProvider as LinguiI18nProvider } from '@lingui/react';
|
|
4
5
|
|
|
5
|
-
export const locales = {
|
|
6
|
-
en: 'English',
|
|
7
|
-
de: 'Deutsch',
|
|
8
|
-
};
|
|
9
6
|
export const defaultLocale = 'en';
|
|
10
7
|
|
|
11
8
|
/**
|
|
@@ -13,16 +10,12 @@ export const defaultLocale = 'en';
|
|
|
13
10
|
* @param locale any locale string
|
|
14
11
|
*/
|
|
15
12
|
export async function dynamicActivate(locale: string, onActivate?: () => void) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// const { messages } = await import(`../../i18n/locales/${locale}.po`);
|
|
20
|
-
// i18n.load(locale, messages);
|
|
21
|
-
// i18n.activate(locale);
|
|
13
|
+
const messages = await loadI18nMessages(locale);
|
|
14
|
+
i18n.load(locale, messages);
|
|
15
|
+
i18n.activate(locale);
|
|
22
16
|
onActivate?.();
|
|
23
17
|
}
|
|
24
18
|
|
|
25
19
|
export function I18nProvider({ children }: { children: React.ReactNode }) {
|
|
26
|
-
|
|
27
|
-
return <>{children}</>;
|
|
20
|
+
return <LinguiI18nProvider i18n={i18n}>{children}</LinguiI18nProvider>;
|
|
28
21
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ColumnFiltersState } from '@tanstack/react-table';
|
|
2
|
+
|
|
3
|
+
export interface SavedView {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
scope: 'user' | 'global';
|
|
7
|
+
filters: ColumnFiltersState;
|
|
8
|
+
searchTerm?: string;
|
|
9
|
+
pageId?: string;
|
|
10
|
+
blockId?: string;
|
|
11
|
+
createdAt: string; // ISO timestamp string
|
|
12
|
+
updatedAt: string; // ISO timestamp string
|
|
13
|
+
createdBy?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface SavedViewsData {
|
|
17
|
+
userViews: SavedView[];
|
|
18
|
+
globalViews: SavedView[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface SavedViewsStore {
|
|
22
|
+
[pageId: string]: {
|
|
23
|
+
[blockId: string]: SavedView[];
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface SaveViewInput {
|
|
28
|
+
name: string;
|
|
29
|
+
scope: 'user' | 'global';
|
|
30
|
+
filters: ColumnFiltersState;
|
|
31
|
+
searchTerm?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface UpdateViewInput {
|
|
35
|
+
id: string;
|
|
36
|
+
name?: string;
|
|
37
|
+
filters?: ColumnFiltersState;
|
|
38
|
+
searchTerm?: string;
|
|
39
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ColumnFiltersState } from '@tanstack/react-table';
|
|
2
|
+
|
|
3
|
+
import { SavedView } from '../types/saved-views.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Checks if the current filters and search term match any of the provided saved views
|
|
7
|
+
* @param currentFilters - The current column filters
|
|
8
|
+
* @param currentSearchTerm - The current search term
|
|
9
|
+
* @param views - Array of saved views to check against
|
|
10
|
+
* @returns The matching saved view if found, undefined otherwise
|
|
11
|
+
*/
|
|
12
|
+
export function findMatchingSavedView(
|
|
13
|
+
currentFilters: ColumnFiltersState,
|
|
14
|
+
currentSearchTerm: string,
|
|
15
|
+
views: SavedView[],
|
|
16
|
+
): SavedView | undefined {
|
|
17
|
+
return views.find(view => {
|
|
18
|
+
const filtersMatch = JSON.stringify(view.filters) === JSON.stringify(currentFilters);
|
|
19
|
+
const searchMatch = (view.searchTerm || '') === currentSearchTerm;
|
|
20
|
+
return filtersMatch && searchMatch;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Checks if the current filters match any saved view (user or global)
|
|
26
|
+
* @param currentFilters - The current column filters
|
|
27
|
+
* @param currentSearchTerm - The current search term
|
|
28
|
+
* @param userViews - Array of user saved views
|
|
29
|
+
* @param globalViews - Array of global saved views
|
|
30
|
+
* @returns true if a matching view is found, false otherwise
|
|
31
|
+
*/
|
|
32
|
+
export function isMatchingSavedView(
|
|
33
|
+
currentFilters: ColumnFiltersState,
|
|
34
|
+
currentSearchTerm: string,
|
|
35
|
+
userViews: SavedView[],
|
|
36
|
+
globalViews: SavedView[],
|
|
37
|
+
): boolean {
|
|
38
|
+
const allViews = [...userViews, ...globalViews];
|
|
39
|
+
return findMatchingSavedView(currentFilters, currentSearchTerm, allViews) !== undefined;
|
|
40
|
+
}
|