feat(dashboard): собрать ops-дашборд на ReUI Frame с живыми данными
Docker images / prepare-release (push) Successful in 10s
Docker images / backend-test (push) Successful in 2m13s
Docker images / frontend-image (push) Successful in 3m14s
Docker images / updater-image (push) Successful in 47s
Docker images / backend-image (push) Successful in 2m44s
Docker images / notify-webhook (push) Skipped
Docker images / publish-release (push) Successful in 14s
Docker images / prepare-release (push) Successful in 10s
Docker images / backend-test (push) Successful in 2m13s
Docker images / frontend-image (push) Successful in 3m14s
Docker images / updater-image (push) Successful in 47s
Docker images / backend-image (push) Successful in 2m44s
Docker images / notify-webhook (push) Skipped
Docker images / publish-release (push) Successful in 14s
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
5f2b4e2d40
commit
36c5305db7
10 files changed
+1580
-917
No files matched your search
@@ -0,0 +1,90 @@
|
||||
"use client"
|
||||
|
||||
import Link from "next/link"
|
||||
import {
|
||||
Timeline,
|
||||
TimelineContent,
|
||||
TimelineDate,
|
||||
TimelineHeader,
|
||||
TimelineIndicator,
|
||||
TimelineItem,
|
||||
TimelineSeparator,
|
||||
TimelineTitle,
|
||||
} from "@/components/reui/timeline"
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/components/reui/alert"
|
||||
import { cn } from "@/lib/utils"
|
||||
import type { EventItem } from "@mmapp/contracts/events"
|
||||
|
||||
function formatEventAge(iso: string): string {
|
||||
const ts = Date.parse(iso)
|
||||
if (!Number.isFinite(ts)) return "—"
|
||||
const diffMs = Math.max(0, Date.now() - ts)
|
||||
const minutes = Math.floor(diffMs / 60_000)
|
||||
if (minutes < 1) return "сейчас"
|
||||
if (minutes < 60) return `${minutes}м`
|
||||
const hours = Math.floor(minutes / 60)
|
||||
if (hours < 24) return `${hours}ч`
|
||||
const days = Math.floor(hours / 24)
|
||||
return `${days}д`
|
||||
}
|
||||
|
||||
const LEVEL_DOT: Record<EventItem["level"], string> = {
|
||||
critical: "border-destructive bg-destructive/20 group-data-completed/timeline-item:border-destructive",
|
||||
warning: "border-warning bg-warning/20 group-data-completed/timeline-item:border-warning",
|
||||
info: "border-info bg-info/20 group-data-completed/timeline-item:border-info",
|
||||
}
|
||||
|
||||
/**
|
||||
* Compact activity timeline.
|
||||
* Preview: https://reui.io/preview/base/timeline-3
|
||||
* Docs: https://reui.io/docs/components/base/timeline
|
||||
*/
|
||||
export function DashboardEventsTimeline({
|
||||
events,
|
||||
loading,
|
||||
error,
|
||||
}: {
|
||||
events: EventItem[]
|
||||
loading?: boolean
|
||||
error?: string | null
|
||||
}) {
|
||||
if (loading && events.length === 0) {
|
||||
return <p className="text-muted-foreground px-5 py-6 text-sm">Загрузка событий…</p>
|
||||
}
|
||||
if (error && events.length === 0) {
|
||||
return (
|
||||
<div className="px-5 py-4">
|
||||
<Alert variant="destructive">
|
||||
<AlertTitle>События недоступны</AlertTitle>
|
||||
<AlertDescription>{error}</AlertDescription>
|
||||
</Alert>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (events.length === 0) {
|
||||
return (
|
||||
<p className="text-muted-foreground px-5 py-6 text-sm">
|
||||
Событий пока нет.{" "}
|
||||
<Link href="/alerts" className="underline underline-offset-2">
|
||||
Оповещения
|
||||
</Link>
|
||||
</p>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Timeline defaultValue={events.length} className="px-5 py-4">
|
||||
{events.map((event, index) => (
|
||||
<TimelineItem key={event.id} step={index + 1}>
|
||||
<TimelineHeader>
|
||||
<TimelineSeparator />
|
||||
<TimelineDate>{formatEventAge(event.createdAt)}</TimelineDate>
|
||||
<TimelineTitle className="text-[13px] leading-tight">{event.title}</TimelineTitle>
|
||||
<TimelineIndicator className={cn(LEVEL_DOT[event.level])} />
|
||||
</TimelineHeader>
|
||||
<TimelineContent className="text-xs leading-snug">{event.message}</TimelineContent>
|
||||
</TimelineItem>
|
||||
))}
|
||||
</Timeline>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user