diff --git a/src/Backend/AutopilotMonitor.Functions.Tests/AuthFunctionSideEffectTests.cs b/src/Backend/AutopilotMonitor.Functions.Tests/AuthFunctionSideEffectTests.cs index 10dc7440..9f4fed41 100644 --- a/src/Backend/AutopilotMonitor.Functions.Tests/AuthFunctionSideEffectTests.cs +++ b/src/Backend/AutopilotMonitor.Functions.Tests/AuthFunctionSideEffectTests.cs @@ -131,7 +131,7 @@ public class AuthFunctionSideEffectTests _globalNotificationMock.Verify(x => x.CreateNotificationAsync( "preview_signup", "New Preview Signup", It.Is(m => m.Contains(TenantId) && m.Contains("contoso.com") && m.Contains(Upn)), - null), Times.Once); + $"/admin/tenants/management?tenantId={TenantId}"), Times.Once); } [Fact] diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/AuthFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/AuthFunction.cs index 8facecab..56d81896 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/AuthFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/AuthFunction.cs @@ -326,7 +326,8 @@ public class AuthFunction _ = _globalNotificationService.CreateNotificationAsync( "preview_signup", "New Preview Signup", - $"Tenant {tenantId} ({domain}), UPN: {upn}"); + $"Tenant {tenantId} ({domain}), UPN: {upn}", + href: $"/admin/tenants/management?tenantId={Uri.EscapeDataString(tenantId)}"); } /// diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitDiagFilesReportFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitDiagFilesReportFunction.cs index b7f179e3..d10acd10 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitDiagFilesReportFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitDiagFilesReportFunction.cs @@ -137,7 +137,8 @@ namespace AutopilotMonitor.Functions.Functions.Reports _ = _globalNotificationService.CreateNotificationAsync( "diag_files_report", "New Diag Files Report", - $"{userIdentifier} (Tenant: {request.TenantId})"); + $"{userIdentifier} (Tenant: {request.TenantId})", + href: $"/admin/reports/session-reports?reportId={Uri.EscapeDataString(metadata.ReportId)}"); _logger.LogInformation("Diag-files report submitted: ReportId={ReportId}, By={User}", metadata.ReportId, userIdentifier); diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitSessionReportFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitSessionReportFunction.cs index f6ff5873..6299251a 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitSessionReportFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitSessionReportFunction.cs @@ -140,7 +140,8 @@ namespace AutopilotMonitor.Functions.Functions.Reports _ = _globalNotificationService.CreateNotificationAsync( "session_report", "New Session Report", - $"{userIdentifier} — Session {sessionId} (Tenant: {request.TenantId})"); + $"{userIdentifier} — Session {sessionId} (Tenant: {request.TenantId})", + href: $"/admin/reports/session-reports?reportId={Uri.EscapeDataString(metadata.ReportId)}"); _logger.LogInformation("Session report submitted: ReportId={ReportId}, Session={SessionId}, By={User}", metadata.ReportId, sessionId, userIdentifier); diff --git a/src/Web/autopilot-monitor-web/app/about/layout.tsx b/src/Web/autopilot-monitor-web/app/about/layout.tsx index c8d81ddb..df6f8dbb 100644 --- a/src/Web/autopilot-monitor-web/app/about/layout.tsx +++ b/src/Web/autopilot-monitor-web/app/about/layout.tsx @@ -26,13 +26,13 @@ export const metadata: Metadata = { "Autopilot Monitor overview", ], openGraph: { - title: "About AutopilotMonitor – Real-Time Windows Autopilot Monitoring", + title: "About Autopilot Monitor – Real-Time Windows Autopilot Monitoring", description: "Free, open-source real-time monitoring and troubleshooting for Windows Autopilot enrollments. Track every phase, run analyze rules, and resolve issues faster — built by Oliver Kieselbach.", url: `${SITE_URL}/about`, }, twitter: { - title: "About AutopilotMonitor – Real-Time Windows Autopilot Monitoring", + title: "About Autopilot Monitor – Real-Time Windows Autopilot Monitoring", description: "Free, open-source real-time monitoring and troubleshooting for Windows Autopilot enrollments. Track every phase, run analyze rules, and resolve issues faster.", }, diff --git a/src/Web/autopilot-monitor-web/app/about/page.tsx b/src/Web/autopilot-monitor-web/app/about/page.tsx index d13b94fc..008a0396 100644 --- a/src/Web/autopilot-monitor-web/app/about/page.tsx +++ b/src/Web/autopilot-monitor-web/app/about/page.tsx @@ -1,5 +1,6 @@ import Link from "next/link"; -import { PublicPageHeader } from "../../components/PublicPageHeader"; +import { LandingNavbar } from "../../components/landing/LandingNavbar"; +import { SiteFooter } from "../../components/SiteFooter"; import { DOCS_URL } from "@/utils/config"; const FEATURES = [ @@ -47,25 +48,40 @@ const FEATURES = [ }, ]; +// Landing v2: one accent, no rainbow — every feature card uses the +// green brand accent regardless of its legacy color key. +const ACCENT_STYLE = { + bg: "bg-[var(--lp-accent-soft)]", + text: "text-[var(--lp-ink)]", + dot: "bg-[var(--lp-accent)]", +}; const colorMap: Record = { - blue: { bg: "bg-blue-100", text: "text-blue-600", dot: "bg-blue-400" }, - indigo: { bg: "bg-indigo-100", text: "text-indigo-600", dot: "bg-indigo-400" }, - purple: { bg: "bg-purple-100", text: "text-purple-600", dot: "bg-purple-400" }, - green: { bg: "bg-green-100", text: "text-green-600", dot: "bg-green-400" }, - orange: { bg: "bg-orange-100", text: "text-orange-600", dot: "bg-orange-400" }, - red: { bg: "bg-red-100", text: "text-red-600", dot: "bg-red-400" }, + blue: ACCENT_STYLE, + indigo: ACCENT_STYLE, + purple: ACCENT_STYLE, + green: ACCENT_STYLE, + orange: ACCENT_STYLE, + red: ACCENT_STYLE, }; export default function AboutPage() { return ( -
- +
+ +
+
+

