@vendure/dashboard 3.5.0-minor-202510012036 → 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/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/package.json +9 -9
- package/src/app/routes/_authenticated/_shipping-methods/components/test-address-form.tsx +13 -12
- package/src/app/routes/_authenticated/_shipping-methods/components/test-order-builder.tsx +3 -2
- package/src/lib/components/data-table/my-views-button.tsx +12 -12
- package/src/lib/components/data-table/save-view-button.tsx +5 -1
- package/src/lib/constants.ts +10 -0
- package/src/lib/graphql/api.ts +17 -4
- package/src/lib/graphql/graphql-env.d.ts +29 -50
- package/src/lib/hooks/use-saved-views.ts +7 -0
- package/src/lib/providers/auth.tsx +2 -2
- package/src/lib/providers/channel-provider.tsx +3 -2
- 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(
|
|
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,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
|
+
}
|