mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 12:42:38 +00:00
changed default scope for app health
This commit is contained in:
@@ -198,11 +198,9 @@ export default function AppDetailPage() {
|
||||
const { globalAdminMode } = useAdminMode();
|
||||
|
||||
const isGlobalAdmin = globalAdminMode && user?.isGlobalAdmin;
|
||||
// URL-flag takes priority for initial scope; if the global banner is active
|
||||
// but URL didn't specify, we default to aggregated (empty string).
|
||||
const [selectedTenantId, setSelectedTenantId] = useState<string>(
|
||||
isGlobalAdmin ? urlTenantId : ""
|
||||
);
|
||||
// selectedTenantId source of truth, see scope-init effect below for the rules.
|
||||
const [selectedTenantId, setSelectedTenantId] = useState<string>("");
|
||||
const [scopeInitialized, setScopeInitialized] = useState(false);
|
||||
const [tenants, setTenants] = useState<TenantInfo[]>([]);
|
||||
|
||||
const useGlobalEndpoint = Boolean(isGlobalAdmin && (urlGlobal || selectedTenantId !== tenantId || !tenantId));
|
||||
@@ -287,7 +285,26 @@ export default function AppDetailPage() {
|
||||
[isGlobalAdmin]
|
||||
);
|
||||
|
||||
const hasInitialFetch = useRef(false);
|
||||
// Initialize the scope once tenantId is available.
|
||||
// Three cases for GAs:
|
||||
// 1. URL carries ?global=1&tenantId=X → use X (came from list with explicit tenant)
|
||||
// 2. URL carries ?global=1 (no tenantId) → aggregated (came from "All tenants" view)
|
||||
// 3. No ?global flag (direct nav, bookmark, deep link) → default to own tenant
|
||||
// Regular users always use their own tenant; selectedTenantId stays empty.
|
||||
useEffect(() => {
|
||||
if (scopeInitialized) return;
|
||||
if (!tenantId) return;
|
||||
if (isGlobalAdmin) {
|
||||
if (urlGlobal) {
|
||||
// Came from list — honor whatever the list propagated (specific tenant or aggregated)
|
||||
setSelectedTenantId(urlTenantId);
|
||||
} else {
|
||||
// Direct navigation — default to own tenant
|
||||
setSelectedTenantId(tenantId);
|
||||
}
|
||||
}
|
||||
setScopeInitialized(true);
|
||||
}, [tenantId, isGlobalAdmin, urlGlobal, urlTenantId, scopeInitialized]);
|
||||
|
||||
// Fetch tenant list once in global mode.
|
||||
useEffect(() => {
|
||||
@@ -370,22 +387,16 @@ export default function AppDetailPage() {
|
||||
}
|
||||
};
|
||||
|
||||
// Single fetch effect: re-runs when scope, app, days, or tenant selection change.
|
||||
// Gated on scopeInitialized so we don't waste a backend hit fetching the
|
||||
// wrong scope before the GA default-to-own-tenant has settled.
|
||||
useEffect(() => {
|
||||
if (!isGlobalAdmin && !tenantId) return;
|
||||
if (hasInitialFetch.current) return;
|
||||
hasInitialFetch.current = true;
|
||||
fetchAnalytics();
|
||||
fetchSessions(0, statusFilter);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [tenantId, isGlobalAdmin]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasInitialFetch.current) return;
|
||||
if (!scopeInitialized) return;
|
||||
fetchAnalytics();
|
||||
setSessionsOffset(0);
|
||||
fetchSessions(0, statusFilter);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [days, selectedTenantId]);
|
||||
}, [scopeInitialized, days, selectedTenantId]);
|
||||
|
||||
function formatDuration(s: number) {
|
||||
if (!s) return "—";
|
||||
|
||||
@@ -62,9 +62,12 @@ export default function AppsPage() {
|
||||
const { addNotification } = useNotifications();
|
||||
const { globalAdminMode } = useAdminMode();
|
||||
|
||||
// Global admin: tenant selector state
|
||||
// Global admin: tenant selector state.
|
||||
// Default for GAs is their own tenant (set once tenantId loads), not aggregated —
|
||||
// gives the standard "view your tenant first, opt-in to aggregated/override".
|
||||
const [tenants, setTenants] = useState<TenantInfo[]>([]);
|
||||
const [selectedTenantId, setSelectedTenantId] = useState<string>("");
|
||||
const [scopeInitialized, setScopeInitialized] = useState(false);
|
||||
|
||||
const isGlobalAdmin = globalAdminMode && user?.isGlobalAdmin;
|
||||
// "aggregated" = GA view across all tenants (no tenant selected)
|
||||
@@ -75,7 +78,6 @@ export default function AppsPage() {
|
||||
);
|
||||
const effectiveTenantId = isGlobalAdmin ? selectedTenantId : tenantId;
|
||||
|
||||
const hasInitialFetch = useRef(false);
|
||||
const isTimeRangeMount = useRef(true);
|
||||
|
||||
// Fetch tenant list for Global Admin selector
|
||||
@@ -146,22 +148,30 @@ export default function AppsPage() {
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize the scope once tenantId is available.
|
||||
// - Regular users: scope is implicitly their own tenant; just mark initialized.
|
||||
// - GAs: default selectedTenantId to their own tenant (not aggregated).
|
||||
// This runs exactly once and never again — user choices afterwards stand on their own.
|
||||
useEffect(() => {
|
||||
if (!isGlobalAdmin && !tenantId) return;
|
||||
if (hasInitialFetch.current) return;
|
||||
hasInitialFetch.current = true;
|
||||
fetchApps(timeRange);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [tenantId, isGlobalAdmin]);
|
||||
if (scopeInitialized) return;
|
||||
if (!tenantId) return;
|
||||
if (isGlobalAdmin) {
|
||||
setSelectedTenantId(tenantId);
|
||||
}
|
||||
setScopeInitialized(true);
|
||||
}, [tenantId, isGlobalAdmin, scopeInitialized]);
|
||||
|
||||
// Fetch whenever the effective scope or time range changes — gated on
|
||||
// scopeInitialized so we don't do an initial aggregated-fetch before the
|
||||
// GA default-to-own-tenant kicks in (would otherwise cause a wasted backend hit).
|
||||
useEffect(() => {
|
||||
if (!scopeInitialized) return;
|
||||
if (isTimeRangeMount.current) {
|
||||
isTimeRangeMount.current = false;
|
||||
return;
|
||||
}
|
||||
fetchApps(timeRange);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [timeRange, selectedTenantId]);
|
||||
}, [scopeInitialized, timeRange, selectedTenantId]);
|
||||
|
||||
const filteredAndSorted = useMemo<AppRow[]>(() => {
|
||||
if (!data?.apps) return [];
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user