mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 12:42:38 +00:00
feat(web): small "Docs" link in every portal page header
Session details, diagnosis, annotations, fleet health, geographic performance, SLA, software, usage metrics, audit log, system health, IME log patterns and the rules pages link to their guide from the end of the header control group. Navbar help links use the DOCS_PATHS catalog (service announcements no longer goes through a redirect). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,7 @@ import AnalyzeRuleCard, { RuleTrendPoint, RuleRegressionInfo } from "./component
|
||||
import TemplateConfigModal from "./components/TemplateConfigModal";
|
||||
import { SectionCardHeader } from "@/components/SectionCardHeader";
|
||||
import { DOCS_PATHS } from "@/lib/docsPaths";
|
||||
import { DocsLink } from "@/components/DocsLink";
|
||||
|
||||
export default function AnalyzeRulesPage() {
|
||||
const { user, getAccessToken } = useAuth();
|
||||
@@ -545,14 +546,17 @@ export default function AnalyzeRulesPage() {
|
||||
{/* Header */}
|
||||
<header className="bg-white shadow">
|
||||
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex flex-wrap items-center justify-between gap-y-3">
|
||||
<div>
|
||||
<div>
|
||||
<h1 className="text-2xl font-normal text-gray-900">Analyze Rules</h1>
|
||||
<p className="text-sm text-gray-600 mt-1">Manage event analysis rules for issue detection</p>
|
||||
</div>
|
||||
</div>
|
||||
<TenantScopeSelector scope={scope} />
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<TenantScopeSelector scope={scope} />
|
||||
<DocsLink path={DOCS_PATHS.analyzeRules} label="Docs" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -21,6 +21,8 @@ import {
|
||||
type AnnotationLane,
|
||||
type AnnotationVerdict,
|
||||
} from "../sessions/components/sessionAnnotationLogic";
|
||||
import { DocsLink } from "@/components/DocsLink";
|
||||
import { DOCS_PATHS } from "@/lib/docsPaths";
|
||||
|
||||
/**
|
||||
* Annotations overview: every annotated session in one list, so a judged session can be
|
||||
@@ -150,7 +152,10 @@ export default function AnnotationsPage() {
|
||||
Every session your team has judged — open one to read or update the verdict.
|
||||
</p>
|
||||
</div>
|
||||
<TenantScopeSelector scope={scope} allowAggregated />
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<TenantScopeSelector scope={scope} allowAggregated />
|
||||
<DocsLink path={DOCS_PATHS.annotations} label="Docs" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -12,6 +12,8 @@ import InstallsTab from "./components/InstallsTab";
|
||||
import InventoryTab from "./components/InventoryTab";
|
||||
import VulnerabilitiesTab from "./components/VulnerabilitiesTab";
|
||||
import type { TimeRange } from "./components/types";
|
||||
import { DocsLink } from "@/components/DocsLink";
|
||||
import { DOCS_PATHS } from "@/lib/docsPaths";
|
||||
|
||||
const TABS = [
|
||||
{ id: "installs", label: "Installs" },
|
||||
@@ -54,6 +56,7 @@ function SoftwareHub() {
|
||||
value={timeRange}
|
||||
onChange={(v) => setTimeRange(v as typeof timeRange)}
|
||||
/>
|
||||
<DocsLink path={DOCS_PATHS.softwareInventory} label="Docs" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ import { extractContinuation } from "@/lib/paginationLink";
|
||||
import { useAggregatedAdminScope } from "@/hooks";
|
||||
import { TenantScopeSelector } from "@/components/TenantScopeSelector";
|
||||
import { GlobalAdminBanner, globalAdminSubtitle } from "@/components/GlobalAdminBanner";
|
||||
import { DocsLink } from "@/components/DocsLink";
|
||||
import { DOCS_PATHS } from "@/lib/docsPaths";
|
||||
|
||||
|
||||
interface AuditLogEntry {
|
||||
@@ -272,6 +274,7 @@ export default function AuditPage() {
|
||||
</svg>
|
||||
<span>{refreshing ? 'Refreshing...' : 'Refresh'}</span>
|
||||
</button>
|
||||
<DocsLink path={DOCS_PATHS.auditLog} label="Docs" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,6 +17,8 @@ import { Session, EnrollmentEvent, RuleResult } from "@/types";
|
||||
import { useAdminMode } from "@/hooks/useAdminMode";
|
||||
import { isGuid } from "@/utils/inputValidation";
|
||||
import { safeHttpUrl } from "@/lib/safeDocUrl";
|
||||
import { DocsLink } from "@/components/DocsLink";
|
||||
import { DOCS_PATHS } from "@/lib/docsPaths";
|
||||
|
||||
export default function DiagnosisPage() {
|
||||
// useSearchParams() in DiagnosisContent requires a Suspense boundary for static prerender.
|
||||
@@ -363,6 +365,7 @@ function DiagnosisContent() {
|
||||
>
|
||||
Full Details
|
||||
</button>
|
||||
<DocsLink path={DOCS_PATHS.guidedDiagnosis} label="Docs" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -24,6 +24,8 @@ import { SegmentedControl, TIME_RANGE_OPTIONS } from "@/components/SegmentedCont
|
||||
import { CardSkeleton } from "@/components/skeletons/PageSkeleton";
|
||||
import { TableSkeleton } from "@/components/skeletons/TableSkeleton";
|
||||
import { formatDuration } from "@/lib/formatting";
|
||||
import { DocsLink } from "@/components/DocsLink";
|
||||
import { DOCS_PATHS } from "@/lib/docsPaths";
|
||||
|
||||
interface AppMetric {
|
||||
appName: string;
|
||||
@@ -265,6 +267,7 @@ export default function FleetHealthPage() {
|
||||
value={timeRange}
|
||||
onChange={(v) => setTimeRange(v as typeof timeRange)}
|
||||
/>
|
||||
<DocsLink path={DOCS_PATHS.fleetHealth} label="Docs" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -19,6 +19,7 @@ import { GatherRuleFormFields } from "./components/GatherRuleFormFields";
|
||||
import { GatherRuleCard } from "./components/GatherRuleCard";
|
||||
import { SectionCardHeader } from "@/components/SectionCardHeader";
|
||||
import { DOCS_PATHS } from "@/lib/docsPaths";
|
||||
import { DocsLink } from "@/components/DocsLink";
|
||||
|
||||
export default function GatherRulesPage() {
|
||||
const { user, getAccessToken } = useAuth();
|
||||
@@ -382,14 +383,17 @@ export default function GatherRulesPage() {
|
||||
{/* Header */}
|
||||
<header className="bg-white shadow">
|
||||
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex flex-wrap items-center justify-between gap-y-3">
|
||||
<div>
|
||||
<div>
|
||||
<h1 className="text-2xl font-normal text-gray-900">Gather Rules</h1>
|
||||
<p className="text-sm text-gray-600 mt-1">Manage data collection rules for device enrollment</p>
|
||||
</div>
|
||||
</div>
|
||||
<TenantScopeSelector scope={scope} />
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<TenantScopeSelector scope={scope} />
|
||||
<DocsLink path={DOCS_PATHS.gatherRules} label="Docs" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -14,6 +14,8 @@ import { GlobalAdminBanner, globalAdminSubtitle } from "@/components/GlobalAdmin
|
||||
import { TenantScopeSelector } from "@/components/TenantScopeSelector";
|
||||
import { SegmentedControl, TIME_RANGE_OPTIONS } from "@/components/SegmentedControl";
|
||||
import { CalculatingCard } from "@/components/CalculatingCard";
|
||||
import { DocsLink } from "@/components/DocsLink";
|
||||
import { DOCS_PATHS } from "@/lib/docsPaths";
|
||||
|
||||
// A cross-tenant geo aggregation can take tens of seconds server-side; the default 30s fetch
|
||||
// timeout would abort it client-side while the server keeps computing.
|
||||
@@ -277,6 +279,7 @@ export default function GeographicPerformancePage() {
|
||||
value={groupBy}
|
||||
onChange={(v) => setGroupBy(v as GroupBy)}
|
||||
/>
|
||||
<DocsLink path={DOCS_PATHS.geographicPerformance} label="Docs" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,6 +11,8 @@ import { api } from '@/lib/api';
|
||||
import { authenticatedFetch, TokenExpiredError } from "@/lib/authenticatedFetch";
|
||||
import { isUrlDetail, visibleHealthChecks, visibleHealthDetails } from '@/lib/healthCheckView';
|
||||
import type { DetailedHealthCheckResponse, HealthCheck, McpHealthCheckResponse } from '@/utils/wire-types.generated';
|
||||
import { DocsLink } from "@/components/DocsLink";
|
||||
import { DOCS_PATHS } from "@/lib/docsPaths";
|
||||
|
||||
function formatDetailValue(value: unknown): string {
|
||||
return Array.isArray(value) ? value.join(', ') : typeof value === 'object' ? JSON.stringify(value) : String(value);
|
||||
@@ -231,30 +233,33 @@ export default function HealthCheckPage() {
|
||||
<div className="min-h-screen bg-gray-50 dark:bg-gray-900">
|
||||
{/* Header */}
|
||||
<header className="bg-white shadow dark:bg-gray-800 dark:shadow-gray-700">
|
||||
<div className="py-6 px-4 sm:px-6 lg:px-8 flex items-center justify-between">
|
||||
<div className="py-6 px-4 sm:px-6 lg:px-8 flex flex-wrap items-center justify-between gap-y-3">
|
||||
<h1 className="text-2xl font-normal text-gray-900 dark:text-white">System Health</h1>
|
||||
<button
|
||||
onClick={() => { performHealthCheck(); performMcpCheck(); }}
|
||||
disabled={loading}
|
||||
className="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors text-sm font-medium flex items-center gap-2"
|
||||
>
|
||||
{loading ? (
|
||||
<>
|
||||
<svg className="animate-spin h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
Checking...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
Re-check
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<button
|
||||
onClick={() => { performHealthCheck(); performMcpCheck(); }}
|
||||
disabled={loading}
|
||||
className="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors text-sm font-medium flex items-center gap-2"
|
||||
>
|
||||
{loading ? (
|
||||
<>
|
||||
<svg className="animate-spin h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
Checking...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
Re-check
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
<DocsLink path={DOCS_PATHS.systemHealth} label="Docs" />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ import { EmptyState } from "@/components/rules/EmptyState";
|
||||
import { ImeLogPattern, PatternForm, EMPTY_FORM, ACTION_LABELS } from "./types";
|
||||
import ImePatternCard from "./components/ImePatternCard";
|
||||
import { trackEvent } from "@/lib/appInsights";
|
||||
import { DocsLink } from "@/components/DocsLink";
|
||||
import { DOCS_PATHS } from "@/lib/docsPaths";
|
||||
|
||||
export default function ImeLogPatternsPage() {
|
||||
const { tenantId } = useTenant();
|
||||
@@ -208,11 +210,14 @@ export default function ImeLogPatternsPage() {
|
||||
{/* Header */}
|
||||
<header className="bg-white shadow">
|
||||
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
<div>
|
||||
<h1 className="text-2xl font-normal text-gray-900">IME Log Patterns</h1>
|
||||
<p className="text-sm text-gray-600 mt-1">
|
||||
Regex patterns used by the agent to parse Intune Management Extension logs during enrollment tracking.
|
||||
</p>
|
||||
<div className="flex flex-wrap items-center justify-between gap-y-3">
|
||||
<div>
|
||||
<h1 className="text-2xl font-normal text-gray-900">IME Log Patterns</h1>
|
||||
<p className="text-sm text-gray-600 mt-1">
|
||||
Regex patterns used by the agent to parse Intune Management Extension logs during enrollment tracking.
|
||||
</p>
|
||||
</div>
|
||||
<DocsLink path={DOCS_PATHS.imeLogPatterns} label="Docs" />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -47,6 +47,8 @@ import { generateUiExport, generateCsvExport, generateSessionCsvExport, generate
|
||||
import { trackEvent } from "@/lib/appInsights";
|
||||
import { useAdminMode } from "@/hooks/useAdminMode";
|
||||
import { useGlobalAdminUi } from "@/hooks/useGlobalAdminUi";
|
||||
import { DocsLink } from "@/components/DocsLink";
|
||||
import { DOCS_PATHS } from "@/lib/docsPaths";
|
||||
|
||||
export default function SessionDetailPage() {
|
||||
// useSearchParams() in SessionDetailContent requires a Suspense boundary for static prerender.
|
||||
@@ -573,6 +575,7 @@ function SessionDetailContent() {
|
||||
Inspector
|
||||
</a>
|
||||
)}
|
||||
<DocsLink path={DOCS_PATHS.sessionDetails} label="Docs" />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -59,6 +59,8 @@ interface SlaWeeklyTrend {
|
||||
// enum serialized as int; rendered via statusLabels below), unlike the string status
|
||||
// on SessionSummary.
|
||||
import type { SlaViolatorSession } from "@/utils/wire-types.generated";
|
||||
import { DocsLink } from "@/components/DocsLink";
|
||||
import { DOCS_PATHS } from "@/lib/docsPaths";
|
||||
|
||||
interface TopFailingApp {
|
||||
appName: string;
|
||||
@@ -240,6 +242,7 @@ export default function SlaPage() {
|
||||
</svg>
|
||||
<span>{refreshing ? 'Refreshing...' : 'Refresh'}</span>
|
||||
</button>
|
||||
<DocsLink path={DOCS_PATHS.slaCompliance} label="Docs" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,6 +10,8 @@ import { useGlobalAdminScope } from "@/hooks";
|
||||
import { GlobalAdminBanner, globalAdminSubtitle } from "@/components/GlobalAdminBanner";
|
||||
import { TenantScopeSelector } from "@/components/TenantScopeSelector";
|
||||
import { CardSkeleton } from "@/components/skeletons/PageSkeleton";
|
||||
import { DocsLink } from "@/components/DocsLink";
|
||||
import { DOCS_PATHS } from "@/lib/docsPaths";
|
||||
|
||||
interface SessionMetrics {
|
||||
total: number;
|
||||
@@ -209,6 +211,7 @@ export default function UsageMetricsPage() {
|
||||
</svg>
|
||||
<span>{refreshing ? 'Refreshing...' : 'Refresh'}</span>
|
||||
</button>
|
||||
<DocsLink path={DOCS_PATHS.usageMetrics} label="Docs" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,6 +15,7 @@ import { useAdminMode } from '@/hooks/useAdminMode';
|
||||
import { useEditionInfo } from '@/hooks/useEditionInfo';
|
||||
import GlobalSearch from './GlobalSearch';
|
||||
import { DOCS_URL } from "@/utils/config";
|
||||
import { DOCS_PATHS } from "@/lib/docsPaths";
|
||||
|
||||
export default function Navbar() {
|
||||
const { isAuthenticated, user, hasGlobalScope, logout } = useAuth();
|
||||
@@ -503,7 +504,7 @@ export default function Navbar() {
|
||||
</a>
|
||||
|
||||
<a
|
||||
href={`${DOCS_URL}/changelog/platform-changelog`}
|
||||
href={`${DOCS_URL}${DOCS_PATHS.platformChangelog}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-full flex items-center gap-2.5 px-3 py-2 text-sm text-gray-700 hover:bg-gray-50 transition-colors"
|
||||
@@ -516,7 +517,7 @@ export default function Navbar() {
|
||||
</a>
|
||||
|
||||
<a
|
||||
href={`${DOCS_URL}/troubleshooting/service-announcements`}
|
||||
href={`${DOCS_URL}${DOCS_PATHS.serviceAnnouncements}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-full flex items-center gap-2.5 px-3 py-2 text-sm text-gray-700 hover:bg-gray-50 transition-colors"
|
||||
@@ -718,11 +719,11 @@ export default function Navbar() {
|
||||
<svg className="w-4 h-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}><path strokeLinecap="round" strokeLinejoin="round" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" /></svg>
|
||||
<span>Documentation</span>
|
||||
</a>
|
||||
<a href={`${DOCS_URL}/changelog/platform-changelog`} target="_blank" rel="noopener noreferrer" className="w-full flex items-center gap-2.5 px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors" onClick={() => { setShowOverflow(false); setOverflowSubmenu(null); }}>
|
||||
<a href={`${DOCS_URL}${DOCS_PATHS.platformChangelog}`} target="_blank" rel="noopener noreferrer" className="w-full flex items-center gap-2.5 px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors" onClick={() => { setShowOverflow(false); setOverflowSubmenu(null); }}>
|
||||
<svg className="w-4 h-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}><path strokeLinecap="round" strokeLinejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" /></svg>
|
||||
<span>Changelog</span>
|
||||
</a>
|
||||
<a href={`${DOCS_URL}/troubleshooting/service-announcements`} target="_blank" rel="noopener noreferrer" className="w-full flex items-center gap-2.5 px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors" onClick={() => { setShowOverflow(false); setOverflowSubmenu(null); }}>
|
||||
<a href={`${DOCS_URL}${DOCS_PATHS.serviceAnnouncements}`} target="_blank" rel="noopener noreferrer" className="w-full flex items-center gap-2.5 px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors" onClick={() => { setShowOverflow(false); setOverflowSubmenu(null); }}>
|
||||
<svg className="w-4 h-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}><path strokeLinecap="round" strokeLinejoin="round" d="M12 9v2m0 4h.01M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z" /></svg>
|
||||
<span>Service Announcements</span>
|
||||
</a>
|
||||
|
||||
@@ -30,6 +30,21 @@ export const DOCS_PATHS = {
|
||||
// Rules
|
||||
analyzeRules: "/rules/analyze-rules",
|
||||
gatherRules: "/rules/gather-rules",
|
||||
imeLogPatterns: "/rules/ime-log-patterns",
|
||||
// Portal pages (page-header "Docs" link)
|
||||
sessionDetails: "/portal-guide/session-details-and-diagnosis",
|
||||
guidedDiagnosis: "/portal-guide/session-details-and-diagnosis#guided-diagnosis",
|
||||
annotations: "/portal-guide/session-details-and-diagnosis#annotations",
|
||||
fleetHealth: "/portal-guide/fleet-health",
|
||||
geographicPerformance: "/portal-guide/geographic-performance",
|
||||
slaCompliance: "/portal-guide/sla-compliance",
|
||||
softwareInventory: "/portal-guide/software-inventory-and-vulnerabilities",
|
||||
usageMetrics: "/portal-guide/usage-metrics",
|
||||
auditLog: "/portal-guide/audit-log-and-system-health#audit-log",
|
||||
systemHealth: "/portal-guide/audit-log-and-system-health#system-health",
|
||||
// Navbar help menu
|
||||
platformChangelog: "/changelog/platform-changelog",
|
||||
serviceAnnouncements: "/troubleshooting-and-support/service-announcements",
|
||||
// Dual app-registration window (sign-in banners, failed-sign-in screen)
|
||||
appRegistrationMigration: "/troubleshooting-and-support/app-registration-migration",
|
||||
appRegistrationMigrationAfter: "/troubleshooting-and-support/app-registration-migration#after-the-migration",
|
||||
|
||||
Reference in New Issue
Block a user