forked from baron/baron-sso
devfront: 개요 페이지 경로와 레이아웃 정리
This commit is contained in:
@@ -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 /> },
|
||||
|
||||
@@ -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;
|
||||
@@ -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"
|
||||
|
||||
@@ -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축: 기간"
|
||||
|
||||
@@ -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 = ""
|
||||
|
||||
Reference in New Issue
Block a user