260707_3
This commit is contained in:
@@ -133,42 +133,49 @@ function buildPage(state: DashboardState): HTMLElement {
|
|||||||
grid.className = "b01-dashboard__grid";
|
grid.className = "b01-dashboard__grid";
|
||||||
|
|
||||||
if (state.user.role === "SYSTEM_ADMIN") {
|
if (state.user.role === "SYSTEM_ADMIN") {
|
||||||
|
// 순서: 리소스 현황(최상단), 프로젝트, 사용자 관리(사용자), 가입요청(1행 전체), 회사관리(회사목록), 시스템 로그(감사로그), 기본정보(프로필), 보안
|
||||||
grid.append(
|
grid.append(
|
||||||
section(L("B01_Dashboard_Resources"), buildResourcePanel(state.resources), true),
|
section(L("B01_Dashboard_Resources"), buildResourcePanel(state.resources), true),
|
||||||
section(L("B01_Dashboard_Companies"), companyTable(state.allCompanies), true),
|
|
||||||
section(L("B01_Dashboard_Users"), userTable(state.allUsers), true),
|
|
||||||
section(L("B01_Dashboard_Projects"), projectTable(state.allProjects), true),
|
section(L("B01_Dashboard_Projects"), projectTable(state.allProjects), true),
|
||||||
section(L("B01_Dashboard_JoinRequests"), joinRequestTable(state.allJoinRequests, true)),
|
section(L("B01_Dashboard_Users"), userTable(state.allUsers), true),
|
||||||
|
section(L("B01_Dashboard_JoinRequests"), joinRequestTable(state.allJoinRequests, true), true),
|
||||||
|
section(L("B01_Dashboard_Companies"), companyTable(state.allCompanies), true),
|
||||||
section(L("B01_Dashboard_AuditLogs"), auditLogTable(state.auditLogs), true),
|
section(L("B01_Dashboard_AuditLogs"), auditLogTable(state.auditLogs), true),
|
||||||
);
|
);
|
||||||
} else {
|
} else if (state.user.role === "ADMIN") {
|
||||||
|
// 순서: 프로젝트, 사용자 관리(멤버), 가입요청(1행 전체), 회사관리(회사패널), 기본정보(프로필), 보안
|
||||||
grid.append(
|
grid.append(
|
||||||
section(
|
section(L("B01_Dashboard_Projects"), projectTable(state.companyProjects), true, [
|
||||||
L("B01_Dashboard_Projects"),
|
|
||||||
projectTable(state.user.role === "ADMIN" ? state.companyProjects : state.userProjects),
|
|
||||||
true,
|
|
||||||
[
|
|
||||||
createButton({
|
createButton({
|
||||||
label: L("B01_Dashboard_NewProject"),
|
label: L("B01_Dashboard_NewProject"),
|
||||||
onClick: () => navigateTo(ROUTES.B02_PROJ_REGISTER),
|
onClick: () => navigateTo(ROUTES.B02_PROJ_REGISTER),
|
||||||
}),
|
}),
|
||||||
],
|
]),
|
||||||
),
|
section(L("B01_Dashboard_Members"), memberTable(state.members), true, [
|
||||||
section(L("B01_Dashboard_Company"), buildCompanyPanel(state)),
|
|
||||||
);
|
|
||||||
if (state.user.role === "ADMIN") {
|
|
||||||
grid.append(
|
|
||||||
section(L("B01_Dashboard_Members"), memberTable(state.members), false, [
|
|
||||||
createButton({
|
createButton({
|
||||||
label: L("B01_Dashboard_AddMember"),
|
label: L("B01_Dashboard_AddMember"),
|
||||||
variant: "ghost",
|
variant: "ghost",
|
||||||
onClick: () => openAddMemberModal(),
|
onClick: () => openAddMemberModal(),
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
section(L("B01_Dashboard_JoinRequests"), joinRequestTable(state.joinRequests, false)),
|
section(L("B01_Dashboard_JoinRequests"), joinRequestTable(state.joinRequests, false), true),
|
||||||
|
section(L("B01_Dashboard_Company"), buildCompanyPanel(state), true),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// 일반 사용자 (USER)
|
||||||
|
// 순서: 프로젝트, 회사관리(회사패널), 기본정보(프로필), 보안
|
||||||
|
grid.append(
|
||||||
|
section(L("B01_Dashboard_Projects"), projectTable(state.userProjects), true, [
|
||||||
|
createButton({
|
||||||
|
label: L("B01_Dashboard_NewProject"),
|
||||||
|
onClick: () => navigateTo(ROUTES.B02_PROJ_REGISTER),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
section(L("B01_Dashboard_Company"), buildCompanyPanel(state), true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// 기본정보 (프로필) & 보안 순서
|
||||||
grid.append(
|
grid.append(
|
||||||
section(L("B01_Dashboard_Profile"), buildProfileForm(state.user)),
|
section(L("B01_Dashboard_Profile"), buildProfileForm(state.user)),
|
||||||
section(L("B01_Account_Section_Security"), buildSecurityForm()),
|
section(L("B01_Account_Section_Security"), buildSecurityForm()),
|
||||||
@@ -432,10 +439,23 @@ function formatChartTime(iso: string | null | undefined): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function buildResourceChart(resources: ResourceData | null): HTMLElement {
|
function buildResourceChart(resources: ResourceData | null): HTMLElement {
|
||||||
|
const box = document.createElement("div");
|
||||||
|
box.className = "b01-dashboard__chart";
|
||||||
|
|
||||||
|
const caption = document.createElement("p");
|
||||||
|
caption.className = "b01-dashboard__chart-caption";
|
||||||
|
caption.textContent = L("B01_Dashboard_Resources_ChartCaption");
|
||||||
|
box.append(caption);
|
||||||
|
|
||||||
|
const chartWrap = document.createElement("div");
|
||||||
|
chartWrap.className = "b01-dashboard__chart-content";
|
||||||
|
box.append(chartWrap);
|
||||||
|
|
||||||
const history = resources?.history ?? [];
|
const history = resources?.history ?? [];
|
||||||
|
|
||||||
// 7일간의 고정 타임라인 생성 (4시간 간격, 총 43개 포인트)
|
// 7일간의 고정 타임라인 생성 (4시간 간격, 총 43개 포인트)
|
||||||
const points: { timestamp: Date; cpu: number | null; mem: number | null; disk: number | null }[] = [];
|
const points: { timestamp: Date; cpu: number | null; mem: number | null; disk: number | null }[] =
|
||||||
|
[];
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
// 12시간 단위(정오 또는 자정)로 올림 정렬하여 기준점 계산
|
// 12시간 단위(정오 또는 자정)로 올림 정렬하여 기준점 계산
|
||||||
@@ -446,7 +466,7 @@ function buildResourceChart(resources: ResourceData | null): HTMLElement {
|
|||||||
now.getHours() >= 12 ? 24 : 12,
|
now.getHours() >= 12 ? 24 : 12,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
for (let i = 0; i <= 42; i++) {
|
for (let i = 0; i <= 42; i++) {
|
||||||
@@ -491,10 +511,22 @@ function buildResourceChart(resources: ResourceData | null): HTMLElement {
|
|||||||
return "";
|
return "";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let resizeTimeout: number | null = null;
|
||||||
|
const observer = new ResizeObserver((entries) => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
const width = Math.floor(entry.contentRect.width);
|
||||||
|
if (width <= 0) continue;
|
||||||
|
|
||||||
|
if (resizeTimeout) {
|
||||||
|
window.cancelAnimationFrame(resizeTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
resizeTimeout = window.requestAnimationFrame(() => {
|
||||||
|
chartWrap.innerHTML = "";
|
||||||
const chart = createLineChart({
|
const chart = createLineChart({
|
||||||
ariaLabel: L("B01_Dashboard_Resources_ChartAria"),
|
ariaLabel: L("B01_Dashboard_Resources_ChartAria"),
|
||||||
xLabels,
|
xLabels,
|
||||||
width: 800,
|
width: width,
|
||||||
height: 140,
|
height: 140,
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
@@ -514,12 +546,13 @@ function buildResourceChart(resources: ResourceData | null): HTMLElement {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
const caption = document.createElement("p");
|
chartWrap.append(chart);
|
||||||
caption.className = "b01-dashboard__chart-caption";
|
});
|
||||||
caption.textContent = L("B01_Dashboard_Resources_ChartCaption");
|
}
|
||||||
const box = document.createElement("div");
|
});
|
||||||
box.className = "b01-dashboard__chart";
|
|
||||||
box.append(caption, chart);
|
observer.observe(box);
|
||||||
|
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -699,11 +699,11 @@ const BASE_CSS = `
|
|||||||
}
|
}
|
||||||
.ui-chart__tick {
|
.ui-chart__tick {
|
||||||
fill: var(--color-text-muted);
|
fill: var(--color-text-muted);
|
||||||
font-size: 10px;
|
font-size: 12px;
|
||||||
font-family: var(--font-body);
|
font-family: var(--font-body);
|
||||||
}
|
}
|
||||||
.ui-chart__tick--x {
|
.ui-chart__tick--x {
|
||||||
font-size: 9px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
.ui-chart__line {
|
.ui-chart__line {
|
||||||
fill: none;
|
fill: none;
|
||||||
|
|||||||
Reference in New Issue
Block a user