@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.
@@ -7,6 +7,7 @@ import { AccordionContent, AccordionItem, AccordionTrigger } from '@/vdb/compone
7
7
  import { Button } from '@/vdb/components/ui/button.js';
8
8
  import { Input } from '@/vdb/components/ui/input.js';
9
9
  import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/vdb/components/ui/table.js';
10
+ import { LS_KEY_SHIPPING_TEST_ORDER } from '@/vdb/constants.js';
10
11
  import { useChannel } from '@/vdb/hooks/use-channel.js';
11
12
  import { useLocalFormat } from '@/vdb/hooks/use-local-format.js';
12
13
  import { Trans } from '@lingui/react/macro';
@@ -38,7 +39,7 @@ export function TestOrderBuilder({ onOrderLinesChange }: Readonly<TestOrderBuild
38
39
  const { activeChannel } = useChannel();
39
40
  const [lines, setLines] = useState<TestOrderLine[]>(() => {
40
41
  try {
41
- const stored = localStorage.getItem('shippingTestOrder');
42
+ const stored = localStorage.getItem(LS_KEY_SHIPPING_TEST_ORDER);
42
43
  return stored ? JSON.parse(stored) : [];
43
44
  } catch {
44
45
  return [];
@@ -51,7 +52,7 @@ export function TestOrderBuilder({ onOrderLinesChange }: Readonly<TestOrderBuild
51
52
 
52
53
  useEffect(() => {
53
54
  try {
54
- localStorage.setItem('shippingTestOrder', JSON.stringify(lines));
55
+ localStorage.setItem(LS_KEY_SHIPPING_TEST_ORDER, JSON.stringify(lines));
55
56
  } catch {
56
57
  // Ignore localStorage errors
57
58
  }
@@ -1,23 +1,27 @@
1
- import { Bookmark } from 'lucide-react';
2
- import React, { useState, useMemo } from 'react';
3
- import { Button } from '../ui/button.js';
4
- import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip.js';
5
1
  import { Trans } from '@lingui/react/macro';
6
- import { UserViewsSheet } from './user-views-sheet.js';
2
+ import { Bookmark } from 'lucide-react';
3
+ import React, { useMemo, useState } from 'react';
7
4
  import { useSavedViews } from '../../hooks/use-saved-views.js';
8
5
  import { findMatchingSavedView } from '../../utils/saved-views-utils.js';
6
+ import { Button } from '../ui/button.js';
7
+ import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip.js';
9
8
  import { useDataTableContext } from './data-table-context.js';
9
+ import { UserViewsSheet } from './user-views-sheet.js';
10
10
 
11
11
  export const MyViewsButton: React.FC = () => {
12
12
  const [sheetOpen, setSheetOpen] = useState(false);
13
- const { userViews } = useSavedViews();
14
- const { columnFilters, searchTerm, handleApplyView } = useDataTableContext();
13
+ const { userViews, savedViewsAreAvailable } = useSavedViews();
14
+ const { columnFilters, searchTerm } = useDataTableContext();
15
15
 
16
16
  // Find the active view using centralized utility
17
17
  const activeView = useMemo(() => {
18
18
  return findMatchingSavedView(columnFilters, searchTerm, userViews);
19
19
  }, [userViews, columnFilters, searchTerm]);
20
20
 
21
+ if (!savedViewsAreAvailable) {
22
+ return null;
23
+ }
24
+
21
25
  return (
22
26
  <>
23
27
  <div className="flex items-center gap-2">
@@ -35,11 +39,7 @@ export const MyViewsButton: React.FC = () => {
35
39
  <Trans>My saved views</Trans>
36
40
  </TooltipContent>
37
41
  </Tooltip>
38
- {activeView && (
39
- <span className="text-sm text-muted-foreground">
40
- {activeView.name}
41
- </span>
42
- )}
42
+ {activeView && <span className="text-sm text-muted-foreground">{activeView.name}</span>}
43
43
  </div>
44
44
  <UserViewsSheet open={sheetOpen} onOpenChange={setSheetOpen} />
45
45
  </>
@@ -13,7 +13,7 @@ interface SaveViewButtonProps {
13
13
 
14
14
  export const SaveViewButton: React.FC<SaveViewButtonProps> = ({ disabled }) => {
15
15
  const [dialogOpen, setDialogOpen] = useState(false);
16
- const { userViews, globalViews } = useSavedViews();
16
+ const { userViews, globalViews, savedViewsAreAvailable } = useSavedViews();
17
17
  const { columnFilters, searchTerm } = useDataTableContext();
18
18
 
19
19
  const hasFilters = columnFilters.length > 0 || (searchTerm && searchTerm.length > 0);
@@ -24,6 +24,10 @@ export const SaveViewButton: React.FC<SaveViewButtonProps> = ({ disabled }) => {
24
24
  return null;
25
25
  }
26
26
 
27
+ if (!savedViewsAreAvailable) {
28
+ return null;
29
+ }
30
+
27
31
  return (
28
32
  <>
29
33
  <Button variant="outline" size="sm" onClick={() => setDialogOpen(true)} disabled={disabled}>
@@ -3,6 +3,16 @@ export const AUTHENTICATED_ROUTE_PREFIX = '/_authenticated';
3
3
  export const DEFAULT_CHANNEL_CODE = '__default_channel__';
4
4
  export const SUPER_ADMIN_ROLE_CODE = '__super_admin_role__';
5
5
  export const CUSTOMER_ROLE_CODE = '__customer_role__';
6
+
7
+ /**
8
+ * Local storage keys
9
+ */
10
+ export const LS_KEY_SESSION_TOKEN = 'vendure-session-token';
11
+ export const LS_KEY_USER_SETTINGS = 'vendure-user-settings';
12
+ export const LS_KEY_SELECTED_CHANNEL_TOKEN = 'vendure-selected-channel-token';
13
+ export const LS_KEY_SHIPPING_TEST_ORDER = 'vendure-shipping-test-order';
14
+ export const LS_KEY_SHIPPING_TEST_ADDRESS = 'vendure-shipping-test-address';
15
+
6
16
  /**
7
17
  * This is copied from the generated types from @vendure/common/lib/generated-types.d.ts
8
18
  * It is used to provide a list of available currency codes for the user to select from.
@@ -1,3 +1,8 @@
1
+ import {
2
+ LS_KEY_SELECTED_CHANNEL_TOKEN,
3
+ LS_KEY_SESSION_TOKEN,
4
+ LS_KEY_USER_SETTINGS,
5
+ } from '@/vdb/constants.js';
1
6
  import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
2
7
  import { AwesomeGraphQLClient } from 'awesome-graphql-client';
3
8
  import { DocumentNode, print } from 'graphql';
@@ -12,8 +17,6 @@ const API_URL =
12
17
  `:${uiConfig.api.port !== 'auto' ? uiConfig.api.port : window.location.port}` +
13
18
  `/${uiConfig.api.adminApiPath}`;
14
19
 
15
- export const SELECTED_CHANNEL_TOKEN_KEY = 'vendure-selected-channel-token';
16
-
17
20
  export type Variables = object;
18
21
  export type RequestDocument = string | DocumentNode;
19
22
 
@@ -21,9 +24,13 @@ const awesomeClient = new AwesomeGraphQLClient({
21
24
  endpoint: API_URL,
22
25
  fetch: async (url: string, options: RequestInit = {}) => {
23
26
  // Get the active channel token from localStorage
24
- const channelToken = localStorage.getItem(SELECTED_CHANNEL_TOKEN_KEY);
27
+ const channelToken = localStorage.getItem(LS_KEY_SELECTED_CHANNEL_TOKEN);
28
+ const sessionToken = localStorage.getItem(LS_KEY_SESSION_TOKEN);
25
29
  const headers = new Headers(options.headers);
26
30
 
31
+ if (sessionToken) {
32
+ headers.set('Authorization', `Bearer ${sessionToken}`);
33
+ }
27
34
  if (channelToken) {
28
35
  headers.set(uiConfig.api.channelTokenKey, channelToken);
29
36
  }
@@ -31,7 +38,7 @@ const awesomeClient = new AwesomeGraphQLClient({
31
38
  // Get the content language from user settings and add as query parameter
32
39
  let finalUrl = url;
33
40
  try {
34
- const userSettings = localStorage.getItem('vendure-user-settings');
41
+ const userSettings = localStorage.getItem(LS_KEY_USER_SETTINGS);
35
42
  if (userSettings) {
36
43
  const settings = JSON.parse(userSettings);
37
44
  const contentLanguage = settings.contentLanguage;
@@ -52,6 +59,12 @@ const awesomeClient = new AwesomeGraphQLClient({
52
59
  headers,
53
60
  credentials: 'include',
54
61
  mode: 'cors',
62
+ }).then(res => {
63
+ const authToken = res.headers.get('vendure-auth-token');
64
+ if (authToken) {
65
+ localStorage.setItem(LS_KEY_SESSION_TOKEN, authToken);
66
+ }
67
+ return res;
55
68
  });
56
69
  },
57
70
  });