diff --git a/react/src/components/MainLayout/MainLayout.tsx b/react/src/components/MainLayout/MainLayout.tsx
index 3853d1f51d..c161e72b25 100644
--- a/react/src/components/MainLayout/MainLayout.tsx
+++ b/react/src/components/MainLayout/MainLayout.tsx
@@ -6,6 +6,7 @@ import BAIErrorBoundary from '../BAIErrorBoundary';
import BAISider from '../BAISider';
import Flex from '../Flex';
import ForceTOTPChecker from '../ForceTOTPChecker';
+import NetworkStatusBanner from '../NetworkStatusBanner';
import PasswordChangeRequestAlert from '../PasswordChangeRequestAlert';
import { DRAWER_WIDTH } from '../WEBUINotificationDrawer';
import WebUIHeader from './WebUIHeader';
@@ -169,6 +170,7 @@ function MainLayout() {
zIndex: HEADER_Z_INDEX_IN_MAIN_LAYOUT,
}}
>
+
setSideCollapsed((v) => !v)}
containerElement={contentScrollFlexRef.current}
diff --git a/react/src/components/NetworkStatusBanner.tsx b/react/src/components/NetworkStatusBanner.tsx
new file mode 100644
index 0000000000..99f7c8f0d0
--- /dev/null
+++ b/react/src/components/NetworkStatusBanner.tsx
@@ -0,0 +1,55 @@
+import { useNetwork } from 'ahooks';
+import { Alert } from 'antd';
+import { createStyles } from 'antd-style';
+import { atom, useAtom } from 'jotai';
+import { useTranslation } from 'react-i18next';
+
+const networkSoftTimeoutAtom = atom(false);
+
+const useStyles = createStyles(({ token, css }) => ({
+ borderError: css`
+ border-bottom: 1px solid ${token.colorErrorBorder} !important;
+ `,
+ borderWarning: css`
+ border-bottom: 1px solid ${token.colorWarningBorder} !important;
+ `,
+}));
+const NetworkStatusBanner = () => {
+ const { t } = useTranslation();
+ const network = useNetwork();
+
+ const { styles } = useStyles();
+
+ const [softTimeout, setSoftTimeout] = useAtom(networkSoftTimeoutAtom);
+
+ // const handler = (()=>{
+ // });
+
+ // useEffect(()=>{
+ // document.addEventListener('backendai.client.softtimeout', handler);
+ // return ()=>{
+ // document.removeEventListener('backendai.client.softtimeout', handler);
+ // }
+ // },[])
+
+ return !network.online ? (
+
+ ) : softTimeout ? (
+ {
+ setSoftTimeout(false);
+ }}
+ />
+ ) : null;
+};
+
+export default NetworkStatusBanner;
diff --git a/resources/i18n/de.json b/resources/i18n/de.json
index afac50441d..8760552f97 100644
--- a/resources/i18n/de.json
+++ b/resources/i18n/de.json
@@ -68,7 +68,7 @@
"MyEnvironments": "Meine Umgebungen",
"ResourcePolicy": "Ressourcenpolitik"
},
- "YouAreOffline": "Du bist jetzt offline",
+ "YouAreOffline": "Offline: Keine Verbindung zu einem Netzwerk.",
"YouAreOnline": "Sie sind jetzt online",
"NOTFOUND": " Hoppla!
Seite nicht gefunden...
",
"DescNOTFOUND": "Die von Ihnen gesuchte Seite konnte leider nicht gefunden werden.",
diff --git a/resources/i18n/el.json b/resources/i18n/el.json
index 2f5180374f..9a1176e578 100644
--- a/resources/i18n/el.json
+++ b/resources/i18n/el.json
@@ -68,7 +68,7 @@
"MyEnvironments": "Τα περιβάλλοντα μου",
"ResourcePolicy": "Πολιτική Πόρων"
},
- "YouAreOffline": "Είστε πλέον εκτός σύνδεσης",
+ "YouAreOffline": "Offline: Δεν είναι συνδεδεμένος σε κανένα δίκτυο.",
"YouAreOnline": "Είστε πλέον συνδεδεμένοι",
"NOTFOUND": " α0d4554eb75c21z0 Ωχ!
Η σελίδα δεν βρέθηκε ...
",
"DescNOTFOUND": "Δυστυχώς, δεν ήταν δυνατή η εύρεση της σελίδας που αναζητάτε.",
diff --git a/resources/i18n/en.json b/resources/i18n/en.json
index ab21c3852e..d7ac6323c0 100644
--- a/resources/i18n/en.json
+++ b/resources/i18n/en.json
@@ -68,7 +68,7 @@
"MyEnvironments": "My Environments",
"ResourcePolicy": "Resource Policy"
},
- "YouAreOffline": "You are now offline",
+ "YouAreOffline": "Offline: Not connected to any networks.",
"YouAreOnline": "You are now online",
"NOTFOUND": "Oops!
Page not Found...
",
"DescNOTFOUND": "Sorry, the page you are looking for could not be found.",
diff --git a/resources/i18n/es.json b/resources/i18n/es.json
index f4a1a9c2cd..1869de7e30 100644
--- a/resources/i18n/es.json
+++ b/resources/i18n/es.json
@@ -1505,7 +1505,7 @@
"DescNOTFOUND": "Lo sentimos, no se ha encontrado la página que busca.",
"NOTFOUND": "¡Oops!
Página no encontrada...
",
"UNAUTHORIZEDACCESS": "Acceso no autorizado",
- "YouAreOffline": "Ahora está desconectado",
+ "YouAreOffline": "Desconectado: No conectado a ninguna red.",
"YouAreOnline": "Ya está en línea",
"menu": {
"AIAccelerator": "Acelerador de IA",
diff --git a/resources/i18n/fi.json b/resources/i18n/fi.json
index eccf96236c..4105812cc5 100644
--- a/resources/i18n/fi.json
+++ b/resources/i18n/fi.json
@@ -1503,7 +1503,7 @@
"DescNOTFOUND": "Valitettavasti etsimääsi sivua ei löytynyt.",
"NOTFOUND": "Oops!
Sivua ei löydy...
",
"UNAUTHORIZEDACCESS": "Luvaton pääsy",
- "YouAreOffline": "Olet nyt offline-tilassa",
+ "YouAreOffline": "Offline: Ei yhteyttä mihinkään verkkoon.",
"YouAreOnline": "Olet nyt verkossa",
"menu": {
"AIAccelerator": "AI-kiihdyttämö",
diff --git a/resources/i18n/fr.json b/resources/i18n/fr.json
index fb53639fa8..33180b379b 100644
--- a/resources/i18n/fr.json
+++ b/resources/i18n/fr.json
@@ -68,7 +68,7 @@
"MyEnvironments": "Mes environnements",
"ResourcePolicy": "Politique des ressources"
},
- "YouAreOffline": "Vous êtes maintenant hors ligne",
+ "YouAreOffline": "Hors ligne : N'est connecté à aucun réseau.",
"YouAreOnline": "Vous êtes maintenant en ligne",
"NOTFOUND": " Oups !
Page non trouvée...
",
"DescNOTFOUND": "Désolé, la page que vous recherchez est introuvable.",
diff --git a/resources/i18n/id.json b/resources/i18n/id.json
index 5dfa85c427..4b74eddd01 100644
--- a/resources/i18n/id.json
+++ b/resources/i18n/id.json
@@ -68,7 +68,7 @@
"MyEnvironments": "Lingkungan Saya",
"ResourcePolicy": "Kebijakan Sumber Daya"
},
- "YouAreOffline": "Anda sekarang offline",
+ "YouAreOffline": "Offline: Tidak terhubung ke jaringan apa pun.",
"YouAreOnline": "Anda sekarang online",
"NOTFOUND": " Ups!
Halaman tidak ditemukan...
",
"DescNOTFOUND": "Maaf, halaman yang anda cari tidak ditemukan.",
diff --git a/resources/i18n/it.json b/resources/i18n/it.json
index 8146dbd297..de99ccf7cb 100644
--- a/resources/i18n/it.json
+++ b/resources/i18n/it.json
@@ -68,7 +68,7 @@
"MyEnvironments": "I miei ambienti",
"ResourcePolicy": "Politica delle risorse"
},
- "YouAreOffline": "Ora sei offline",
+ "YouAreOffline": "Non in linea: Non è collegato ad alcuna rete.",
"YouAreOnline": "Ora sei online",
"NOTFOUND": " Ops!
Pagina non trovata...
",
"DescNOTFOUND": "Siamo spiacenti, la pagina che stai cercando non è stata trovata.",
diff --git a/resources/i18n/ja.json b/resources/i18n/ja.json
index 7d9041d814..c8f98ff540 100644
--- a/resources/i18n/ja.json
+++ b/resources/i18n/ja.json
@@ -68,7 +68,7 @@
"MyEnvironments": "私の環境",
"ResourcePolicy": "リソースポリシー"
},
- "YouAreOffline": "あなたは今オフラインです",
+ "YouAreOffline": "オフライン:どのネットワークにも接続されていない。",
"YouAreOnline": "あなたは今オンラインです",
"NOTFOUND": " おっと!
ページが見つかりません...
",
"DescNOTFOUND": "申し訳ありませんが、お探しのページが見つかりませんでした。",
diff --git a/resources/i18n/ko.json b/resources/i18n/ko.json
index 4254236b51..411b34172d 100644
--- a/resources/i18n/ko.json
+++ b/resources/i18n/ko.json
@@ -68,7 +68,7 @@
"MyEnvironments": "나의 실행 환경",
"ResourcePolicy": "자원 정책"
},
- "YouAreOffline": "오프라인 상태가 되었습니다",
+ "YouAreOffline": "오프라인: 네트워크에 연결되어 있지 않습니다.",
"YouAreOnline": "온라인 상태가 되었습니다",
"NOTFOUND": "요청하신 페이지를 찾을 수 없습니다.
",
"DescNOTFOUND": "요청하신 페이지가 사라졌거나, 잘못된 경로를 입력하였습니다.",
diff --git a/resources/i18n/mn.json b/resources/i18n/mn.json
index 44a9831858..b2b980f3ee 100644
--- a/resources/i18n/mn.json
+++ b/resources/i18n/mn.json
@@ -68,7 +68,7 @@
"MyEnvironments": "Миний орчин",
"ResourcePolicy": "Нөөцийн бодлого"
},
- "YouAreOffline": "Та одоо офлайн байна",
+ "YouAreOffline": "Офлайн: Ямар ч сүлжээнд холбогдоогүй.",
"YouAreOnline": "Та одоо онлайн байна",
"NOTFOUND": " Өө!
хуудас олдсонгүй ...
",
"DescNOTFOUND": "Уучлаарай, таны хайж буй хуудас олдсонгүй.",
diff --git a/resources/i18n/ms.json b/resources/i18n/ms.json
index 847a8db145..7d57f4f9b3 100644
--- a/resources/i18n/ms.json
+++ b/resources/i18n/ms.json
@@ -68,7 +68,7 @@
"MyEnvironments": "Persekitaran Saya",
"ResourcePolicy": "Dasar Sumber"
},
- "YouAreOffline": "Anda kini berada di luar talian",
+ "YouAreOffline": "Luar talian: Tidak disambungkan ke mana-mana rangkaian.",
"YouAreOnline": "Anda kini dalam talian",
"NOTFOUND": " Alamak!
Halaman tidak dijumpai ...
",
"DescNOTFOUND": "Maaf, halaman yang anda cari tidak dapat dijumpai.",
diff --git a/resources/i18n/pl.json b/resources/i18n/pl.json
index a5ad1ec575..c288e77a9b 100644
--- a/resources/i18n/pl.json
+++ b/resources/i18n/pl.json
@@ -68,7 +68,7 @@
"MyEnvironments": "Moje Środowiska",
"ResourcePolicy": "Polityka zasobów"
},
- "YouAreOffline": "Jesteś teraz offline",
+ "YouAreOffline": "Offline: Brak połączenia z siecią.",
"YouAreOnline": "Jesteś teraz online",
"NOTFOUND": " Ups!
Nie znaleziono strony...
",
"DescNOTFOUND": "Przepraszamy, nie można znaleźć strony, której szukasz.",
diff --git a/resources/i18n/pt-BR.json b/resources/i18n/pt-BR.json
index f241397c42..1bdce1a09c 100644
--- a/resources/i18n/pt-BR.json
+++ b/resources/i18n/pt-BR.json
@@ -68,7 +68,7 @@
"MyEnvironments": "Meus ambientes",
"ResourcePolicy": "Política de Recursos"
},
- "YouAreOffline": "Agora você está offline",
+ "YouAreOffline": "Desligado: Não está ligado a nenhuma rede.",
"YouAreOnline": "Agora você está online",
"NOTFOUND": " Ops!
Página não encontrada ...
",
"DescNOTFOUND": "Desculpe, a página que você está procurando não foi encontrada.",
diff --git a/resources/i18n/pt.json b/resources/i18n/pt.json
index 59971597d7..4f3ebe8fef 100644
--- a/resources/i18n/pt.json
+++ b/resources/i18n/pt.json
@@ -68,7 +68,7 @@
"MyEnvironments": "Meus ambientes",
"ResourcePolicy": "Política de Recursos"
},
- "YouAreOffline": "Agora você está offline",
+ "YouAreOffline": "Desligado: Não está ligado a nenhuma rede.",
"YouAreOnline": "Agora você está online",
"NOTFOUND": " Ops!
Página não encontrada ...
",
"DescNOTFOUND": "Desculpe, a página que você está procurando não foi encontrada.",
diff --git a/resources/i18n/ru.json b/resources/i18n/ru.json
index 0b52912774..411cd34e87 100644
--- a/resources/i18n/ru.json
+++ b/resources/i18n/ru.json
@@ -68,7 +68,7 @@
"MyEnvironments": "Моя среда",
"ResourcePolicy": "Ресурсная политика"
},
- "YouAreOffline": "Вы сейчас не в сети",
+ "YouAreOffline": "Не в сети: Не подключен ни к одной сети.",
"YouAreOnline": "Вы сейчас в сети",
"NOTFOUND": " Ой!
Страница не найдена ...
",
"DescNOTFOUND": "Извините, страница, которую вы ищете, не может быть найдена.",
diff --git a/resources/i18n/tr.json b/resources/i18n/tr.json
index 0d57188532..89ef6c935d 100644
--- a/resources/i18n/tr.json
+++ b/resources/i18n/tr.json
@@ -68,7 +68,7 @@
"MyEnvironments": "Ortamlarım",
"ResourcePolicy": "Kaynak Politikası"
},
- "YouAreOffline": "Şu anda çevrimdışısın",
+ "YouAreOffline": "Çevrimdışı: Herhangi bir ağa bağlı değil.",
"YouAreOnline": "artık çevrimiçisin",
"NOTFOUND": " Hata!
Sayfa Bulunamadı...
",
"DescNOTFOUND": "Üzgünüz, aradığınız sayfa bulunamadı.",
diff --git a/resources/i18n/vi.json b/resources/i18n/vi.json
index 251f61aa12..bda6b26633 100644
--- a/resources/i18n/vi.json
+++ b/resources/i18n/vi.json
@@ -68,7 +68,7 @@
"MyEnvironments": "Môi trường của tôi",
"ResourcePolicy": "Chính sách tài nguyên"
},
- "YouAreOffline": "Bạn hiện đang ngoại tuyến",
+ "YouAreOffline": "Ngoại tuyến: Không kết nối với bất kỳ mạng nào.",
"YouAreOnline": "Bạn hiện đang trực tuyến",
"NOTFOUND": " Rất tiếc!
Không tìm thấy trang ...
",
"DescNOTFOUND": "Xin lỗi, không thể tìm thấy trang bạn đang tìm.",
diff --git a/resources/i18n/zh-CN.json b/resources/i18n/zh-CN.json
index bee577bebf..a3af896a6a 100644
--- a/resources/i18n/zh-CN.json
+++ b/resources/i18n/zh-CN.json
@@ -68,7 +68,7 @@
"MyEnvironments": "我的环境",
"ResourcePolicy": "资源政策"
},
- "YouAreOffline": "您现在离线",
+ "YouAreOffline": "脱机:未连接任何网络。",
"YouAreOnline": "您现在在线",
"NOTFOUND": " 糟糕!
页面未找到...
",
"DescNOTFOUND": "抱歉,找不到您要找的页面。",
diff --git a/resources/i18n/zh-TW.json b/resources/i18n/zh-TW.json
index ac2a404fb3..d55c426d5c 100644
--- a/resources/i18n/zh-TW.json
+++ b/resources/i18n/zh-TW.json
@@ -68,7 +68,7 @@
"MyEnvironments": "我的環境",
"ResourcePolicy": "資源政策"
},
- "YouAreOffline": "您現在離線",
+ "YouAreOffline": "脱机:未连接任何网络。",
"YouAreOnline": "您現在在線",
"NOTFOUND": " 糟糕!
頁面未找到...
",
"DescNOTFOUND": "抱歉,找不到您要找的頁面。",
diff --git a/src/backend-ai-app.ts b/src/backend-ai-app.ts
index 8050c44bc9..cf7046a1dc 100644
--- a/src/backend-ai-app.ts
+++ b/src/backend-ai-app.ts
@@ -5,8 +5,6 @@
export const UPDATE_PAGE = 'UPDATE_PAGE';
export const UPDATE_OFFLINE = 'UPDATE_OFFLINE';
export const UPDATE_DRAWER_STATE = 'UPDATE_DRAWER_STATE';
-export const OPEN_SNACKBAR = 'OPEN_SNACKBAR';
-export const CLOSE_SNACKBAR = 'CLOSE_SNACKBAR';
export const navigate =
(path: any, params: Record = {}) =>
@@ -192,30 +190,6 @@ const updatePage = (page, params) => {
};
};
-let offlineTimer;
-
-export const showOffline = () => (dispatch) => {
- dispatch({
- type: OPEN_SNACKBAR,
- });
- window.clearTimeout(offlineTimer);
- offlineTimer = window.setTimeout(
- () => dispatch({ type: CLOSE_SNACKBAR }),
- 3000,
- );
-};
-
-export const updateOffline = (offline) => (dispatch, getState) => {
- // Show the snackbar only if offline status changes.
- if (offline !== getState().app.offline) {
- dispatch(showOffline());
- }
- dispatch({
- type: UPDATE_OFFLINE,
- offline,
- });
-};
-
export const updateDrawerState = (opened) => {
return {
type: UPDATE_DRAWER_STATE,
diff --git a/src/components/backend-ai-offline-indicator.ts b/src/components/backend-ai-offline-indicator.ts
deleted file mode 100644
index 97832181ae..0000000000
--- a/src/components/backend-ai-offline-indicator.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- @license
- Copyright (c) 2015-2024 Lablup Inc. All rights reserved.
- */
-import { css, CSSResultGroup, html, LitElement } from 'lit';
-import { customElement } from 'lit/decorators.js';
-
-/**
- Backend.AI Offline Indicator
-
- Example:
-
-
-
-@group Backend.AI Web UI
- @element backend-ai-offline-indicator
- */
-
-@customElement('backend-ai-offline-indicator')
-export default class BackendAIOfflineIndicator extends LitElement {
- static get styles(): CSSResultGroup | undefined {
- return [
- css`
- :host {
- display: block;
- position: fixed;
- top: 100%;
- left: 0;
- right: 0;
- padding: 12px;
- background-color: #246;
- color: white;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
- text-align: center;
- will-change: transform;
- transform: translate3d(0, 0, 0);
- transition-property: visibility, transform;
- transition-duration: 0.2s;
- visibility: hidden;
- }
-
- :host([active]) {
- visibility: visible;
- transform: translate3d(0, -100%, 0);
- }
-
- @media (min-width: 460px) {
- :host {
- width: 320px;
- margin: auto;
- }
- }
- `,
- ];
- }
-
- render() {
- return html`
-
- `;
- }
-}
-
-declare global {
- interface HTMLElementTagNameMap {
- 'backend-ai-offline-indicator': BackendAIOfflineIndicator;
- }
-}
diff --git a/src/components/backend-ai-webui.ts b/src/components/backend-ai-webui.ts
index dcec0fc4e9..c9e9efbe4e 100644
--- a/src/components/backend-ai-webui.ts
+++ b/src/components/backend-ai-webui.ts
@@ -2,7 +2,7 @@
@license
Copyright (c) 2015-2024 Lablup Inc. All rights reserved.
*/
-import { navigate, updateOffline } from '../backend-ai-app';
+import { navigate } from '../backend-ai-app';
// import '../lib/backend.ai-client-esm';
import { default as TabCount } from '../lib/TabCounter';
import {
@@ -19,7 +19,6 @@ import './backend-ai-help-button';
import './backend-ai-indicator-pool';
import './backend-ai-login';
import BackendAIMetadataStore from './backend-ai-metadata-store';
-import './backend-ai-offline-indicator';
import { BackendAIPage } from './backend-ai-page';
import './backend-ai-project-switcher';
import './backend-ai-resource-broker';
@@ -52,7 +51,6 @@ import { customElement, property, query } from 'lit/decorators.js';
import toml from 'markty-toml';
// PWA components
import { connect } from 'pwa-helpers/connect-mixin';
-import { installOfflineWatcher } from 'pwa-helpers/network';
import { installRouter } from 'pwa-helpers/router';
registerTranslateConfig({
@@ -107,7 +105,6 @@ export default class BackendAIWebUI extends connect(store)(LitElement) {
| 'feedback'
| 'notification'
| 'task' = '';
- @property({ type: Boolean }) _offlineIndicatorOpened = false;
@property({ type: Boolean }) _offline = false;
@property({ type: Object }) config = Object();
@property({ type: Object }) notification;
@@ -236,7 +233,6 @@ export default class BackendAIWebUI extends connect(store)(LitElement) {
installRouter((location) =>
store.dispatch(navigate(decodeURIComponent(location.pathname))),
);
- installOfflineWatcher((offline) => store.dispatch(updateOffline(offline)));
let configPath;
if (globalThis.isElectron) {
configPath = './config.toml';
@@ -867,7 +863,6 @@ export default class BackendAIWebUI extends connect(store)(LitElement) {
this._page = state.app.page;
this._pageParams = state.app.params;
this._offline = state.app.offline;
- this._offlineIndicatorOpened = state.app.offlineIndicatorOpened;
// this._drawerOpened = state.app.drawerOpened;
globalThis.currentPage = this._page;
globalThis.currentPageParams = this._pageParams;
@@ -966,9 +961,7 @@ export default class BackendAIWebUI extends connect(store)(LitElement) {
-
- ${this._offline ? _t('webui.YouAreOffline') : _t('webui.YouAreOnline')}.
-
+
diff --git a/src/reducers/app.ts b/src/reducers/app.ts
index b0243f3b6f..c7eb4aad4d 100644
--- a/src/reducers/app.ts
+++ b/src/reducers/app.ts
@@ -36,16 +36,6 @@ const app = (state = INITIAL_STATE, action) => {
...state,
drawerOpened: action.opened,
};
- case OPEN_SNACKBAR:
- return {
- ...state,
- offlineIndicatorOpened: true,
- };
- case CLOSE_SNACKBAR:
- return {
- ...state,
- offlineIndicatorOpened: false,
- };
default:
return state;
}
diff --git a/src/types/backend-ai-console.d.ts b/src/types/backend-ai-console.d.ts
index eeb3a48132..bae36fa078 100644
--- a/src/types/backend-ai-console.d.ts
+++ b/src/types/backend-ai-console.d.ts
@@ -4,7 +4,6 @@ import './backend-ai-dialog';
import './backend-ai-help-button';
import './backend-ai-indicator-pool';
import './backend-ai-login';
-import './backend-ai-offline-indicator';
import './backend-ai-resource-broker';
import './backend-ai-settings-store';
import './backend-ai-sidepanel-notification';