- 셸 = 위 머리 48(AISLO · 회사 이름 — 시스템 관리자 회사 전환 · 찾기 자리 · [?] · 알림 자리 · 사용자 메뉴) + 왼쪽 메뉴 210 + 챗봇 단추
- 등록부 B01_Dashboard_UI_Views.ts — { key, title, group, roles, icon, mount(host, ctx) } · 주소 ?view= · 같은 주소 안 이동 = 페이지만 갈아 끼움(MountedPage)
- 역할 넷(일반 · 회사 관리자 · 산림청 · 시스템 관리자) · 권한 없는 묶음 · 항목 숨김 · 권한 없는 열쇠 = 홈
- 열쇠마다 옛 구역 부품 그대로 얹음(B01_Dashboard_UI_Legacy.ts) — 기능 빠짐 0
- 옛 ☰ 서랍 · 구역 접기 · 회사 알약 걷음 — 테마 · 언어 · 터치 · 설정 · 로그아웃은 사용자 메뉴로
- 아이콘 = Tabler(MIT) 선 아이콘 몇 개(ui_template_icons.ts · 라이센스 글 함께)
- 시험 — test_b01_settings_cards 옛 한 페이지 단정(buildPage · 접힘 · 알약) 지움 · 셸 회사 고르기 단정으로 바꿈 · test_546_b01_shell 새로
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
287 lines
9.9 KiB
TypeScript
287 lines
9.9 KiB
TypeScript
/* =============================================================================
|
|
* B01_Dashboard_UI_Legacy.ts
|
|
* 옛 한 페이지 대시보드의 구역 부품을 세부 페이지에 그대로 얹음(546-1) — 기능 빠짐 0.
|
|
* 새 모양 페이지가 등록부(`B01_Dashboard_UI_Views.ts`) 줄을 갈아 끼우면 여기 그 구역은 지움.
|
|
* 자료 = 열 때마다 역할별로 다시 읽음(옛 화면이 주소 바뀔 때마다 다시 읽던 것과 같음).
|
|
* ========================================================================== */
|
|
|
|
import { navigateTo } from "../A00_Common/router";
|
|
import { settingLinks } from "../A00_Common/m_settings_nav";
|
|
import { createButton, hideLoadingOverlay, showLoadingOverlay } from "@ui/ui_template_elements";
|
|
import { section } from "@ui/ui_template_general_blocks";
|
|
import {
|
|
fetchAllCompanies,
|
|
fetchAllUsers,
|
|
fetchAuditLogs,
|
|
fetchCompanyJoinRequests,
|
|
fetchCompanyMembers,
|
|
fetchCompanyProjects,
|
|
fetchSystemResources,
|
|
fetchUserCompany,
|
|
fetchUserProjects,
|
|
type AuditLog,
|
|
type CompanyInfo,
|
|
type DashboardUser,
|
|
type JoinRequest,
|
|
type Member,
|
|
type ProjectItem,
|
|
type ResourceData,
|
|
} from "./B01_Dashboard_Api_Fetch";
|
|
import { auditLogTable, userTable } from "./B01_Dashboard_UI_Admin";
|
|
import {
|
|
assignedPlanTable,
|
|
fetchAssignedPlans,
|
|
type AssignedPlan,
|
|
} from "./B01_Dashboard_UI_AssignedPlans";
|
|
import { openCalcSitesDialog } from "./B01_Dashboard_UI_CalcSites";
|
|
import { L } from "./B01_Dashboard_UI_Common";
|
|
import {
|
|
buildCompanyPanel,
|
|
companyTable,
|
|
joinRequestTable,
|
|
memberTable,
|
|
} from "./B01_Dashboard_UI_Company";
|
|
import { openAddMemberModal, openCreateCompanyModal } from "./B01_Dashboard_UI_Modals";
|
|
import { openNewProjectPicker } from "./B01_Dashboard_UI_NewProject";
|
|
import { buildProfileForm, buildSecurityForm } from "./B01_Dashboard_UI_Profile";
|
|
import { projectTable } from "./B01_Dashboard_UI_Projects";
|
|
import { buildResourcePanel } from "./B01_Dashboard_UI_Resources";
|
|
import { buildTempUploadSection } from "./B01_Dashboard_UI_TempUpload";
|
|
|
|
export interface DashboardState {
|
|
user: DashboardUser;
|
|
userProjects: ProjectItem[];
|
|
companyProjects: ProjectItem[];
|
|
allProjects: ProjectItem[];
|
|
company: CompanyInfo | null;
|
|
members: Member[];
|
|
joinRequests: JoinRequest[];
|
|
allCompanies: CompanyInfo[];
|
|
allUsers: DashboardUser[];
|
|
allJoinRequests: JoinRequest[];
|
|
auditLogs: AuditLog[];
|
|
resources: ResourceData | null;
|
|
/** 우리 회사에 지정된 예정노선(528-2) — 회사관리자 · 사용자만 */
|
|
assignedPlans: AssignedPlan[];
|
|
/** 시스템 관리자가 고른 회사(29-1) — 프로젝트 · 사용자 · 가입 요청 · 회사 관리가 이 회사 것 */
|
|
adminCompanyId: number | null;
|
|
}
|
|
|
|
/** 고른 회사 id 자리 — M02 도 같은 키를 읽음(이름 바꾸지 않음) */
|
|
export const ADMIN_COMPANY_KEY = "aislo.adminCompany";
|
|
|
|
/** 고른 회사 — 저장값이 없거나 없는 회사면 자기 회사 */
|
|
export function pickAdminCompany(user: DashboardUser, companies: CompanyInfo[]): number | null {
|
|
const saved = Number(sessionStorage.getItem(ADMIN_COMPANY_KEY));
|
|
if (companies.some((c) => c.id === saved)) return saved;
|
|
return user.company_id ?? companies[0]?.id ?? null;
|
|
}
|
|
|
|
async function loadRoleData(state: DashboardState): Promise<void> {
|
|
if (state.user.role === "SYSTEM_ADMIN") {
|
|
// 회사 목록을 먼저 — 고른 회사를 가린 뒤 그 회사 것만 읽음(29-1)
|
|
state.allCompanies = await fetchAllCompanies().catch(() => []);
|
|
const companyId = pickAdminCompany(state.user, state.allCompanies);
|
|
state.adminCompanyId = companyId;
|
|
const results = await Promise.allSettled([
|
|
fetchAllUsers(companyId),
|
|
fetchCompanyJoinRequests(companyId),
|
|
fetchAuditLogs(),
|
|
fetchSystemResources(7),
|
|
fetchCompanyProjects(companyId),
|
|
]);
|
|
state.allUsers = results[0].status === "fulfilled" ? results[0].value : [];
|
|
state.allJoinRequests = results[1].status === "fulfilled" ? results[1].value : [];
|
|
state.auditLogs = results[2].status === "fulfilled" ? results[2].value : [];
|
|
state.resources = results[3].status === "fulfilled" ? results[3].value : null;
|
|
state.allProjects = results[4].status === "fulfilled" ? results[4].value : [];
|
|
|
|
results.forEach((res, idx) => {
|
|
if (res.status === "rejected") {
|
|
console.error(`System Admin API failed at index ${idx}:`, res.reason);
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
const [projects, company, assigned] = await Promise.all([
|
|
fetchUserProjects().catch(() => []),
|
|
fetchUserCompany().catch(() => null),
|
|
fetchAssignedPlans().catch(() => []),
|
|
]);
|
|
state.userProjects = projects;
|
|
state.company = company;
|
|
state.assignedPlans = assigned;
|
|
if (state.user.role === "ADMIN") {
|
|
const [members, requests, companyProjects] = await Promise.all([
|
|
fetchCompanyMembers().catch(() => []),
|
|
fetchCompanyJoinRequests().catch(() => []),
|
|
fetchCompanyProjects().catch(() => []),
|
|
]);
|
|
state.members = members;
|
|
state.joinRequests = requests;
|
|
state.companyProjects = companyProjects;
|
|
}
|
|
}
|
|
|
|
/** 설정 카드 공용 양식 — 제목 + 한 줄 설명 · 누르면 이동 */
|
|
function settingCard(title: string, desc: string, go: () => void): HTMLElement {
|
|
const card = document.createElement("button");
|
|
card.type = "button";
|
|
card.className = "b01-dashboard__setting-card";
|
|
const head = document.createElement("strong");
|
|
head.className = "b01-dashboard__setting-title";
|
|
head.textContent = title;
|
|
const sub = document.createElement("span");
|
|
sub.className = "b01-dashboard__setting-desc";
|
|
sub.textContent = desc;
|
|
card.append(head, sub);
|
|
card.addEventListener("click", go);
|
|
return card;
|
|
}
|
|
|
|
/** 설계 기본값 카드 — 카드 규칙은 `settingLinks` 한 벌(334) · 계산 자리 = 창(504-2) */
|
|
function buildSystemSettingsPanel(user: DashboardUser, companyId: number | null): HTMLElement {
|
|
const wrap = document.createElement("div");
|
|
wrap.className = "b01-dashboard__setting-grid";
|
|
wrap.append(
|
|
...settingLinks(user, companyId).map((link) =>
|
|
settingCard(link.title, link.desc, () =>
|
|
link.key === "calcSites" ? void openCalcSitesDialog() : navigateTo(link.route, link.query),
|
|
),
|
|
),
|
|
);
|
|
return wrap;
|
|
}
|
|
|
|
const addButton = (onClick: () => void): HTMLElement[] => [createButton({ label: "+", onClick })];
|
|
|
|
/** 열쇠별 옛 구역 — 역할 갈래는 옛 `buildPage` 그대로 */
|
|
const SECTIONS: Record<string, (s: DashboardState) => HTMLElement[]> = {
|
|
projects: (s) => {
|
|
const list =
|
|
s.user.role === "SYSTEM_ADMIN"
|
|
? s.allProjects
|
|
: s.user.role === "ADMIN"
|
|
? s.companyProjects
|
|
: s.userProjects;
|
|
return [
|
|
section(
|
|
L("B01_Dashboard_Projects"),
|
|
projectTable(list, s.user),
|
|
true,
|
|
addButton(() => void openNewProjectPicker()),
|
|
),
|
|
];
|
|
},
|
|
assigned: (s) => [section(L("DE_Assigned_Title"), assignedPlanTable(s.assignedPlans), true)],
|
|
temp: () => [buildTempUploadSection()],
|
|
people: (s) =>
|
|
s.user.role === "SYSTEM_ADMIN"
|
|
? [
|
|
section(
|
|
L("B01_Dashboard_Users"),
|
|
userTable(s.allUsers, s.user),
|
|
true,
|
|
addButton(() => openAddMemberModal(undefined, s.adminCompanyId)),
|
|
),
|
|
section(L("B01_Dashboard_JoinRequests"), joinRequestTable(s.allJoinRequests, true), true),
|
|
]
|
|
: [
|
|
section(
|
|
L("B01_Dashboard_Members"),
|
|
memberTable(s.members, s.user),
|
|
true,
|
|
addButton(() => openAddMemberModal()),
|
|
),
|
|
section(L("B01_Dashboard_JoinRequests"), joinRequestTable(s.joinRequests, false), true),
|
|
],
|
|
company: (s) =>
|
|
s.user.role === "SYSTEM_ADMIN"
|
|
? [
|
|
section(
|
|
L("B01_Dashboard_Companies"),
|
|
companyTable(
|
|
s.allCompanies.filter((c) => c.id === s.adminCompanyId),
|
|
s.user,
|
|
),
|
|
true,
|
|
),
|
|
]
|
|
: [section(L("B01_Dashboard_Company"), buildCompanyPanel(s), true)],
|
|
companyDefaults: (s) => [
|
|
section(
|
|
L("B01_Dashboard_SystemSettings"),
|
|
buildSystemSettingsPanel(s.user, s.adminCompanyId),
|
|
true,
|
|
),
|
|
],
|
|
sysOverview: (s) => [
|
|
section(L("B01_Dashboard_Resources"), buildResourcePanel(s.resources), true),
|
|
],
|
|
sysCompanies: (s) => [
|
|
section(
|
|
L("B01_Dashboard_Companies"),
|
|
companyTable(s.allCompanies, s.user),
|
|
true,
|
|
addButton(() => openCreateCompanyModal()),
|
|
),
|
|
],
|
|
sysUsers: (s) => [
|
|
section(
|
|
L("B01_Dashboard_Users"),
|
|
userTable(s.allUsers, s.user),
|
|
true,
|
|
addButton(() => openAddMemberModal(undefined, s.adminCompanyId)),
|
|
),
|
|
],
|
|
sysDefaults: (s) => [
|
|
section(
|
|
L("B01_Dashboard_SystemSettings"),
|
|
buildSystemSettingsPanel(s.user, s.adminCompanyId),
|
|
true,
|
|
),
|
|
],
|
|
sysLogs: (s) => [section(L("B01_Dashboard_AuditLogs"), auditLogTable(s.auditLogs), true)],
|
|
me: (s) => [
|
|
section(L("B01_Dashboard_Profile"), buildProfileForm(s.user), true),
|
|
section(L("B01_Account_Section_Security"), buildSecurityForm(), true),
|
|
],
|
|
};
|
|
|
|
export type LegacyKey = keyof typeof SECTIONS;
|
|
|
|
/** 옛 구역을 host 에 얹음 — 자료를 다 읽은 뒤 그림 · 그 사이 떠났으면(host 떨어짐) 안 그림 */
|
|
export async function mountLegacy(
|
|
key: LegacyKey,
|
|
host: HTMLElement,
|
|
me: DashboardUser,
|
|
): Promise<void> {
|
|
const state: DashboardState = {
|
|
user: me,
|
|
userProjects: [],
|
|
companyProjects: [],
|
|
allProjects: [],
|
|
company: null,
|
|
members: [],
|
|
joinRequests: [],
|
|
allCompanies: [],
|
|
allUsers: [],
|
|
allJoinRequests: [],
|
|
auditLogs: [],
|
|
resources: null,
|
|
assignedPlans: [],
|
|
adminCompanyId: null,
|
|
};
|
|
showLoadingOverlay();
|
|
try {
|
|
await loadRoleData(state);
|
|
} finally {
|
|
hideLoadingOverlay();
|
|
}
|
|
if (!host.isConnected) return;
|
|
const grid = document.createElement("div");
|
|
grid.className = "b01-dashboard__grid";
|
|
grid.append(...SECTIONS[key](state));
|
|
host.append(grid);
|
|
}
|