Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import './style.scss';
import parse from 'html-react-parser';
import { isUndefined } from 'lodash-es';
import { ReactNode, useEffect, useMemo } from 'react';
import QRCode from 'react-qr-code';
import { useNavigate } from 'react-router';
import { shallow } from 'zustand/shallow';

Expand All @@ -13,12 +14,29 @@ import { Card } from '../../../../shared/defguard-ui/components/Layout/Card/Card
import { ExpandableCard } from '../../../../shared/defguard-ui/components/Layout/ExpandableCard/ExpandableCard';
import { MessageBox } from '../../../../shared/defguard-ui/components/Layout/MessageBox/MessageBox';
import { MessageBoxType } from '../../../../shared/defguard-ui/components/Layout/MessageBox/types';
import { isPresent } from '../../../../shared/defguard-ui/utils/isPresent';
import { useAppStore } from '../../../../shared/hooks/store/useAppStore';
import { useAuthStore } from '../../../../shared/hooks/store/useAuthStore';
import useApi from '../../../../shared/hooks/useApi';
import { useClipboard } from '../../../../shared/hooks/useClipboard';
import { useAddDevicePageStore } from '../../hooks/useAddDevicePageStore';

const useLocalProxy = import.meta.env.DEV;

const extractProxyPort = (input: string): string | undefined => {
try {
const url = new URL(input);
const port = url.port;
const parsed = port ? parseInt(port, 10) : undefined;
if (parsed && !isNaN(parsed)) {
return `:${parsed}`;
}
return undefined;
} catch {
return undefined;
}
};

export const AddDeviceTokenStep = () => {
const { writeToClipboard } = useClipboard();
const { LL } = useI18nContext();
Expand All @@ -40,6 +58,26 @@ export const AddDeviceTokenStep = () => {
shallow,
);

const mobileQrData = useMemo(() => {
if (isPresent(url) && isPresent(token)) {
let targetUrl: string;
if (useLocalProxy) {
const proxyPort = extractProxyPort(url) ?? '';
targetUrl = `http://10.0.2.2${proxyPort}`;
} else {
targetUrl = url;
}
const registration = {
token,
url: targetUrl,
};
const registrationJson = JSON.stringify(registration);
const encoded = btoa(registrationJson);
return encoded;
}
return undefined;
}, [token, url]);

const tokenActions = useMemo(
(): ReactNode[] => [
<ActionButton
Expand Down Expand Up @@ -108,6 +146,17 @@ export const AddDeviceTokenStep = () => {
<ExpandableCard title={localLL.tokenCardTitle()} actions={tokenActions} expanded>
<p>{token}</p>
</ExpandableCard>
<MessageBox message="If you have defguard client installed on a mobile device you can scan the QR below with your defguard client application." />
{isPresent(mobileQrData) && (
<ExpandableCard
id="mobile-qr-code"
title="Scan with mobile device"
expanded
disableExpand
>
<QRCode value={mobileQrData} size={250} />
</ExpandableCard>
)}
</Card>
</>
);
Expand Down
18 changes: 18 additions & 0 deletions web/src/pages/addDevice/steps/AddDeviceTokenStep/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,23 @@
.expandable-card {
margin-bottom: 25px;
}

#mobile-qr-code {
.expanded-content {
display: flex;
flex-flow: column;
align-items: center;
justify-content: center;
overflow: hidden;
box-sizing: border-box;
row-gap: 20px;

p {
max-width: 80%;
margin: 0;
padding: 0;
}
}
}
}
}
4 changes: 3 additions & 1 deletion web/src/pages/overview-index/OverviewIndexPage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import './style.scss';

import { useQuery } from '@tanstack/react-query';
import { range } from 'lodash-es';
import { orderBy, range } from 'lodash-es';
import { useEffect } from 'react';
import Skeleton from 'react-loading-skeleton';
import { useLocation, useNavigate } from 'react-router';
Expand Down Expand Up @@ -35,6 +35,8 @@ export const OverviewIndexPage = () => {
queryKey: ['network'],
queryFn: getNetworks,
placeholderData: (perv) => perv,
select: (networks) =>
orderBy(networks, (network) => network.name.toLowerCase(), ['asc']),
});

const resetWizard = useWizardStore((state) => state.resetState);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useQuery } from '@tanstack/react-query';
import { orderBy } from 'lodash-es';
import { useMemo } from 'react';
import { useLocation, useNavigate, useParams } from 'react-router-dom';

Expand Down Expand Up @@ -26,6 +27,8 @@ export const OverviewNetworkSelection = () => {
queryKey: ['network'],
queryFn: getNetworks,
placeholderData: (perv) => perv,
select: (networks) =>
orderBy(networks, (network) => network.name.toLowerCase(), ['asc']),
});

const selectionValue = useMemo(() => {
Expand Down
2 changes: 2 additions & 0 deletions web/src/pages/overview/OverviewPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export const OverviewPage = () => {
queryKey: ['network'],
queryFn: getNetworks,
placeholderData: (perv) => perv,
select: (networks) =>
orderBy(networks, (network) => network.name.toLowerCase(), ['asc']),
});

const { data: networkStats } = useQuery({
Expand Down