Skip to content

Commit afe8f18

Browse files
handle update service fallback
cache update service response
1 parent 6266eae commit afe8f18

File tree

11 files changed

+75
-24
lines changed

11 files changed

+75
-24
lines changed

webnext/src/pages/ClientDownload/ClientDownloadPage.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import './style.scss';
2-
import { useLoaderData, useNavigate } from '@tanstack/react-router';
2+
import { useQuery } from '@tanstack/react-query';
3+
import { useNavigate } from '@tanstack/react-router';
34
import { useMemo, useState } from 'react';
45
import { m } from '../../paraglide/messages';
56
import { Page } from '../../shared/components/Page/Page';
@@ -16,19 +17,17 @@ import { ModalControls } from '../../shared/defguard-ui/components/ModalControls
1617
import { SizedBox } from '../../shared/defguard-ui/components/SizedBox/SizedBox';
1718
import { ThemeSpacing } from '../../shared/defguard-ui/types';
1819
import { isPresent } from '../../shared/defguard-ui/utils/isPresent';
20+
import { getClientArtifactsQueryOptions } from '../../shared/query/queryOptions';
1921
import { openVirtualLink } from '../../shared/utils/openVirtualLink';
2022
import androidIcon from './assets/android.png';
2123
import apple_video_src from './assets/apple_hardware_help.mp4';
2224
import iosIcon from './assets/ios.png';
2325
import laptopIcon from './assets/laptop.png';
2426
import desktopIcon from './assets/pc-tower.png';
2527

