1
0
forked from baron/baron-sso

devfront: 개요 페이지 경로와 레이아웃 정리

This commit is contained in:
2026-05-14 17:01:50 +09:00
parent c0894eeb8a
commit 0327409631
5 changed files with 26 additions and 72 deletions

View File

@@ -9,7 +9,7 @@ import ClientDetailsPage from "../features/clients/ClientDetailsPage";
import ClientGeneralPage from "../features/clients/ClientGeneralPage";
import ClientRelationsPage from "../features/clients/ClientRelationsPage";
import ClientsPage from "../features/clients/ClientsPage";
import DashboardPage from "../features/dashboard/DashboardPage";
import GlobalOverviewPage from "../features/overview/GlobalOverviewPage";
import DeveloperRequestPage from "../features/developer-request/DeveloperRequestPage";
import ProfilePage from "../features/profile/ProfilePage";
import { DEVFRONT_AUTH_CALLBACK_PATH } from "../lib/authConfig";
@@ -30,7 +30,7 @@ export const devFrontRoutes: RouteObject[] = [
{
element: <AppLayout />,
children: [
{ index: true, element: <DashboardPage /> },
{ index: true, element: <GlobalOverviewPage /> },
{ path: "clients", element: <ClientsPage /> },
{ path: "clients/new", element: <ClientGeneralPage /> },
{ path: "clients/:id", element: <ClientDetailsPage /> },

View File

@@ -8,7 +8,7 @@ import {
Layers3,
ShieldCheck,
} from "lucide-react";
import { type ReactNode, useMemo, useState } from "react";
import { useMemo, useState } from "react";
import { useAuth } from "react-oidc-context";
import { useNavigate } from "react-router-dom";
import {
@@ -22,6 +22,11 @@ import {
} from "../../lib/devApi";
import { t } from "../../lib/i18n";
import { resolveProfileRole } from "../../lib/role";
import {
OverviewAxisNotes,
OverviewMetric,
OverviewSelectionChips,
} from "../../../../common/core/components/overview";
type ClientDistribution = {
activeClients: number;
@@ -261,24 +266,6 @@ function formatMetric(value: number | undefined) {
return value === undefined ? "-" : value.toLocaleString();
}
function OverviewMetric({
icon,
label,
value,
}: {
icon: ReactNode;
label: string;
value: string;
}) {
return (
<span className="inline-flex items-center gap-2 whitespace-nowrap text-sm">
<span className="text-muted-foreground">{icon}</span>
<span className="text-muted-foreground">{label}</span>
<span className="font-semibold tabular-nums">{value}</span>
</span>
);
}
function RPUsageMixedChart({
period,
rows,
@@ -425,10 +412,10 @@ function RPUsageMixedChart({
</svg>
</div>
<div className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-muted-foreground">
<span>{t("ui.dev.dashboard.chart.x_axis", "X축: 기간")}</span>
<span>{t("ui.dev.dashboard.chart.y_axis", "Y축: 로그인 요청 수")}</span>
</div>
<OverviewAxisNotes
xAxisLabel={t("ui.common.chart.axis.x", "X축: 기간")}
yAxisLabel={t("ui.common.chart.axis.y", "Y축: 로그인 요청 수")}
/>
{multiLinePoints && multiLinePoints.length > 0 ? (
<div className="grid gap-x-6 gap-y-2 border-t border-border/60 pt-2 text-xs md:grid-cols-2 xl:grid-cols-3">
@@ -486,7 +473,7 @@ function RPUsageMixedChart({
);
}
function DashboardPage() {
function GlobalOverviewPage() {
const navigate = useNavigate();
const auth = useAuth();
const hasAccessToken = Boolean(auth.user?.access_token);
@@ -633,7 +620,7 @@ function DashboardPage() {
<div className="rounded-xl border border-border/60 bg-card p-8 text-center">
<div className="space-y-3">
<h2 className="text-2xl font-semibold tracking-tight">
{t("ui.dev.dashboard.title", "대시보드")}
{t("ui.common.overview.title", "운영 현황")}
</h2>
<p className="font-medium text-foreground">
{isDeveloperRequestPending
@@ -678,7 +665,7 @@ function DashboardPage() {
<div className="flex flex-wrap items-end justify-between gap-4">
<div className="space-y-1">
<h2 className="text-2xl font-semibold tracking-tight">
{t("ui.dev.dashboard.title", "Dashboard")}
{t("ui.common.overview.title", "운영 현황")}
</h2>
<p className="text-sm text-muted-foreground">
{t(
@@ -736,9 +723,9 @@ function DashboardPage() {
</div>
<div className="flex h-8 items-center gap-1" aria-label="집계 단위">
{[
["day", t("ui.dev.dashboard.chart.period_day", "일")],
["week", t("ui.dev.dashboard.chart.period_week", "주")],
["month", t("ui.dev.dashboard.chart.period_month", "월")],
["day", t("ui.common.chart.period.day", "일")],
["week", t("ui.common.chart.period.week", "주")],
["month", t("ui.common.chart.period.month", "월")],
].map(([value, label]) => (
<button
key={value}
@@ -757,31 +744,13 @@ function DashboardPage() {
</div>
</div>
<div className="flex flex-wrap gap-2 rounded-xl border border-border/60 bg-card/60 p-3">
<label className="inline-flex items-center gap-2 rounded-full border border-border/60 px-3 py-1.5 text-xs">
<input
type="checkbox"
checked={isAllClientsSelected}
onChange={selectAllClients}
className="h-3.5 w-3.5"
/>
<span>{t("ui.dev.dashboard.chart.filter_all", "전체")}</span>
</label>
{clientFilterOptions.map((client) => (
<label
key={client.id}
className="inline-flex items-center gap-2 rounded-full border border-border/60 px-3 py-1.5 text-xs"
>
<input
type="checkbox"
checked={selectedClientIds.includes(client.id)}
onChange={() => toggleClientSelection(client.id)}
className="h-3.5 w-3.5"
/>
<span>{client.label}</span>
</label>
))}
</div>
<OverviewSelectionChips
allLabel={t("ui.dev.dashboard.chart.filter_all", "전체")}
options={clientFilterOptions}
selectedIds={selectedClientIds}
onSelectAll={selectAllClients}
onToggle={toggleClientSelection}
/>
{usageQuery.isError ? (
<div className="text-sm text-muted-foreground">{usageErrorText}</div>
@@ -910,4 +879,4 @@ function DashboardPage() {
);
}
export default DashboardPage;
export default GlobalOverviewPage;

View File

@@ -967,7 +967,6 @@ start_import = "Start Import"
[ui.admin.overview]
kicker = "Global Overview"
title = "Tenant-independent control plane"
[ui.admin.overview.playbook]
title = "Admin playbook"
@@ -1658,7 +1657,6 @@ private_headless = "Server side App (Headless Login)"
[ui.dev.dashboard]
ready_badge = "devfront ready"
title = "Dashboard"
[ui.dev.dashboard.badge]
consent_guard = "Consent guard ready"
@@ -1676,9 +1674,6 @@ title = "Application Distribution"
[ui.dev.dashboard.chart]
aria = "RP request overview"
filter_all = "All"
period_day = "Day"
period_month = "Month"
period_week = "Week"
series = "Login {{login}} / Users {{subjects}}"
title = "Login requests by application"
x_axis = "X-axis: Period"

View File

@@ -967,7 +967,6 @@ start_import = "임포트 시작"
[ui.admin.overview]
kicker = "Global Overview"
title = "Tenant-independent control plane"
[ui.admin.overview.playbook]
title = "Admin playbook"
@@ -1657,7 +1656,6 @@ private_headless = "Server side App (Headless Login)"
[ui.dev.dashboard]
ready_badge = "devfront ready"
title = "대시보드"
[ui.dev.dashboard.badge]
consent_guard = "Consent guard ready"
@@ -1675,9 +1673,6 @@ title = "애플리케이션 구성 요약"
[ui.dev.dashboard.chart]
aria = "RP 요청 현황"
filter_all = "전체"
period_day = "일"
period_month = "월"
period_week = "주"
series = "로그인 {{login}} / 사용자 {{subjects}}"
title = "애플리케이션별 로그인 요청 현황"
x_axis = "X축: 기간"

View File

@@ -1006,7 +1006,6 @@ start_import = ""
[ui.admin.overview]
kicker = ""
title = ""
[ui.admin.overview.playbook]
title = ""
@@ -1714,7 +1713,6 @@ private_headless = ""
[ui.dev.dashboard]
ready_badge = ""
title = ""
[ui.dev.dashboard.badge]
consent_guard = ""
@@ -1732,9 +1730,6 @@ title = ""
[ui.dev.dashboard.chart]
aria = ""
filter_all = ""
period_day = ""
period_month = ""
period_week = ""
series = ""
title = ""
x_axis = ""