feat: restructure navigation, customize list columns, and move action buttons to search bar
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).
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { state } from '../../core/state';
|
||||
import { openHwModal } from '../../components/Modal/HWModal';
|
||||
import { formatInline, createBadge, sortAssets, dynamicSort } from '../../core/utils';
|
||||
import { formatInline, createBadge, sortAssets, dynamicSort, getActionButtonsHTML } from '../../core/utils';
|
||||
import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema';
|
||||
import { setupTableSorting, SortState } from '../../core/tableHandler';
|
||||
import { createIcons, RefreshCcw } from 'lucide';
|
||||
import { createIcons, RefreshCcw, Download, Upload, FileSpreadsheet, Plus } from 'lucide';
|
||||
|
||||
/**
|
||||
* 서버 자산 목록 뷰
|
||||
@@ -16,25 +16,26 @@ export function renderServerList(container: HTMLElement) {
|
||||
const filterBar = document.createElement('div');
|
||||
filterBar.className = 'search-bar';
|
||||
|
||||
const corps = Array.from(new Set(fullList.map(a => a[ASSET_SCHEMA.CORP.key]))).filter(Boolean).sort();
|
||||
const orgUnits = Array.from(new Set(fullList.map(a => a[ASSET_SCHEMA.ORG.key]))).filter(Boolean).sort();
|
||||
const corps = Array.from(new Set(fullList.map(a => a[ASSET_SCHEMA.PURCHASE_CORP.key]))).filter(Boolean).sort();
|
||||
const orgUnits = Array.from(new Set(fullList.map(a => a[ASSET_SCHEMA.CURRENT_DEPT.key]))).filter(Boolean).sort();
|
||||
|
||||
filterBar.innerHTML = `
|
||||
<div class="search-item flex-1">
|
||||
<label>통합 검색 (${ASSET_SCHEMA.ASSET_CODE.ui}/${ASSET_SCHEMA.ORG.ui}/${ASSET_SCHEMA.MODEL.ui})</label>
|
||||
<label>통합 검색 (${ASSET_SCHEMA.CURRENT_DEPT.ui}/${ASSET_SCHEMA.MODEL_NAME.ui})</label>
|
||||
<input type="text" id="filter-keyword" placeholder="검색어를 입력하세요..." autocomplete="off">
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<label>${ASSET_SCHEMA.CORP.ui}</label>
|
||||
<label>${ASSET_SCHEMA.PURCHASE_CORP.ui}</label>
|
||||
<select id="filter-corp"><option value="">전체 법인</option>${corps.map(c => `<option value="${c}">${c}</option>`).join('')}</select>
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<label>${ASSET_SCHEMA.ORG.ui}</label>
|
||||
<label>${ASSET_SCHEMA.CURRENT_DEPT.ui}</label>
|
||||
<select id="filter-org-unit"><option value="">전체 조직</option>${orgUnits.map(o => `<option value="${o}">${o}</option>`).join('')}</select>
|
||||
</div>
|
||||
<button id="btn-reset-filters" class="btn btn-outline btn-reset">
|
||||
<i data-lucide="refresh-ccw"></i> ${UI_TEXT.ACTION.RESET_FILTER}
|
||||
</button>
|
||||
${getActionButtonsHTML()}
|
||||
`;
|
||||
container.appendChild(filterBar);
|
||||
|
||||
@@ -45,13 +46,12 @@ export function renderServerList(container: HTMLElement) {
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center" style="width:50px;">No</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.CORP.key}">${ASSET_SCHEMA.CORP.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.ORG.key}">${ASSET_SCHEMA.ORG.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.ASSET_CODE.key}">${ASSET_SCHEMA.ASSET_CODE.ui}</th>
|
||||
<th data-sort="${ASSET_SCHEMA.DETAIL_PURPOSE.key}">${ASSET_SCHEMA.DETAIL_PURPOSE.ui}</th>
|
||||
<th data-sort="상세">상세</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.LOCATION.key}">${ASSET_SCHEMA.LOCATION.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.MANAGER_MAIN.key}">담당자(정/부)</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.CURRENT_DEPT.key}">${ASSET_SCHEMA.CURRENT_DEPT.ui}</th>
|
||||
<th data-sort="${ASSET_SCHEMA.ASSET_PURPOSE.key}">${ASSET_SCHEMA.ASSET_PURPOSE.ui}</th>
|
||||
<th data-sort="${ASSET_SCHEMA.MODEL_NAME.key}">${ASSET_SCHEMA.MODEL_NAME.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.LOCATION.key}">${ASSET_SCHEMA.LOCATION.ui}(건물)</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.LOC_DETAIL.key}">${ASSET_SCHEMA.LOC_DETAIL.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.MEMO.key}">${ASSET_SCHEMA.MEMO.ui}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="dynamic-tbody"></tbody>
|
||||
@@ -72,11 +72,11 @@ export function renderServerList(container: HTMLElement) {
|
||||
|
||||
let filtered = fullList.filter(asset => {
|
||||
const matchKeyword = !keyword ||
|
||||
String(asset[ASSET_SCHEMA.ASSET_CODE.key]||'').toLowerCase().includes(keyword) ||
|
||||
String(asset[ASSET_SCHEMA.ORG.key]||'').toLowerCase().includes(keyword) ||
|
||||
String(asset[ASSET_SCHEMA.MODEL.key]||'').toLowerCase().includes(keyword);
|
||||
const matchCorp = !corp || asset[ASSET_SCHEMA.CORP.key] === corp;
|
||||
const matchOrg = !orgUnit || asset[ASSET_SCHEMA.ORG.key] === orgUnit;
|
||||
String(asset[ASSET_SCHEMA.CURRENT_DEPT.key]||'').toLowerCase().includes(keyword) ||
|
||||
String(asset[ASSET_SCHEMA.MODEL_NAME.key]||'').toLowerCase().includes(keyword) ||
|
||||
String(asset[ASSET_SCHEMA.ASSET_PURPOSE.key]||'').toLowerCase().includes(keyword);
|
||||
const matchCorp = !corp || asset[ASSET_SCHEMA.PURCHASE_CORP.key] === corp;
|
||||
const matchOrg = !orgUnit || asset[ASSET_SCHEMA.CURRENT_DEPT.key] === orgUnit;
|
||||
return matchKeyword && matchCorp && matchOrg;
|
||||
});
|
||||
|
||||
@@ -86,7 +86,7 @@ export function renderServerList(container: HTMLElement) {
|
||||
|
||||
tbody.innerHTML = '';
|
||||
if (filtered.length === 0) {
|
||||
tbody.innerHTML = `<tr><td colspan="8" class="text-center" style="padding: 3rem; color: var(--text-muted);">${UI_TEXT.MESSAGES.NO_DATA}</td></tr>`;
|
||||
tbody.innerHTML = `<tr><td colspan="7" class="text-center" style="padding: 3rem; color: var(--text-muted);">${UI_TEXT.MESSAGES.NO_DATA}</td></tr>`;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -94,22 +94,14 @@ export function renderServerList(container: HTMLElement) {
|
||||
const tr = document.createElement('tr');
|
||||
tr.style.cursor = 'pointer';
|
||||
|
||||
const mainManager = asset[ASSET_SCHEMA.MANAGER_MAIN.key] || '';
|
||||
const subManager = asset[ASSET_SCHEMA.MANAGER_SUB.key] || '';
|
||||
const managerHtml = [
|
||||
mainManager ? `${createBadge('정', 'primary')} ${mainManager}` : '',
|
||||
subManager ? `${createBadge('부', 'muted')} ${subManager}` : ''
|
||||
].filter(v => v !== '').join(' / ');
|
||||
|
||||
tr.innerHTML = `
|
||||
<td class="text-center">${idx+1}</td>
|
||||
<td class="text-center">${asset[ASSET_SCHEMA.CORP.key]}</td>
|
||||
<td class="text-center">${asset[ASSET_SCHEMA.ORG.key]||'-'}</td>
|
||||
<td class="text-center">${asset[ASSET_SCHEMA.ASSET_CODE.key]}</td>
|
||||
<td>${formatInline(asset[ASSET_SCHEMA.DETAIL_PURPOSE.key])}</td>
|
||||
<td>${formatInline(asset.상세)}</td>
|
||||
<td class="text-center">${asset[ASSET_SCHEMA.CURRENT_DEPT.key]||'-'}</td>
|
||||
<td>${formatInline(asset[ASSET_SCHEMA.ASSET_PURPOSE.key])}</td>
|
||||
<td>${formatInline(asset[ASSET_SCHEMA.MODEL_NAME.key]||asset[ASSET_SCHEMA.ASSET_NAME.key]||'-')}</td>
|
||||
<td class="text-center">${formatInline(asset[ASSET_SCHEMA.LOCATION.key])}</td>
|
||||
<td class="text-center">${managerHtml || '-'}</td>
|
||||
<td class="text-center">${formatInline(asset[ASSET_SCHEMA.LOC_DETAIL.key]||'-')}</td>
|
||||
<td class="text-center">${formatInline(asset[ASSET_SCHEMA.MEMO.key]||'-')}</td>
|
||||
`;
|
||||
tr.addEventListener('click', () => openHwModal(asset, 'view'));
|
||||
tbody.appendChild(tr);
|
||||
@@ -132,5 +124,5 @@ export function renderServerList(container: HTMLElement) {
|
||||
});
|
||||
|
||||
updateTable();
|
||||
createIcons({ icons: { RefreshCcw } });
|
||||
createIcons({ icons: { RefreshCcw, Download, Upload, FileSpreadsheet, Plus } });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user