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 = {
 									}
 								}
 							}
+							/**
+							 * Y​o​u​ ​d​o​n​'​t​ ​h​a​v​e​ ​a​c​c​e​s​s​ ​t​o​ ​a​n​y​ ​n​e​t​w​o​r​k​s
+							 */
+							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 = {
 									}
 								}
 							}
-							/**
-							 * Y​o​u​ ​d​o​n​'​t​ ​h​a​v​e​ ​a​c​c​e​s​s​ ​t​o​ ​a​n​y​ ​n​e​t​w​o​r​k​s
-							 */
-							noNetworksMessage: string
 							config: {
 								messageBox: {
 									/**
@@ -323,6 +319,10 @@ type RootTranslation = {
 								 * M​y​ ​D​e​v​i​c​e​ ​N​a​m​e
 								 */
 								deviceNameLabel: string
+								/**
+								 * Y​o​u​ ​d​o​n​'​t​ ​h​a​v​e​ ​a​c​c​e​s​s​ ​t​o​ ​a​n​y​ ​n​e​t​w​o​r​k​s
+								 */
+								noNetworksMessage: string
 								/**
 								 * U​s​e​ ​p​r​o​v​i​d​e​d​ ​c​o​n​f​i​g​u​r​a​t​i​o​n​ ​f​i​l​e​ ​b​e​l​o​w​ ​b​y​ ​s​c​a​n​n​i​n​g​ ​Q​R​ ​C​o​d​e​ ​o​r​ ​i​m​p​o​r​t​i​n​g​ ​i​t​ ​a​s​ ​f​i​l​e​ ​o​n​ ​y​o​u​r​ ​d​e​v​i​c​e​s​ ​W​i​r​e​G​u​a​r​d​ ​a​p​p​.
 								 */
@@ -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} />
+      )}
     </>
   );
 };