Skip to content

Commit 627da6c

Browse files
authored
feat: Use modal for authentication (#2443)
fix: Change broken `NotificationManager` calls to `showNotify()`
1 parent 403ffac commit 627da6c

File tree

3 files changed

+80
-15
lines changed

3 files changed

+80
-15
lines changed

src/Main.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,16 @@ const ConnectedDashboardPage = lazy(() =>
5252
import('./components/dashboard-page/Dashboard').then((module) => ({ default: module.ConnectedDashboardPage })),
5353
);
5454

55+
import { AuthForm } from './components/modal/components/AuthModal';
56+
5557
export function Main() {
5658
const { theme } = store.getState();
5759
return (
5860
<React.StrictMode>
5961
<ReactNotifications />
6062
<I18nextProvider i18n={i18n}>
6163
<NiceModal.Provider>
64+
<AuthForm id="auth-form" onAuth={() => null} />
6265
<Provider store={store}>
6366
<ThemeSwitcherProvider
6467
themeMap={{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React, { ChangeEvent } from 'react';
2+
import { useInputChange } from '../../../hooks/useInputChange';
3+
4+
import Modal, { ModalBody, ModalFooter, ModalHeader } from '../Modal';
5+
import NiceModal, { useModal } from '@ebay/nice-modal-react';
6+
7+
type AuthFormProps = {
8+
onAuth(token: string): void;
9+
};
10+
11+
export const AuthForm = NiceModal.create((props: AuthFormProps): JSX.Element => {
12+
const { onAuth } = props;
13+
14+
const modal = useModal();
15+
16+
const [authForm, handleInputChange] = useInputChange({ token: '' });
17+
18+
const onLoginClick = async (): Promise<void> => {
19+
await onAuth(authForm['token']);
20+
modal.remove();
21+
};
22+
23+
const handleKeyDown = async (e): Promise<void> => {
24+
if (e.key == 'Enter') {
25+
onLoginClick();
26+
}
27+
};
28+
29+
return (
30+
<Modal isOpen={modal.visible}>
31+
<ModalHeader>
32+
<h3>Enter Admin Token</h3>
33+
</ModalHeader>
34+
<ModalBody>
35+
<div className="mb-3">
36+
<label className="form-label">Token</label>
37+
<input
38+
name="token"
39+
onChange={handleInputChange as (event: ChangeEvent<HTMLInputElement>) => void}
40+
onKeyDown={handleKeyDown}
41+
type="password"
42+
className="form-control"
43+
autoCapitalize="none"
44+
value={authForm['token']}
45+
/>
46+
</div>
47+
</ModalBody>
48+
<ModalFooter>
49+
<button type="button" className="btn btn-primary" onClick={onLoginClick}>
50+
Login
51+
</button>
52+
</ModalFooter>
53+
</Modal>
54+
);
55+
});

src/ws-client.ts

+22-15
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
stringifyWithPreservingUndefinedAsNull,
1010
} from './utils';
1111

12+
import NiceModal from '@ebay/nice-modal-react';
1213
import { Store } from 'react-notifications-component';
1314
import keyBy from 'lodash/keyBy';
1415

@@ -113,21 +114,27 @@ class Api {
113114
}
114115
}
115116

116-
urlProvider = async () => {
117-
const url = new URL(this.url)
118-
let token = new URLSearchParams(window.location.search).get("token")
119-
?? local.get<string>(TOKEN_LOCAL_STORAGE_ITEM_NAME);
120-
const authRequired = !!local.get(AUTH_FLAG_LOCAL_STORAGE_ITEM_NAME);
121-
if (authRequired) {
122-
if (!token) {
123-
token = prompt("Enter your z2m admin token") as string;
124-
if (token) {
125-
local.set(TOKEN_LOCAL_STORAGE_ITEM_NAME, token);
117+
urlProvider = async (): Promise<string> => {
118+
const promise = new Promise<string>((resolve) => {
119+
const url = new URL(this.url)
120+
let token = new URLSearchParams(window.location.search).get("token")
121+
?? local.get<string>(TOKEN_LOCAL_STORAGE_ITEM_NAME);
122+
const authRequired = !!local.get(AUTH_FLAG_LOCAL_STORAGE_ITEM_NAME);
123+
if (authRequired) {
124+
if (!token) {
125+
NiceModal.show('auth-form', { onAuth: (token: string) => {
126+
local.set(TOKEN_LOCAL_STORAGE_ITEM_NAME, token);
127+
url.searchParams.append("token", token);
128+
resolve(url.toString());
129+
}});
130+
return;
126131
}
132+
url.searchParams.append("token", token);
127133
}
128-
url.searchParams.append("token", token);
129-
}
130-
return url.toString();
134+
resolve(url.toString());
135+
});
136+
137+
return promise;
131138
}
132139

133140
connect(): void {
@@ -277,7 +284,7 @@ class Api {
277284
if (e.code === UNAUTHORIZED_ERROR_CODE) {
278285
local.set(AUTH_FLAG_LOCAL_STORAGE_ITEM_NAME, true);
279286
local.remove(TOKEN_LOCAL_STORAGE_ITEM_NAME);
280-
NotificationManager.error("Unauthorized");
287+
showNotify('error', "Unauthorized", false);
281288
setTimeout(() => {
282289
window.location.reload();
283290
}, 1000);
@@ -296,7 +303,7 @@ class Api {
296303
this.processDeviceStateMessage(data);
297304
}
298305
} catch (e) {
299-
NotificationManager.error(e.message);
306+
showNotify('error', e.message, false);
300307
console.error(event.data);
301308
}
302309

0 commit comments

Comments
 (0)