1. Restructured navigation hierarchy (Hardware, Software, Ops Support, etc.). 2. Customized table columns for all asset categories according to new specs. 3. Moved Template/Upload/Export/Add buttons to search bar with layout optimization. 4. Hidden Asset Code and Previous User from list views (Modal only). 5. Added Current/Previous User and detailed PC spec fields (GPU, HDD3/4).
168 lines
6.7 KiB
TypeScript
168 lines
6.7 KiB
TypeScript
import { state, loadMasterDataFromDB, saveAsset } from './core/state';
|
|
import { renderNavigation } from './components/Navigation';
|
|
import { renderDashboard } from './views/DashboardView';
|
|
import { renderSWTable } from './views/SW_Table';
|
|
import { downloadTemplate, exportToExcel, parseExcel } from './core/excelHandler';
|
|
import { initBaseModal } from './components/Modal/BaseModal';
|
|
import { initHwModal, openHwModal } from './components/Modal/HWModal';
|
|
import { initSwModal, openSwModal } from './components/Modal/SWModal';
|
|
import { initSwUserModal } from './components/Modal/SWUserModal';
|
|
import { initDomainModal, openDomainModal } from './components/Modal/DomainModal';
|
|
import { initUploadPreviewModal, openUploadPreview } from './components/Modal/UploadPreviewModal';
|
|
import { initDashboardDetailModal } from './components/Modal/DashboardDetailModal';
|
|
import { initGuide } from './components/Guide';
|
|
import { createIcons, Download, Upload, FileSpreadsheet, Plus, X, LayoutDashboard, Monitor, Server, Database, Laptop, CalendarClock, Key, Cpu, Layers, Users, Paperclip, Edit2, History, RefreshCcw, BookOpen, Settings } from 'lucide';
|
|
|
|
// --- DB 저장을 위한 세분화된 헬퍼 함수들 ---
|
|
async function apiBatchSave(url: string, data: any[], label: string) {
|
|
try {
|
|
const response = await fetch(url, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(data)
|
|
});
|
|
if (!response.ok) {
|
|
const errorData = await response.json().catch(() => ({}));
|
|
throw new Error(`${label} DB 저장 실패: ${errorData.error || response.statusText}`);
|
|
}
|
|
console.log(`✅ ${label} DB 저장 완료`);
|
|
} catch (err) {
|
|
console.error(`❌ ${label} DB 저장 오류:`, err);
|
|
alert(`${label} 저장 중 오류가 발생했습니다: ${(err as any).message}`);
|
|
}
|
|
}
|
|
|
|
const savePcToDB = () => apiBatchSave(`http://${location.hostname}:3000/api/pc/batch`, state.masterData.pc, '개인PC');
|
|
const saveServerToDB = () => apiBatchSave(`http://${location.hostname}:3000/api/server/batch`, state.masterData.server, '서버');
|
|
const saveStorageToDB = () => apiBatchSave(`http://${location.hostname}:3000/api/storage/batch`, state.masterData.storage, '스토리지');
|
|
const saveNetworkToDB = () => apiBatchSave(`http://${location.hostname}:3000/api/network/batch`, state.masterData.network, '네트워크');
|
|
const saveEquipToDB = () => apiBatchSave(`http://${location.hostname}:3000/api/equipment/batch`, state.masterData.equipment, '업무지원장비');
|
|
const saveSwInternalToDB = () => apiBatchSave(`http://${location.hostname}:3000/api/sw/internal/batch`, state.masterData.swInternal, '내부SW');
|
|
const saveSwExternalToDB = () => apiBatchSave(`http://${location.hostname}:3000/api/sw/external/batch`, state.masterData.swExternal, '외부SW');
|
|
const saveCloudToDB = () => apiBatchSave(`http://${location.hostname}:3000/api/cloud/batch`, state.masterData.cloud, '클라우드');
|
|
const saveSwUsersToDB = () => apiBatchSave(`http://${location.hostname}:3000/api/asset/software/assignment/batch`, state.masterData.swUsers, 'SW사용자');
|
|
const saveLogsToDB = () => apiBatchSave(`http://${location.hostname}:3000/api/asset/history/batch`, state.masterData.logs, '자산 로그');
|
|
|
|
// 화면 갱신 통합 핸들러
|
|
function refreshView() {
|
|
const mainContent = document.getElementById('main-content')!;
|
|
if (!mainContent) return;
|
|
|
|
if (state.activeSubTab === '대시보드') {
|
|
renderDashboard(mainContent);
|
|
} else {
|
|
renderSWTable(mainContent);
|
|
}
|
|
}
|
|
|
|
// 통합 저장 및 갱신
|
|
async function saveAllDataToDB() {
|
|
await Promise.all([
|
|
savePcToDB(), saveServerToDB(), saveStorageToDB(), saveNetworkToDB(),
|
|
saveEquipToDB(), saveSwInternalToDB(), saveSwExternalToDB(),
|
|
saveCloudToDB(), saveSwUsersToDB(), saveLogsToDB()
|
|
]);
|
|
await loadMasterDataFromDB();
|
|
refreshView();
|
|
}
|
|
|
|
// --- App Initialization ---
|
|
function initApp() {
|
|
const mainContent = document.getElementById('main-content')!;
|
|
if (!mainContent) return;
|
|
|
|
const { closeAllModals } = initBaseModal();
|
|
|
|
try {
|
|
renderNavigation((tab) => {
|
|
if (tab === '대시보드') {
|
|
renderDashboard(mainContent);
|
|
} else {
|
|
renderSWTable(mainContent);
|
|
}
|
|
});
|
|
|
|
initHwModal(() => saveAllDataToDB(), closeAllModals);
|
|
initSwModal(() => saveAllDataToDB(), closeAllModals);
|
|
|
|
initSwUserModal(() => {
|
|
saveSwUsersToDB().then(() => {
|
|
loadMasterDataFromDB().then(() => refreshView());
|
|
});
|
|
}, closeAllModals);
|
|
|
|
initDashboardDetailModal();
|
|
initDomainModal();
|
|
initUploadPreviewModal(async () => {
|
|
await loadMasterDataFromDB();
|
|
refreshView();
|
|
});
|
|
initGuide();
|
|
|
|
loadMasterDataFromDB().then((success) => {
|
|
if (success) {
|
|
refreshView();
|
|
}
|
|
});
|
|
} catch (e) { console.error('❌ Initialization failed:', e); }
|
|
|
|
console.log('🚀 ITAM App Multi-Table Optimized');
|
|
|
|
// --- 통합 이벤트 위임 (Dynamic Elements 지원) ---
|
|
document.addEventListener('click', (e) => {
|
|
const target = e.target as HTMLElement;
|
|
|
|
// 양식 다운로드
|
|
if (target.closest('#btn-download-template')) {
|
|
downloadTemplate();
|
|
return;
|
|
}
|
|
|
|
// 엑셀 내보내기
|
|
if (target.closest('#btn-export-excel')) {
|
|
exportToExcel(state.masterData);
|
|
return;
|
|
}
|
|
|
|
// 자산 추가
|
|
if (target.closest('#btn-add-asset')) {
|
|
const tab = state.activeSubTab;
|
|
const cat = state.activeCategory;
|
|
const newId = Math.random().toString(36).substring(2, 9);
|
|
|
|
if (cat === 'hw') {
|
|
openHwModal({ id: newId, asset_code: '', category: tab } as any, 'add');
|
|
} else if (cat === 'sw') {
|
|
openSwModal({ id: newId, asset_type: tab === '대시보드' ? '외부SW' : tab } as any, 'add');
|
|
} else if (cat === 'ops') {
|
|
if (tab === '도메인') openDomainModal(null);
|
|
}
|
|
return;
|
|
}
|
|
});
|
|
|
|
// 엑셀 업로드 (Change 이벤트 위임)
|
|
document.addEventListener('change', async (e) => {
|
|
const target = e.target as HTMLInputElement;
|
|
if (target.id === 'excel-upload') {
|
|
const file = target.files?.[0];
|
|
if (file) {
|
|
try {
|
|
const data = await parseExcel(file);
|
|
openUploadPreview(data);
|
|
target.value = '';
|
|
} catch (err) {
|
|
alert('엑셀 파일을 읽는 중 오류가 발생했습니다.');
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
createIcons({
|
|
icons: { Download, Upload, FileSpreadsheet, Plus, X, LayoutDashboard, Monitor, Server, Database, Laptop, CalendarClock, Key, Cpu, Layers, Users, Paperclip, Edit2, History, RefreshCcw, BookOpen, Settings }
|
|
});
|
|
window.addEventListener('refresh-view', () => refreshView());
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', initApp);
|