fix: sync dashboard page query state
Keep the selected dashboard page in sync with lightweight URL query params so direct terminal links can land on the right page without exposing extra client state. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,21 @@
|
|||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import { getToken, checkAuth, setToken, setRefreshToken, currentUser, setCurrentUser, getPreferences, savePreferences } from "./lib/api.js";
|
import { getToken, checkAuth, setToken, setRefreshToken, currentUser, setCurrentUser, getPreferences, savePreferences } from "./lib/api.js";
|
||||||
|
|
||||||
|
const KNOWN_PAGES = new Set([
|
||||||
|
"dashboard",
|
||||||
|
"docker",
|
||||||
|
"gitea",
|
||||||
|
"files",
|
||||||
|
"terminal",
|
||||||
|
"openclaw",
|
||||||
|
"chat-digest",
|
||||||
|
"settings",
|
||||||
|
"security",
|
||||||
|
"litellm",
|
||||||
|
"cc-connect",
|
||||||
|
"info-engine",
|
||||||
|
]);
|
||||||
|
|
||||||
let page = $state("dashboard");
|
let page = $state("dashboard");
|
||||||
let dark = $state(false);
|
let dark = $state(false);
|
||||||
let sidebarOpen = $state(false);
|
let sidebarOpen = $state(false);
|
||||||
@@ -27,6 +42,26 @@
|
|||||||
let sidebarOrder = $state(null);
|
let sidebarOrder = $state(null);
|
||||||
let orderSaveTimer = null;
|
let orderSaveTimer = null;
|
||||||
|
|
||||||
|
function getRequestedPage() {
|
||||||
|
const requestedPage = new URLSearchParams(window.location.search).get("page");
|
||||||
|
return KNOWN_PAGES.has(requestedPage) ? requestedPage : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function canOpenPage(pageId) {
|
||||||
|
if (!pageId || !KNOWN_PAGES.has(pageId)) return false;
|
||||||
|
if (pageId === "settings") return userRole === "admin";
|
||||||
|
if (["litellm", "cc-connect", "info-engine"].includes(pageId)) return hasPageAccess("dashboard");
|
||||||
|
return hasPageAccess(pageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncPageQuery(pageId) {
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
if (pageId === "dashboard") url.searchParams.delete("page");
|
||||||
|
else url.searchParams.set("page", pageId);
|
||||||
|
if (pageId !== "terminal") url.searchParams.delete("host");
|
||||||
|
history.replaceState({}, "", `${url.pathname}${url.search}${url.hash}`);
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchUserInfo() {
|
async function fetchUserInfo() {
|
||||||
try {
|
try {
|
||||||
const data = await checkAuth();
|
const data = await checkAuth();
|
||||||
@@ -78,6 +113,8 @@
|
|||||||
setRefreshToken(data.refresh_token);
|
setRefreshToken(data.refresh_token);
|
||||||
authorized = true;
|
authorized = true;
|
||||||
await fetchUserInfo();
|
await fetchUserInfo();
|
||||||
|
const requestedPage = getRequestedPage();
|
||||||
|
if (canOpenPage(requestedPage)) page = requestedPage;
|
||||||
loading = false;
|
loading = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -96,6 +133,8 @@
|
|||||||
try {
|
try {
|
||||||
await fetchUserInfo();
|
await fetchUserInfo();
|
||||||
authorized = true;
|
authorized = true;
|
||||||
|
const requestedPage = getRequestedPage();
|
||||||
|
if (canOpenPage(requestedPage)) page = requestedPage;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Auth check failed:", e);
|
console.error("Auth check failed:", e);
|
||||||
setToken("");
|
setToken("");
|
||||||
@@ -105,6 +144,11 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (!authorized || loading || !canOpenPage(page)) return;
|
||||||
|
syncPageQuery(page);
|
||||||
|
});
|
||||||
|
|
||||||
function toggleTheme() {
|
function toggleTheme() {
|
||||||
dark = !dark;
|
dark = !dark;
|
||||||
if (dark) {
|
if (dark) {
|
||||||
|
|||||||
Reference in New Issue
Block a user