refactor: enhance UI components with PanelCard integration and improved layout consistency
CI / changes (push) Successful in 13s
CI / commitlint (push) Has been skipped
CI / openapi (push) Has been skipped
CI / web (push) Successful in 1m6s
CI / go (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / release (push) Successful in 4m17s
CI / changes (push) Successful in 13s
CI / commitlint (push) Has been skipped
CI / openapi (push) Has been skipped
CI / web (push) Successful in 1m6s
CI / go (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / release (push) Successful in 4m17s
Updated multiple components to utilize the new PanelCard for better organization and presentation of content. Refactored DataGridShell, DataGridCard, and various analytics components to streamline layouts and enhance user experience. Adjusted styles for consistency across components, including pagination and toolbar elements, ensuring a cohesive interface throughout the application.
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
import type { ApiKeyRole } from '@/types/api'
|
||||
|
||||
import { apiKeyRoleRu } from '@/lib/ui-labels'
|
||||
|
||||
export const API_KEY_ROLE_ITEMS: ReadonlyArray<{ value: ApiKeyRole; label: string }> = [
|
||||
{ value: 'viewer', label: 'viewer — только чтение' },
|
||||
{ value: 'editor', label: 'editor — CRUD без apply' },
|
||||
{ value: 'operator', label: 'operator — полный доступ' },
|
||||
{ value: 'node', label: 'node — только API ноды' },
|
||||
{ value: 'viewer', label: `${apiKeyRoleRu('viewer')} — только чтение` },
|
||||
{ value: 'editor', label: `${apiKeyRoleRu('editor')} — CRUD без применения` },
|
||||
{ value: 'operator', label: `${apiKeyRoleRu('operator')} — полный доступ` },
|
||||
{ value: 'node', label: `${apiKeyRoleRu('node')} — только API ноды` },
|
||||
]
|
||||
|
||||
export function apiKeyRoleLabel(role: ApiKeyRole): string {
|
||||
|
||||
@@ -25,6 +25,17 @@ export const DATA_GRID_PAGINATION_RU = {
|
||||
nextPageLabel: 'Следующая страница',
|
||||
}
|
||||
|
||||
export const DATA_GRID_MESSAGES_RU = {
|
||||
emptyMessage: 'Нет данных',
|
||||
loadingMessage: 'Загрузка…',
|
||||
fetchingMoreMessage: 'Загрузка…',
|
||||
selectAllLabel: 'Выбрать все',
|
||||
selectRowLabel: 'Выбрать строку',
|
||||
pinRowLabel: 'Закрепить строку',
|
||||
unpinRowLabel: 'Открепить строку',
|
||||
allRecordsLoadedMessage: 'Все записи загружены',
|
||||
}
|
||||
|
||||
export const DATA_GRID_DENSE_LAYOUT: NonNullable<DataGridProps<object>['tableLayout']> = {
|
||||
...DATA_GRID_TABLE_LAYOUT,
|
||||
dense: true,
|
||||
|
||||
@@ -30,3 +30,25 @@ export function deploymentProgress(speakers: SpeakerRow[]): DeploymentProgress {
|
||||
mode: 'online',
|
||||
}
|
||||
}
|
||||
|
||||
export function deploymentProgressMeta(deploy: DeploymentProgress): {
|
||||
label: string
|
||||
hint: string
|
||||
} {
|
||||
if (deploy.total === 0) {
|
||||
return {
|
||||
label: 'Деплой на спикерах',
|
||||
hint: 'Нет зарегистрированных BIRD-спикеров',
|
||||
}
|
||||
}
|
||||
if (deploy.mode === 'revision') {
|
||||
return {
|
||||
label: `Применена ревизия (${deploy.synced} из ${deploy.total} спикеров)`,
|
||||
hint: 'Доля спикеров, на которых последняя опубликованная ревизия уже применена',
|
||||
}
|
||||
}
|
||||
return {
|
||||
label: `Спикеры в сети (${deploy.synced} из ${deploy.total})`,
|
||||
hint: 'Ревизии ещё не публиковались — показана доступность агента на нодах',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ export function peerSessionBreakdown(peers: PeerRow[]): BreakdownSlice[] {
|
||||
if (established > 0) {
|
||||
slices.push({
|
||||
key: 'established',
|
||||
label: 'Established',
|
||||
label: 'Установлена',
|
||||
count: established,
|
||||
color: 'var(--color-chart-2)',
|
||||
})
|
||||
@@ -22,7 +22,7 @@ export function peerSessionBreakdown(peers: PeerRow[]): BreakdownSlice[] {
|
||||
if (pending > 0) {
|
||||
slices.push({
|
||||
key: 'pending',
|
||||
label: 'Не Established',
|
||||
label: 'Не установлена',
|
||||
count: pending,
|
||||
color: 'var(--color-warning)',
|
||||
})
|
||||
|
||||
@@ -35,7 +35,7 @@ export function readinessBreakdown(
|
||||
const slices: BreakdownSlice[] = [
|
||||
{
|
||||
key: 'health',
|
||||
label: 'Health OK',
|
||||
label: 'API доступен',
|
||||
count: 1,
|
||||
color: 'var(--color-chart-2)',
|
||||
},
|
||||
@@ -44,7 +44,7 @@ export function readinessBreakdown(
|
||||
if (okCount > 0) {
|
||||
slices.push({
|
||||
key: 'checks-ok',
|
||||
label: 'Checks OK',
|
||||
label: 'Проверки в норме',
|
||||
count: okCount,
|
||||
color: 'var(--color-chart-1)',
|
||||
})
|
||||
@@ -52,7 +52,7 @@ export function readinessBreakdown(
|
||||
if (failCount > 0) {
|
||||
slices.push({
|
||||
key: 'checks-fail',
|
||||
label: 'Checks fail',
|
||||
label: 'Ошибки проверок',
|
||||
count: failCount,
|
||||
color: 'var(--color-warning)',
|
||||
})
|
||||
@@ -61,7 +61,7 @@ export function readinessBreakdown(
|
||||
if (slices.length === 1 && okCount === 0 && failCount === 0) {
|
||||
slices.push({
|
||||
key: 'ready',
|
||||
label: ready?.status === 'ok' ? 'Ready' : 'Ready pending',
|
||||
label: ready?.status === 'ok' ? 'Готов' : 'Ожидает готовности',
|
||||
count: 1,
|
||||
color: 'var(--color-chart-4)',
|
||||
})
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import type { JobRow, PeerRow, RevisionRow, SpeakerRow } from '@/types/api'
|
||||
|
||||
import { jobKindRu, jobStatusRu } from '@/lib/ui-labels'
|
||||
|
||||
import type { PlatformActivityItem } from './types'
|
||||
|
||||
const JOB_KIND_RU: Record<string, string> = {
|
||||
module_refresh: 'Обновление модуля',
|
||||
apply: 'Применение конфигурации',
|
||||
rollback: 'Откат ревизии',
|
||||
bird_reload: 'Перезагрузка BIRD',
|
||||
}
|
||||
|
||||
function jobMessage(job: JobRow): string {
|
||||
const kind = JOB_KIND_RU[job.kind] ?? job.kind
|
||||
return `${kind} · ${job.status}`
|
||||
return `${jobKindRu(job.kind)} · ${jobStatusRu(job.status)}`
|
||||
}
|
||||
|
||||
export function recentPlatformActivity(
|
||||
@@ -45,7 +39,7 @@ export function recentPlatformActivity(
|
||||
for (const peer of peers.filter((p) => p.session_mismatch).slice(0, 2)) {
|
||||
items.push({
|
||||
id: `peer-${peer.id}`,
|
||||
message: `Mismatch сессии: ${peer.name ?? peer.neighbor}`,
|
||||
message: `Расхождение сессии: ${peer.name ?? peer.neighbor}`,
|
||||
status: 'mismatch',
|
||||
kind: 'network',
|
||||
})
|
||||
|
||||
@@ -27,3 +27,97 @@ export function moduleTypeRu(type: string): string {
|
||||
return type
|
||||
}
|
||||
}
|
||||
|
||||
const JOB_KIND_RU: Record<string, string> = {
|
||||
module_refresh: 'Обновление модуля',
|
||||
apply: 'Применение конфигурации',
|
||||
rollback: 'Откат ревизии',
|
||||
bird_reload: 'Перезагрузка BIRD',
|
||||
}
|
||||
|
||||
export function jobKindRu(kind: string): string {
|
||||
return JOB_KIND_RU[kind] ?? kind
|
||||
}
|
||||
|
||||
const JOB_STATUS_RU: Record<string, string> = {
|
||||
queued: 'В очереди',
|
||||
running: 'Выполняется',
|
||||
succeeded: 'Успешно',
|
||||
failed: 'Ошибка',
|
||||
error: 'Ошибка',
|
||||
cancelled: 'Отменена',
|
||||
canceled: 'Отменена',
|
||||
pending: 'Ожидает',
|
||||
approved: 'Одобрен',
|
||||
revoked: 'Отозван',
|
||||
active: 'Активен',
|
||||
ok: 'В норме',
|
||||
mismatch: 'Расхождение',
|
||||
established: 'Установлена',
|
||||
healthy: 'В норме',
|
||||
warning: 'Предупреждение',
|
||||
stale: 'Устарело',
|
||||
overdue: 'Просрочено',
|
||||
paused: 'Приостановлен',
|
||||
disabled: 'Выключен',
|
||||
archived: 'В архиве',
|
||||
block: 'block',
|
||||
accept: 'accept',
|
||||
}
|
||||
|
||||
export function jobStatusRu(status: string): string {
|
||||
return JOB_STATUS_RU[status.toLowerCase()] ?? status
|
||||
}
|
||||
|
||||
export function bgpSessionStateRu(state: string | null | undefined): string {
|
||||
if (!state) return '—'
|
||||
if (state === 'Established') return 'Установлена'
|
||||
return state
|
||||
}
|
||||
|
||||
export function speakerOnlineLabel(agentOk: boolean | undefined): string {
|
||||
if (agentOk === true) return 'В сети'
|
||||
if (agentOk === false) return 'Не в сети'
|
||||
return '—'
|
||||
}
|
||||
|
||||
export function firewallClientStatusRu(status: string): string {
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
return 'Ожидает'
|
||||
case 'approved':
|
||||
return 'Одобрен'
|
||||
case 'revoked':
|
||||
return 'Отозван'
|
||||
default:
|
||||
return status
|
||||
}
|
||||
}
|
||||
|
||||
export function apiKeyRoleRu(role: string): string {
|
||||
switch (role) {
|
||||
case 'viewer':
|
||||
return 'Наблюдатель'
|
||||
case 'editor':
|
||||
return 'Редактор'
|
||||
case 'operator':
|
||||
return 'Оператор'
|
||||
case 'node':
|
||||
return 'Нода'
|
||||
default:
|
||||
return role
|
||||
}
|
||||
}
|
||||
|
||||
export function readyCheckRu(key: string): string {
|
||||
switch (key) {
|
||||
case 'postgres':
|
||||
return 'PostgreSQL'
|
||||
case 'store':
|
||||
return 'Хранилище'
|
||||
case 'jobs':
|
||||
return 'Очередь задач'
|
||||
default:
|
||||
return key
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user