From 0be0fc3bb5d0831bc68800279f51ecd85986db14 Mon Sep 17 00:00:00 2001 From: sarthurdev <965089+sarthurdev@users.noreply.github.com> Date: Mon, 24 Mar 2025 13:00:20 +0100 Subject: [PATCH 1/2] feat: Use modal for authentication fix: Change broken `NotificationManager` calls to `showNotify()` --- src/Main.tsx | 3 + src/components/modal/components/AuthModal.tsx | 55 +++++++++++++++++++ src/ws-client.ts | 37 ++++++++----- 3 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 src/components/modal/components/AuthModal.tsx diff --git a/src/Main.tsx b/src/Main.tsx index f750b1855..6311d03a4 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -52,6 +52,8 @@ const ConnectedDashboardPage = lazy(() => import('./components/dashboard-page/Dashboard').then((module) => ({ default: module.ConnectedDashboardPage })), ); +import { AuthForm } from './components/modal/components/AuthModal'; + export function Main() { const { theme } = store.getState(); return ( @@ -59,6 +61,7 @@ export function Main() { + null} /> { + const { onAuth } = props; + + const modal = useModal(); + + const [authForm, handleInputChange] = useInputChange({ token: '' }); + + const onLoginClick = async (): Promise => { + await onAuth(authForm['token']); + modal.remove(); + }; + + const handleKeyDown = async (e): Promise => { + if (e.key == 'Enter') { + onLoginClick(); + } + }; + + return ( + + + Enter Admin Token + + + + Token + ) => void} + onKeyDown={handleKeyDown} + type="password" + className="form-control" + autoCapitalize="none" + value={authForm['token']} + /> + + + + + Login + + + + ); +}); diff --git a/src/ws-client.ts b/src/ws-client.ts index 302ff125a..b56b791be 100644 --- a/src/ws-client.ts +++ b/src/ws-client.ts @@ -9,6 +9,7 @@ import { stringifyWithPreservingUndefinedAsNull, } from './utils'; +import NiceModal from '@ebay/nice-modal-react'; import { Store } from 'react-notifications-component'; import keyBy from 'lodash/keyBy'; @@ -113,21 +114,27 @@ class Api { } } - urlProvider = async () => { - const url = new URL(this.url) - let token = new URLSearchParams(window.location.search).get("token") - ?? local.get(TOKEN_LOCAL_STORAGE_ITEM_NAME); - const authRequired = !!local.get(AUTH_FLAG_LOCAL_STORAGE_ITEM_NAME); - if (authRequired) { - if (!token) { - token = prompt("Enter your z2m admin token") as string; - if (token) { - local.set(TOKEN_LOCAL_STORAGE_ITEM_NAME, token); + urlProvider = async (): Promise => { + const promise = new Promise((resolve) => { + const url = new URL(this.url) + let token = new URLSearchParams(window.location.search).get("token") + ?? local.get(TOKEN_LOCAL_STORAGE_ITEM_NAME); + const authRequired = !!local.get(AUTH_FLAG_LOCAL_STORAGE_ITEM_NAME); + if (authRequired) { + if (!token) { + NiceModal.show('auth-form', { onAuth: (token: string) => { + local.set(TOKEN_LOCAL_STORAGE_ITEM_NAME, token); + url.searchParams.append("token", token); + resolve(url.toString()); + }}); + return; } + url.searchParams.append("token", token); } - url.searchParams.append("token", token); - } - return url.toString(); + resolve(url.toString()); + }); + + return promise; } connect(): void { @@ -277,7 +284,7 @@ class Api { if (e.code === UNAUTHORIZED_ERROR_CODE) { local.set(AUTH_FLAG_LOCAL_STORAGE_ITEM_NAME, true); local.remove(TOKEN_LOCAL_STORAGE_ITEM_NAME); - NotificationManager.error("Unauthorized"); + showNotify('error', "Unauthorized", false); setTimeout(() => { window.location.reload(); }, 1000); @@ -296,7 +303,7 @@ class Api { this.processDeviceStateMessage(data); } } catch (e) { - NotificationManager.error(e.message); + showNotify('error', e.message, false); console.error(event.data); } From 7e45dd33c93ac9f497d6fb316736427b2324b865 Mon Sep 17 00:00:00 2001 From: sarthurdev <965089+sarthurdev@users.noreply.github.com> Date: Sun, 6 Apr 2025 13:18:11 +0200 Subject: [PATCH 2/2] fix: Ensure DOM is loaded before API connect --- src/Main.tsx | 9 ++++++++- src/index.tsx | 4 ---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Main.tsx b/src/Main.tsx index 6311d03a4..499301f3b 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -1,4 +1,4 @@ -import React, { lazy, Suspense } from 'react'; +import React, { lazy, Suspense, useEffect } from 'react'; import NiceModal from '@ebay/nice-modal-react'; import { HashRouter, Route, Switch } from 'react-router-dom'; import { ReactNotifications } from 'react-notifications-component'; @@ -54,8 +54,15 @@ const ConnectedDashboardPage = lazy(() => import { AuthForm } from './components/modal/components/AuthModal'; +import api from './ws-client'; + export function Main() { const { theme } = store.getState(); + + useEffect(() => { + api.connect(); + }, []); + return ( diff --git a/src/index.tsx b/src/index.tsx index 53d885329..df33fdb4c 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -6,12 +6,8 @@ import './styles/styles.global.scss'; import React from 'react'; import { createRoot } from 'react-dom/client'; -import api from './ws-client'; - import { Main } from './Main'; -api.connect(); - const domNode = document.getElementById('root'); if (domNode) { createRoot(domNode).render();