diff --git a/src/Backend/AutopilotMonitor.Functions.Tests/AuthFunctionSideEffectTests.cs b/src/Backend/AutopilotMonitor.Functions.Tests/AuthFunctionSideEffectTests.cs index 10dc7440e..9f4fed41d 100644 --- a/src/Backend/AutopilotMonitor.Functions.Tests/AuthFunctionSideEffectTests.cs +++ b/src/Backend/AutopilotMonitor.Functions.Tests/AuthFunctionSideEffectTests.cs @@ -131,7 +131,7 @@ public async Task HandleNewTenantDomain_WhenDomainEmpty_ExtractsAndSaves() _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 8facecabe..56d818965 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/AuthFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Infrastructure/AuthFunction.cs @@ -326,7 +326,8 @@ internal async Task HandleNewTenantDomainAsync( _ = _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 b7f179e37..d10acd106 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitDiagFilesReportFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitDiagFilesReportFunction.cs @@ -137,7 +137,8 @@ await _maintenanceRepo.LogAuditEntryAsync( _ = _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 f6ff58731..6299251a4 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitSessionReportFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/Reports/SubmitSessionReportFunction.cs @@ -140,7 +140,8 @@ await _maintenanceRepo.LogAuditEntryAsync( _ = _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 c8d81ddb2..df6f8dbb3 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 d13b94fc3..008a03962 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 d9173ca9d..3207c10ae 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 dec349773..52f715bce 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 ec9f9b20b..db597bb17 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 3d1ec95eb..29eb8bb90 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 db0b3cd3c..d17ed0e03 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 81237807f..379b66214 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 9b0d31684..31fe8b14f 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 714a73501..ef2a4a695 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 5fc4a2669..9a270bb8d 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 88cf1198b..9a587f85c 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" />
    -