From 6a6a03648475a62c5756fdd43935504ca920dd75 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski <jchmielewski@teonite.com> Date: Wed, 20 Mar 2024 11:39:24 +0100 Subject: [PATCH 1/2] Display "no networks" message UI --- web/src/i18n/en/index.ts | 1 + web/src/i18n/i18n-types.ts | 8 ++++++++ .../ConfigureDeviceCard/ConfigureDeviceCard.tsx | 11 +++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/web/src/i18n/en/index.ts b/web/src/i18n/en/index.ts index 3d5dbf5..b91c450 100644 --- a/web/src/i18n/en/index.ts +++ b/web/src/i18n/en/index.ts @@ -134,6 +134,7 @@ If you have any questions, please consult your assigned admin.All necessary info }, }, }, + noNetworksMessage: "You don't have access to any networks", config: { messageBox: { auto: ` diff --git a/web/src/i18n/i18n-types.ts b/web/src/i18n/i18n-types.ts index a2d9682..ae9799b 100644 --- a/web/src/i18n/i18n-types.ts +++ b/web/src/i18n/i18n-types.ts @@ -293,6 +293,10 @@ type RootTranslation = { } } } + /** + * You don't have access to any networks + */ + noNetworksMessage: string config: { messageBox: { /** @@ -851,6 +855,10 @@ export type TranslationFunctions = { } } } + /** + * You don't have access to any networks + */ + noNetworksMessage: () => LocalizedString config: { messageBox: { /** diff --git a/web/src/pages/enrollment/steps/DeviceStep/components/ConfigureDeviceCard/ConfigureDeviceCard.tsx b/web/src/pages/enrollment/steps/DeviceStep/components/ConfigureDeviceCard/ConfigureDeviceCard.tsx index 0ac6e19..fc5df46 100644 --- a/web/src/pages/enrollment/steps/DeviceStep/components/ConfigureDeviceCard/ConfigureDeviceCard.tsx +++ b/web/src/pages/enrollment/steps/DeviceStep/components/ConfigureDeviceCard/ConfigureDeviceCard.tsx @@ -4,6 +4,8 @@ import { isUndefined } from 'lodash-es'; import { useI18nContext } from '../../../../../../i18n/i18n-react'; import { Card } from '../../../../../../shared/components/layout/Card/Card'; +import { MessageBox } from '../../../../../../shared/components/layout/MessageBox/MessageBox'; +import { MessageBoxType } from '../../../../../../shared/components/layout/MessageBox/types'; import { EnrollmentStepIndicator } from '../../../../components/EnrollmentStepIndicator/EnrollmentStepIndicator'; import { useEnrollmentStore } from '../../../../hooks/store/useEnrollmentStore'; import { CreateDevice } from './components/CreateDevice'; @@ -14,6 +16,8 @@ export const ConfigureDeviceCard = () => { const deviceState = useEnrollmentStore((state) => state.deviceState); + // TODO + const networksAvailable = false; const configAvailable = deviceState && !isUndefined(deviceState?.device) && @@ -25,8 +29,11 @@ export const ConfigureDeviceCard = () => { <Card id="configure-device-card"> <EnrollmentStepIndicator /> <h3>{cardLL.title()}</h3> - {!configAvailable && <CreateDevice />} - {configAvailable && <DeviceConfiguration />} + {networksAvailable && !configAvailable && <CreateDevice />} + {networksAvailable && configAvailable && <DeviceConfiguration />} + {!networksAvailable && ( + <MessageBox message={cardLL.noNetworksMessage()} type={MessageBoxType.WARNING} /> + )} </Card> ); }; From 4cce3b321d916f32414beb5ae2c1809ca6fa617f Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski <jchmielewski@teonite.com> Date: Wed, 20 Mar 2024 13:03:16 +0100 Subject: [PATCH 2/2] Determine whether user has network access --- web/src/i18n/en/index.ts | 2 +- web/src/i18n/i18n-types.ts | 16 +-- .../ConfigureDeviceCard.tsx | 11 +- .../DeviceConfiguration.tsx | 127 ++++++++++-------- 4 files changed, 79 insertions(+), 77 deletions(-) diff --git a/web/src/i18n/en/index.ts b/web/src/i18n/en/index.ts index b91c450..e156319 100644 --- a/web/src/i18n/en/index.ts +++ b/web/src/i18n/en/index.ts @@ -134,7 +134,6 @@ If you have any questions, please consult your assigned admin.All necessary info }, }, }, - noNetworksMessage: "You don't have access to any networks", config: { messageBox: { auto: ` @@ -152,6 +151,7 @@ If you have any questions, please consult your assigned admin.All necessary info `, }, deviceNameLabel: 'My Device Name', + noNetworksMessage: "You don't have access to any networks", cardTitle: 'Use provided configuration file below by scanning QR Code or importing it as file on your devices WireGuard app.', card: { diff --git a/web/src/i18n/i18n-types.ts b/web/src/i18n/i18n-types.ts index ae9799b..fc6be39 100644 --- a/web/src/i18n/i18n-types.ts +++ b/web/src/i18n/i18n-types.ts @@ -293,10 +293,6 @@ type RootTranslation = { } } } - /** - * You don't have access to any networks - */ - noNetworksMessage: string config: { messageBox: { /** @@ -323,6 +319,10 @@ type RootTranslation = { * My Device Name */ deviceNameLabel: string + /** + * You don't have access to any networks + */ + noNetworksMessage: string /** * Use provided configuration file below by scanning QR Code or importing it as file on your devices WireGuard app. */ @@ -855,10 +855,6 @@ export type TranslationFunctions = { } } } - /** - * You don't have access to any networks - */ - noNetworksMessage: () => LocalizedString config: { messageBox: { /** @@ -885,6 +881,10 @@ export type TranslationFunctions = { * My Device Name */ deviceNameLabel: () => LocalizedString + /** + * You don't have access to any networks + */ + noNetworksMessage: () => LocalizedString /** * Use provided configuration file below by scanning QR Code or importing it as file on your devices WireGuard app. */ diff --git a/web/src/pages/enrollment/steps/DeviceStep/components/ConfigureDeviceCard/ConfigureDeviceCard.tsx b/web/src/pages/enrollment/steps/DeviceStep/components/ConfigureDeviceCard/ConfigureDeviceCard.tsx index fc5df46..0ac6e19 100644 --- a/web/src/pages/enrollment/steps/DeviceStep/components/ConfigureDeviceCard/ConfigureDeviceCard.tsx +++ b/web/src/pages/enrollment/steps/DeviceStep/components/ConfigureDeviceCard/ConfigureDeviceCard.tsx @@ -4,8 +4,6 @@ import { isUndefined } from 'lodash-es'; import { useI18nContext } from '../../../../../../i18n/i18n-react'; import { Card } from '../../../../../../shared/components/layout/Card/Card'; -import { MessageBox } from '../../../../../../shared/components/layout/MessageBox/MessageBox'; -import { MessageBoxType } from '../../../../../../shared/components/layout/MessageBox/types'; import { EnrollmentStepIndicator } from '../../../../components/EnrollmentStepIndicator/EnrollmentStepIndicator'; import { useEnrollmentStore } from '../../../../hooks/store/useEnrollmentStore'; import { CreateDevice } from './components/CreateDevice'; @@ -16,8 +14,6 @@ export const ConfigureDeviceCard = () => { const deviceState = useEnrollmentStore((state) => state.deviceState); - // TODO - const networksAvailable = false; const configAvailable = deviceState && !isUndefined(deviceState?.device) && @@ -29,11 +25,8 @@ export const ConfigureDeviceCard = () => { <Card id="configure-device-card"> <EnrollmentStepIndicator /> <h3>{cardLL.title()}</h3> - {networksAvailable && !configAvailable && <CreateDevice />} - {networksAvailable && configAvailable && <DeviceConfiguration />} - {!networksAvailable && ( - <MessageBox message={cardLL.noNetworksMessage()} type={MessageBoxType.WARNING} /> - )} + {!configAvailable && <CreateDevice />} + {configAvailable && <DeviceConfiguration />} </Card> ); }; diff --git a/web/src/pages/enrollment/steps/DeviceStep/components/ConfigureDeviceCard/components/DeviceConfiguration/DeviceConfiguration.tsx b/web/src/pages/enrollment/steps/DeviceStep/components/ConfigureDeviceCard/components/DeviceConfiguration/DeviceConfiguration.tsx index cefa030..a0b75ff 100644 --- a/web/src/pages/enrollment/steps/DeviceStep/components/ConfigureDeviceCard/components/DeviceConfiguration/DeviceConfiguration.tsx +++ b/web/src/pages/enrollment/steps/DeviceStep/components/ConfigureDeviceCard/components/DeviceConfiguration/DeviceConfiguration.tsx @@ -12,6 +12,7 @@ import { Card } from '../../../../../../../../shared/components/layout/Card/Card import { useTheme } from '../../../../../../../../shared/components/layout/hooks/theme/useTheme'; import { Input } from '../../../../../../../../shared/components/layout/Input/Input'; import { MessageBox } from '../../../../../../../../shared/components/layout/MessageBox/MessageBox'; +import { MessageBoxType } from '../../../../../../../../shared/components/layout/MessageBox/types'; import { Select } from '../../../../../../../../shared/components/layout/Select/Select'; import { SelectOption } from '../../../../../../../../shared/components/layout/Select/types'; import SvgIconHamburger from '../../../../../../../../shared/components/svg/IconHamburger'; @@ -42,7 +43,7 @@ export const DeviceConfiguration = () => { })) ?? [], [deviceState?.configs], ); - + const networksAvailable = deviceState?.configs?.length > 0 ?? false; const preparedConfig = useMemo(() => { if (deviceState?.device?.privateKey) { return selected?.config.replace('YOUR_PRIVATE_KEY', deviceState.device.privateKey); @@ -76,65 +77,73 @@ export const DeviceConfiguration = () => { return; }} /> - - <div className="qr-info"> - <p>{cardLL.cardTitle()}</p> - </div> - - <Card id="device-config-card"> - <div className="top"> - <SvgIconHamburger /> - <label>{cardLL.card.selectLabel()}:</label> - <Select<DeviceConfig> - identify={networkIdentifier} - options={selectOptions} - onChangeSingle={(config) => setSelected(config)} - selected={selected} - /> - <div className="actions"> - <ActionButton variant={ActionButtonVariant.QRCODE} active /> - <ActionButton - variant={ActionButtonVariant.COPY} - disabled={isUndefined(selected) || !window.isSecureContext} - onClick={() => { - if (selected && window.isSecureContext) { - if (deviceState?.device?.privateKey && preparedConfig) { - navigator.clipboard - .writeText(preparedConfig) - .catch((e) => console.error(e)); - } else { - navigator.clipboard - .writeText(selected.config) - .catch((e) => console.error(e)); - } - } - }} - /> - <ActionButton - disabled={isUndefined(selected)} - variant={ActionButtonVariant.DOWNLOAD} - onClick={() => { - if (preparedConfig && selected) { - downloadWGConfig( - deviceState?.device?.privateKey ? preparedConfig : selected.config, - `${selected.network_name.toLowerCase().replace(/\s+/g, '-')}`, - ); - } - }} - /> + {networksAvailable && ( + <> + <div className="qr-info"> + <p>{cardLL.cardTitle()}</p> </div> - </div> - <div className="qr"> - {!isUndefined(preparedConfig) && ( - <QRCode - size={275} - value={preparedConfig} - bgColor={colors.surfaceDefaultModal} - fgColor={colors.textBodyPrimary} - /> - )} - </div> - </Card> + + <Card id="device-config-card"> + <div className="top"> + <SvgIconHamburger /> + <label>{cardLL.card.selectLabel()}:</label> + <Select<DeviceConfig> + identify={networkIdentifier} + options={selectOptions} + onChangeSingle={(config) => setSelected(config)} + selected={selected} + /> + <div className="actions"> + <ActionButton variant={ActionButtonVariant.QRCODE} active /> + <ActionButton + variant={ActionButtonVariant.COPY} + disabled={isUndefined(selected) || !window.isSecureContext} + onClick={() => { + if (selected && window.isSecureContext) { + if (deviceState?.device?.privateKey && preparedConfig) { + navigator.clipboard + .writeText(preparedConfig) + .catch((e) => console.error(e)); + } else { + navigator.clipboard + .writeText(selected.config) + .catch((e) => console.error(e)); + } + } + }} + /> + <ActionButton + disabled={isUndefined(selected)} + variant={ActionButtonVariant.DOWNLOAD} + onClick={() => { + if (preparedConfig && selected) { + downloadWGConfig( + deviceState?.device?.privateKey + ? preparedConfig + : selected.config, + `${selected.network_name.toLowerCase().replace(/\s+/g, '-')}`, + ); + } + }} + /> + </div> + </div> + <div className="qr"> + {!isUndefined(preparedConfig) && ( + <QRCode + size={275} + value={preparedConfig} + bgColor={colors.surfaceDefaultModal} + fgColor={colors.textBodyPrimary} + /> + )} + </div> + </Card> + </> + )} + {!networksAvailable && ( + <MessageBox message={cardLL.noNetworksMessage()} type={MessageBoxType.WARNING} /> + )} </> ); };