feat: refine job detail UI with improved layout and scrolling capabilities. Enhance spacing and overflow handling for log entries and error messages, ensuring better readability and user experience. Integrate ScrollArea for log entries to manage overflow effectively.
CI / changes (push) Successful in 6s
CI / openapi (push) Has been skipped
CI / go (push) Has been skipped
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, , evobgp-web) (push) Successful in 1m5s
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, evobgp-all, evobgp-web-all) (push) Successful in 1m7s
CI / docker-bird (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / docker-go-prime (push) Has been skipped
CI / docker-go (deploy/docker/evobgp-agent/Dockerfile, , evobgp-agent) (push) Has been skipped
CI / docker-go (evobgp-all, 1, deploy/docker/gobinary/Dockerfile, , evobgp-all) (push) Has been skipped
CI / docker-go (evobgp-api, 1, deploy/docker/gobinary/Dockerfile, , evobgp-api) (push) Has been skipped
CI / docker-go (evobgp-deploy, 0, deploy/docker/gobinary/Dockerfile, , evobgp-deploy) (push) Has been skipped
CI / docker-go (evobgp-ingest, 0, deploy/docker/gobinary/Dockerfile, , evobgp-ingest) (push) Has been skipped
CI / docker-go (evobgp-node, 0, deploy/docker/gobinary/Dockerfile, , evobgp-node) (push) Has been skipped
CI / docker-go (evobgp-render, 0, deploy/docker/gobinary/Dockerfile, , evobgp-render) (push) Has been skipped
CI / docker-go (evobgp-scheduler, 0, deploy/docker/gobinary/Dockerfile, , evobgp-scheduler) (push) Has been skipped
CI / changes (push) Successful in 6s
CI / openapi (push) Has been skipped
CI / go (push) Has been skipped
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, , evobgp-web) (push) Successful in 1m5s
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, evobgp-all, evobgp-web-all) (push) Successful in 1m7s
CI / docker-bird (push) Has been skipped
CI / bird2 (push) Has been skipped
CI / docker-go-prime (push) Has been skipped
CI / docker-go (deploy/docker/evobgp-agent/Dockerfile, , evobgp-agent) (push) Has been skipped
CI / docker-go (evobgp-all, 1, deploy/docker/gobinary/Dockerfile, , evobgp-all) (push) Has been skipped
CI / docker-go (evobgp-api, 1, deploy/docker/gobinary/Dockerfile, , evobgp-api) (push) Has been skipped
CI / docker-go (evobgp-deploy, 0, deploy/docker/gobinary/Dockerfile, , evobgp-deploy) (push) Has been skipped
CI / docker-go (evobgp-ingest, 0, deploy/docker/gobinary/Dockerfile, , evobgp-ingest) (push) Has been skipped
CI / docker-go (evobgp-node, 0, deploy/docker/gobinary/Dockerfile, , evobgp-node) (push) Has been skipped
CI / docker-go (evobgp-render, 0, deploy/docker/gobinary/Dockerfile, , evobgp-render) (push) Has been skipped
CI / docker-go (evobgp-scheduler, 0, deploy/docker/gobinary/Dockerfile, , evobgp-scheduler) (push) Has been skipped
This commit is contained in:
@@ -889,12 +889,12 @@
|
|||||||
{@const jobReport = jobReportsById.get(job.job_id)}
|
{@const jobReport = jobReportsById.get(job.job_id)}
|
||||||
{@const logEntries = getJobLogEntries(detailedJob)}
|
{@const logEntries = getJobLogEntries(detailedJob)}
|
||||||
{@const logTotal = getJobLogTotal(detailedJob, logEntries)}
|
{@const logTotal = getJobLogTotal(detailedJob, logEntries)}
|
||||||
<div class="space-y-3 py-3 px-2 sm:px-3">
|
<div class="min-w-0 max-w-full overflow-hidden space-y-3 py-3 px-2 sm:px-3">
|
||||||
{#if isDetailsLoading}
|
{#if isDetailsLoading}
|
||||||
<p class="text-muted-foreground text-xs">Догружаем свежие детали задачи…</p>
|
<p class="text-muted-foreground text-xs">Догружаем свежие детали задачи…</p>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="grid gap-2 text-sm sm:grid-cols-2 lg:grid-cols-3">
|
<div class="grid min-w-0 gap-2 text-sm sm:grid-cols-2 lg:grid-cols-3">
|
||||||
<div class="space-y-1">
|
<div class="min-w-0 space-y-1">
|
||||||
<p class="text-muted-foreground text-xs">job_id</p>
|
<p class="text-muted-foreground text-xs">job_id</p>
|
||||||
<p class="font-mono break-all text-xs">{detailedJob.job_id}</p>
|
<p class="font-mono break-all text-xs">{detailedJob.job_id}</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -916,63 +916,65 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#if detailedJob.error}
|
{#if detailedJob.error}
|
||||||
<div class="rounded-md border border-destructive/30 bg-destructive/5 p-3">
|
<div class="min-w-0 overflow-hidden rounded-md border border-destructive/30 bg-destructive/5 p-3">
|
||||||
<p class="text-muted-foreground mb-1 text-xs">error</p>
|
<p class="text-muted-foreground mb-1 text-xs">error</p>
|
||||||
<p class="text-destructive break-words text-sm">{detailedJob.error}</p>
|
<p class="text-destructive break-words text-sm">{detailedJob.error}</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if logEntries.length > 0}
|
{#if logEntries.length > 0}
|
||||||
<div class="space-y-2">
|
<div class="min-w-0 space-y-2">
|
||||||
<div class="flex flex-wrap items-center justify-between gap-2">
|
<div class="flex flex-wrap items-center justify-between gap-2">
|
||||||
<p class="text-sm font-medium">Журнал обработки</p>
|
<p class="text-sm font-medium">Журнал обработки</p>
|
||||||
<p class="text-muted-foreground rounded-md border bg-muted/50 px-2 py-0.5 text-xs">
|
<p class="text-muted-foreground rounded-md border bg-muted/50 px-2 py-0.5 text-xs">
|
||||||
{logEntries.length} записей, всего {logTotal} префиксов
|
{logEntries.length} записей, всего {logTotal} префиксов
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<ScrollArea class="max-h-[28rem] rounded-md border bg-muted/10 p-2">
|
||||||
{#each logEntries as entry, idx (`${job.job_id}-${idx}`)}
|
<div class="space-y-2">
|
||||||
<div class="bg-card/90 space-y-3 rounded-lg border border-border/70 p-4 shadow-sm">
|
{#each logEntries as entry, idx (`${job.job_id}-${idx}`)}
|
||||||
<p class="text-sm font-medium break-words leading-relaxed">{entry.message}</p>
|
<div class="bg-card/90 min-w-0 space-y-3 rounded-lg border border-border/70 p-3 shadow-sm">
|
||||||
<div class="grid gap-2 md:grid-cols-2">
|
<p class="text-sm font-medium break-words leading-relaxed">{entry.message}</p>
|
||||||
<div class="bg-muted/60 flex flex-col gap-1 rounded-md border px-2.5 py-2">
|
<div class="grid min-w-0 gap-2 md:grid-cols-2">
|
||||||
<span class="text-muted-foreground text-[11px] uppercase tracking-wide">source</span>
|
<div class="bg-muted/60 min-w-0 flex flex-col gap-1 rounded-md border px-2.5 py-2">
|
||||||
<span class="bg-background font-mono rounded px-1.5 py-0.5 text-xs break-all">{entry.source}</span>
|
<span class="text-muted-foreground text-[11px] uppercase tracking-wide">source</span>
|
||||||
</div>
|
<span class="bg-background min-w-0 overflow-hidden font-mono rounded px-1.5 py-0.5 text-xs break-all">{entry.source}</span>
|
||||||
<div class="bg-muted/60 flex flex-col gap-1 rounded-md border px-2.5 py-2">
|
</div>
|
||||||
<span class="text-muted-foreground text-[11px] uppercase tracking-wide">kind</span>
|
<div class="bg-muted/60 min-w-0 flex flex-col gap-1 rounded-md border px-2.5 py-2">
|
||||||
<span class="bg-background font-mono rounded px-1.5 py-0.5 text-xs break-all">{entry.kind}</span>
|
<span class="text-muted-foreground text-[11px] uppercase tracking-wide">kind</span>
|
||||||
</div>
|
<span class="bg-background min-w-0 overflow-hidden font-mono rounded px-1.5 py-0.5 text-xs break-all">{entry.kind}</span>
|
||||||
<div class="bg-muted/60 flex flex-col gap-1 rounded-md border px-2.5 py-2">
|
</div>
|
||||||
<span class="text-muted-foreground text-[11px] uppercase tracking-wide">community</span>
|
<div class="bg-muted/60 min-w-0 flex flex-col gap-1 rounded-md border px-2.5 py-2">
|
||||||
<span class="bg-background font-mono rounded px-1.5 py-0.5 text-xs break-all">{entry.community}</span>
|
<span class="text-muted-foreground text-[11px] uppercase tracking-wide">community</span>
|
||||||
</div>
|
<span class="bg-background min-w-0 overflow-hidden font-mono rounded px-1.5 py-0.5 text-xs break-all">{entry.community}</span>
|
||||||
<div class="bg-muted/60 flex flex-col gap-1 rounded-md border px-2.5 py-2">
|
</div>
|
||||||
<span class="text-muted-foreground text-[11px] uppercase tracking-wide">prefixes</span>
|
<div class="bg-muted/60 min-w-0 flex flex-col gap-1 rounded-md border px-2.5 py-2">
|
||||||
<span class="bg-background font-mono rounded px-1.5 py-0.5 text-xs break-all">{entry.prefix_count}</span>
|
<span class="text-muted-foreground text-[11px] uppercase tracking-wide">prefixes</span>
|
||||||
|
<span class="bg-background min-w-0 overflow-hidden font-mono rounded px-1.5 py-0.5 text-xs break-all">{entry.prefix_count}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{#if entry.sample && entry.sample.length > 0}
|
||||||
|
<div class="min-w-0 space-y-1.5">
|
||||||
|
<p class="text-muted-foreground text-[11px] uppercase tracking-wide">sample</p>
|
||||||
|
<ScrollArea class="max-h-28 rounded-md border bg-muted/35 p-2.5">
|
||||||
|
<div class="space-y-1.5">
|
||||||
|
{#each entry.sample as sampleValue, sampleIdx (`${job.job_id}-${idx}-sample-${sampleIdx}`)}
|
||||||
|
<p class="bg-background font-mono rounded px-2 py-1 text-xs break-all">{sampleValue}</p>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</ScrollArea>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if entry.sample && entry.sample.length > 0}
|
{/each}
|
||||||
<div class="space-y-1.5">
|
</div>
|
||||||
<p class="text-muted-foreground text-[11px] uppercase tracking-wide">sample</p>
|
</ScrollArea>
|
||||||
<ScrollArea class="max-h-28 rounded-md border bg-muted/35 p-2.5">
|
|
||||||
<div class="space-y-1.5">
|
|
||||||
{#each entry.sample as sampleValue, sampleIdx (`${job.job_id}-${idx}-sample-${sampleIdx}`)}
|
|
||||||
<p class="bg-background font-mono rounded px-2 py-1 text-xs break-all">{sampleValue}</p>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</ScrollArea>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if isReportLoading}
|
{#if isReportLoading}
|
||||||
<p class="text-muted-foreground text-xs">Собираем подробный отчёт по источникам и агрегации…</p>
|
<p class="text-muted-foreground text-xs">Собираем подробный отчёт по источникам и агрегации…</p>
|
||||||
{/if}
|
{/if}
|
||||||
{#if jobReport}
|
{#if jobReport}
|
||||||
<div class="space-y-3">
|
<div class="min-w-0 overflow-hidden space-y-3">
|
||||||
<div class="flex flex-wrap items-center justify-between gap-2">
|
<div class="flex flex-wrap items-center justify-between gap-2">
|
||||||
<p class="text-sm font-medium">Операции по модулю</p>
|
<p class="text-sm font-medium">Операции по модулю</p>
|
||||||
<div class="flex flex-wrap gap-1.5">
|
<div class="flex flex-wrap gap-1.5">
|
||||||
@@ -985,20 +987,20 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid gap-2 md:grid-cols-2 xl:grid-cols-4">
|
<div class="grid min-w-0 gap-2 md:grid-cols-2 xl:grid-cols-4">
|
||||||
<div class="rounded-md border bg-muted/40 p-2.5">
|
<div class="min-w-0 overflow-hidden rounded-md border bg-muted/40 p-2.5">
|
||||||
<p class="text-muted-foreground text-[11px] uppercase">Агрегация</p>
|
<p class="text-muted-foreground text-[11px] uppercase">Агрегация</p>
|
||||||
<p class="text-sm font-semibold">{jobReport.aggregationTotal} префиксов</p>
|
<p class="text-sm font-semibold">{jobReport.aggregationTotal} префиксов</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-md border bg-muted/40 p-2.5">
|
<div class="min-w-0 overflow-hidden rounded-md border bg-muted/40 p-2.5">
|
||||||
<p class="text-muted-foreground text-[11px] uppercase">Домены</p>
|
<p class="text-muted-foreground text-[11px] uppercase">Домены</p>
|
||||||
<p class="text-sm font-semibold">{jobReport.domains.length}</p>
|
<p class="text-sm font-semibold">{jobReport.domains.length}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-md border bg-muted/40 p-2.5">
|
<div class="min-w-0 overflow-hidden rounded-md border bg-muted/40 p-2.5">
|
||||||
<p class="text-muted-foreground text-[11px] uppercase">ASN</p>
|
<p class="text-muted-foreground text-[11px] uppercase">ASN</p>
|
||||||
<p class="text-sm font-semibold">{jobReport.asn.length}</p>
|
<p class="text-sm font-semibold">{jobReport.asn.length}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-md border bg-muted/40 p-2.5">
|
<div class="min-w-0 overflow-hidden rounded-md border bg-muted/40 p-2.5">
|
||||||
<p class="text-muted-foreground text-[11px] uppercase">CDN/IP Range</p>
|
<p class="text-muted-foreground text-[11px] uppercase">CDN/IP Range</p>
|
||||||
<p class="text-sm font-semibold">{jobReport.cdn.length}/{jobReport.ipRanges.length}</p>
|
<p class="text-sm font-semibold">{jobReport.cdn.length}/{jobReport.ipRanges.length}</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -1013,8 +1015,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="grid gap-3 xl:grid-cols-2">
|
<div class="grid min-w-0 gap-3 xl:grid-cols-2">
|
||||||
<div class="min-w-0 space-y-1.5 rounded-lg border p-3">
|
<div class="min-w-0 overflow-hidden space-y-1.5 rounded-lg border p-3">
|
||||||
<p class="text-sm font-medium">Домены: какой домен какие IP/префиксы вернул</p>
|
<p class="text-sm font-medium">Домены: какой домен какие IP/префиксы вернул</p>
|
||||||
<ScrollArea class="max-h-44 rounded border bg-muted/25 p-2">
|
<ScrollArea class="max-h-44 rounded border bg-muted/25 p-2">
|
||||||
{#each jobReport.domains as row (`${job.job_id}-domain-${row.source}`)}
|
{#each jobReport.domains as row (`${job.job_id}-domain-${row.source}`)}
|
||||||
@@ -1028,7 +1030,7 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
<div class="min-w-0 space-y-1.5 rounded-lg border p-3">
|
<div class="min-w-0 overflow-hidden space-y-1.5 rounded-lg border p-3">
|
||||||
<p class="text-sm font-medium">ASN: сколько префиксов получено по AS</p>
|
<p class="text-sm font-medium">ASN: сколько префиксов получено по AS</p>
|
||||||
<ScrollArea class="max-h-44 rounded border bg-muted/25 p-2">
|
<ScrollArea class="max-h-44 rounded border bg-muted/25 p-2">
|
||||||
{#each jobReport.asn as row (`${job.job_id}-asn-${row.asn}`)}
|
{#each jobReport.asn as row (`${job.job_id}-asn-${row.asn}`)}
|
||||||
@@ -1041,7 +1043,7 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
<div class="min-w-0 space-y-1.5 rounded-lg border p-3">
|
<div class="min-w-0 overflow-hidden space-y-1.5 rounded-lg border p-3">
|
||||||
<p class="text-sm font-medium">CDN: из каждой ссылки полученные IP/префиксы</p>
|
<p class="text-sm font-medium">CDN: из каждой ссылки полученные IP/префиксы</p>
|
||||||
<ScrollArea class="max-h-44 rounded border bg-muted/25 p-2">
|
<ScrollArea class="max-h-44 rounded border bg-muted/25 p-2">
|
||||||
{#each jobReport.cdn as row (`${job.job_id}-cdn-${row.source}`)}
|
{#each jobReport.cdn as row (`${job.job_id}-cdn-${row.source}`)}
|
||||||
@@ -1055,7 +1057,7 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
<div class="min-w-0 space-y-1.5 rounded-lg border p-3">
|
<div class="min-w-0 overflow-hidden space-y-1.5 rounded-lg border p-3">
|
||||||
<p class="text-sm font-medium">IP range: итог по статическим диапазонам</p>
|
<p class="text-sm font-medium">IP range: итог по статическим диапазонам</p>
|
||||||
<ScrollArea class="max-h-44 rounded border bg-muted/25 p-2">
|
<ScrollArea class="max-h-44 rounded border bg-muted/25 p-2">
|
||||||
{#each jobReport.ipRanges as row (`${job.job_id}-ipr-${row.source}`)}
|
{#each jobReport.ipRanges as row (`${job.job_id}-ipr-${row.source}`)}
|
||||||
@@ -1072,10 +1074,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="space-y-1">
|
<div class="min-w-0 overflow-hidden space-y-1">
|
||||||
<p class="text-muted-foreground text-xs">Meta (raw JSON)</p>
|
<p class="text-muted-foreground text-xs">Meta (raw JSON)</p>
|
||||||
<ScrollArea class="max-h-56 rounded-md border bg-muted/30 p-3">
|
<ScrollArea class="max-h-56 rounded-md border bg-muted/30 p-3">
|
||||||
<pre class="font-mono text-xs whitespace-pre-wrap">{JSON.stringify(detailedJob.meta ?? {}, null, 2)}</pre>
|
<pre class="font-mono text-xs whitespace-pre-wrap break-all [overflow-wrap:anywhere]">{JSON.stringify(detailedJob.meta ?? {}, null, 2)}</pre>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user