260707_1_대시보드정리 1차
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
createButton,
|
||||
createCard,
|
||||
createInputField,
|
||||
createLineChart,
|
||||
createTag,
|
||||
hideLoadingOverlay,
|
||||
showLoadingOverlay,
|
||||
@@ -13,6 +14,7 @@ import {
|
||||
} from "@ui/ui_template_elements";
|
||||
import {
|
||||
addCompanyMember,
|
||||
changePassword,
|
||||
createCompany,
|
||||
fetchAllCompanies,
|
||||
fetchAllJoinRequests,
|
||||
@@ -40,6 +42,8 @@ import {
|
||||
} from "./B01_Dashboard_Api_Fetch";
|
||||
import "./B01_Dashboard_UI_Style.css";
|
||||
|
||||
const PASSWORD_MIN_LENGTH = 8;
|
||||
|
||||
function L(key: keyof typeof ui_locales): string {
|
||||
return ui_locales[key][currentLanguageIndex];
|
||||
}
|
||||
@@ -125,7 +129,7 @@ function buildPage(state: DashboardState): HTMLElement {
|
||||
|
||||
if (state.user.role === "SYSTEM_ADMIN") {
|
||||
grid.append(
|
||||
section(L("B01_Dashboard_Resources"), buildResourceMetrics(state.resources), true),
|
||||
section(L("B01_Dashboard_Resources"), buildResourcePanel(state.resources), true),
|
||||
section(L("B01_Dashboard_Companies"), companyTable(state.allCompanies)),
|
||||
section(L("B01_Dashboard_Users"), userTable(state.allUsers)),
|
||||
section(L("B01_Dashboard_JoinRequests"), joinRequestTable(state.allJoinRequests, true)),
|
||||
@@ -159,7 +163,10 @@ function buildPage(state: DashboardState): HTMLElement {
|
||||
);
|
||||
}
|
||||
}
|
||||
grid.append(section(L("B01_Dashboard_Profile"), buildProfileForm(state.user), true));
|
||||
grid.append(
|
||||
section(L("B01_Dashboard_Profile"), buildProfileForm(state.user)),
|
||||
section(L("B01_Account_Section_Security"), buildSecurityForm()),
|
||||
);
|
||||
page.append(grid);
|
||||
return page;
|
||||
}
|
||||
@@ -373,6 +380,13 @@ function actionPair(approve: () => void, reject: () => void): HTMLElement {
|
||||
return row;
|
||||
}
|
||||
|
||||
function buildResourcePanel(resources: ResourceData | null): HTMLElement {
|
||||
const wrap = document.createElement("div");
|
||||
wrap.className = "b01-dashboard__resource-panel";
|
||||
wrap.append(buildResourceMetrics(resources), buildResourceChart(resources));
|
||||
return wrap;
|
||||
}
|
||||
|
||||
function buildResourceMetrics(resources: ResourceData | null): HTMLElement {
|
||||
const values = resources?.current;
|
||||
const grid = document.createElement("div");
|
||||
@@ -399,6 +413,46 @@ function buildResourceMetrics(resources: ResourceData | null): HTMLElement {
|
||||
return grid;
|
||||
}
|
||||
|
||||
function formatChartTime(iso: string | null | undefined): string {
|
||||
if (!iso) return "";
|
||||
const d = new Date(iso);
|
||||
if (Number.isNaN(d.getTime())) return "";
|
||||
const pad = (n: number) => String(n).padStart(2, "0");
|
||||
return `${pad(d.getMonth() + 1)}/${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
||||
}
|
||||
|
||||
function buildResourceChart(resources: ResourceData | null): HTMLElement {
|
||||
const history = resources?.history ?? [];
|
||||
const chart = createLineChart({
|
||||
ariaLabel: L("B01_Dashboard_Resources_ChartAria"),
|
||||
xLabels: history.map((p) => formatChartTime(p.timestamp)),
|
||||
series: [
|
||||
{
|
||||
name: L("B01_Dashboard_Metric_Cpu"),
|
||||
colorIndex: 0,
|
||||
values: history.map((p) => p.cpu_usage_percent),
|
||||
},
|
||||
{
|
||||
name: L("B01_Dashboard_Metric_Memory"),
|
||||
colorIndex: 1,
|
||||
values: history.map((p) => p.memory_usage_percent),
|
||||
},
|
||||
{
|
||||
name: L("B01_Dashboard_Metric_Disk"),
|
||||
colorIndex: 2,
|
||||
values: history.map((p) => p.disk_usage_percent),
|
||||
},
|
||||
],
|
||||
});
|
||||
const caption = document.createElement("p");
|
||||
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);
|
||||
return box;
|
||||
}
|
||||
|
||||
function companyTable(companies: CompanyInfo[]): HTMLElement {
|
||||
return table(
|
||||
[
|
||||
@@ -478,6 +532,68 @@ function buildProfileForm(user: DashboardUser): HTMLElement {
|
||||
return wrap;
|
||||
}
|
||||
|
||||
function buildSecurityForm(): HTMLElement {
|
||||
const currentPassword = createInputField({
|
||||
label: L("B01_Account_Field_CurrentPw"),
|
||||
type: "password",
|
||||
required: true,
|
||||
});
|
||||
const newPassword = createInputField({
|
||||
label: L("B01_Account_Field_NewPw"),
|
||||
type: "password",
|
||||
required: true,
|
||||
});
|
||||
const confirmPassword = createInputField({
|
||||
label: L("B01_Account_Field_ConfirmPw"),
|
||||
type: "password",
|
||||
required: true,
|
||||
});
|
||||
const grid = document.createElement("div");
|
||||
grid.className = "b01-dashboard__form-grid";
|
||||
grid.append(currentPassword.root, newPassword.root, confirmPassword.root);
|
||||
const save = createButton({
|
||||
label: L("B01_Account_Save_Password"),
|
||||
variant: "ghost",
|
||||
onClick: async function onB01_Password_Save_Click() {
|
||||
currentPassword.setError();
|
||||
newPassword.setError();
|
||||
confirmPassword.setError();
|
||||
|
||||
const currentValue = currentPassword.input.value;
|
||||
const nextValue = newPassword.input.value;
|
||||
const confirmValue = confirmPassword.input.value;
|
||||
if (isBlank(currentValue) || isBlank(nextValue) || isBlank(confirmValue)) {
|
||||
currentPassword.setError(isBlank(currentValue) ? L("Common_Msg_RequiredField") : undefined);
|
||||
newPassword.setError(isBlank(nextValue) ? L("Common_Msg_RequiredField") : undefined);
|
||||
confirmPassword.setError(isBlank(confirmValue) ? L("Common_Msg_RequiredField") : undefined);
|
||||
return;
|
||||
}
|
||||
if (nextValue.length < PASSWORD_MIN_LENGTH) {
|
||||
newPassword.setError(L("B01_Account_Error_PwLength"));
|
||||
return;
|
||||
}
|
||||
if (nextValue !== confirmValue) {
|
||||
confirmPassword.setError(L("B01_Account_Error_PwMismatch"));
|
||||
return;
|
||||
}
|
||||
await runRequest(() =>
|
||||
changePassword({
|
||||
current_password: currentValue,
|
||||
new_password: nextValue,
|
||||
new_password_confirm: confirmValue,
|
||||
logout_all: false,
|
||||
}),
|
||||
);
|
||||
currentPassword.input.value = "";
|
||||
newPassword.input.value = "";
|
||||
confirmPassword.input.value = "";
|
||||
},
|
||||
});
|
||||
const wrap = document.createElement("div");
|
||||
wrap.append(grid, save);
|
||||
return wrap;
|
||||
}
|
||||
|
||||
function openCreateCompanyModal(): void {
|
||||
const name = createInputField({ label: L("B01_Dashboard_Table_Company"), required: true });
|
||||
const number = createInputField({
|
||||
|
||||
Reference in New Issue
Block a user