353 lines
17 KiB
TypeScript
353 lines
17 KiB
TypeScript
import { state } from '../../core/state';
|
|
import { HardwareAsset } from '../../core/excelHandler';
|
|
import { createIcons, Paperclip } from 'lucide';
|
|
|
|
let currentAsset: HardwareAsset | null = null;
|
|
let isEditMode = false;
|
|
|
|
const HW_MODAL_HTML = `
|
|
<div id="hw-asset-modal" class="modal-overlay hidden">
|
|
<div class="modal-content wide">
|
|
<div class="modal-header">
|
|
<h2 id="hw-modal-title">자산 상세 정보</h2>
|
|
<button id="btn-close-hw-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="hw-asset-form" class="grid-form">
|
|
<input type="hidden" id="hw-asset-id" />
|
|
<input type="hidden" id="hw-asset-type" />
|
|
|
|
<!-- Group 1: 기본 정보 -->
|
|
<div class="form-section-title">기본 정보 (Identity)</div>
|
|
<div class="form-group">
|
|
<label for="hw-법인">구매법인</label>
|
|
<input type="text" id="hw-법인" required />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="hw-자산코드">자산번호/코드</label>
|
|
<input type="text" id="hw-자산코드" required />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="hw-구매일">구매일자</label>
|
|
<input type="text" id="hw-구매일" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="hw-현사용조직">현 사용조직</label>
|
|
<input type="text" id="hw-현사용조직" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="hw-이전사용조직">이전 사용조직</label>
|
|
<input type="text" id="hw-이전사용조직" />
|
|
</div>
|
|
<div class="form-group server-only">
|
|
<label for="hw-용도">용도</label>
|
|
<input type="text" id="hw-용도" />
|
|
</div>
|
|
<div class="form-group server-only">
|
|
<label for="hw-상세">상세 내용</label>
|
|
<input type="text" id="hw-상세" />
|
|
</div>
|
|
<div class="form-group non-server">
|
|
<label for="hw-명칭">명칭</label>
|
|
<input type="text" id="hw-명칭" />
|
|
</div>
|
|
<div class="form-group full-width server-only">
|
|
<label for="hw-비고">비고</label>
|
|
<input type="text" id="hw-비고" />
|
|
</div>
|
|
|
|
<!-- Group 2: 네트워크 정보 -->
|
|
<div class="form-section-title server-only">네트워크 정보 (Connectivity) <span class="badge-security" style="margin-left: 0.5rem;">보안 정보</span></div>
|
|
<div class="form-group server-only">
|
|
<label for="hw-IP주소">IP 주소 1</label>
|
|
<input type="text" id="hw-IP주소" />
|
|
</div>
|
|
<div class="form-group server-only">
|
|
<label for="hw-IP2">IP 주소 2</label>
|
|
<input type="text" id="hw-IP2" />
|
|
</div>
|
|
<div class="form-group server-only">
|
|
<label for="hw-원격접속">원격 도구</label>
|
|
<input type="text" id="hw-원격접속" />
|
|
</div>
|
|
<div class="form-group server-only">
|
|
<label for="hw-서버ID">서버 ID</label>
|
|
<input type="text" id="hw-서버ID" />
|
|
</div>
|
|
<div class="form-group server-only">
|
|
<label for="hw-서버PW">서버 PW</label>
|
|
<input type="text" id="hw-서버PW" />
|
|
</div>
|
|
<div class="form-group non-server" id="hw-IP주소-group">
|
|
<label for="hw-IP주소-non-server">IP 주소</label>
|
|
<input type="text" id="hw-IP주소-non-server" />
|
|
</div>
|
|
|
|
<!-- Group 3: 시스템 사양 -->
|
|
<div class="form-section-title">시스템 사양 (Specifications)</div>
|
|
<div class="form-group">
|
|
<label for="hw-모델명">모델명</label>
|
|
<input type="text" id="hw-모델명" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="hw-OS">운영체제 (OS)</label>
|
|
<input type="text" id="hw-OS" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="hw-CPU">CPU 사양</label>
|
|
<input type="text" id="hw-CPU" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="hw-RAM">RAM 용량</label>
|
|
<input type="text" id="hw-RAM" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="hw-SSD1">Storage 1 (SSD/HDD)</label>
|
|
<input type="text" id="hw-SSD1" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="hw-SSD2">Storage 2 (SSD/HDD)</label>
|
|
<input type="text" id="hw-SSD2" />
|
|
</div>
|
|
<div class="form-group server-only">
|
|
<label for="hw-모니터링">모니터링 여부</label>
|
|
<input type="text" id="hw-모니터링" />
|
|
</div>
|
|
<div class="form-group" id="hw-비품유형-group" style="display:none;">
|
|
<label for="hw-비품유형">비품유형</label>
|
|
<select id="hw-비품유형">
|
|
<option value="노트북">노트북</option><option value="태블릿">태블릿</option><option value="휴대폰">휴대폰</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group full-width non-server">
|
|
<label for="hw-HW사양">H/W 사양 상세</label>
|
|
<textarea id="hw-HW사양" rows="2"></textarea>
|
|
</div>
|
|
|
|
<!-- Group 4: 관리 및 운영 -->
|
|
<div class="form-section-title">관리 및 운영 (Operation)</div>
|
|
<div class="form-group">
|
|
<label for="hw-위치">설치위치</label>
|
|
<input type="text" id="hw-위치" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="hw-담당자_정">담당자 (정)</label>
|
|
<input type="text" id="hw-담당자_정" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="hw-담당자_부">담당자 (부)</label>
|
|
<input type="text" id="hw-담당자_부" />
|
|
</div>
|
|
<div class="form-group non-server">
|
|
<label for="hw-구매일">구매일</label>
|
|
<input type="text" id="hw-구매일" />
|
|
</div>
|
|
<div class="form-group non-server">
|
|
<label for="hw-금액">금액</label>
|
|
<input type="text" id="hw-금액" oninput="this.value = this.value.replace(/[^0-9]/g, '').replace(/\\B(?=(\\d{3})+(?!\d))/g, ',')" />
|
|
</div>
|
|
<div class="form-group full-width">
|
|
<label>품의서 (파일 증빙)</label>
|
|
<div style="display:flex; align-items:center; gap:0.5rem;">
|
|
<input type="file" id="hw-품의서" />
|
|
<span id="hw-품의서명" style="font-size:0.75rem; color:var(--text-light)"></span>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button id="btn-delete-hw-asset" class="btn btn-outline btn-danger">삭제</button>
|
|
<div class="footer-actions">
|
|
<button id="btn-revert-hw-edit" class="btn btn-outline hidden">수정 취소</button>
|
|
<button id="btn-cancel-hw-modal" class="btn btn-outline">닫기</button>
|
|
<button id="btn-save-hw-asset" class="btn btn-primary">수정</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
export function openHwModal(asset: HardwareAsset) {
|
|
currentAsset = asset;
|
|
isEditMode = false;
|
|
|
|
const modal = document.getElementById('hw-asset-modal')!;
|
|
const form = document.getElementById('hw-asset-form') as HTMLFormElement;
|
|
const saveBtn = document.getElementById('btn-save-hw-asset')!;
|
|
const revertBtn = document.getElementById('btn-revert-hw-edit')!;
|
|
|
|
form.reset();
|
|
form.classList.remove('is-edit-mode');
|
|
form.classList.add('is-view-mode');
|
|
saveBtn.textContent = '수정';
|
|
revertBtn.classList.add('hidden');
|
|
|
|
fillHwFormData(asset);
|
|
|
|
modal.classList.remove('hidden');
|
|
createIcons({ icons: { Paperclip } });
|
|
}
|
|
|
|
function fillHwFormData(asset: HardwareAsset) {
|
|
(document.getElementById('hw-asset-id') as HTMLInputElement).value = asset.id;
|
|
(document.getElementById('hw-asset-type') as HTMLInputElement).value = asset.type;
|
|
(document.getElementById('hw-법인') as HTMLInputElement).value = asset.법인;
|
|
(document.getElementById('hw-자산코드') as HTMLInputElement).value = asset.자산코드;
|
|
(document.getElementById('hw-위치') as HTMLInputElement).value = asset.위치;
|
|
(document.getElementById('hw-현사용조직') as HTMLInputElement).value = asset.현사용조직 || '';
|
|
(document.getElementById('hw-이전사용조직') as HTMLInputElement).value = asset.이전사용조직 || '';
|
|
(document.getElementById('hw-모델명') as HTMLInputElement).value = asset.모델명 || '';
|
|
(document.getElementById('hw-OS') as HTMLInputElement).value = asset.OS || '';
|
|
(document.getElementById('hw-CPU') as HTMLInputElement).value = asset.CPU || '';
|
|
(document.getElementById('hw-RAM') as HTMLInputElement).value = asset.RAM || '';
|
|
(document.getElementById('hw-SSD1') as HTMLInputElement).value = asset.SSD1 || '';
|
|
(document.getElementById('hw-SSD2') as HTMLInputElement).value = asset.SSD2 || '';
|
|
(document.getElementById('hw-구매일') as HTMLInputElement).value = asset.구매일 || '';
|
|
(document.getElementById('hw-담당자_정') as HTMLInputElement).value = asset.담당자_정 || asset.관리자 || '';
|
|
(document.getElementById('hw-담당자_부') as HTMLInputElement).value = asset.담당자_부 || '';
|
|
(document.getElementById('hw-품의서명') as HTMLElement).textContent = asset.품의서명 || '';
|
|
|
|
const serverOnly = document.querySelectorAll('.server-only');
|
|
const nonServer = document.querySelectorAll('.non-server');
|
|
const equipGroup = document.getElementById('hw-비품유형-group')!;
|
|
|
|
if (asset.type === '서버') {
|
|
serverOnly.forEach(el => (el as HTMLElement).style.display = 'flex');
|
|
nonServer.forEach(el => (el as HTMLElement).style.display = 'none');
|
|
equipGroup.style.display = 'none';
|
|
|
|
(document.getElementById('hw-용도') as HTMLInputElement).value = asset.용도 || '';
|
|
(document.getElementById('hw-상세') as HTMLInputElement).value = asset.상세 || '';
|
|
(document.getElementById('hw-비고') as HTMLInputElement).value = asset.비고 || '';
|
|
(document.getElementById('hw-IP주소') as HTMLInputElement).value = asset.IP주소 || '';
|
|
(document.getElementById('hw-IP2') as HTMLInputElement).value = (asset as any).IP2 || '';
|
|
(document.getElementById('hw-원격접속') as HTMLInputElement).value = asset.원격접속 || '';
|
|
(document.getElementById('hw-서버ID') as HTMLInputElement).value = (asset as any).서버ID || '';
|
|
(document.getElementById('hw-서버PW') as HTMLInputElement).value = (asset as any).서버PW || '';
|
|
(document.getElementById('hw-모니터링') as HTMLInputElement).value = asset.모니터링 || '';
|
|
} else {
|
|
serverOnly.forEach(el => (el as HTMLElement).style.display = 'none');
|
|
nonServer.forEach(el => (el as HTMLElement).style.display = 'flex');
|
|
|
|
(document.getElementById('hw-명칭') as HTMLInputElement).value = asset.명칭 || '';
|
|
(document.getElementById('hw-구매일') as HTMLInputElement).value = asset.구매일 || '';
|
|
(document.getElementById('hw-금액') as HTMLInputElement).value = asset.금액 || '';
|
|
(document.getElementById('hw-HW사양') as HTMLTextAreaElement).value = asset.HW사양 || '';
|
|
(document.getElementById('hw-IP주소-non-server') as HTMLInputElement).value = asset.IP주소 || '';
|
|
|
|
if (asset.type === '전산비품') {
|
|
equipGroup.style.display = 'flex';
|
|
(document.getElementById('hw-비품유형') as HTMLSelectElement).value = asset.비품유형 || '노트북';
|
|
} else {
|
|
equipGroup.style.display = 'none';
|
|
}
|
|
}
|
|
}
|
|
|
|
export function initHwModal(onSave: () => void, closeModals: () => void) {
|
|
// HTML 주입
|
|
if (!document.getElementById('hw-asset-modal')) {
|
|
document.body.insertAdjacentHTML('beforeend', HW_MODAL_HTML);
|
|
}
|
|
|
|
const modal = document.getElementById('hw-asset-modal')!;
|
|
const form = document.getElementById('hw-asset-form') as HTMLFormElement;
|
|
const closeBtn = document.getElementById('btn-close-hw-modal')!;
|
|
const cancelBtn = document.getElementById('btn-cancel-hw-modal')!;
|
|
const saveBtn = document.getElementById('btn-save-hw-asset')!;
|
|
const revertBtn = document.getElementById('btn-revert-hw-edit')!;
|
|
const deleteBtn = document.getElementById('btn-delete-hw-asset')!;
|
|
|
|
const closeModal = () => {
|
|
closeModals();
|
|
isEditMode = false;
|
|
};
|
|
|
|
const switchToViewMode = () => {
|
|
isEditMode = false;
|
|
form.classList.remove('is-edit-mode');
|
|
form.classList.add('is-view-mode');
|
|
saveBtn.textContent = '수정';
|
|
revertBtn.classList.add('hidden');
|
|
if (currentAsset) fillHwFormData(currentAsset);
|
|
};
|
|
|
|
closeBtn.addEventListener('click', closeModal);
|
|
cancelBtn.addEventListener('click', closeModal);
|
|
modal.addEventListener('click', (e) => { if (e.target === modal) closeModal(); });
|
|
revertBtn.addEventListener('click', () => { switchToViewMode(); });
|
|
|
|
saveBtn.addEventListener('click', () => {
|
|
if (!currentAsset) return;
|
|
|
|
if (!isEditMode) {
|
|
isEditMode = true;
|
|
form.classList.remove('is-view-mode');
|
|
form.classList.add('is-edit-mode');
|
|
saveBtn.textContent = '저장';
|
|
revertBtn.classList.remove('hidden');
|
|
return;
|
|
}
|
|
|
|
const assetId = (document.getElementById('hw-asset-id') as HTMLInputElement).value;
|
|
const type = (document.getElementById('hw-asset-type') as HTMLInputElement).value;
|
|
|
|
const updated: HardwareAsset = {
|
|
...currentAsset,
|
|
법인: (document.getElementById('hw-법인') as HTMLInputElement).value,
|
|
자산코드: (document.getElementById('hw-자산코드') as HTMLInputElement).value,
|
|
위치: (document.getElementById('hw-위치') as HTMLInputElement).value,
|
|
현사용조직: (document.getElementById('hw-현사용조직') as HTMLInputElement).value,
|
|
이전사용조직: (document.getElementById('hw-이전사용조직') as HTMLInputElement).value,
|
|
모델명: (document.getElementById('hw-모델명') as HTMLInputElement).value,
|
|
OS: (document.getElementById('hw-OS') as HTMLInputElement).value,
|
|
CPU: (document.getElementById('hw-CPU') as HTMLInputElement).value,
|
|
RAM: (document.getElementById('hw-RAM') as HTMLInputElement).value,
|
|
SSD1: (document.getElementById('hw-SSD1') as HTMLInputElement).value,
|
|
SSD2: (document.getElementById('hw-SSD2') as HTMLInputElement).value,
|
|
구매일: (document.getElementById('hw-구매일') as HTMLInputElement).value,
|
|
담당자_정: (document.getElementById('hw-담당자_정') as HTMLInputElement).value,
|
|
관리자: (document.getElementById('hw-담당자_정') as HTMLInputElement).value,
|
|
담당자_부: (document.getElementById('hw-담당자_부') as HTMLInputElement).value,
|
|
};
|
|
|
|
if (type === '서버') {
|
|
updated.용도 = (document.getElementById('hw-용도') as HTMLInputElement).value;
|
|
updated.상세 = (document.getElementById('hw-상세') as HTMLInputElement).value;
|
|
updated.비고 = (document.getElementById('hw-비고') as HTMLInputElement).value;
|
|
updated.IP주소 = (document.getElementById('hw-IP주소') as HTMLInputElement).value;
|
|
(updated as any).IP2 = (document.getElementById('hw-IP2') as HTMLInputElement).value;
|
|
updated.원격접속 = (document.getElementById('hw-원격접속') as HTMLInputElement).value;
|
|
(updated as any).서버ID = (document.getElementById('hw-서버ID') as HTMLInputElement).value;
|
|
(updated as any).서버PW = (document.getElementById('hw-서버PW') as HTMLInputElement).value;
|
|
updated.모니터링 = (document.getElementById('hw-모니터링') as HTMLInputElement).value;
|
|
} else {
|
|
updated.명칭 = (document.getElementById('hw-명칭') as HTMLInputElement).value;
|
|
updated.구매일 = (document.getElementById('hw-구매일') as HTMLInputElement).value;
|
|
updated.금액 = (document.getElementById('hw-금액') as HTMLInputElement).value;
|
|
updated.HW사양 = (document.getElementById('hw-HW사양') as HTMLTextAreaElement).value;
|
|
updated.IP주소 = (document.getElementById('hw-IP주소-non-server') as HTMLInputElement).value;
|
|
|
|
if (type === '전산비품') {
|
|
updated.비품유형 = (document.getElementById('hw-비품유형') as HTMLSelectElement).value;
|
|
}
|
|
}
|
|
|
|
const idx = state.masterData.hw.findIndex(a => a.id === assetId);
|
|
if (idx > -1) {
|
|
state.masterData.hw[idx] = updated;
|
|
onSave();
|
|
switchToViewMode();
|
|
}
|
|
});
|
|
|
|
deleteBtn.addEventListener('click', () => {
|
|
if (!currentAsset) return;
|
|
if (confirm('정말로 이 자산을 삭제하시겠습니까?')) {
|
|
state.masterData.hw = state.masterData.hw.filter(a => a.id !== currentAsset!.id);
|
|
onSave();
|
|
closeModal();
|
|
}
|
|
});
|
|
}
|