About

+

+ About Autopilot Monitor +

+
+
-
+
{/* What is Autopilot Monitor */} -
-

What is Autopilot Monitor?

+
+

What is Autopilot Monitor?

Autopilot Monitor is a free, open-source, real-time monitoring and troubleshooting platform for Windows Autopilot enrollments managed through{" "} @@ -100,7 +116,7 @@ export default function AboutPage() { {FEATURES.map((f) => { const c = colorMap[f.color]; return ( -

+

{f.title}

{f.description}

    @@ -118,8 +134,8 @@ export default function AboutPage() {
{/* Who It's For */} -
-

Who Is It For?

+
+

Who Is It For?

Autopilot Monitor is built for anyone responsible for deploying or supporting Windows devices through Microsoft Intune and Autopilot. @@ -142,17 +158,17 @@ export default function AboutPage() { "Autopilot Monitor is a multi-tenant service with strict per-tenant data isolation — telemetry, configuration, and diagnostics are partitioned and access-scoped to each tenant. MSPs can be granted delegated read access across several customer tenants from a single login.", }, ].map((item) => ( -

-

{item.title}

-

{item.description}

+
+

{item.title}

+

{item.description}

))}
{/* How It Works */} -
-

How It Works

+
+

How It Works

Autopilot Monitor uses a lightweight .NET agent deployed to devices via an Intune bootstrapper script. The agent monitors the enrollment process in real time and streams telemetry events @@ -169,7 +185,7 @@ export default function AboutPage() { { step: "5", text: "On completion, the agent uploads a diagnostics bundle if configured, then removes itself." }, ].map((item) => (

  • - + {item.step} {item.text} @@ -179,8 +195,8 @@ export default function AboutPage() {
  • {/* Tech Stack & Platform */} -
    -

    Technology & Platform

    +
    +

    Technology & Platform

    Autopilot Monitor is built on modern, enterprise-grade technology designed to scale with large device fleets and multi-tenant deployments. @@ -190,7 +206,7 @@ export default function AboutPage() { { title: "Backend", items: [ - "Azure Functions (.NET 10 Isolated, Flex Consumption) — serverless, scalable API", + "Azure Functions (.NET Isolated, Flex Consumption) — serverless, scalable API", "Azure Table Storage — high-throughput event ingestion", "Azure Blob Storage — diagnostics and log bundle storage", "Azure SignalR Service — real-time push to the portal", @@ -199,7 +215,7 @@ export default function AboutPage() { { title: "Portal (Web Frontend)", items: [ - "Next.js 15 (React 18) + TypeScript — fast, server-rendered React app", + "Next.js (React) + TypeScript — fast, statically delivered web app", "Microsoft Entra ID (MSAL) — secure authentication", "Role-based access control (Admin / Operator / Viewer)", "Multi-tenant architecture with delegated MSP access", @@ -241,8 +257,8 @@ export default function AboutPage() {

    {/* Open Source */} -
    -

    Open Source & Free to Use

    +
    +

    Open Source & Free to Use

    Autopilot Monitor is fully open source and free to use. The complete source code is available on GitHub under an open license. Contributions, bug reports, and feature requests from the @@ -257,16 +273,16 @@ export default function AboutPage() {

    The hosted service is operated by glueckkanja AG — see the{" "} - Imprint for company - details and the Terms of Use{" "} + Imprint for company + details and the Terms of Use{" "} for what each plan does and does not commit to.

    @@ -274,10 +290,10 @@ export default function AboutPage() { View on GitHub Submit Feedback @@ -285,7 +301,7 @@ export default function AboutPage() { href="https://www.linkedin.com/in/oliver-kieselbach/" target="_blank" rel="noopener noreferrer" - className="inline-flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-4 py-2.5 text-sm font-medium text-gray-700 hover:border-gray-300 hover:bg-gray-100 transition-colors" + className="inline-flex items-center gap-2 rounded-lg border border-[var(--lp-line-soft)] bg-gray-50 px-4 py-2.5 text-sm font-medium text-gray-700 hover:border-gray-300 hover:bg-gray-100 transition-colors" > Oliver Kieselbach on LinkedIn @@ -293,22 +309,23 @@ export default function AboutPage() {
    {/* Quick Links */} -
    -

    Explore Further

    +
    +

    Explore Further

    +
    ); } diff --git a/src/Web/autopilot-monitor-web/app/admin/backups/components/RestoreRowDiffModal.tsx b/src/Web/autopilot-monitor-web/app/admin/backups/components/RestoreRowDiffModal.tsx index d9173ca9..3207c10a 100644 --- a/src/Web/autopilot-monitor-web/app/admin/backups/components/RestoreRowDiffModal.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/backups/components/RestoreRowDiffModal.tsx @@ -159,7 +159,7 @@ export function RestoreRowDiffModal({ type="button" onClick={commit} disabled={committing} - className="px-3 py-1.5 bg-blue-600 hover:bg-blue-700 disabled:opacity-50 text-white text-sm rounded-md transition-colors" + className="px-3 py-1.5 bg-green-600 hover:bg-green-700 disabled:opacity-50 text-white text-sm rounded-md transition-colors" > {committing ? "Restoring…" : "Restore row"} diff --git a/src/Web/autopilot-monitor-web/app/admin/backups/detail/page.tsx b/src/Web/autopilot-monitor-web/app/admin/backups/detail/page.tsx index dec34977..52f715bc 100644 --- a/src/Web/autopilot-monitor-web/app/admin/backups/detail/page.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/backups/detail/page.tsx @@ -276,7 +276,7 @@ function RestoreInputRow({ // — only null is rejected. Match that here so an Azure Table row with // a literal empty key (legal per spec) can be previewed/restored. disabled={disabled || !tableName} - className="px-3 py-1.5 bg-blue-600 hover:bg-blue-700 disabled:opacity-50 text-white text-sm rounded-md transition-colors" + className="px-3 py-1.5 bg-green-600 hover:bg-green-700 disabled:opacity-50 text-white text-sm rounded-md transition-colors" > Preview restore diff --git a/src/Web/autopilot-monitor-web/app/admin/backups/page.tsx b/src/Web/autopilot-monitor-web/app/admin/backups/page.tsx index ec9f9b20..db597bb1 100644 --- a/src/Web/autopilot-monitor-web/app/admin/backups/page.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/backups/page.tsx @@ -134,7 +134,7 @@ export default function BackupsListPage() { type="button" onClick={triggerBackup} disabled={triggering || activeJob !== null} - className="px-3 py-1.5 bg-blue-600 hover:bg-blue-700 disabled:opacity-50 text-white text-sm rounded-md transition-colors" + className="px-3 py-1.5 bg-green-600 hover:bg-green-700 disabled:opacity-50 text-white text-sm rounded-md transition-colors" > {triggering ? "Triggering…" : "Run backup now"} diff --git a/src/Web/autopilot-monitor-web/app/admin/components/AdminConfigSettingsSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/AdminConfigSettingsSection.tsx index 3d1ec95e..29eb8bb9 100644 --- a/src/Web/autopilot-monitor-web/app/admin/components/AdminConfigSettingsSection.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/components/AdminConfigSettingsSection.tsx @@ -104,7 +104,7 @@ export function AdminConfigSettingsSection({ max="1000" value={globalRateLimit} onChange={(e) => setGlobalRateLimit(parseInt(e.target.value) || 100)} - className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors" + className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-green-500 transition-colors" />
    @@ -121,7 +121,7 @@ export function AdminConfigSettingsSection({ max="10000" value={userRateLimit} onChange={(e) => setUserRateLimit(parseInt(e.target.value) || 120)} - className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors" + className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-green-500 transition-colors" /> @@ -138,7 +138,7 @@ export function AdminConfigSettingsSection({ max="10000" value={globalAdminRateLimit} onChange={(e) => setGlobalAdminRateLimit(parseInt(e.target.value) || 600)} - className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors" + className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-green-500 transition-colors" /> @@ -158,7 +158,7 @@ export function AdminConfigSettingsSection({ value={platformStatsBlobSasUrl} onChange={(e) => setPlatformStatsBlobSasUrl(e.target.value)} placeholder="https://storageaccount.blob.core.windows.net/publicstats?sv=...&sig=..." - className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors font-mono text-sm" + className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-green-500 transition-colors font-mono text-sm" /> @@ -177,7 +177,7 @@ export function AdminConfigSettingsSection({ value={agentMigrateApiBaseUrl} onChange={(e) => setAgentMigrateApiBaseUrl(e.target.value)} placeholder="https://autopilotmonitor-api-us.azurewebsites.net" - className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors font-mono text-sm" + className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-green-500 transition-colors font-mono text-sm" /> @@ -195,7 +195,7 @@ export function AdminConfigSettingsSection({ onChange={(e) => setAgentMigrateTenantOverridesJson(e.target.value)} placeholder='{"11111111-2222-3333-4444-555555555555": "https://autopilotmonitor-api-us.azurewebsites.net", "66666666-7777-8888-9999-000000000000": ""}' rows={3} - className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors font-mono text-sm" + className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-green-500 transition-colors font-mono text-sm" /> @@ -214,7 +214,7 @@ export function AdminConfigSettingsSection({ max="120" value={collectorIdleTimeoutMinutes} onChange={(e) => setCollectorIdleTimeoutMinutes(parseInt(e.target.value) || 0)} - className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors" + className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-green-500 transition-colors" /> @@ -233,7 +233,7 @@ export function AdminConfigSettingsSection({ max="60" value={desktopDetectorNoCandidateTimeoutMinutes} onChange={(e) => setDesktopDetectorNoCandidateTimeoutMinutes(parseInt(e.target.value) || 0)} - className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors" + className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-green-500 transition-colors" /> @@ -253,7 +253,7 @@ export function AdminConfigSettingsSection({ max="168" value={slaNotificationCooldownHours} onChange={(e) => setSlaNotificationCooldownHours(parseInt(e.target.value) || 24)} - className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors" + className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-green-500 transition-colors" /> @@ -264,7 +264,7 @@ export function AdminConfigSettingsSection({ type="checkbox" checked={allowAgentDowngrade} onChange={(e) => setAllowAgentDowngrade(e.target.checked)} - className="mt-1 h-5 w-5 rounded border-indigo-300 dark:border-indigo-600 text-indigo-600 focus:ring-indigo-500" + className="mt-1 h-5 w-5 rounded border-indigo-300 dark:border-indigo-600 text-green-600 focus:ring-green-500" /> Allow agent downgrade @@ -289,7 +289,7 @@ export function AdminConfigSettingsSection({ value={modernDeploymentHarmlessEventIds} onChange={(e) => setModernDeploymentHarmlessEventIds(e.target.value)} placeholder="100, 1005, 1010" - className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-colors font-mono text-sm" + className="mt-1 block w-full px-4 py-2 border border-indigo-300 dark:border-indigo-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-green-500 transition-colors font-mono text-sm" /> @@ -300,7 +300,7 @@ export function AdminConfigSettingsSection({ type="checkbox" checked={enableIndexDualWrite} onChange={(e) => setEnableIndexDualWrite(e.target.checked)} - className="mt-1 h-5 w-5 rounded border-indigo-300 dark:border-indigo-600 text-indigo-600 focus:ring-indigo-500" + className="mt-1 h-5 w-5 rounded border-indigo-300 dark:border-indigo-600 text-green-600 focus:ring-green-500" /> V2 Decision Engine: Enable index-table dual-write @@ -328,7 +328,7 @@ export function AdminConfigSettingsSection({ type="checkbox" checked={sessionDeletionKillSwitch} onChange={(e) => setSessionDeletionKillSwitch(e.target.checked)} - className="mt-1 h-5 w-5 rounded border-red-300 dark:border-red-600 text-red-600 focus:ring-red-500" + className="mt-1 h-5 w-5 rounded border-red-300 dark:border-red-600 text-red-600 accent-red-600 focus:ring-red-500" /> Cascade-Delete Kill-Switch (emergency) diff --git a/src/Web/autopilot-monitor-web/app/admin/components/DeviceBlockSection.tsx b/src/Web/autopilot-monitor-web/app/admin/components/DeviceBlockSection.tsx index db0b3cd3..d17ed0e0 100644 --- a/src/Web/autopilot-monitor-web/app/admin/components/DeviceBlockSection.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/components/DeviceBlockSection.tsx @@ -542,7 +542,7 @@ function DeviceBlockSectionInner({ diff --git a/src/Web/autopilot-monitor-web/app/admin/customs-archive/page.tsx b/src/Web/autopilot-monitor-web/app/admin/customs-archive/page.tsx index 81237807..379b6621 100644 --- a/src/Web/autopilot-monitor-web/app/admin/customs-archive/page.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/customs-archive/page.tsx @@ -102,7 +102,7 @@ export default function CustomsArchivePage() { type="button" onClick={load} disabled={loading} - className="px-3 py-1.5 bg-blue-600 hover:bg-blue-700 disabled:opacity-50 text-white text-sm rounded-md transition-colors" + className="px-3 py-1.5 bg-green-600 hover:bg-green-700 disabled:opacity-50 text-white text-sm rounded-md transition-colors" > {loading ? "Loading…" : "Refresh"} diff --git a/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionMcpUsage.tsx b/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionMcpUsage.tsx index 9b0d3168..31fe8b14 100644 --- a/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionMcpUsage.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/metrics/sections/SectionMcpUsage.tsx @@ -1,5 +1,6 @@ "use client"; +import { SegmentedControl, TIME_RANGE_OPTIONS } from "@/components/SegmentedControl"; import { useCallback, useEffect, useState } from "react"; import { useAuth } from "../../../../contexts/AuthContext"; import { authenticatedFetch, TokenExpiredError } from "@/lib/authenticatedFetch"; @@ -134,21 +135,11 @@ export function SectionMcpUsage() {

    API usage across all MCP-enabled users

    -
    - {(["7d", "30d", "90d"] as DateRange[]).map((range) => ( - - ))} -
    + setDateRange(v as DateRange)} + /> diff --git a/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/components/RestoreBrowserTab.tsx b/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/components/RestoreBrowserTab.tsx index 714a7350..ef2a4a69 100644 --- a/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/components/RestoreBrowserTab.tsx +++ b/src/Web/autopilot-monitor-web/app/admin/ops/session-cleanup/components/RestoreBrowserTab.tsx @@ -276,7 +276,7 @@ export function RestoreBrowserTab({ getAccessToken, setError, setSuccessMessage setSelectedTenantId(""); } }} - className="h-4 w-4 rounded border-gray-300 dark:border-gray-600 text-purple-600 focus:ring-purple-500" + className="h-4 w-4 rounded border-gray-300 dark:border-gray-600 text-purple-600 accent-purple-600 focus:ring-purple-500" />
    {/* Daily Limit */} @@ -214,7 +214,7 @@ export function SectionUsagePlans() { min={0} value={tier.dailyRequestLimit} onChange={(e) => updateTier(index, "dailyRequestLimit", parseInt(e.target.value) || 0)} - className="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500" + className="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-green-500" /> {/* Monthly Limit */} @@ -225,7 +225,7 @@ export function SectionUsagePlans() { min={0} value={tier.monthlyRequestLimit} onChange={(e) => updateTier(index, "monthlyRequestLimit", parseInt(e.target.value) || 0)} - className="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500" + className="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-green-500" /> {/* Description */} @@ -236,7 +236,7 @@ export function SectionUsagePlans() { value={tier.description} onChange={(e) => updateTier(index, "description", e.target.value)} placeholder="Brief description" - className="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500" + className="w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-green-500" /> diff --git a/src/Web/autopilot-monitor-web/app/analyze-rules/components/AnalyzeRuleCard.tsx b/src/Web/autopilot-monitor-web/app/analyze-rules/components/AnalyzeRuleCard.tsx index 5fc4a266..9a270bb8 100644 --- a/src/Web/autopilot-monitor-web/app/analyze-rules/components/AnalyzeRuleCard.tsx +++ b/src/Web/autopilot-monitor-web/app/analyze-rules/components/AnalyzeRuleCard.tsx @@ -578,7 +578,7 @@ export default function AnalyzeRuleCard({ Export {canEdit && ( - @@ -655,7 +655,7 @@ export default function AnalyzeRuleCard({ } else { onSaveEdit(rule); } - }} disabled={saving} className="px-6 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center space-x-2 text-sm font-medium"> + }} disabled={saving} className="px-6 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center space-x-2 text-sm font-medium"> {saving ? (<>
    Saving...) : (Save Changes)} diff --git a/src/Web/autopilot-monitor-web/app/analyze-rules/components/AnalyzeRuleFormFields.tsx b/src/Web/autopilot-monitor-web/app/analyze-rules/components/AnalyzeRuleFormFields.tsx index 88cf1198..9a587f85 100644 --- a/src/Web/autopilot-monitor-web/app/analyze-rules/components/AnalyzeRuleFormFields.tsx +++ b/src/Web/autopilot-monitor-web/app/analyze-rules/components/AnalyzeRuleFormFields.tsx @@ -25,7 +25,7 @@ export default function AnalyzeRuleFormFields({ form, setForm, showRuleId, exist {showRuleId && (
    - setForm({ ...form, ruleId: e.target.value })} placeholder="e.g., ANALYZE-CUSTOM-001" autoComplete="off" className={`w-full px-4 py-2 border rounded-lg text-sm text-gray-900 placeholder-gray-500 focus:outline-none focus:ring-2 ${isDuplicate ? "border-red-400 focus:ring-red-300 focus:border-red-400" : "border-gray-300 focus:ring-indigo-500 focus:border-indigo-500"}`} /> + setForm({ ...form, ruleId: e.target.value })} placeholder="e.g., ANALYZE-CUSTOM-001" autoComplete="off" className={`w-full px-4 py-2 border rounded-lg text-sm text-gray-900 placeholder-gray-500 focus:outline-none focus:ring-2 ${isDuplicate ? "border-red-400 focus:ring-red-300 focus:border-red-400" : "border-gray-300 focus:ring-green-500 focus:border-green-500"}`} /> {isDuplicate && (

    A rule with this ID already exists. Please choose a unique Rule ID.

    )} @@ -33,31 +33,31 @@ export default function AnalyzeRuleFormFields({ form, setForm, showRuleId, exist )}
    - setForm({ ...form, title: e.target.value })} placeholder="e.g., Proxy Authentication Failure" autoComplete="off" className="w-full px-4 py-2 border border-gray-300 rounded-lg text-sm text-gray-900 placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" /> + setForm({ ...form, title: e.target.value })} placeholder="e.g., Proxy Authentication Failure" autoComplete="off" className="w-full px-4 py-2 border border-gray-300 rounded-lg text-sm text-gray-900 placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-green-500" />
    -