refactor(web): общие форматтеры, единая навигация, RBAC-гейтинг и чистка мёртвого кода
- lib/format.ts: ru-RU форматтеры дат/чисел в одном месте — убраны дубли из 8 компонентов (agent-card, fleet-grid, blocked-ips/ports, facts, lifecycle, host-firewall, lists-columns, system-monitor) - lib/nav.ts: единый конфиг маршрутов — sidebar, ⌘K-поиск и breadcrumbs рендерятся из одного источника (было 3 расходящихся копии) - lib/permissions.ts + useCan: клиентский RBAC — кнопки создания/подтверждения скрываются без fw:*:write/admin (сервер остаётся авторитетным) - удалён мёртвый код ~2500 строк: stepper, data-grid dnd/virtual/visibility варианты, settings-shell
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Shared ru-RU formatters — single source for dates/numbers across the app.
|
||||
* All timestamps are ISO strings from the API.
|
||||
*/
|
||||
|
||||
const packetFmt = new Intl.NumberFormat('ru-RU', {
|
||||
notation: 'compact',
|
||||
maximumFractionDigits: 1,
|
||||
})
|
||||
|
||||
const numberFmt = new Intl.NumberFormat('ru-RU')
|
||||
|
||||
const shortDateTimeFmt = new Intl.DateTimeFormat('ru-RU', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
})
|
||||
|
||||
const dateTimeFmt = new Intl.DateTimeFormat('ru-RU')
|
||||
|
||||
const stampDateTimeFmt = new Intl.DateTimeFormat('ru-RU', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
})
|
||||
|
||||
const timeFmt = new Intl.DateTimeFormat('ru-RU', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
})
|
||||
|
||||
/** Compact packet counter: 1,2K / 3,4M */
|
||||
export function formatPackets(n: number | undefined | null): string {
|
||||
if (n === undefined || n === null) return '—'
|
||||
return packetFmt.format(n)
|
||||
}
|
||||
|
||||
export function formatNumber(n: number | undefined | null): string {
|
||||
if (n === undefined || n === null) return '—'
|
||||
return numberFmt.format(n)
|
||||
}
|
||||
|
||||
/** dd.MM HH:mm — dense "seen" stamps in grids/cards */
|
||||
export function formatShortDateTime(iso: string | null | undefined): string {
|
||||
if (!iso) return '—'
|
||||
const t = Date.parse(iso)
|
||||
if (Number.isNaN(t)) return '—'
|
||||
return shortDateTimeFmt.format(new Date(t))
|
||||
}
|
||||
|
||||
/** Full locale date-time for detail panels */
|
||||
export function formatDateTime(iso: string | null | undefined): string {
|
||||
if (!iso) return '—'
|
||||
const t = Date.parse(iso)
|
||||
if (Number.isNaN(t)) return iso
|
||||
return dateTimeFmt.format(new Date(t))
|
||||
}
|
||||
|
||||
/** dd.MM.yyyy HH:mm:ss — block-stats "seen" stamps */
|
||||
export function formatStampDateTime(iso: string | null | undefined): string {
|
||||
if (!iso) return '—'
|
||||
const t = Date.parse(iso)
|
||||
if (Number.isNaN(t)) return iso
|
||||
return stampDateTimeFmt.format(new Date(t))
|
||||
}
|
||||
|
||||
export function formatTime(d: Date): string {
|
||||
return timeFmt.format(d)
|
||||
}
|
||||
Reference in New Issue
Block a user