@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.
- package/README.md +4 -0
- package/dist/plugin/dashboard.plugin.d.ts +25 -6
- package/dist/plugin/dashboard.plugin.js +184 -27
- package/dist/plugin/default-page.html +188 -0
- 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 +8 -6
- 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 +3 -4
- package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +4 -6
- 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 +4 -4
- 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.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-select.tsx +3 -3
- package/src/app/routes/_authenticated/_products/components/product-options-table.tsx +9 -6
- package/src/app/routes/_authenticated/_products/products.graphql.ts +31 -31
- package/src/app/routes/_authenticated/_products/products.tsx +11 -6
- package/src/app/routes/_authenticated/_products/products_.$id.tsx +4 -4
- package/src/app/routes/_authenticated/_products/products_.$id_.variants.tsx +11 -11
- package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$id.tsx +8 -12
- package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$productOptionGroupId.options_.$id.tsx +2 -2
- 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 +4 -3
- package/src/app/routes/_authenticated/_shipping-methods/components/test-order-builder.tsx +4 -3
- 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/zones.tsx +4 -4
- package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +8 -5
- package/src/app/routes/_authenticated/index.tsx +6 -2
- 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-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/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 +9 -15
- package/src/lib/components/data-table/add-filter-menu.tsx +4 -4
- package/src/lib/components/data-table/data-table-bulk-action-item.tsx +8 -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-faceted-filter.tsx +2 -1
- 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 +4 -2
- package/src/lib/components/data-table/data-table.tsx +3 -3
- package/src/lib/components/data-table/filters/data-table-boolean-filter.tsx +4 -4
- package/src/lib/components/data-table/global-views-bar.tsx +1 -1
- package/src/lib/components/data-table/human-readable-operator.tsx +1 -1
- package/src/lib/components/data-table/manage-global-views-button.tsx +1 -1
- package/src/lib/components/data-table/my-views-button.tsx +13 -13
- package/src/lib/components/data-table/refresh-button.tsx +1 -1
- package/src/lib/components/data-table/save-view-button.tsx +11 -11
- package/src/lib/components/data-table/use-generated-columns.tsx +10 -7
- package/src/lib/components/data-table/views-sheet.tsx +79 -71
- package/src/lib/components/date-range-picker.tsx +36 -34
- 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 +21 -18
- 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/constants.ts +10 -0
- package/src/lib/framework/dashboard-widget/base-widget.tsx +11 -9
- package/src/lib/framework/dashboard-widget/latest-orders-widget/index.tsx +6 -4
- package/src/lib/framework/dashboard-widget/metrics-widget/index.tsx +8 -5
- package/src/lib/framework/dashboard-widget/orders-summary/index.tsx +7 -4
- package/src/lib/framework/dashboard-widget/widget-filters-context.tsx +3 -1
- package/src/lib/framework/defaults.ts +34 -63
- 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/use-extended-router.tsx +48 -23
- package/src/lib/graphql/api.ts +22 -7
- package/src/lib/graphql/graphql-env.d.ts +13 -25
- 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 +1 -1
- package/src/lib/hooks/use-local-format.ts +15 -1
- package/src/lib/hooks/use-saved-views.ts +7 -0
- package/src/lib/hooks/use-ui-language-loader.ts +30 -0
- package/src/lib/lib/load-i18n-messages.ts +17 -0
- package/src/lib/lib/trans.tsx +15 -11
- package/src/lib/providers/auth.tsx +2 -2
- package/src/lib/providers/channel-provider.tsx +3 -2
- package/src/lib/providers/i18n-provider.tsx +7 -14
- package/src/lib/providers/user-settings.tsx +46 -5
|
@@ -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';
|
|
@@ -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,
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
getSettingsStoreValueDocument,
|
|
4
4
|
setSettingsStoreValueDocument,
|
|
5
5
|
} from '@/vdb/graphql/settings-store-operations.js';
|
|
6
|
+
import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
|
|
6
7
|
import { SavedView, SavedViewsStore, SaveViewInput, UpdateViewInput } from '@/vdb/types/saved-views.js';
|
|
7
8
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
8
9
|
import { ColumnFiltersState } from '@tanstack/react-table';
|
|
@@ -19,6 +20,7 @@ const generateId = () => {
|
|
|
19
20
|
|
|
20
21
|
export function useSavedViews() {
|
|
21
22
|
const queryClient = useQueryClient();
|
|
23
|
+
const { settingsStoreIsAvailable } = useUserSettings();
|
|
22
24
|
const { pageId } = usePage();
|
|
23
25
|
const pageBlock = usePageBlock({ optional: true });
|
|
24
26
|
const blockId = pageBlock?.blockId || 'default';
|
|
@@ -38,6 +40,8 @@ export function useSavedViews() {
|
|
|
38
40
|
const allUserViews = (result?.getSettingsStoreValue as SavedViewsStore) || {};
|
|
39
41
|
return allUserViews[pageId]?.[blockId] || [];
|
|
40
42
|
},
|
|
43
|
+
retry: false,
|
|
44
|
+
enabled: settingsStoreIsAvailable,
|
|
41
45
|
});
|
|
42
46
|
|
|
43
47
|
// Query for global views
|
|
@@ -48,6 +52,8 @@ export function useSavedViews() {
|
|
|
48
52
|
const allGlobalViews = (result?.getSettingsStoreValue as SavedViewsStore) || {};
|
|
49
53
|
return allGlobalViews[pageId]?.[blockId] || [];
|
|
50
54
|
},
|
|
55
|
+
retry: false,
|
|
56
|
+
enabled: settingsStoreIsAvailable,
|
|
51
57
|
});
|
|
52
58
|
|
|
53
59
|
// Save user view mutation
|
|
@@ -217,6 +223,7 @@ export function useSavedViews() {
|
|
|
217
223
|
const canManageGlobalViews = hasPermissions(['WriteDashboardGlobalViews']);
|
|
218
224
|
|
|
219
225
|
return {
|
|
226
|
+
savedViewsAreAvailable: settingsStoreIsAvailable,
|
|
220
227
|
userViews: userViewsData || [],
|
|
221
228
|
globalViews: globalViewsData || [],
|
|
222
229
|
isLoading: userViewsLoading || globalViewsLoading,
|
|
@@ -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
|
+
}
|
|
@@ -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,3 +1,4 @@
|
|
|
1
|
+
import { LS_KEY_SELECTED_CHANNEL_TOKEN } from '@/vdb/constants.js';
|
|
1
2
|
import { api } from '@/vdb/graphql/api.js';
|
|
2
3
|
import { graphql, ResultOf } from '@/vdb/graphql/graphql.js';
|
|
3
4
|
import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
|
|
@@ -170,8 +171,7 @@ export function AuthProvider({ children }: Readonly<{ children: React.ReactNode
|
|
|
170
171
|
// Clear all cached queries to prevent stale data
|
|
171
172
|
queryClient.clear();
|
|
172
173
|
// Clear selected channel from localStorage
|
|
173
|
-
localStorage.removeItem(
|
|
174
|
-
localStorage.removeItem('vendure-selected-channel-token');
|
|
174
|
+
localStorage.removeItem(LS_KEY_SELECTED_CHANNEL_TOKEN);
|
|
175
175
|
setStatus('unauthenticated');
|
|
176
176
|
setIsLoginLogoutInProgress(false);
|
|
177
177
|
onLogoutSuccess?.();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LS_KEY_SELECTED_CHANNEL_TOKEN } from '@/vdb/constants.js';
|
|
2
|
+
import { api } from '@/vdb/graphql/api.js';
|
|
2
3
|
import { graphql, ResultOf } from '@/vdb/graphql/graphql.js';
|
|
3
4
|
import { useAuth } from '@/vdb/hooks/use-auth.js';
|
|
4
5
|
import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
|
|
@@ -94,7 +95,7 @@ export interface ChannelContext {
|
|
|
94
95
|
*/
|
|
95
96
|
function setChannelTokenInLocalStorage(channelToken: string) {
|
|
96
97
|
try {
|
|
97
|
-
localStorage.setItem(
|
|
98
|
+
localStorage.setItem(LS_KEY_SELECTED_CHANNEL_TOKEN, channelToken);
|
|
98
99
|
} catch (e) {
|
|
99
100
|
console.error('Failed to store selected channel in localStorage', e);
|
|
100
101
|
}
|
|
@@ -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
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LS_KEY_USER_SETTINGS } from '@/vdb/constants.js';
|
|
1
2
|
import { QueryClient, useMutation, useQuery } from '@tanstack/react-query';
|
|
2
3
|
import { ColumnFiltersState } from '@tanstack/react-table';
|
|
3
4
|
import React, { createContext, useEffect, useRef, useState } from 'react';
|
|
@@ -43,6 +44,12 @@ const defaultSettings: UserSettings = {
|
|
|
43
44
|
};
|
|
44
45
|
|
|
45
46
|
export interface UserSettingsContextType {
|
|
47
|
+
/**
|
|
48
|
+
* @description
|
|
49
|
+
* Whether the server-side SettingsStore is available to use
|
|
50
|
+
* (i.e. the Vendure instance has the DashboardPlugin configured)
|
|
51
|
+
*/
|
|
52
|
+
settingsStoreIsAvailable: boolean;
|
|
46
53
|
settings: UserSettings;
|
|
47
54
|
setDisplayLanguage: (language: string) => void;
|
|
48
55
|
setDisplayLocale: (locale: string | undefined) => void;
|
|
@@ -63,7 +70,6 @@ export interface UserSettingsContextType {
|
|
|
63
70
|
|
|
64
71
|
export const UserSettingsContext = createContext<UserSettingsContextType | undefined>(undefined);
|
|
65
72
|
|
|
66
|
-
const STORAGE_KEY = 'vendure-user-settings';
|
|
67
73
|
const SETTINGS_STORE_KEY = 'vendure.dashboard.userSettings';
|
|
68
74
|
|
|
69
75
|
interface UserSettingsProviderProps {
|
|
@@ -75,7 +81,7 @@ export const UserSettingsProvider: React.FC<UserSettingsProviderProps> = ({ quer
|
|
|
75
81
|
// Load settings from localStorage or use defaults
|
|
76
82
|
const loadSettings = (): UserSettings => {
|
|
77
83
|
try {
|
|
78
|
-
const storedSettings = localStorage.getItem(
|
|
84
|
+
const storedSettings = localStorage.getItem(LS_KEY_USER_SETTINGS);
|
|
79
85
|
if (storedSettings) {
|
|
80
86
|
return { ...defaultSettings, ...JSON.parse(storedSettings) };
|
|
81
87
|
}
|
|
@@ -86,19 +92,35 @@ export const UserSettingsProvider: React.FC<UserSettingsProviderProps> = ({ quer
|
|
|
86
92
|
};
|
|
87
93
|
|
|
88
94
|
const [settings, setSettings] = useState<UserSettings>(loadSettings);
|
|
95
|
+
const [settingsStoreIsAvailable, setSettingsStoreIsAvailable] = useState<boolean>(true);
|
|
89
96
|
const [serverSettings, setServerSettings] = useState<UserSettings | null>(null);
|
|
90
97
|
const [isReady, setIsReady] = useState(false);
|
|
91
98
|
const previousContentLanguage = useRef(settings.contentLanguage);
|
|
92
99
|
const saveInProgressRef = useRef(false);
|
|
93
100
|
|
|
94
101
|
// Load settings from server on mount
|
|
95
|
-
const {
|
|
102
|
+
const {
|
|
103
|
+
data: serverSettingsResponse,
|
|
104
|
+
isSuccess: serverSettingsLoaded,
|
|
105
|
+
error,
|
|
106
|
+
} = useQuery({
|
|
96
107
|
queryKey: ['user-settings', SETTINGS_STORE_KEY],
|
|
97
108
|
queryFn: () => api.query(getSettingsStoreValueDocument, { key: SETTINGS_STORE_KEY }),
|
|
98
109
|
retry: false,
|
|
99
110
|
staleTime: 0,
|
|
111
|
+
enabled: settingsStoreIsAvailable,
|
|
100
112
|
});
|
|
101
113
|
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
if (
|
|
116
|
+
settingsStoreIsAvailable &&
|
|
117
|
+
error?.message.includes('Settings store field not registered: vendure.dashboard.userSettings')
|
|
118
|
+
) {
|
|
119
|
+
logSettingsStoreWarning();
|
|
120
|
+
setSettingsStoreIsAvailable(false);
|
|
121
|
+
}
|
|
122
|
+
}, [settingsStoreIsAvailable, error]);
|
|
123
|
+
|
|
102
124
|
// Mutation to save settings to server
|
|
103
125
|
const saveToServerMutation = useMutation({
|
|
104
126
|
mutationFn: (settingsToSave: UserSettings) =>
|
|
@@ -144,7 +166,7 @@ export const UserSettingsProvider: React.FC<UserSettingsProviderProps> = ({ quer
|
|
|
144
166
|
// Save settings to localStorage whenever they change
|
|
145
167
|
useEffect(() => {
|
|
146
168
|
try {
|
|
147
|
-
localStorage.setItem(
|
|
169
|
+
localStorage.setItem(LS_KEY_USER_SETTINGS, JSON.stringify(settings));
|
|
148
170
|
} catch (e) {
|
|
149
171
|
console.error('Failed to save user settings to localStorage', e);
|
|
150
172
|
}
|
|
@@ -152,7 +174,7 @@ export const UserSettingsProvider: React.FC<UserSettingsProviderProps> = ({ quer
|
|
|
152
174
|
|
|
153
175
|
// Save to server when settings differ from server state
|
|
154
176
|
useEffect(() => {
|
|
155
|
-
if (isReady && serverSettings && !saveInProgressRef.current) {
|
|
177
|
+
if (settingsStoreIsAvailable && isReady && serverSettings && !saveInProgressRef.current) {
|
|
156
178
|
const serverDiffers = JSON.stringify(serverSettings) !== JSON.stringify(settings);
|
|
157
179
|
|
|
158
180
|
if (serverDiffers) {
|
|
@@ -177,6 +199,7 @@ export const UserSettingsProvider: React.FC<UserSettingsProviderProps> = ({ quer
|
|
|
177
199
|
};
|
|
178
200
|
|
|
179
201
|
const contextValue: UserSettingsContextType = {
|
|
202
|
+
settingsStoreIsAvailable,
|
|
180
203
|
settings,
|
|
181
204
|
setDisplayLanguage: language => updateSetting('displayLanguage', language),
|
|
182
205
|
setDisplayLocale: locale => updateSetting('displayLocale', locale),
|
|
@@ -201,3 +224,21 @@ export const UserSettingsProvider: React.FC<UserSettingsProviderProps> = ({ quer
|
|
|
201
224
|
|
|
202
225
|
return <UserSettingsContext.Provider value={contextValue}>{children}</UserSettingsContext.Provider>;
|
|
203
226
|
};
|
|
227
|
+
|
|
228
|
+
function logSettingsStoreWarning() {
|
|
229
|
+
// eslint-disable-next-line no-console
|
|
230
|
+
console.warn(
|
|
231
|
+
[
|
|
232
|
+
`User settings could not be fetched from the Vendure server.`,
|
|
233
|
+
`This suggests that the DashboardPlugin is not configured.`,
|
|
234
|
+
`Check your VendureConfig and ensure the DashboardPlugin is in your plugins array.`,
|
|
235
|
+
``,
|
|
236
|
+
`By setting up the DashboardPlugin, you can take advantage of:`,
|
|
237
|
+
` - Persisted settings across browsers and devices`,
|
|
238
|
+
` - Saved views on list pages`,
|
|
239
|
+
` - Metrics on the Insights page`,
|
|
240
|
+
``,
|
|
241
|
+
`https://docs.vendure.io/reference/core-plugins/dashboard-plugin/`,
|
|
242
|
+
].join('\n'),
|
|
243
|
+
);
|
|
244
|
+
}
|