1
0
forked from baron/baron-sso

feat: apply sticky header and inner scroll to audit logs page

This commit is contained in:
2026-03-19 13:15:50 +09:00
parent f072d37362
commit 926c26b1ad

View File

@@ -158,8 +158,8 @@ function AuditLogsPage() {
} }
return ( return (
<div className="space-y-8"> <div className="space-y-6 flex flex-col h-[calc(100vh-theme(spacing.32))]">
<header className="flex flex-wrap items-start justify-between gap-4"> <header className="flex flex-wrap items-start justify-between gap-4 flex-shrink-0">
<div> <div>
<div className="flex items-center gap-2 text-sm text-[var(--color-muted)]"> <div className="flex items-center gap-2 text-sm text-[var(--color-muted)]">
<span>{t("ui.admin.audit.breadcrumb.section", "Audit")}</span> <span>{t("ui.admin.audit.breadcrumb.section", "Audit")}</span>
@@ -194,27 +194,24 @@ function AuditLogsPage() {
</div> </div>
</header> </header>
<div className="space-y-4"> <Card className="glass-panel flex-1 flex flex-col min-h-0 overflow-hidden">
<Card className="glass-panel"> <CardHeader className="flex flex-row items-center justify-between flex-shrink-0">
<CardHeader className="flex flex-row items-center justify-between">
<div> <div>
<CardTitle> <CardTitle>
{t("ui.admin.audit.registry.title", "Audit registry")} {t("ui.admin.audit.registry.title", "Audit registry")}
</CardTitle> </CardTitle>
<CardDescription> <CardDescription>
{t( {t("msg.admin.audit.registry.count", "로드된 로그 {{count}}건", {
"msg.admin.audit.registry.count", count: logs.length,
"로드된 로그 {{count}}건", })}
{ count: logs.length },
)}
</CardDescription> </CardDescription>
</div> </div>
<Badge variant="muted"> <Badge variant="muted">
{t("ui.common.badge.command_only", "Command only")} {t("ui.common.badge.command_only", "Command only")}
</Badge> </Badge>
</CardHeader> </CardHeader>
<CardContent> <CardContent className="flex-1 flex flex-col min-h-0 pt-0">
<div className="mb-4 flex flex-wrap items-center gap-2"> <div className="mb-4 flex flex-wrap items-center gap-2 flex-shrink-0">
<div className="flex flex-1 items-center gap-2 rounded-full border border-[var(--color-border)] bg-[rgba(255,255,255,0.02)] px-4 py-2 text-[var(--color-muted)]"> <div className="flex flex-1 items-center gap-2 rounded-full border border-[var(--color-border)] bg-[rgba(255,255,255,0.02)] px-4 py-2 text-[var(--color-muted)]">
<Search size={14} /> <Search size={14} />
<input <input
@@ -267,8 +264,10 @@ function AuditLogsPage() {
)) ))
)} )}
</div> </div>
<div className="flex-1 rounded-md border overflow-hidden flex flex-col">
<div className="flex-1 overflow-auto relative custom-scrollbar">
<Table className="table-fixed"> <Table className="table-fixed">
<TableHeader> <TableHeader className="sticky top-0 bg-muted/90 backdrop-blur z-10 shadow-sm">
<TableRow> <TableRow>
<TableHead className="w-[140px]"> <TableHead className="w-[140px]">
{t("ui.admin.audit.table.time", "TIME")} {t("ui.admin.audit.table.time", "TIME")}
@@ -286,7 +285,10 @@ function AuditLogsPage() {
{t("ui.admin.audit.table.status", "STATUS")} {t("ui.admin.audit.table.status", "STATUS")}
</TableHead> </TableHead>
<TableHead> <TableHead>
{t("ui.admin.audit.table.action_target", "Action / Target")} {t(
"ui.admin.audit.table.action_target",
"Action / Target",
)}
</TableHead> </TableHead>
<TableHead className="w-[80px]" /> <TableHead className="w-[80px]" />
</TableRow> </TableRow>
@@ -424,7 +426,9 @@ function AuditLogsPage() {
"ui.admin.audit.copy.target", "ui.admin.audit.copy.target",
"Copy target", "Copy target",
)} )}
onClick={() => handleCopy(details.target || "")} onClick={() =>
handleCopy(details.target || "")
}
> >
<Copy className="h-3 w-3" /> <Copy className="h-3 w-3" />
</Button> </Button>
@@ -513,7 +517,9 @@ function AuditLogsPage() {
"Actor ID · {{value}}", "Actor ID · {{value}}",
{ {
value: value:
row.user_id || details.actor_id || "-", row.user_id ||
details.actor_id ||
"-",
}, },
)} )}
</div> </div>
@@ -522,7 +528,9 @@ function AuditLogsPage() {
"ui.admin.audit.details.tenant", "ui.admin.audit.details.tenant",
"Tenant · {{value}}", "Tenant · {{value}}",
{ {
value: formatCellValue(details.tenant_id), value: formatCellValue(
details.tenant_id,
),
}, },
)} )}
</div> </div>
@@ -538,7 +546,10 @@ function AuditLogsPage() {
</div> </div>
<div className="space-y-1"> <div className="space-y-1">
<div className="uppercase tracking-[0.16em]"> <div className="uppercase tracking-[0.16em]">
{t("ui.admin.audit.details.result", "Result")} {t(
"ui.admin.audit.details.result",
"Result",
)}
</div> </div>
<div className="break-all"> <div className="break-all">
{t( {t(
@@ -577,7 +588,9 @@ function AuditLogsPage() {
})} })}
</TableBody> </TableBody>
</Table> </Table>
<div className="pt-4 text-center"> </div>
</div>
<div className="pt-4 text-center flex-shrink-0">
{hasNextPage ? ( {hasNextPage ? (
<Button <Button
variant="outline" variant="outline"
@@ -597,7 +610,6 @@ function AuditLogsPage() {
</CardContent> </CardContent>
</Card> </Card>
</div> </div>
</div>
); );
} }