fix: persist environment selection in Zustand store instead of URL params
Environment selector was losing its value on navigation because URL search params were silently dropped by navigate() calls. Moved to a Zustand store with localStorage persistence so the selection survives navigation, page refresh, and new tabs. Switching environment now resets all filters, clears URL params, invalidates queries, and remounts pages via Outlet key. Also syncs openapi.json schema with running backend. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Outlet, useNavigate, useLocation, useSearchParams } from 'react-router';
|
||||
import { Outlet, useNavigate, useLocation } from 'react-router';
|
||||
import {
|
||||
AppShell,
|
||||
Sidebar,
|
||||
@@ -23,6 +23,7 @@ import { useSearchExecutions, useAttributeKeys } from '../api/queries/executions
|
||||
import { useUsers, useGroups, useRoles } from '../api/queries/admin/rbac';
|
||||
import type { UserDetail, GroupDetail, RoleDetail } from '../api/queries/admin/rbac';
|
||||
import { useAuthStore } from '../auth/auth-store';
|
||||
import { useEnvironmentStore } from '../api/environment-store';
|
||||
import { useState, useMemo, useCallback, useEffect, useRef, createElement } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import { ContentTabs } from './ContentTabs';
|
||||
@@ -272,23 +273,12 @@ const SK_COLLAPSED = 'sidebar:collapsed';
|
||||
function LayoutContent() {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const queryClient = useQueryClient();
|
||||
const { timeRange, autoRefresh, refreshTimeRange } = useGlobalFilters();
|
||||
|
||||
// --- Environment filtering -----------------------------------------
|
||||
const selectedEnv = searchParams.get('env') || undefined;
|
||||
const setSelectedEnv = useCallback((env: string | undefined) => {
|
||||
setSearchParams((prev) => {
|
||||
const next = new URLSearchParams(prev);
|
||||
if (env) {
|
||||
next.set('env', env);
|
||||
} else {
|
||||
next.delete('env');
|
||||
}
|
||||
return next;
|
||||
}, { replace: true });
|
||||
}, [setSearchParams]);
|
||||
const selectedEnv = useEnvironmentStore((s) => s.environment);
|
||||
const setSelectedEnvRaw = useEnvironmentStore((s) => s.setEnvironment);
|
||||
|
||||
const { data: catalog } = useRouteCatalog(timeRange.start.toISOString(), timeRange.end.toISOString(), selectedEnv);
|
||||
const { data: allAgents } = useAgents(); // unfiltered — for environment discovery
|
||||
@@ -330,6 +320,15 @@ function LayoutContent() {
|
||||
// --- Sidebar filter -----------------------------------------------
|
||||
const [filterQuery, setFilterQuery] = useState('');
|
||||
|
||||
const setSelectedEnv = useCallback((env: string | undefined) => {
|
||||
setSelectedEnvRaw(env);
|
||||
setFilterQuery('');
|
||||
if (location.search) {
|
||||
navigate(location.pathname, { replace: true });
|
||||
}
|
||||
queryClient.invalidateQueries();
|
||||
}, [setSelectedEnvRaw, navigate, location.pathname, location.search, queryClient]);
|
||||
|
||||
// --- Section open states ------------------------------------------
|
||||
const [appsOpen, setAppsOpen] = useState(() => isAdminPage ? false : readCollapsed(SK_APPS, true));
|
||||
const [adminOpen, setAdminOpen] = useState(() => isAdminPage ? true : readCollapsed(SK_ADMIN, false));
|
||||
@@ -537,6 +536,7 @@ function LayoutContent() {
|
||||
// --- Callbacks ----------------------------------------------------
|
||||
const handleLogout = useCallback(() => {
|
||||
logout();
|
||||
useEnvironmentStore.getState().setEnvironment(undefined);
|
||||
navigate('/login');
|
||||
}, [logout, navigate]);
|
||||
|
||||
@@ -729,7 +729,7 @@ function LayoutContent() {
|
||||
)}
|
||||
|
||||
<main style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden', minHeight: 0 }}>
|
||||
<Outlet />
|
||||
<Outlet key={selectedEnv ?? '__all__'} />
|
||||
</main>
|
||||
</AppShell>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user