feat: integrate sonner for toast notifications and enhance UI feedback
Added the sonner library for toast notifications across various components, improving user feedback for actions such as saving settings, syncing rules, and handling errors. Updated the layout to include a Toaster component for consistent notification display. Refactored alert messages in the backups, gre, and filters pages to utilize the new notification system, enhancing overall user experience.
This commit is contained in:
@@ -6,6 +6,7 @@ import { PageHeader } from "@/components/page-header"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Button, buttonVariants } from "@/components/ui/button"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
@@ -101,7 +102,10 @@ function SnapshotTables({ snap }: { snap: SchedulerRunSnapshot }) {
|
||||
<p className="text-xs text-amber-600 dark:text-amber-400">Прогон пропущен: предыдущий сбор трафика ещё выполнялся.</p>
|
||||
) : null}
|
||||
{t.fatalError ? (
|
||||
<p className="text-xs text-destructive">Критическая ошибка: {t.fatalError}</p>
|
||||
<Alert variant="destructive" className="py-2">
|
||||
<AlertCircleIcon />
|
||||
<AlertDescription className="text-xs">Критическая ошибка: {t.fatalError}</AlertDescription>
|
||||
</Alert>
|
||||
) : null}
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Сэмплы на момент <span className="font-mono tabular-nums">{new Date(t.sampledAt).toLocaleString("ru-RU")}</span>
|
||||
@@ -154,7 +158,12 @@ function SnapshotTables({ snap }: { snap: SchedulerRunSnapshot }) {
|
||||
{u.skipped ? (
|
||||
<p className="text-xs text-amber-600 dark:text-amber-400">Прогон пропущен: сбор ресурсов уже выполняется.</p>
|
||||
) : null}
|
||||
{u.fatalError ? <p className="text-xs text-destructive">Критическая ошибка: {u.fatalError}</p> : null}
|
||||
{u.fatalError ? (
|
||||
<Alert variant="destructive" className="py-2">
|
||||
<AlertCircleIcon />
|
||||
<AlertDescription className="text-xs">Критическая ошибка: {u.fatalError}</AlertDescription>
|
||||
</Alert>
|
||||
) : null}
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Сэмплы на <span className="font-mono tabular-nums">{new Date(u.sampledAt).toLocaleString("ru-RU")}</span>
|
||||
</p>
|
||||
@@ -221,7 +230,12 @@ function SnapshotTables({ snap }: { snap: SchedulerRunSnapshot }) {
|
||||
{s.skipped ? (
|
||||
<p className="text-xs text-amber-600 dark:text-amber-400">Прогон пропущен: предыдущая проверка API ещё выполнялась.</p>
|
||||
) : null}
|
||||
{s.fatalError ? <p className="text-xs text-destructive">Критическая ошибка: {s.fatalError}</p> : null}
|
||||
{s.fatalError ? (
|
||||
<Alert variant="destructive" className="py-2">
|
||||
<AlertCircleIcon />
|
||||
<AlertDescription className="text-xs">Критическая ошибка: {s.fatalError}</AlertDescription>
|
||||
</Alert>
|
||||
) : null}
|
||||
<p className="text-xs text-muted-foreground">
|
||||
GET <span className="font-mono">/system/identity</span> на{" "}
|
||||
<span className="font-mono tabular-nums">{new Date(s.sampledAt).toLocaleString("ru-RU")}</span>
|
||||
@@ -272,7 +286,12 @@ function SnapshotTables({ snap }: { snap: SchedulerRunSnapshot }) {
|
||||
{p.skipped ? (
|
||||
<p className="text-xs text-amber-600 dark:text-amber-400">Прогон пропущен: сбор ping уже выполняется.</p>
|
||||
) : null}
|
||||
{p.fatalError ? <p className="text-xs text-destructive">Критическая ошибка: {p.fatalError}</p> : null}
|
||||
{p.fatalError ? (
|
||||
<Alert variant="destructive" className="py-2">
|
||||
<AlertCircleIcon />
|
||||
<AlertDescription className="text-xs">Критическая ошибка: {p.fatalError}</AlertDescription>
|
||||
</Alert>
|
||||
) : null}
|
||||
{p.skippedByInterval != null && p.skippedByInterval > 0 ? (
|
||||
<p className="text-xs text-muted-foreground">Пропущено по интервалу проб: {p.skippedByInterval}</p>
|
||||
) : null}
|
||||
@@ -384,7 +403,12 @@ function SnapshotTables({ snap }: { snap: SchedulerRunSnapshot }) {
|
||||
{g.skipped ? (
|
||||
<p className="text-xs text-amber-600 dark:text-amber-400">Прогон пропущен: предыдущий сбор GRE/BGP ещё выполнялся.</p>
|
||||
) : null}
|
||||
{g.fatalError ? <p className="text-xs text-destructive">Критическая ошибка: {g.fatalError}</p> : null}
|
||||
{g.fatalError ? (
|
||||
<Alert variant="destructive" className="py-2">
|
||||
<AlertCircleIcon />
|
||||
<AlertDescription className="text-xs">Критическая ошибка: {g.fatalError}</AlertDescription>
|
||||
</Alert>
|
||||
) : null}
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Запись в SQLite на{" "}
|
||||
<span className="font-mono tabular-nums">{new Date(g.sampledAt).toLocaleString("ru-RU")}</span>
|
||||
@@ -470,13 +494,16 @@ function SnapshotTables({ snap }: { snap: SchedulerRunSnapshot }) {
|
||||
</div>
|
||||
</dl>
|
||||
{a.errors?.length ? (
|
||||
<div className="rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive space-y-1">
|
||||
{a.errors.map((e, i) => (
|
||||
<p key={i} className="break-words">
|
||||
{e}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
<Alert variant="destructive" className="py-2">
|
||||
<AlertCircleIcon />
|
||||
<AlertDescription className="space-y-1 text-xs">
|
||||
{a.errors.map((e, i) => (
|
||||
<p key={i} className="break-words">
|
||||
{e}
|
||||
</p>
|
||||
))}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
) : null}
|
||||
{a.ruleDiag && a.ruleDiag.length > 0 ? (
|
||||
<div className="rounded-md border border-border bg-muted/20 px-3 py-2 space-y-2">
|
||||
@@ -824,12 +851,11 @@ export default function DataCollectionPage() {
|
||||
)}
|
||||
|
||||
{isLive && collectorError && (
|
||||
<Card className="border-destructive/50">
|
||||
<CardContent className="flex items-start gap-2 pt-4 pb-4 px-4">
|
||||
<AlertCircleIcon className="size-4 text-destructive shrink-0 mt-0.5" />
|
||||
<p className="text-sm text-destructive">{collectorError}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Alert variant="destructive">
|
||||
<AlertCircleIcon />
|
||||
<AlertTitle>Ошибка загрузки статуса коллекторов</AlertTitle>
|
||||
<AlertDescription>{collectorError}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{isLive && (
|
||||
|
||||
Reference in New Issue
Block a user