fix timestamp handling

fix design for config pages
This commit is contained in:
Oliver Kieselbach
2026-02-17 16:45:42 +01:00
parent 6f06dfc30a
commit a22cfa571d
6 changed files with 40 additions and 51 deletions
@@ -612,7 +612,10 @@ namespace AutopilotMonitor.Functions.Services
EventId = entity.GetString("EventId") ?? string.Empty,
SessionId = entity.GetString("SessionId") ?? string.Empty,
TenantId = entity.PartitionKey,
Timestamp = entity.GetDateTime("Timestamp") ?? DateTime.UtcNow,
Timestamp = DateTime.SpecifyKind(
entity.GetDateTimeOffset("Timestamp")?.UtcDateTime
?? entity.GetDateTime("Timestamp")
?? DateTime.UtcNow, DateTimeKind.Utc),
EventType = entity.GetString("EventType") ?? string.Empty,
Severity = (EventSeverity)(entity.GetInt32("Severity") ?? 0),
Source = entity.GetString("Source") ?? string.Empty,
@@ -628,25 +628,22 @@ export default function AdminConfigurationPage() {
return (
<ProtectedRoute>
<div className="min-h-screen bg-gradient-to-br from-purple-50 to-violet-100">
<div className="min-h-screen bg-gray-50">
{/* Header */}
<header className="bg-white shadow-sm border-b border-gray-200">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
<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 items-center space-x-4">
<div>
<button
onClick={() => router.push("/")}
className="flex items-center space-x-2 text-gray-600 hover:text-gray-900 transition-colors"
className="text-sm text-gray-600 hover:text-gray-900 mb-2 flex items-center"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
<span>Back to Dashboard</span>
&larr; Back to Dashboard
</button>
</div>
<div>
<h1 className="text-2xl font-bold text-purple-900">Admin Configuration</h1>
<p className="text-sm text-purple-600">Galactic Admin Operations</p>
<div>
<h1 className="text-3xl font-bold text-gray-900">Admin Configuration</h1>
<p className="text-sm text-gray-600 mt-1">Galactic Admin Operations</p>
</div>
</div>
</div>
</div>
@@ -653,20 +653,19 @@ export default function AnalyzeRulesPage() {
return (
<ProtectedRoute>
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
<div className="min-h-screen bg-gray-50">
{/* Header */}
<header className="bg-white shadow-sm border-b border-gray-200">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
<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 items-center space-x-4">
<button onClick={() => router.push("/")} className="flex items-center space-x-2 text-gray-600 hover:text-gray-900 transition-colors">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" /></svg>
<span>Back to Dashboard</span>
</button>
</div>
<div>
<h1 className="text-2xl font-bold text-gray-900">Analyze Rules</h1>
<p className="text-sm text-gray-500">Manage event analysis rules for issue detection</p>
<button onClick={() => router.push("/")} className="text-sm text-gray-600 hover:text-gray-900 mb-2 flex items-center">
&larr; Back to Dashboard
</button>
<div>
<h1 className="text-3xl font-bold 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>
</div>
</div>
@@ -649,25 +649,22 @@ export default function GatherRulesPage() {
return (
<ProtectedRoute>
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
<div className="min-h-screen bg-gray-50">
{/* Header */}
<header className="bg-white shadow-sm border-b border-gray-200">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
<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 items-center space-x-4">
<div>
<button
onClick={() => router.push("/")}
className="flex items-center space-x-2 text-gray-600 hover:text-gray-900 transition-colors"
className="text-sm text-gray-600 hover:text-gray-900 mb-2 flex items-center"
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
<span>Back to Dashboard</span>
&larr; Back to Dashboard
</button>
</div>
<div>
<h1 className="text-2xl font-bold text-gray-900">Gather Rules</h1>
<p className="text-sm text-gray-500">Manage data collection rules for device enrollment</p>
<div>
<h1 className="text-3xl font-bold 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>
</div>
</div>
@@ -369,7 +369,7 @@ export default function ProgressPortalPage() {
return (
<ProtectedRoute>
<div className="min-h-screen bg-gradient-to-b from-blue-50 to-white">
<div className="min-h-screen bg-gray-50">
<div className="max-w-2xl mx-auto px-4 py-6 sm:py-12">
{/* Collapsible Header + Search */}
{headerCollapsed && session ? (
@@ -1580,18 +1580,11 @@ function DeviceDetailsCard({ events }: { events: EnrollmentEvent[] }) {
const agentStarted = getEventData("agent_started");
const bootTime = getEventData("boot_time");
// Calculate boot time from first event timestamp minus uptimeMinutes.
// The device-reported bootTimeUtc can be inconsistent with event timestamps due to
// timezone handling on the device side. Using firstEvent - uptime gives a result
// that is always consistent with the event timeline shown in the UI.
const estimatedBootTime = (() => {
const uptimeMinutes = bootTime?.uptimeMinutes ?? agentStarted?.uptimeMinutes;
if (!uptimeMinutes) return null;
const timestamps = events.map(e => new Date(e.timestamp).getTime()).filter(t => !isNaN(t));
if (timestamps.length === 0) return null;
const firstEventMs = Math.min(...timestamps);
return new Date(firstEventMs - uptimeMinutes * 60 * 1000);
})();
// Boot time from bootTimeUtc (device-reported UTC with Z suffix, parsed correctly as UTC by browser).
// Now that event timestamps are also serialized with Z suffix (Kind=Utc), both are consistent.
const estimatedBootTime = (bootTime?.bootTimeUtc || bootTime?.bootTime)
? new Date(bootTime?.bootTimeUtc ?? bootTime?.bootTime)
: null;
const osInfo = getEventData("os_info");
const networkAdapters = getEventData("network_adapters");
const dnsConfig = getEventData("dns_configuration");