Refactor: SW 상세 모달 동적 필드 전환 및 클라우드 통합, 자산 유형 명칭 일원화
This commit is contained in:
@@ -27,10 +27,17 @@ const SW_MODAL_HTML = `
|
||||
<div class="modal-form-area">
|
||||
<form id="sw-asset-form" class="grid-form">
|
||||
<input type="hidden" id="sw-asset-id" />
|
||||
<input type="hidden" id="sw-asset-type" />
|
||||
|
||||
|
||||
<!-- Group 1: 기본 정보 (Identity) -->
|
||||
<div class="form-section-title">기본 정보 (Identity)</div>
|
||||
<div class="form-group">
|
||||
<label for="sw-asset-type">자산 유형</label>
|
||||
<select id="sw-asset-type" required>
|
||||
<option value="구독SW">구독SW</option>
|
||||
<option value="영구SW">영구SW</option>
|
||||
<option value="클라우드">클라우드</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="sw-분야">분야</label>
|
||||
<select id="sw-분야" required>
|
||||
@@ -40,14 +47,11 @@ const SW_MODAL_HTML = `
|
||||
<option value="설계S/W">설계S/W</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sw-법인">법인</label>
|
||||
<select id="sw-법인" required>${generateOptionsHTML(CORP_LIST)}</select>
|
||||
</div>
|
||||
<div class="form-group sw-standard-field">
|
||||
<label for="sw-자산번호">자산번호</label>
|
||||
<input type="text" id="sw-자산번호" readonly placeholder="자동 생성" />
|
||||
</div>
|
||||
<div class="form-group full-width">
|
||||
<label for="sw-제품명">제품명 / 서비스명</label>
|
||||
<input type="text" id="sw-제품명" required />
|
||||
@@ -57,7 +61,7 @@ const SW_MODAL_HTML = `
|
||||
<input type="text" id="sw-플랫폼명" placeholder="예: AWS, Cafe24" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="sw-부서">부서</label>
|
||||
<label for="sw-부서">조직 / 부서</label>
|
||||
<input type="text" id="sw-부서" />
|
||||
</div>
|
||||
|
||||
@@ -148,14 +152,10 @@ const SW_MODAL_HTML = `
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="sw-user-section" class="user-management-section" style="margin-top: 2rem;">
|
||||
<div class="section-header" style="display:flex; justify-content:space-between; align-items:center; margin-bottom:1rem;">
|
||||
<h3 style="font-size:1rem; font-weight:600;">사용자 할당 현황</h3>
|
||||
<button type="button" id="btn-open-sw-user" class="btn btn-outline btn-sm">
|
||||
할당 관리 <i data-lucide="users" style="width:14px; height:14px;"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div id="sw-assigned-users-summary" class="user-summary-grid"></div>
|
||||
<div id="sw-user-section" class="user-management-section" style="margin-top: 2rem; border-top: 1px solid var(--border-color); padding-top: 1.5rem;">
|
||||
<button type="button" id="btn-open-sw-user" class="btn btn-outline btn-sm" title="사용자 관리">
|
||||
<i data-lucide="users" style="width:16px; height:16px; margin-right:4px;"></i> 사용자 관리
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -250,10 +250,10 @@ function applySwTypeUI(type: string) {
|
||||
if (keyGroup) keyGroup.style.display = 'none';
|
||||
if (typeGroup) typeGroup.style.display = 'flex';
|
||||
if (expiryGroup) expiryGroup.style.display = 'flex';
|
||||
} else {
|
||||
} else if (type === '영구SW') {
|
||||
if (keyGroup) keyGroup.style.display = 'flex';
|
||||
if (typeGroup) typeGroup.style.display = 'none';
|
||||
if (expiryGroup) expiryGroup.style.display = 'flex';
|
||||
if (expiryGroup) expiryGroup.style.display = 'none'; // 영구는 유지보수 기간이 비고에 들어가는 경우가 많아 만료일 숨김 처리
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,7 +263,7 @@ function fillSwFormData(asset: SoftwareAsset) {
|
||||
setFieldValue('sw-asset-type', asset.type);
|
||||
setFieldValue('sw-분야', asset.분야 || '업무공통');
|
||||
setFieldValue('sw-법인', asset.법인);
|
||||
setFieldValue('sw-자산번호', asset.자산번호 || '');
|
||||
|
||||
setFieldValue('sw-부서', asset.부서 || '');
|
||||
setFieldValue('sw-제품명', asset.제품명);
|
||||
setFieldValue('sw-수량', asset.수량);
|
||||
@@ -287,25 +287,10 @@ function fillSwFormData(asset: SoftwareAsset) {
|
||||
setFieldValue('sw-라이선스키', (asset as any).라이선스키 || '');
|
||||
}
|
||||
|
||||
renderUserSummary(asset.id);
|
||||
renderSwHistory(asset.id);
|
||||
}
|
||||
|
||||
function renderUserSummary(swId: string) {
|
||||
const container = document.getElementById('sw-assigned-users-summary');
|
||||
if (!container) return;
|
||||
const userMapping = state.masterData.swUsers.find(u => u.sw_id === swId);
|
||||
if (!userMapping || !userMapping.userData || userMapping.userData.length === 0) {
|
||||
container.innerHTML = '<div class="empty-summary">할당된 사용자가 없습니다.</div>';
|
||||
return;
|
||||
}
|
||||
container.innerHTML = userMapping.userData.map(u => `
|
||||
<div class="user-badge-item">
|
||||
<span class="u-name">${u[3] || '이름없음'}</span>
|
||||
<span class="u-dept">${u[1] || '부서없음'}</span>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
|
||||
function renderSwHistory(swId: string) {
|
||||
const container = document.getElementById('sw-history-list');
|
||||
@@ -354,6 +339,11 @@ export function initSwModal(onSave: () => void, closeModals: () => void) {
|
||||
const deleteBtn = document.getElementById('btn-delete-sw-asset')!;
|
||||
const userAssignBtn = document.getElementById('btn-open-sw-user')!;
|
||||
const btnOpenUpdate = document.getElementById('btn-open-sw-update')!;
|
||||
const typeSelect = document.getElementById('sw-asset-type') as HTMLSelectElement;
|
||||
|
||||
typeSelect?.addEventListener('change', () => {
|
||||
applySwTypeUI(typeSelect.value);
|
||||
});
|
||||
|
||||
// 날짜 스마트 마스킹 적용
|
||||
['sw-구매일', 'sw-시작일', 'sw-만료일', 'sw-update-start', 'sw-update-end'].forEach(id => {
|
||||
@@ -392,7 +382,7 @@ export function initSwModal(onSave: () => void, closeModals: () => void) {
|
||||
분야: getFieldValue('sw-분야'),
|
||||
법인: getFieldValue('sw-법인'),
|
||||
부서: getFieldValue('sw-부서'),
|
||||
자산번호: getFieldValue('sw-자산번호'),
|
||||
|
||||
제품명: getFieldValue('sw-제품명'),
|
||||
수량: parseInt(getFieldValue('sw-수량') || '0'),
|
||||
금액: getFieldValue('sw-금액'),
|
||||
@@ -418,21 +408,27 @@ export function initSwModal(onSave: () => void, closeModals: () => void) {
|
||||
}
|
||||
|
||||
// 데이터 저장 로직 (state 업데이트)
|
||||
const oldType = currentSwAsset.type;
|
||||
const newType = updated.type;
|
||||
|
||||
// 유형이 변경된 경우 기존 리스트에서 삭제
|
||||
if (oldType !== newType) {
|
||||
if (oldType === '구독SW') state.masterData.subSw = state.masterData.subSw.filter(a => a.id !== updated.id);
|
||||
else if (oldType === '영구SW') state.masterData.permSw = state.masterData.permSw.filter(a => a.id !== updated.id);
|
||||
else if (oldType === '클라우드') state.masterData.cloud = state.masterData.cloud.filter(a => a.id !== updated.id);
|
||||
}
|
||||
|
||||
let targetList: SoftwareAsset[] = [];
|
||||
if (type === '구독SW') targetList = state.masterData.subSw;
|
||||
else if (type === '영구SW') targetList = state.masterData.permSw;
|
||||
else if (type === '클라우드') targetList = state.masterData.cloud;
|
||||
if (newType === '구독SW') targetList = state.masterData.subSw;
|
||||
else if (newType === '영구SW') targetList = state.masterData.permSw;
|
||||
else if (newType === '클라우드') targetList = state.masterData.cloud;
|
||||
|
||||
const idx = targetList.findIndex(a => a.id === updated.id);
|
||||
if (idx > -1) targetList[idx] = updated;
|
||||
else targetList.push(updated);
|
||||
|
||||
onSave();
|
||||
setEditLock('sw-asset-form', 'view', {
|
||||
saveBtnId: 'btn-save-sw-asset',
|
||||
revertBtnId: 'btn-revert-sw-edit'
|
||||
});
|
||||
isEditMode = false;
|
||||
closeModalAction();
|
||||
});
|
||||
|
||||
deleteBtn.addEventListener('click', () => {
|
||||
|
||||
Reference in New Issue
Block a user