forked from baron/baron-sso
i18n refresh and frontend fixes
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user