@vendure/dashboard 3.5.0-minor-202510012036 → 3.5.0-minor-202510071456

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 (38) hide show
  1. package/dist/plugin/dashboard.plugin.d.ts +25 -6
  2. package/dist/plugin/dashboard.plugin.js +184 -27
  3. package/dist/plugin/default-page.html +188 -0
  4. package/dist/vite/utils/tsconfig-utils.js +2 -1
  5. package/package.json +10 -9
  6. package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +4 -8
  7. package/src/app/routes/_authenticated/_global-settings/utils/global-languages.ts +268 -0
  8. package/src/app/routes/_authenticated/_orders/components/order-address.tsx +15 -15
  9. package/src/app/routes/_authenticated/_orders/components/order-detail-shared.tsx +4 -4
  10. package/src/app/routes/_authenticated/_product-variants/components/add-currency-dropdown.tsx +49 -0
  11. package/src/app/routes/_authenticated/_product-variants/components/add-stock-location-dropdown.tsx +56 -0
  12. package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +12 -0
  13. package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +178 -50
  14. package/src/app/routes/_authenticated/_products/components/product-variants-table.tsx +0 -11
  15. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +3 -14
  16. package/src/app/routes/_authenticated/_shipping-methods/components/test-address-form.tsx +13 -12
  17. package/src/app/routes/_authenticated/_shipping-methods/components/test-order-builder.tsx +3 -2
  18. package/src/lib/components/data-input/customer-group-input.tsx +0 -1
  19. package/src/lib/components/data-input/money-input.tsx +7 -11
  20. package/src/lib/components/data-input/number-input.tsx +6 -1
  21. package/src/lib/components/data-table/data-table-filter-badge.tsx +15 -8
  22. package/src/lib/components/data-table/data-table.tsx +2 -2
  23. package/src/lib/components/data-table/my-views-button.tsx +12 -12
  24. package/src/lib/components/data-table/save-view-button.tsx +5 -1
  25. package/src/lib/components/layout/generated-breadcrumbs.tsx +4 -12
  26. package/src/lib/components/shared/configurable-operation-input.tsx +1 -1
  27. package/src/lib/constants.ts +10 -0
  28. package/src/lib/framework/dashboard-widget/latest-orders-widget/index.tsx +0 -2
  29. package/src/lib/framework/extension-api/types/layout.ts +41 -1
  30. package/src/lib/framework/form-engine/value-transformers.ts +8 -1
  31. package/src/lib/framework/layout-engine/page-layout.tsx +58 -48
  32. package/src/lib/framework/page/detail-page.tsx +12 -15
  33. package/src/lib/graphql/api.ts +17 -4
  34. package/src/lib/graphql/graphql-env.d.ts +29 -50
  35. package/src/lib/hooks/use-saved-views.ts +7 -0
  36. package/src/lib/providers/auth.tsx +2 -2
  37. package/src/lib/providers/channel-provider.tsx +4 -2
  38. package/src/lib/providers/user-settings.tsx +46 -5
@@ -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,
@@ -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('vendure-selected-channel');
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 { api, SELECTED_CHANNEL_TOKEN_KEY } from '@/vdb/graphql/api.js';
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';
@@ -15,6 +16,7 @@ const channelFragment = graphql(`
15
16
  defaultCurrencyCode
16
17
  pricesIncludeTax
17
18
  availableLanguageCodes
19
+ availableCurrencyCodes
18
20
  }
19
21
  `);
20
22
 
@@ -94,7 +96,7 @@ export interface ChannelContext {
94
96
  */
95
97
  function setChannelTokenInLocalStorage(channelToken: string) {
96
98
  try {
97
- localStorage.setItem(SELECTED_CHANNEL_TOKEN_KEY, channelToken);
99
+ localStorage.setItem(LS_KEY_SELECTED_CHANNEL_TOKEN, channelToken);
98
100
  } catch (e) {
99
101
  console.error('Failed to store selected channel in localStorage', e);
100
102
  }
@@ -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(STORAGE_KEY);
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 { data: serverSettingsResponse, isSuccess: serverSettingsLoaded } = useQuery({
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(STORAGE_KEY, JSON.stringify(settings));
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
+ }