1
0
forked from baron/baron-sso

i18n refresh and frontend fixes

This commit is contained in:
Lectom C Han
2026-02-10 19:15:51 +09:00
parent 2441c64598
commit b6d3b69cda
44 changed files with 8603 additions and 1760 deletions

View File

@@ -16,30 +16,39 @@ import {
CardHeader,
CardTitle,
} from "../../components/ui/card";
import { t } from "../../lib/i18n";
const summaryCards = [
{
label: "Total Tenants",
labelKey: "ui.admin.overview.summary.total_tenants",
labelFallback: "Total Tenants",
value: "-",
hint: "Tenant-aware core",
hintKey: "msg.admin.overview.summary.total_tenants",
hintFallback: "Tenant-aware core",
icon: Users,
},
{
label: "OIDC Clients",
labelKey: "ui.admin.overview.summary.oidc_clients",
labelFallback: "OIDC Clients",
value: "-",
hint: "Hydra registry",
hintKey: "msg.admin.overview.summary.oidc_clients",
hintFallback: "Hydra registry",
icon: ShieldCheck,
},
{
label: "Audit Events (24h)",
labelKey: "ui.admin.overview.summary.audit_events_24h",
labelFallback: "Audit Events (24h)",
value: "-",
hint: "ClickHouse stream",
hintKey: "msg.admin.overview.summary.audit_events_24h",
hintFallback: "ClickHouse stream",
icon: Activity,
},
{
label: "Policy Gate",
labelKey: "ui.admin.overview.summary.policy_gate",
labelFallback: "Policy Gate",
value: "Planned",
hint: "Keto + Admin checks",
hintKey: "msg.admin.overview.summary.policy_gate",
hintFallback: "Keto + Admin checks",
icon: Database,
},
];
@@ -50,44 +59,67 @@ function GlobalOverviewPage() {
<div className="flex flex-wrap items-start justify-between gap-4">
<div className="space-y-2">
<p className="text-xs uppercase tracking-[0.2em] text-[var(--color-muted)]">
Global Overview
{t("ui.admin.overview.kicker", "Global Overview")}
</p>
<h2 className="text-3xl font-semibold">
Tenant-independent control plane
{t("ui.admin.overview.title", "Tenant-independent control plane")}
</h2>
<p className="text-sm text-[var(--color-muted)]">
.
{t(
"msg.admin.overview.description",
"모든 테넌트 공통 지표와 정책 상태를 한 곳에서 확인합니다.",
)}
</p>
</div>
<div className="flex items-center gap-2">
<Badge variant="muted">IDP: Ory primary</Badge>
<Badge variant="muted">Fallback: Descope</Badge>
<Badge variant="muted">
{t("msg.admin.overview.idp_primary", "IDP: Ory primary")}
</Badge>
<Badge variant="muted">
{t("msg.admin.overview.idp_fallback", "Fallback: Descope")}
</Badge>
</div>
</div>
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
{summaryCards.map(({ label, value, hint, icon: Icon }) => (
<Card key={label} className="bg-[var(--color-panel)]">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardDescription>{label}</CardDescription>
<div className="rounded-full border border-[var(--color-border)] p-2 text-[var(--color-muted)]">
<Icon size={16} />
</div>
</CardHeader>
<CardContent>
<div className="text-2xl font-semibold">{value}</div>
<p className="mt-1 text-xs text-[var(--color-muted)]">{hint}</p>
</CardContent>
</Card>
))}
{summaryCards.map(
({
labelKey,
labelFallback,
value,
hintKey,
hintFallback,
icon: Icon,
}) => (
<Card key={labelKey} className="bg-[var(--color-panel)]">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardDescription>{t(labelKey, labelFallback)}</CardDescription>
<div className="rounded-full border border-[var(--color-border)] p-2 text-[var(--color-muted)]">
<Icon size={16} />
</div>
</CardHeader>
<CardContent>
<div className="text-2xl font-semibold">{value}</div>
<p className="mt-1 text-xs text-[var(--color-muted)]">
{t(hintKey, hintFallback)}
</p>
</CardContent>
</Card>
),
)}
</div>
<div className="grid gap-6 lg:grid-cols-[1.4fr,1fr]">
<Card className="bg-[var(--color-panel)]">
<CardHeader>
<CardTitle className="text-xl">Admin playbook</CardTitle>
<CardTitle className="text-xl">
{t("ui.admin.overview.playbook.title", "Admin playbook")}
</CardTitle>
<CardDescription>
, , .
{t(
"msg.admin.overview.playbook.description",
"운영 정책, 레이트리밋, 감사 로그의 기본 룰을 요약합니다.",
)}
</CardDescription>
</CardHeader>
<CardContent className="space-y-3 text-sm text-[var(--color-muted)]">
@@ -97,11 +129,16 @@ function GlobalOverviewPage() {
</div>
<div>
<p className="font-semibold text-foreground">
Backend-only IDP access
{t(
"msg.admin.overview.playbook.idp_title",
"Backend-only IDP access",
)}
</p>
<p>
IDP backend를 , Hydra/Kratos
admin .
{t(
"msg.admin.overview.playbook.idp_body",
"모든 IDP 호출은 backend를 통해서만 수행하며, Hydra/Kratos admin 포트는 외부에 노출하지 않습니다.",
)}
</p>
</div>
</div>
@@ -111,11 +148,16 @@ function GlobalOverviewPage() {
</div>
<div>
<p className="font-semibold text-foreground">
Tenant isolation
{t(
"msg.admin.overview.playbook.tenant_title",
"Tenant isolation",
)}
</p>
<p>
Tenant , Keto
.
{t(
"msg.admin.overview.playbook.tenant_body",
"Tenant 헤더와 감사 로그 규칙을 기본 적용하며, 향후 Keto 정책으로 확장 예정입니다.",
)}
</p>
</div>
</div>
@@ -124,9 +166,14 @@ function GlobalOverviewPage() {
<Card className="bg-[var(--color-panel)]">
<CardHeader>
<CardTitle className="text-xl"> </CardTitle>
<CardTitle className="text-xl">
{t("ui.admin.overview.quick_links.title", "빠른 이동")}
</CardTitle>
<CardDescription>
.
{t(
"msg.admin.overview.quick_links.description",
"주요 운영 화면으로 바로 이동합니다.",
)}
</CardDescription>
</CardHeader>
<CardContent className="space-y-3">
@@ -136,7 +183,7 @@ function GlobalOverviewPage() {
variant="outline"
>
<Link to="/tenants/new">
{t("ui.admin.overview.quick_links.add_tenant", "테넌트 추가")}
<ArrowUpRight size={16} />
</Link>
</Button>
@@ -146,7 +193,10 @@ function GlobalOverviewPage() {
variant="outline"
>
<Link to="/audit-logs">
{t(
"ui.admin.overview.quick_links.view_audit_logs",
"감사 로그 보기",
)}
<ArrowUpRight size={16} />
</Link>
</Button>
@@ -156,7 +206,10 @@ function GlobalOverviewPage() {
variant="outline"
>
<Link to="/dashboard">
{t(
"ui.admin.overview.quick_links.tenant_dashboard",
"테넌트 대시보드",
)}
<ArrowUpRight size={16} />
</Link>
</Button>