feat(07.1-05): user-tz on admin operational pages
- zabbix-wan, rmm-overshell, itglue-writes, ticket-digest, device-link-conflicts, workflow/history, workflow/pipelines/[id]: each gets useUserTimezone() at the component entry; threads tz into every inline toLocaleString call. Migrates 11 of 81 audit leak callsites.
This commit is contained in:
parent
8c56cafe0b
commit
23b179f2a7
7 changed files with 24 additions and 10 deletions
|
|
@ -16,6 +16,7 @@ import {
|
|||
} from '@/components/ui/select';
|
||||
import { CheckCircle2, AlertTriangle, Loader2 } from 'lucide-react';
|
||||
import { PageHeader } from '@/components/navigation/page-header';
|
||||
import { useUserTimezone } from '@/lib/hooks/use-user-timezone';
|
||||
|
||||
interface Candidate {
|
||||
ciId: string;
|
||||
|
|
@ -77,6 +78,7 @@ function dedupeCandidates(candidates: Candidate[]): Candidate[] {
|
|||
}
|
||||
|
||||
export default function DeviceLinkConflictsPage() {
|
||||
const tz = useUserTimezone();
|
||||
const [items, setItems] = useState<Review[] | null>(null);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
|
@ -220,7 +222,7 @@ export default function DeviceLinkConflictsPage() {
|
|||
{r.xref.serial && <span>serial: {r.xref.serial}</span>}
|
||||
{r.xref.mac && <span>mac: {r.xref.mac}</span>}
|
||||
{r.xref.lastSeenAt && (
|
||||
<span>last seen: {new Date(r.xref.lastSeenAt).toLocaleString()}</span>
|
||||
<span>last seen: {new Date(r.xref.lastSeenAt).toLocaleString(undefined, { timeZone: tz })}</span>
|
||||
)}
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { Button } from '@/components/ui/button';
|
|||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
|
||||
import { PageHeader } from '@/components/navigation/page-header';
|
||||
import { useUserTimezone } from '@/lib/hooks/use-user-timezone';
|
||||
|
||||
interface WriteRow {
|
||||
id: string;
|
||||
|
|
@ -47,6 +48,7 @@ function statusVariant(
|
|||
}
|
||||
|
||||
export default function ItglueWritesPage() {
|
||||
const tz = useUserTimezone();
|
||||
const [rows, setRows] = useState<WriteRow[] | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [statusFilter, setStatusFilter] =
|
||||
|
|
@ -141,7 +143,7 @@ export default function ItglueWritesPage() {
|
|||
<span className="font-medium">{w.field_name}</span>
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
{new Date(w.performed_at).toLocaleString()}
|
||||
{new Date(w.performed_at).toLocaleString(undefined, { timeZone: tz })}
|
||||
</p>
|
||||
<p className="text-xs mt-1 break-words">
|
||||
<span className="text-muted-foreground">Before: </span>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
|
|||
import { Loader2, RefreshCw, Terminal } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
import { PageHeader } from '@/components/navigation/page-header';
|
||||
import { useUserTimezone } from '@/lib/hooks/use-user-timezone';
|
||||
|
||||
interface Settings {
|
||||
overshellComponentUid: string | null;
|
||||
|
|
@ -35,6 +36,7 @@ interface ExecRow {
|
|||
}
|
||||
|
||||
export default function RmmOvershellAdminPage() {
|
||||
const tz = useUserTimezone();
|
||||
const [settings, setSettings] = useState<Settings | null>(null);
|
||||
const [counts, setCounts] = useState<{ total: string; running: string; failed_24h: string } | null>(null);
|
||||
const [executions, setExecutions] = useState<ExecRow[] | null>(null);
|
||||
|
|
@ -139,7 +141,7 @@ export default function RmmOvershellAdminPage() {
|
|||
</p>
|
||||
{settings.discoveredAt && (
|
||||
<p className="text-[10px] text-muted-foreground mt-1">
|
||||
discovered {new Date(settings.discoveredAt).toLocaleString()}
|
||||
discovered {new Date(settings.discoveredAt).toLocaleString(undefined, { timeZone: tz })}
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
|
|
@ -196,7 +198,7 @@ export default function RmmOvershellAdminPage() {
|
|||
{settings.logliftDiscoveredAt && (
|
||||
<p className="text-[10px] text-muted-foreground mt-1">
|
||||
discovered{' '}
|
||||
{new Date(settings.logliftDiscoveredAt).toLocaleString()}
|
||||
{new Date(settings.logliftDiscoveredAt).toLocaleString(undefined, { timeZone: tz })}
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
|
|
@ -262,7 +264,7 @@ export default function RmmOvershellAdminPage() {
|
|||
</Badge>
|
||||
</span>
|
||||
<span className="col-span-3 text-xs text-muted-foreground truncate">
|
||||
{new Date(e.queuedAt).toLocaleString()}
|
||||
{new Date(e.queuedAt).toLocaleString(undefined, { timeZone: tz })}
|
||||
</span>
|
||||
<span className="col-span-1 text-right">
|
||||
{e.errorMessage && (
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
Calendar, CalendarDays, CalendarRange, MessageSquare, Bell, Globe, ExternalLink,
|
||||
} from 'lucide-react';
|
||||
import { PageHeader } from '@/components/navigation/page-header';
|
||||
import { useUserTimezone } from '@/lib/hooks/use-user-timezone';
|
||||
|
||||
interface DigestConfig {
|
||||
daily_enabled: boolean;
|
||||
|
|
@ -73,6 +74,7 @@ function PeriodIcon({ period }: { period: string }) {
|
|||
}
|
||||
|
||||
export default function TicketDigestPage() {
|
||||
const tz = useUserTimezone();
|
||||
const [config, setConfig] = useState<DigestConfig | null>(null);
|
||||
const [channels, setChannels] = useState<NotificationChannel[]>([]);
|
||||
const [history, setHistory] = useState<DigestReport[]>([]);
|
||||
|
|
@ -407,7 +409,7 @@ export default function TicketDigestPage() {
|
|||
<div>
|
||||
<span className="font-medium text-sm capitalize">{report.period_type}</span>
|
||||
<span className="text-xs text-muted-foreground ml-2">
|
||||
{new Date(report.generated_at).toLocaleString()}
|
||||
{new Date(report.generated_at).toLocaleString(undefined, { timeZone: tz })}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import {
|
|||
ChevronRight,
|
||||
} from 'lucide-react';
|
||||
import { WorkflowExecutionWithSteps } from '@/lib/types/workflow';
|
||||
import { useUserTimezone } from '@/lib/hooks/use-user-timezone';
|
||||
|
||||
export default function ExecutionHistoryPage() {
|
||||
return (
|
||||
|
|
@ -42,6 +43,7 @@ export default function ExecutionHistoryPage() {
|
|||
}
|
||||
|
||||
function ExecutionHistoryContent() {
|
||||
const tz = useUserTimezone();
|
||||
const searchParams = useSearchParams();
|
||||
const highlightId = searchParams.get('id');
|
||||
|
||||
|
|
@ -189,7 +191,7 @@ function ExecutionHistoryContent() {
|
|||
{exec.duration_ms ? `${exec.duration_ms}ms` : '-'}
|
||||
</TableCell>
|
||||
<TableCell className="text-sm text-muted-foreground">
|
||||
{new Date(exec.created_at).toLocaleString()}
|
||||
{new Date(exec.created_at).toLocaleString(undefined, { timeZone: tz })}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import {
|
|||
Eye,
|
||||
} from 'lucide-react';
|
||||
import StepConfigEditor from '@/components/admin/pipeline/StepConfigEditor';
|
||||
import { useUserTimezone } from '@/lib/hooks/use-user-timezone';
|
||||
|
||||
interface Pipeline {
|
||||
id: number;
|
||||
|
|
@ -91,6 +92,7 @@ const STATUS_ICONS: Record<string, any> = {
|
|||
};
|
||||
|
||||
export default function PipelineEditorPage() {
|
||||
const tz = useUserTimezone();
|
||||
const params = useParams();
|
||||
const router = useRouter();
|
||||
const pipelineId = params.id as string;
|
||||
|
|
@ -579,7 +581,7 @@ export default function PipelineEditorPage() {
|
|||
<span className="text-sm text-muted-foreground">{exec.trigger_source}</span>
|
||||
{exec.duration_ms && <span className="text-sm text-muted-foreground">{exec.duration_ms}ms</span>}
|
||||
<span className="text-xs text-muted-foreground ml-auto">
|
||||
{new Date(exec.started_at).toLocaleString()}
|
||||
{new Date(exec.started_at).toLocaleString(undefined, { timeZone: tz })}
|
||||
</span>
|
||||
</div>
|
||||
{exec.error_message && (
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ import {
|
|||
import { toast } from 'sonner';
|
||||
import { HostManager } from '@/components/zabbix/host-manager';
|
||||
import { PageHeader } from '@/components/navigation/page-header';
|
||||
import { useUserTimezone } from '@/lib/hooks/use-user-timezone';
|
||||
|
||||
type SyncMode = 'all' | 'client' | 'site';
|
||||
|
||||
|
|
@ -139,6 +140,7 @@ interface RmmOnlyRow { alert_uid: string; site_name: string; alert_class: string
|
|||
type PageTab = 'sync' | 'gaps' | 'correlation';
|
||||
|
||||
export default function ZabbixWanPage() {
|
||||
const tz = useUserTimezone();
|
||||
const [activeTab, setActiveTab] = useState<PageTab>('sync');
|
||||
const [mode, setMode] = useState<SyncMode>('all');
|
||||
const [companyId, setCompanyId] = useState<string>('');
|
||||
|
|
@ -209,8 +211,8 @@ export default function ZabbixWanPage() {
|
|||
finally { setSyncing(null); }
|
||||
};
|
||||
|
||||
const fmtSynced = (ts: string | null) => ts ? new Date(ts).toLocaleString() : 'Never';
|
||||
const fmtTs = (ts: string | null) => ts ? new Date(ts).toLocaleString() : '—';
|
||||
const fmtSynced = (ts: string | null) => ts ? new Date(ts).toLocaleString(undefined, { timeZone: tz }) : 'Never';
|
||||
const fmtTs = (ts: string | null) => ts ? new Date(ts).toLocaleString(undefined, { timeZone: tz }) : '—';
|
||||
const fmtDuration = (s: number | null, hasRecovery?: boolean) => {
|
||||
if (s === null || s === undefined) return hasRecovery ? '< 1m' : 'Open';
|
||||
if (s === 0) return hasRecovery ? '< 1m' : 'Open';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue