refactor(webui): clarify shared controls and status feedback
This commit is contained in:
@@ -2,7 +2,7 @@ import { Navigate, Route, Routes } from "react-router-dom";
|
||||
import { lazy, Suspense, useEffect, useMemo, useState } from "react";
|
||||
import { fetchSession, fetchShellAuth, updateProfile } from "./api/auth";
|
||||
import { fetchPlatformModules, fetchPlatformStatus } from "./api/platform";
|
||||
import { AUTH_REQUIRED_EVENT, loadApiSettings, saveApiSettings, type AuthRequiredEventDetail } from "./api/client";
|
||||
import { AUTH_REQUIRED_EVENT, isApiError, loadApiSettings, saveApiSettings, type AuthRequiredEventDetail } from "./api/client";
|
||||
import type { ApiSettings, AuthInfo, AuthSessionInfo, AuthUpdate, AuthUser, LoginResponse, PlatformModuleInfo, PlatformWebModule, UserUiPreferences } from "./types";
|
||||
import AppShell from "./layout/AppShell";
|
||||
import PublicLandingPage from "./features/auth/PublicLandingPage";
|
||||
@@ -32,6 +32,7 @@ export default function App() {
|
||||
const [platformModules, setPlatformModules] = useState<PlatformModuleInfo[] | null>(null);
|
||||
const [remoteWebModules, setRemoteWebModules] = useState<PlatformWebModule[]>([]);
|
||||
const [maintenanceMode, setMaintenanceMode] = useState<{enabled: boolean;message?: string | null;}>({ enabled: false, message: null });
|
||||
const [backendReachable, setBackendReachable] = useState(true);
|
||||
const [systemLanguages, setSystemLanguages] = useState<{available: PlatformLanguage[];enabled: string[];defaultLanguage: string;} | null>(null);
|
||||
const [reloginMessage, setReloginMessage] = useState("");
|
||||
|
||||
@@ -87,6 +88,7 @@ export default function App() {
|
||||
try {
|
||||
const response = await fetchPlatformStatus(settings);
|
||||
if (cancelled) return;
|
||||
setBackendReachable(true);
|
||||
setMaintenanceMode(response.maintenance_mode);
|
||||
if (response.i18n) {
|
||||
setSystemLanguages({
|
||||
@@ -100,7 +102,10 @@ export default function App() {
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
if (!cancelled) setMaintenanceMode({ enabled: false, message: null });
|
||||
if (!cancelled) {
|
||||
setBackendReachable(false);
|
||||
setMaintenanceMode({ enabled: false, message: null });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,9 +126,13 @@ export default function App() {
|
||||
async function bootstrapAuth() {
|
||||
try {
|
||||
const shellAuth = await fetchShellAuth(settings);
|
||||
if (!cancelled) setAuth(normalizeAuthInfo(shellAuth));
|
||||
} catch {
|
||||
if (!cancelled) {
|
||||
setBackendReachable(true);
|
||||
setAuth(normalizeAuthInfo(shellAuth));
|
||||
}
|
||||
} catch (error) {
|
||||
if (!cancelled) {
|
||||
setBackendReachable(isApiError(error));
|
||||
const cleared = { ...settings, accessToken: "" };
|
||||
setSettings(cleared);
|
||||
saveApiSettings(cleared);
|
||||
@@ -243,6 +252,7 @@ export default function App() {
|
||||
try {
|
||||
const sessionInfo = await fetchSession(settings);
|
||||
if (cancelled) return;
|
||||
setBackendReachable(true);
|
||||
const shellRefreshDue = now - lastShellRefreshAt >= 60_000;
|
||||
if (!sessionMatchesAuth(sessionInfo, currentAuth) || shellRefreshDue) {
|
||||
const shellAuth = await fetchShellAuth(settings);
|
||||
@@ -252,7 +262,10 @@ export default function App() {
|
||||
? normalizeAuthInfo(mergeAuthPayload(current, shellAuth))
|
||||
: normalizeAuthInfo(shellAuth));
|
||||
}
|
||||
} catch {
|
||||
} catch (error) {
|
||||
if (!cancelled && !isApiError(error)) {
|
||||
setBackendReachable(false);
|
||||
}
|
||||
|
||||
|
||||
// A background refresh must not log the user out on a transient network error.
|
||||
@@ -273,7 +286,7 @@ export default function App() {
|
||||
<PlatformLanguageProvider systemAvailableLanguages={systemLanguages?.available} systemEnabledLanguageCodes={systemLanguages?.enabled} defaultLanguage={systemLanguages?.defaultLanguage} moduleTranslations={moduleTranslations}>
|
||||
<PlatformModulesProvider modules={webModules}>
|
||||
<UnsavedChangesProvider>
|
||||
<AppShell settings={settings} auth={null} onSettingsChange={updateSettings} onAuthChange={updateAuth} publicMode navItems={navItems} maintenanceMode={maintenanceMode}>
|
||||
<AppShell settings={settings} auth={null} onSettingsChange={updateSettings} onAuthChange={updateAuth} publicMode navItems={navItems} maintenanceMode={maintenanceMode} backendReachable={backendReachable}>
|
||||
<div className="public-landing">
|
||||
<section className="public-card">
|
||||
<div className="public-kicker">i18n:govoplan-core.govoplan.a84c0a85</div>
|
||||
@@ -293,7 +306,7 @@ export default function App() {
|
||||
<PlatformLanguageProvider systemAvailableLanguages={systemLanguages?.available} systemEnabledLanguageCodes={systemLanguages?.enabled} defaultLanguage={systemLanguages?.defaultLanguage} moduleTranslations={moduleTranslations}>
|
||||
<PlatformModulesProvider modules={webModules}>
|
||||
<UnsavedChangesProvider>
|
||||
<AppShell settings={settings} auth={null} onSettingsChange={updateSettings} onAuthChange={updateAuth} publicMode navItems={navItems} maintenanceMode={maintenanceMode}>
|
||||
<AppShell settings={settings} auth={null} onSettingsChange={updateSettings} onAuthChange={updateAuth} publicMode navItems={navItems} maintenanceMode={maintenanceMode} backendReachable={backendReachable}>
|
||||
<PublicLandingPage settings={settings} maintenanceMode={maintenanceMode} onLogin={handlePublicLogin} />
|
||||
</AppShell>
|
||||
</UnsavedChangesProvider>
|
||||
@@ -324,7 +337,7 @@ export default function App() {
|
||||
moduleTranslations={moduleTranslations}>
|
||||
<PlatformModulesProvider modules={webModules}>
|
||||
<UnsavedChangesProvider>
|
||||
<AppShell settings={settings} auth={auth} onSettingsChange={updateSettings} onAuthChange={updateAuth} navItems={navItems} maintenanceMode={maintenanceMode}>
|
||||
<AppShell settings={settings} auth={auth} onSettingsChange={updateSettings} onAuthChange={updateAuth} navItems={navItems} maintenanceMode={maintenanceMode} backendReachable={backendReachable}>
|
||||
<Suspense fallback={<div className="content-pad"><p className="muted">i18n:govoplan-core.loading_module.50161f3c</p></div>}>
|
||||
<Routes key={(auth.active_tenant ?? auth.tenant).id}>
|
||||
<Route path="/" element={<Navigate to={defaultRoute} replace />} />
|
||||
|
||||
Reference in New Issue
Block a user