Skip to content

Commit f3aeb48

Browse files
review fixes
1 parent b5705b6 commit f3aeb48

17 files changed

Lines changed: 257 additions & 51 deletions

File tree

‎new-ui/package.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"dependencies": {
1717
"@biomejs/biome": "2.5.14",
1818
"@floating-ui/react": "^0.27.20",
19+
"@fluentui/keyboard-keys": "^9.0.9",
1920
"@stablelib/base64": "^2.0.1",
2021
"@stablelib/x25519": "^2.0.1",
2122
"@tanstack/react-form": "^1.33.5",

‎new-ui/pnpm-lock.yaml‎

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎new-ui/src/pages/full/AddPage/AddPage.tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { useStartMfaConfiguration } from './hooks/useStartMfaConfiguration';
1515

1616
export const AddPage = () => {
1717
const navigate = useNavigate();
18-
const { data: instances } = useQuery(getInstancesQueryOptions);
18+
const { data: instances, isPending } = useQuery(getInstancesQueryOptions);
1919

2020
const mfaInstances = useMemo(
2121
() => mfaConfigurableInstances(instances ?? []),
@@ -40,7 +40,7 @@ export const AddPage = () => {
4040
actionText="Add instance"
4141
description={`Establish a secure connection to your Defguard instance effortlessly by configuring it with a single token—no manual setup.`}
4242
/>
43-
{!tunnelsDisabled(instances ?? []) && (
43+
{!isPending && !tunnelsDisabled(instances ?? []) && (
4444
<AddCard
4545
image="wireguard"
4646
onClick={() => {
@@ -53,7 +53,7 @@ export const AddPage = () => {
5353
description={`Add and configure a WireGuard tunnel to securely route traffic through an encrypted connection using predefined configuration.`}
5454
/>
5555
)}
56-
{mfaInstances.length > 0 && (
56+
{!isPending && mfaInstances.length > 0 && (
5757
<AddCard
5858
image="lock"
5959
title="Add new MFA method"

‎new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureVerifyEmailStep/ConfigureVerifyEmailStep.tsx‎

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,22 @@ export const ConfigureVerifyEmailStep = ({ onCancel, onSessionExpired }: Props)
3838
fallback: 'Verification failed',
3939
});
4040

41+
// A second call invalidates the code already sent, so fire once, StrictMode included.
42+
const requestedFor = useRef<string | null>(null);
43+
4144
const { mutate: requestCode, isPending: isRequestingCode } = useMutation({
4245
mutationFn: async () => {
4346
if (!isPresent(sessionId)) {
4447
throw new Error('No MFA configuration session');
4548
}
4649
await api.mfaConfigSendCode(sessionId);
4750
},
48-
onError: handleApiError,
51+
onError: (err) => {
52+
requestedFor.current = null;
53+
handleApiError(err);
54+
},
4955
});
5056

51-
// A second call invalidates the code already sent, so fire once, StrictMode included.
52-
const requestedFor = useRef<string | null>(null);
5357
useEffect(() => {
5458
if (!isPresent(sessionId)) return;
5559
if (requestedFor.current === sessionId) return;
@@ -73,18 +77,29 @@ export const ConfigureVerifyEmailStep = ({ onCancel, onSessionExpired }: Props)
7377
onSettled: onCancel,
7478
});
7579

80+
const isBusy = isRequestingCode || isSubmitting || isCancelling;
81+
7682
const handleSubmit = useCallback(
7783
(pastedCode?: string) => {
84+
if (isBusy) return;
7885
const toSubmit = (pastedCode ?? code)?.trim();
7986
if (toSubmit?.length !== CODE_LENGTH) {
8087
setError('Enter a valid code');
8188
return;
8289
}
8390
submitCode(toSubmit);
8491
},
85-
[code, submitCode],
92+
[code, isBusy, submitCode],
8693
);
8794

95+
const handleResend = useCallback(() => {
96+
if (isBusy || !isPresent(sessionId)) return;
97+
requestedFor.current = sessionId;
98+
setCode(null);
99+
setError(null);
100+
requestCode();
101+
}, [isBusy, requestCode, sessionId]);
102+
88103
// Only real input clears the error, CodeInput's own reset passes ''.
89104
const handleCodeChange = useCallback((value: string) => {
90105
setCode(value);
@@ -103,17 +118,15 @@ export const ConfigureVerifyEmailStep = ({ onCancel, onSessionExpired }: Props)
103118
<span>{`We've sent a verification code to your email address.`}</span>
104119
<span>{`Please check your inbox and enter the 6-digit code from the email to continue.`}</span>
105120
</p>
106-
<div
107-
className="code-track"
108-
onKeyDown={(e) => {
109-
if (e.key === 'Enter') handleSubmit();
110-
}}
111-
>
121+
<div className="code-track">
112122
<CodeInput
113123
length={CODE_LENGTH}
114124
value={code}
115125
onChange={handleCodeChange}
116126
error={error}
127+
onSubmit={() => {
128+
handleSubmit();
129+
}}
117130
onSuccessPaste={(value) => {
118131
handleSubmit(value);
119132
}}
@@ -129,10 +142,18 @@ export const ConfigureVerifyEmailStep = ({ onCancel, onSessionExpired }: Props)
129142
}}
130143
/>
131144
<div className="right">
145+
<Button
146+
text="Resend code"
147+
variant={ButtonVariant.Secondary}
148+
loading={isRequestingCode}
149+
disabled={isSubmitting || isCancelling}
150+
onClick={handleResend}
151+
/>
132152
<Button
133153
text="Verify"
134154
variant={ButtonVariant.Primary}
135-
loading={isRequestingCode || isSubmitting}
155+
loading={isSubmitting}
156+
disabled={isRequestingCode || isCancelling}
136157
onClick={() => {
137158
handleSubmit();
138159
}}

‎new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureVerifyTotpStep/ConfigureVerifyTotpStep.tsx‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,19 @@ export const ConfigureVerifyTotpStep = ({ onCancel, onSessionExpired }: Props) =
5454
onSettled: onCancel,
5555
});
5656

57+
const isBusy = isSubmitting || isCancelling;
58+
5759
const handleSubmit = useCallback(
5860
(pastedCode?: string) => {
61+
if (isBusy) return;
5962
const toSubmit = (pastedCode ?? code)?.trim();
6063
if (toSubmit?.length !== CODE_LENGTH) {
6164
setError('Enter a valid code');
6265
return;
6366
}
6467
submitCode(toSubmit);
6568
},
66-
[code, submitCode],
69+
[code, isBusy, submitCode],
6770
);
6871

6972
// Only real input clears the error, CodeInput's own reset passes ''.
@@ -84,17 +87,15 @@ export const ConfigureVerifyTotpStep = ({ onCancel, onSessionExpired }: Props) =
8487
<span>{`Open the authentication app you use with Defguard.`}</span>
8588
<span>{`Enter the 6-digit code it currently displays to continue.`}</span>
8689
</p>
87-
<div
88-
className="code-track"
89-
onKeyDown={(e) => {
90-
if (e.key === 'Enter') handleSubmit();
91-
}}
92-
>
90+
<div className="code-track">
9391
<CodeInput
9492
length={CODE_LENGTH}
9593
value={code}
9694
onChange={handleCodeChange}
9795
error={error}
96+
onSubmit={() => {
97+
handleSubmit();
98+
}}
9899
onSuccessPaste={(value) => {
99100
handleSubmit(value);
100101
}}
@@ -114,6 +115,7 @@ export const ConfigureVerifyTotpStep = ({ onCancel, onSessionExpired }: Props) =
114115
text="Verify"
115116
variant={ButtonVariant.Primary}
116117
loading={isSubmitting}
118+
disabled={isCancelling}
117119
onClick={() => {
118120
handleSubmit();
119121
}}

‎new-ui/src/pages/full/ConfigureMfaPage/wizard/ConfigureFactorStep/ConfigureFactorStep.tsx‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,19 @@ export const ConfigureFactorStep = ({ onCancel, onSessionExpired }: Props) => {
9696
onSettled: onCancel,
9797
});
9898

99+
const isBusy = isStartingSetup || isFinishingSetup || isCancelling;
100+
99101
const handleSubmit = useCallback(
100102
(pastedCode?: string) => {
103+
if (isBusy) return;
101104
const toSubmit = (pastedCode ?? code)?.trim();
102105
if (toSubmit?.length !== CODE_LENGTH) {
103106
setError('Enter a valid code');
104107
return;
105108
}
106109
finishSetup(toSubmit);
107110
},
108-
[code, finishSetup],
111+
[code, finishSetup, isBusy],
109112
);
110113

111114
// Only real input clears the error, CodeInput's own reset passes ''.
@@ -136,17 +139,15 @@ export const ConfigureFactorStep = ({ onCancel, onSessionExpired }: Props) => {
136139
? `Enter 6-digit code from authentication app`
137140
: `Enter 6-digit code from email`}
138141
</p>
139-
<div
140-
className="code-track"
141-
onKeyDown={(e) => {
142-
if (e.key === 'Enter') handleSubmit();
143-
}}
144-
>
142+
<div className="code-track">
145143
<CodeInput
146144
length={CODE_LENGTH}
147145
value={code}
148146
onChange={handleCodeChange}
149147
error={error}
148+
onSubmit={() => {
149+
handleSubmit();
150+
}}
150151
onSuccessPaste={(value) => {
151152
handleSubmit(value);
152153
}}
@@ -166,6 +167,7 @@ export const ConfigureFactorStep = ({ onCancel, onSessionExpired }: Props) => {
166167
text="Configure"
167168
variant={ButtonVariant.Primary}
168169
loading={isStartingSetup || isFinishingSetup}
170+
disabled={isCancelling}
169171
onClick={() => {
170172
handleSubmit();
171173
}}

‎new-ui/src/pages/full/ConfigureMfaPage/wizard/ConfigureFido2Step/ConfigureFido2Step.tsx‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import './style.scss';
2+
import { Enter } from '@fluentui/keyboard-keys';
23
import { useMutation } from '@tanstack/react-query';
34
import { listen } from '@tauri-apps/api/event';
45
import { hostname } from '@tauri-apps/plugin-os';
@@ -101,6 +102,7 @@ export const ConfigureFido2Step = ({ onCancel, onSessionExpired }: Props) => {
101102
});
102103

103104
const handleSubmit = useCallback(() => {
105+
if (isRegistering || isCancelling) return;
104106
if (!isPresent(name) || name.trim().length === 0) {
105107
setError('Name your security key');
106108
return;
@@ -111,14 +113,14 @@ export const ConfigureFido2Step = ({ onCancel, onSessionExpired }: Props) => {
111113
}
112114
setError(null);
113115
register();
114-
}, [collectsPin, name, pin, register]);
116+
}, [collectsPin, isCancelling, isRegistering, name, pin, register]);
115117

116118
return (
117119
<div
118120
id="configure-fido2-step"
119121
className="step-content"
120122
onKeyDown={(e) => {
121-
if (e.key === 'Enter') handleSubmit();
123+
if (e.key === Enter) handleSubmit();
122124
}}
123125
>
124126
<header>
@@ -164,6 +166,7 @@ export const ConfigureFido2Step = ({ onCancel, onSessionExpired }: Props) => {
164166
text="Register"
165167
variant={ButtonVariant.Primary}
166168
loading={isRegistering}
169+
disabled={isCancelling}
167170
onClick={handleSubmit}
168171
/>
169172
</div>

‎new-ui/src/pages/full/ConfigureMfaPage/wizard/ConfigureFinishStep/ConfigureFinishStep.tsx‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import { ButtonVariant } from '../../../../../shared/components/Button/types';
55
import { Controls } from '../../../../../shared/components/Controls/Controls';
66
import { useAppData } from '../../../../../shared/providers/AppDataContext';
77
import { isPresent } from '../../../../../shared/utils/isPresent';
8-
import { useConfigureMfaStore } from '../../hooks/useConfigureMfaStore';
8+
import {
9+
discardMfaConfiguration,
10+
useConfigureMfaStore,
11+
} from '../../hooks/useConfigureMfaStore';
912
import bannerSrc from './assets/banner.png';
1013

1114
export const ConfigureFinishStep = () => {
@@ -31,7 +34,7 @@ export const ConfigureFinishStep = () => {
3134
}
3235
// Reset once the page is gone, or this step re-renders on an empty store.
3336
void navigate({ to: '/full/overview', replace: true }).then(() => {
34-
useConfigureMfaStore.getState().reset();
37+
void discardMfaConfiguration();
3538
});
3639
}}
3740
/>

‎new-ui/src/pages/full/OverviewPage/components/ConnectModal/views/ConnectModalMfaEmail/ConnectModalMfaEmail.tsx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Enter } from '@fluentui/keyboard-keys';
12
import { useCallback, useEffect, useState } from 'react';
23
import { useShallow } from 'zustand/shallow';
34
import { Button } from '../../../../../../../shared/components/Button/Button';
@@ -79,7 +80,7 @@ export const ConnectModalMfaEmail = () => {
7980
<div
8081
id="mfa-email-view"
8182
onKeyDown={(e) => {
82-
if (e.key === 'Enter') handleVerify();
83+
if (e.key === Enter) handleVerify();
8384
}}
8485
>
8586
<p className="view-description">

‎new-ui/src/pages/full/OverviewPage/components/ConnectModal/views/ConnectModalMfaFido2/ConnectModalMfaFido2.tsx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Enter } from '@fluentui/keyboard-keys';
12
import { Fragment, useCallback, useEffect, useState } from 'react';
23
import { useShallow } from 'zustand/shallow';
34
import { Button } from '../../../../../../../shared/components/Button/Button';
@@ -62,7 +63,7 @@ export const ConnectModalMfaFido2 = () => {
6263
<div
6364
id="mfa-fido2-view"
6465
onKeyDown={(e) => {
65-
if (e.key === 'Enter') handleVerify();
66+
if (e.key === Enter) handleVerify();
6667
}}
6768
>
6869
{isAwaitingTouch ? (

0 commit comments

Comments
 (0)