26-
// open link in onClick handler
27-
2828
export const ClientDownloadPage = () => {
29-
const pageData = useLoaderData({
30-
from: '/download',
31-
});
29+
const { data: pageData } = useQuery(getClientArtifactsQueryOptions);
30+
3231
const navigate = useNavigate();
3332

3433
const [confirmModalOpen, setConfirmModalOpen] = useState(false);

webnext/src/pages/ClientDownload/style.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
& > img {
3535
width: 60px;
3636
height: 60px;
37+
user-select: none;
3738
}
3839

3940
.btn {

webnext/src/pages/enrollment/ConfigureClient/ConfigureClientPage.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import './style.scss';
22

3+
import { useQuery } from '@tanstack/react-query';
34
import { useLoaderData } from '@tanstack/react-router';
45
import { capitalCase } from 'change-case';
56
import { QRCodeCanvas } from 'qrcode.react';
@@ -19,13 +20,15 @@ import { Icon } from '../../../shared/defguard-ui/components/Icon';
1920
import type { MenuItemsGroup } from '../../../shared/defguard-ui/components/Menu/types';
2021
import { SizedBox } from '../../../shared/defguard-ui/components/SizedBox/SizedBox';
2122
import { ThemeSpacing } from '../../../shared/defguard-ui/types';
23+
import { getClientArtifactsQueryOptions } from '../../../shared/query/queryOptions';
2224
import { openVirtualLink } from '../../../shared/utils/openVirtualLink';
2325

2426
export const ConfigureClientPage = () => {
2527
const pageData = useLoaderData({
2628
from: '/client-setup',
2729
});
28-
const clientLinks = pageData.clientDownload;
30+
31+
const { data: clientLinks } = useQuery(getClientArtifactsQueryOptions);
2932

3033
const clientDownloadMenu = useMemo(
3134
(): MenuItemsGroup[] => [

webnext/src/routes/client-setup.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { createFileRoute, redirect } from '@tanstack/react-router';
22
import z from 'zod';
3+
import { queryClient } from '../app/query';
34
import { ConfigureClientPage } from '../pages/enrollment/ConfigureClient/ConfigureClientPage';
45
import { api } from '../shared/api/api';
56
import type { EnrollmentStartResponse } from '../shared/api/types';
6-
import { updateServiceApi } from '../shared/api/update-service';
77
import { isPresent } from '../shared/defguard-ui/utils/isPresent';
88
import { useEnrollmentStore } from '../shared/hooks/useEnrollmentStore';
9+
import { getClientArtifactsQueryOptions } from '../shared/query/queryOptions';
910

1011
const schema = z.object({
1112
code: z.string().trim().optional(),
@@ -39,7 +40,8 @@ export const Route = createFileRoute('/client-setup')({
3940
};
4041
},
4142
loader: async ({ context: { openid } }) => {
42-
const clientDownload = await updateServiceApi.getClientArtifacts().catch(() => null);
43+
void queryClient.ensureQueryData(getClientArtifactsQueryOptions);
44+
4345
if (openid) {
4446
try {
4547
const openIdResponse = await api.openId.enrollmentCallback.callbackFn({
@@ -70,7 +72,6 @@ export const Route = createFileRoute('/client-setup')({
7072
}
7173
const state = useEnrollmentStore.getState();
7274
return {
73-
clientDownload,
7475
token: state.token as string,
7576
enrollmentData: state.enrollmentData as EnrollmentStartResponse,
7677
};

webnext/src/routes/download.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
import { createFileRoute } from '@tanstack/react-router';
2+
import { queryClient } from '../app/query';
23
import { ClientDownloadPage } from '../pages/ClientDownload/ClientDownloadPage';
3-
import { updateServiceApi } from '../shared/api/update-service';
4+
import { getClientArtifactsQueryOptions } from '../shared/query/queryOptions';
45

56
export const Route = createFileRoute('/download')({
67
component: ClientDownloadPage,
7-
loader: async () => {
8-
const clientVersionData = await updateServiceApi
9-
.getClientArtifacts()
10-
.catch(() => null);
11-
return clientVersionData;
12-
},
8+
loader: () => queryClient.ensureQueryData(getClientArtifactsQueryOptions),
139
});

webnext/src/shared/api/update-service.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import qs from 'qs';
33

44
const baseUrl = import.meta.env.VITE_UPDATE_BASE_URL as string | undefined;
55

6+
const clientDownloadFallback = 'https://defguard.net/download';
7+
68
const client = axios.create({
79
baseURL: baseUrl ?? 'https://update-service-dev.defguard.net/api',
810
headers: { 'Content-Type': 'application/json' },
@@ -33,7 +35,32 @@ const updateServiceApi = {
3335
source: 'enrollment',
3436
},
3537
})
36-
.then((response) => response.data),
38+
.then((response) => {
39+
const { data } = response;
40+
const res: ClientVersionCheck = {
41+
deb_amd64: data.deb_amd64 ?? clientDownloadFallback,
42+
deb_arm64: data.deb_arm64 ?? clientDownloadFallback,
43+
macos_amd64: data.macos_amd64 ?? clientDownloadFallback,
44+
macos_arm64: data.macos_arm64 ?? clientDownloadFallback,
45+
rpm_amd64: data.rpm_amd64 ?? clientDownloadFallback,
46+
rpm_arm64: data.rpm_arm64 ?? clientDownloadFallback,
47+
windows_amd64: data.windows_amd64 ?? clientDownloadFallback,
48+
};
49+
return res;
50+
})
51+
.catch((e) => {
52+
console.error(e);
53+
const fallback: ClientVersionCheck = {
54+
deb_amd64: clientDownloadFallback,
55+
deb_arm64: clientDownloadFallback,
56+
macos_amd64: clientDownloadFallback,
57+
macos_arm64: clientDownloadFallback,
58+
rpm_amd64: clientDownloadFallback,
59+
rpm_arm64: clientDownloadFallback,
60+
windows_amd64: clientDownloadFallback,
61+
};
62+
return fallback;
63+
}),
3764
} as const;
3865

3966
export { updateServiceApi };

webnext/src/shared/defguard-ui/components/Menu/Menu.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,16 @@ import { MenuHeader } from './components/MenuHeader';
77
import { MenuSpacer } from './components/MenuSpacer';
88
import type { MenuProps } from './types';
99

10-
export const Menu = ({ itemGroups, ref, className, onClose, ...props }: MenuProps) => {
10+
export const Menu = ({
11+
itemGroups,
12+
ref,
13+
className,
14+
onClose,
15+
testId,
16+
...props
17+
}: MenuProps) => {
1118
return (
12-
<div className={clsx('menu', className)} ref={ref} {...props}>
19+
<div className={clsx('menu', className)} ref={ref} data-testid={testId} {...props}>
1320
{itemGroups.map((group, groupIndex) => (
1421
<Fragment key={group.header?.text ?? groupIndex}>
1522
{isPresent(group.header) && <MenuHeader {...group.header} onClose={onClose} />}

webnext/src/shared/defguard-ui/components/Menu/components/MenuHeader.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import { isPresent } from '../../../utils/isPresent';
33
import { InteractionBox } from '../../InteractionBox/InteractionBox';
44
import type { MenuHeaderProps } from '../types';
55

6-
export const MenuHeader = ({ text, onHelp, onClose }: MenuHeaderProps) => {
6+
export const MenuHeader = ({ text, testId, onHelp, onClose }: MenuHeaderProps) => {
77
return (
88
<div
99
className={clsx('menu-header', {
1010
'with-help': isPresent(onHelp),
1111
})}
12+
data-testid={testId}
1213
>
1314
<p className="group-title">{text}</p>
1415
{isPresent(onHelp) && (

webnext/src/shared/defguard-ui/components/Menu/components/MenuItem.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ export const MenuItem = ({
88
text,
99
icon,
1010
items,
11+
testId,
12+
variant,
1113
onClick,
1214
onClose,
13-
variant,
1415
}: MenuItemProps) => {
1516
const hasItems = isPresent(items) && items.length > 0;
1617
const hasIcon = isPresent(icon);
@@ -25,6 +26,7 @@ export const MenuItem = ({
2526
'grid-full': hasIcon && hasItems,
2627
nested: hasItems,
2728
})}
29+
data-testid={testId}
2830
onClick={() => {
2931
if (!disabled) {
3032
onClick?.();

webnext/src/shared/defguard-ui/components/Menu/types.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import type { IconKindValue } from '../Icon/icon-types';
33

44
export interface MenuProps extends HTMLAttributes<HTMLDivElement> {
55
itemGroups: MenuItemsGroup[];
6-
onClose?: () => void;
76
ref?: Ref<HTMLDivElement>;
7+
testId?: string;
8+
onClose?: () => void;
89
}
910

1011
export interface MenuItemsGroup {
@@ -15,16 +16,18 @@ export interface MenuItemsGroup {
1516
export interface MenuItemProps {
1617
text: string;
1718
variant?: 'default' | 'danger';
19+
disabled?: boolean;
1820
icon?: IconKindValue;
1921
items?: MenuItemProps[];
20-
disabled?: boolean;
22+
testId?: string;
2123
onClick?: () => void;
2224
onClose?: () => void;
2325
}
2426

2527
export interface MenuHeaderProps {
2628
text: string;
2729
tooltip?: string;
30+
testId?: string;
2831
onClose?: () => void;
2932
onHelp?: () => void;
3033
}

0 commit comments

Comments
 (0)