Skip to content

Commit ca586d0

Browse files
committed
frontend: add Maintenance Banner
1 parent d2fa93f commit ca586d0

File tree

4 files changed

+62
-0
lines changed

4 files changed

+62
-0
lines changed

frontend/src/components/Banner.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/* esp32-remote-access
2+
* Copyright (C) 2025 Frederic Henrichs <[email protected]>
3+
*
4+
* This library is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU Lesser General Public
6+
* License as published by the Free Software Foundation; either
7+
* version 2 of the License, or (at your option) any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public
15+
* License along with this library; if not, write to the
16+
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17+
* Boston, MA 02111-1307, USA.
18+
*/
19+
20+
import { useState, useEffect } from 'preact/hooks';
21+
import { useTranslation } from 'react-i18next';
22+
import Alert from 'react-bootstrap/Alert';
23+
24+
const BANNER_DISMISSED_KEY = 'bannerDismissed';
25+
26+
export function Banner() {
27+
const { t } = useTranslation("", { useSuspense: false });
28+
const [show, setShow] = useState(false);
29+
30+
useEffect(() => {
31+
const dismissed = sessionStorage.getItem(BANNER_DISMISSED_KEY);
32+
setShow(!dismissed);
33+
}, []);
34+
35+
const handleClose = () => {
36+
setShow(false);
37+
sessionStorage.setItem(BANNER_DISMISSED_KEY, 'true');
38+
};
39+
40+
if (!show) {
41+
return null;
42+
}
43+
44+
return (
45+
<Alert variant="warning" dismissible onClose={handleClose} className="m-0 rounded-0 text-center p-0 py-1">
46+
<Alert.Heading>{t('banner.title')}</Alert.Heading>
47+
<p class="m-0">{t('banner.message')}</p>
48+
</Alert>
49+
);
50+
}

frontend/src/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import { Recovery } from './pages/Recovery.js';
3939
import { Trans, useTranslation } from "react-i18next";
4040
import Median from "median-js-bridge";
4141
import { Footer } from "./components/Footer";
42+
import { Banner } from "./components/Banner";
4243
import favicon from "favicon";
4344
import logo from "logo";
4445
import { Message, MessageType } from './types';
@@ -219,6 +220,7 @@ export function App() {
219220
Median.sidebar.setItems({items: [], enabled: false, persist: false});
220221
}
221222
return <>
223+
<Banner />
222224
<nav hidden={Median.isNativeApp()} id="logo-nav" class="navbar navbar-expand-md navbar-dark sticky-top flex-md-nowrap p-0 pb-2 pt-2 ps-2">
223225
<a href="/"><img class="pt-2 pb-2 ps-2" src={logo} style="max-width: calc(100vw - 72px);" alt="logo" /></a>
224226
</nav>
@@ -248,6 +250,7 @@ export function App() {
248250
case AppState.LoggedIn:
249251
return (
250252
<>
253+
<Banner />
251254
<ErrorAlert />
252255
<Col>
253256
<LocationProvider>
@@ -274,6 +277,7 @@ export function App() {
274277
// we need an extra recovery state, otherwise we would show the login/register page.
275278
case AppState.Recovery:
276279
return (<>
280+
<Banner />
277281
<ErrorAlert />
278282
<LocationProvider>
279283
<Row className="align-items-center justify-content-center flex-grow-1 gap-3 m-0 my-3">

frontend/src/locales/de.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ export const de ={
66
"alert_default_success": "Erfolg!",
77
description,
88
"no_service_worker": "Dein Browser benötigt Unterstützung für ServiceWorker um den Fernzugriff nutzen zu können.",
9+
"banner": {
10+
"title": "Bevorstehende Wartungsarbeiten!",
11+
"message": "Wartungsarbeiten sind für Montag, den 01.12.2025 von 10:00 Uhr bis 11:30 Uhr geplant. Währenddessen ist der Fernzugriff nicht erreichbar."
12+
},
913
"not_now": "Jetzt nicht",
1014
"allow": "Browserdialog anzeigen",
1115
"storage_persistence": {

frontend/src/locales/en.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ export const en = {
66
"alert_default_success": "Success!",
77
description,
88
"no_service_worker": "Your browser needs support for ServiceWorkers to be able to run the Remote Access.",
9+
"banner": {
10+
"title": "Upcoming Maintenance!",
11+
"message": "Maintenance is scheduled for Monday 01.12.2025 from 10:00 A.M. to 11:30 P.M. During this time, Remote Access will be unavailable."
12+
},
913
"not_now": "Not now",
1014
"allow": "Show browser prompt",
1115
"storage_persistence": {

0 commit comments

Comments
 (0)