Implement global table sorting, dashboard UI enhancements, and secret cloud access
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { state } from '../../core/state';
|
||||
import { openSwModal } from '../../components/Modal/SWModal';
|
||||
import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema';
|
||||
import { dynamicSort } from '../../core/utils';
|
||||
import { setupTableSorting, SortState } from '../../core/tableHandler';
|
||||
import { createIcons, Cloud, CreditCard, DollarSign, RefreshCcw } from 'lucide';
|
||||
|
||||
/**
|
||||
@@ -9,6 +11,7 @@ import { createIcons, Cloud, CreditCard, DollarSign, RefreshCcw } from 'lucide';
|
||||
*/
|
||||
export function renderCloudList(container: HTMLElement) {
|
||||
const getFullList = () => state.masterData.cloud || [];
|
||||
let sortState: SortState = { key: '', direction: 'asc' };
|
||||
|
||||
const filterBar = document.createElement('div');
|
||||
filterBar.className = 'search-bar';
|
||||
@@ -37,15 +40,15 @@ export function renderCloudList(container: HTMLElement) {
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">No.</th>
|
||||
<th>${ASSET_SCHEMA.PLATFORM.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.CORP.ui}</th>
|
||||
<th class="text-center">담당부서</th>
|
||||
<th>용도(프로젝트)</th>
|
||||
<th>${ASSET_SCHEMA.ACCOUNT.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.PAY_METHOD.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.PAY_DAY.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.BILLING.ui}</th>
|
||||
<th class="text-center" style="width:50px;">No.</th>
|
||||
<th data-sort="${ASSET_SCHEMA.PLATFORM.key}">${ASSET_SCHEMA.PLATFORM.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.CORP.key}">${ASSET_SCHEMA.CORP.ui}</th>
|
||||
<th class="text-center" data-sort="부서">담당부서</th>
|
||||
<th data-sort="${ASSET_SCHEMA.PRODUCT.key}">용도(프로젝트)</th>
|
||||
<th data-sort="${ASSET_SCHEMA.ACCOUNT.key}">${ASSET_SCHEMA.ACCOUNT.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.PAY_METHOD.key}">${ASSET_SCHEMA.PAY_METHOD.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.PAY_DAY.key}">${ASSET_SCHEMA.PAY_DAY.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.BILLING.key}">${ASSET_SCHEMA.BILLING.ui}</th>
|
||||
<th>${ASSET_SCHEMA.REMARKS.ui}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -63,7 +66,7 @@ export function renderCloudList(container: HTMLElement) {
|
||||
const keyword = keywordInput ? keywordInput.value.toLowerCase().trim() : '';
|
||||
const payment = paymentSelect ? paymentSelect.value : '';
|
||||
|
||||
const filtered = getFullList().filter(asset => {
|
||||
let filtered = getFullList().filter(asset => {
|
||||
const kwMatch = !keyword ||
|
||||
(asset[ASSET_SCHEMA.PRODUCT.key] || '').toLowerCase().includes(keyword) ||
|
||||
(asset.부서 || '').toLowerCase().includes(keyword) ||
|
||||
@@ -72,6 +75,10 @@ export function renderCloudList(container: HTMLElement) {
|
||||
return kwMatch && payMatch;
|
||||
});
|
||||
|
||||
if (sortState.key) {
|
||||
filtered = dynamicSort(filtered, sortState.key, sortState.direction);
|
||||
}
|
||||
|
||||
tbody.innerHTML = '';
|
||||
if (filtered.length === 0) {
|
||||
tbody.innerHTML = `<tr><td colspan="10" class="text-center" style="padding: 3rem; color: var(--text-muted);">${UI_TEXT.MESSAGES.NO_DATA}</td></tr>`;
|
||||
@@ -105,6 +112,12 @@ export function renderCloudList(container: HTMLElement) {
|
||||
tr.addEventListener('click', () => openSwModal(asset, 'view'));
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
setupTableSorting(table, sortState, (key, dir) => {
|
||||
sortState = { key, direction: dir };
|
||||
updateTable();
|
||||
});
|
||||
|
||||
createIcons({ icons: { Cloud, CreditCard, DollarSign, RefreshCcw } });
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { state } from '../../core/state';
|
||||
import { formatPrice } from '../../core/utils';
|
||||
import { formatPrice, dynamicSort } from '../../core/utils';
|
||||
import { createIcons, Plus, Edit2, Trash2 } from 'lucide';
|
||||
import { openDomainModal } from '../../components/Modal/DomainModal';
|
||||
import { setupTableSorting, SortState } from '../../core/tableHandler';
|
||||
|
||||
export function renderDomainList(container: HTMLElement) {
|
||||
container.innerHTML = '';
|
||||
|
||||
let sortState: SortState = { key: '', direction: 'asc' };
|
||||
const fullList = state.masterData.domain;
|
||||
|
||||
const header = document.createElement('div');
|
||||
header.className = 'list-header';
|
||||
header.innerHTML = `
|
||||
@@ -17,58 +21,70 @@ export function renderDomainList(container: HTMLElement) {
|
||||
|
||||
const tableWrapper = document.createElement('div');
|
||||
tableWrapper.className = 'table-container';
|
||||
|
||||
const table = document.createElement('table');
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align:center; width:50px;">No.</th>
|
||||
<th style="text-align:center;">유형</th>
|
||||
<th style="text-align:center;">법인</th>
|
||||
<th style="text-align:left;">서비스명</th>
|
||||
<th style="text-align:left;">관리도메인</th>
|
||||
<th style="text-align:center;">시작일</th>
|
||||
<th style="text-align:center;">만료일</th>
|
||||
<th style="text-align:right;">금액</th>
|
||||
<th style="text-align:center;">담당자</th>
|
||||
<th style="text-align:center;">담당자(부)</th>
|
||||
<th style="text-align:center;" data-sort="type">유형</th>
|
||||
<th style="text-align:center;" data-sort="corp">법인</th>
|
||||
<th style="text-align:left;" data-sort="service_name">서비스명</th>
|
||||
<th style="text-align:left;" data-sort="domain_name">관리도메인</th>
|
||||
<th style="text-align:center;" data-sort="start_date">시작일</th>
|
||||
<th style="text-align:center;" data-sort="expiry_date">만료일</th>
|
||||
<th style="text-align:right;" data-sort="price">금액</th>
|
||||
<th style="text-align:center;" data-sort="manager_main">담당자</th>
|
||||
<th style="text-align:center;" data-sort="manager_sub">담당자(부)</th>
|
||||
<th style="text-align:left;">비고</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${state.masterData.domain.length === 0 ? `
|
||||
<tr>
|
||||
<td colspan="11" style="text-align:center; padding: 3rem; color: var(--text-muted);">등록된 도메인 정보가 없습니다.</td>
|
||||
</tr>
|
||||
` : state.masterData.domain.map((item, idx) => `
|
||||
<tr class="domain-row" data-id="${item.id}" style="cursor:pointer;">
|
||||
<td style="text-align:center;">${idx + 1}</td>
|
||||
<td style="text-align:center;"><span class="badge badge-${item.type}">${item.type}</span></td>
|
||||
<td style="text-align:center;">${item.corp || ''}</td>
|
||||
<td>${item.service_name || ''}</td>
|
||||
<td>${item.domain_name || ''}</td>
|
||||
<td style="text-align:center;">${item.start_date || ''}</td>
|
||||
<td style="text-align:center;">${item.expiry_date || ''}</td>
|
||||
<td style="text-align:right;">${formatPrice(item.price)}</td>
|
||||
<td style="text-align:center;">${item.manager_main || ''}</td>
|
||||
<td style="text-align:center;">${item.manager_sub || ''}</td>
|
||||
<td class="text-truncate" style="max-width:200px;">${item.remarks || ''}</td>
|
||||
</tr>
|
||||
`).join('')}
|
||||
</tbody>
|
||||
<tbody id="dynamic-tbody"></tbody>
|
||||
`;
|
||||
|
||||
tableWrapper.appendChild(table);
|
||||
container.appendChild(tableWrapper);
|
||||
const tbody = table.querySelector('tbody')!;
|
||||
|
||||
// 이벤트 바인딩
|
||||
table.querySelectorAll('.domain-row').forEach(row => {
|
||||
row.addEventListener('click', () => {
|
||||
const id = row.getAttribute('data-id');
|
||||
const item = state.masterData.domain.find(d => d.id === id);
|
||||
if (item) openDomainModal(item);
|
||||
const updateTable = () => {
|
||||
let filtered = [...fullList];
|
||||
|
||||
if (sortState.key) {
|
||||
filtered = dynamicSort(filtered, sortState.key, sortState.direction);
|
||||
}
|
||||
|
||||
tbody.innerHTML = '';
|
||||
if (filtered.length === 0) {
|
||||
tbody.innerHTML = `<tr><td colspan="11" style="text-align:center; padding: 3rem; color: var(--text-muted);">등록된 도메인 정보가 없습니다.</td></tr>`;
|
||||
return;
|
||||
}
|
||||
|
||||
filtered.forEach((item, idx) => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.className = 'domain-row';
|
||||
tr.style.cursor = 'pointer';
|
||||
tr.innerHTML = `
|
||||
<td style="text-align:center;">${idx + 1}</td>
|
||||
<td style="text-align:center;"><span class="badge badge-${item.type}">${item.type}</span></td>
|
||||
<td style="text-align:center;">${item.corp || ''}</td>
|
||||
<td>${item.service_name || ''}</td>
|
||||
<td>${item.domain_name || ''}</td>
|
||||
<td style="text-align:center;">${item.start_date || ''}</td>
|
||||
<td style="text-align:center;">${item.expiry_date || ''}</td>
|
||||
<td style="text-align:right;">${formatPrice(item.price)}</td>
|
||||
<td style="text-align:center;">${item.manager_main || ''}</td>
|
||||
<td style="text-align:center;">${item.manager_sub || ''}</td>
|
||||
<td class="text-truncate" style="max-width:200px;">${item.remarks || ''}</td>
|
||||
`;
|
||||
tr.addEventListener('click', () => openDomainModal(item));
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
});
|
||||
|
||||
setupTableSorting(table, sortState, (key, dir) => {
|
||||
sortState = { key, direction: dir };
|
||||
updateTable();
|
||||
});
|
||||
};
|
||||
|
||||
updateTable();
|
||||
createIcons({ icons: { Plus, Edit2, Trash2 } });
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { state } from '../../core/state';
|
||||
import { openHwModal } from '../../components/Modal/HWModal';
|
||||
import { formatInline, createBadge, sortAssets } from '../../core/utils';
|
||||
import { formatInline, createBadge, sortAssets, dynamicSort } from '../../core/utils';
|
||||
import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema';
|
||||
import { setupTableSorting, SortState } from '../../core/tableHandler';
|
||||
import { createIcons, RefreshCcw } from 'lucide';
|
||||
|
||||
/**
|
||||
@@ -10,6 +11,7 @@ import { createIcons, RefreshCcw } from 'lucide';
|
||||
*/
|
||||
export function renderEquipmentList(container: HTMLElement) {
|
||||
const fullList = sortAssets(state.masterData.equip);
|
||||
let sortState: SortState = { key: '', direction: 'asc' };
|
||||
|
||||
const filterBar = document.createElement('div');
|
||||
filterBar.className = 'search-bar';
|
||||
@@ -36,16 +38,16 @@ export function renderEquipmentList(container: HTMLElement) {
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">No.</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.STATUS.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.CORP.ui}</th>
|
||||
<th class="text-center">유형</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.ASSET_CODE.ui}</th>
|
||||
<th>${ASSET_SCHEMA.MODEL.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.STORE_LOC.ui}</th>
|
||||
<th class="text-center">담당자(정/부)</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.PURCHASE_YM.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.PRICE.ui}</th>
|
||||
<th class="text-center" style="width:50px;">No.</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.STATUS.key}">${ASSET_SCHEMA.STATUS.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.CORP.key}">${ASSET_SCHEMA.CORP.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.TYPE.key}">유형</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.ASSET_CODE.key}">${ASSET_SCHEMA.ASSET_CODE.ui}</th>
|
||||
<th data-sort="${ASSET_SCHEMA.MODEL.key}">${ASSET_SCHEMA.MODEL.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.STORE_LOC.key}">${ASSET_SCHEMA.STORE_LOC.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.MANAGER_MAIN.key}">담당자(정/부)</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.PURCHASE_YM.key}">${ASSET_SCHEMA.PURCHASE_YM.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.PRICE.key}">${ASSET_SCHEMA.PRICE.ui}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="dynamic-tbody"></tbody>
|
||||
@@ -62,7 +64,7 @@ export function renderEquipmentList(container: HTMLElement) {
|
||||
const keyword = keywordInput ? keywordInput.value.toLowerCase().trim() : '';
|
||||
const corp = corpSelect ? corpSelect.value : '';
|
||||
|
||||
const filtered = fullList.filter(asset => {
|
||||
let filtered = fullList.filter(asset => {
|
||||
const matchKeyword = !keyword ||
|
||||
String(asset[ASSET_SCHEMA.ASSET_CODE.key]||'').toLowerCase().includes(keyword) ||
|
||||
String(asset[ASSET_SCHEMA.MODEL.key]||'').toLowerCase().includes(keyword) ||
|
||||
@@ -71,6 +73,10 @@ export function renderEquipmentList(container: HTMLElement) {
|
||||
return matchKeyword && matchCorp;
|
||||
});
|
||||
|
||||
if (sortState.key) {
|
||||
filtered = dynamicSort(filtered, sortState.key, sortState.direction);
|
||||
}
|
||||
|
||||
tbody.innerHTML = '';
|
||||
if (filtered.length === 0) {
|
||||
tbody.innerHTML = `<tr><td colspan="10" class="text-center" style="padding: 3rem; color: var(--text-muted);">${UI_TEXT.MESSAGES.NO_DATA}</td></tr>`;
|
||||
@@ -108,6 +114,12 @@ export function renderEquipmentList(container: HTMLElement) {
|
||||
tr.addEventListener('click', () => openHwModal(asset, 'view'));
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
setupTableSorting(table, sortState, (key, dir) => {
|
||||
sortState = { key, direction: dir };
|
||||
updateTable();
|
||||
});
|
||||
|
||||
createIcons({ icons: { RefreshCcw } });
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { state } from '../../core/state';
|
||||
import { openHwModal } from '../../components/Modal/HWModal';
|
||||
import { formatInline, createBadge, sortAssets } from '../../core/utils';
|
||||
import { formatInline, createBadge, sortAssets, dynamicSort } from '../../core/utils';
|
||||
import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema';
|
||||
import { setupTableSorting, SortState } from '../../core/tableHandler';
|
||||
import { createIcons, RefreshCcw } from 'lucide';
|
||||
|
||||
/**
|
||||
@@ -10,6 +11,7 @@ import { createIcons, RefreshCcw } from 'lucide';
|
||||
*/
|
||||
export function renderMobileList(container: HTMLElement) {
|
||||
const fullList = sortAssets(state.masterData.mobile);
|
||||
let sortState: SortState = { key: '', direction: 'asc' };
|
||||
|
||||
const filterBar = document.createElement('div');
|
||||
filterBar.className = 'search-bar';
|
||||
@@ -36,15 +38,15 @@ export function renderMobileList(container: HTMLElement) {
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">No.</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.STATUS.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.CORP.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.ASSET_CODE.ui}</th>
|
||||
<th>${ASSET_SCHEMA.MODEL.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.STORE_LOC.ui}</th>
|
||||
<th class="text-center">담당자(정/부)</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.PURCHASE_YM.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.PRICE.ui}</th>
|
||||
<th class="text-center" style="width:50px;">No.</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.STATUS.key}">${ASSET_SCHEMA.STATUS.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.CORP.key}">${ASSET_SCHEMA.CORP.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.ASSET_CODE.key}">${ASSET_SCHEMA.ASSET_CODE.ui}</th>
|
||||
<th data-sort="${ASSET_SCHEMA.MODEL.key}">${ASSET_SCHEMA.MODEL.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.STORE_LOC.key}">${ASSET_SCHEMA.STORE_LOC.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.MANAGER_MAIN.key}">담당자(정/부)</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.PURCHASE_YM.key}">${ASSET_SCHEMA.PURCHASE_YM.ui}</th>
|
||||
<th class="text-center" data-sort="${ASSET_SCHEMA.PRICE.key}">${ASSET_SCHEMA.PRICE.ui}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="dynamic-tbody"></tbody>
|
||||
@@ -61,7 +63,7 @@ export function renderMobileList(container: HTMLElement) {
|
||||
const keyword = keywordInput ? keywordInput.value.toLowerCase().trim() : '';
|
||||
const corp = corpSelect ? corpSelect.value : '';
|
||||
|
||||
const filtered = fullList.filter(asset => {
|
||||
let filtered = fullList.filter(asset => {
|
||||
const matchKeyword = !keyword ||
|
||||
String(asset[ASSET_SCHEMA.ASSET_CODE.key]||'').toLowerCase().includes(keyword) ||
|
||||
String(asset[ASSET_SCHEMA.MODEL.key]||'').toLowerCase().includes(keyword) ||
|
||||
@@ -70,6 +72,10 @@ export function renderMobileList(container: HTMLElement) {
|
||||
return matchKeyword && matchCorp;
|
||||
});
|
||||
|
||||
if (sortState.key) {
|
||||
filtered = dynamicSort(filtered, sortState.key, sortState.direction);
|
||||
}
|
||||
|
||||
tbody.innerHTML = '';
|
||||
if (filtered.length === 0) {
|
||||
tbody.innerHTML = `<tr><td colspan="9" class="text-center" style="padding: 3rem; color: var(--text-muted);">${UI_TEXT.MESSAGES.NO_DATA}</td></tr>`;
|
||||
@@ -106,6 +112,12 @@ export function renderMobileList(container: HTMLElement) {
|
||||
tr.addEventListener('click', () => openHwModal(asset, 'view'));
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
setupTableSorting(table, sortState, (key, dir) => {
|
||||
sortState = { key, direction: dir };
|
||||
updateTable();
|
||||
});
|
||||
|
||||
createIcons({ icons: { RefreshCcw } });
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { state } from '../../core/state';
|
||||
import { openHwModal } from '../../components/Modal/HWModal';
|
||||
import { formatInline, createBadge, sortAssets } from '../../core/utils';
|
||||
import { formatInline, createBadge, sortAssets, dynamicSort } from '../../core/utils';
|
||||
import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema';
|
||||
import { setupTableSorting, SortState } from '../../core/tableHandler';
|
||||
import { createIcons, Paperclip, RefreshCcw } from 'lucide';
|
||||
|
||||
/**
|
||||
@@ -10,6 +11,7 @@ import { createIcons, Paperclip, RefreshCcw } from 'lucide';
|
||||
*/
|
||||
export function renderPcList(container: HTMLElement) {
|
||||
const fullList = sortAssets(state.masterData.pc);
|
||||
let sortState: SortState = { key: '', direction: 'asc' };
|
||||
|
||||
const filterBar = document.createElement('div');
|
||||
filterBar.className = 'search-bar';
|
||||
@@ -37,19 +39,19 @@ export function renderPcList(container: HTMLElement) {
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align:center;">No</th>
|
||||
<th style="text-align:center;">${ASSET_SCHEMA.CORP.ui}</th>
|
||||
<th style="text-align:center;">${ASSET_SCHEMA.ORG.ui}</th>
|
||||
<th style="text-align:center;">${ASSET_SCHEMA.ASSET_CODE.ui}</th>
|
||||
<th style="text-align:center;">${ASSET_SCHEMA.USER.ui}</th>
|
||||
<th style="text-align:center;">${ASSET_SCHEMA.LOCATION.ui}</th>
|
||||
<th style="text-align:center;">담당자(정/부)</th>
|
||||
<th style="text-align:center;">${ASSET_SCHEMA.MAINBOARD.ui}</th>
|
||||
<th style="text-align:center;">${ASSET_SCHEMA.CPU.ui}</th>
|
||||
<th style="text-align:center;">${ASSET_SCHEMA.RAM.ui}</th>
|
||||
<th style="text-align:center;">Storage</th>
|
||||
<th style="text-align:center;">${ASSET_SCHEMA.PURCHASE_YM.ui}</th>
|
||||
<th style="text-align:center;">${ASSET_SCHEMA.PRICE.ui}</th>
|
||||
<th style="text-align:center; width:50px;">No</th>
|
||||
<th style="text-align:center;" data-sort="${ASSET_SCHEMA.CORP.key}">${ASSET_SCHEMA.CORP.ui}</th>
|
||||
<th style="text-align:center;" data-sort="${ASSET_SCHEMA.ORG.key}">${ASSET_SCHEMA.ORG.ui}</th>
|
||||
<th style="text-align:center;" data-sort="${ASSET_SCHEMA.ASSET_CODE.key}">${ASSET_SCHEMA.ASSET_CODE.ui}</th>
|
||||
<th style="text-align:center;" data-sort="${ASSET_SCHEMA.USER.key}">${ASSET_SCHEMA.USER.ui}</th>
|
||||
<th style="text-align:center;" data-sort="${ASSET_SCHEMA.LOCATION.key}">${ASSET_SCHEMA.LOCATION.ui}</th>
|
||||
<th style="text-align:center;" data-sort="${ASSET_SCHEMA.MANAGER_MAIN.key}">담당자(정/부)</th>
|
||||
<th style="text-align:center;" data-sort="${ASSET_SCHEMA.MAINBOARD.key}">${ASSET_SCHEMA.MAINBOARD.ui}</th>
|
||||
<th style="text-align:center;" data-sort="${ASSET_SCHEMA.CPU.key}">${ASSET_SCHEMA.CPU.ui}</th>
|
||||
<th style="text-align:center;" data-sort="${ASSET_SCHEMA.RAM.key}">${ASSET_SCHEMA.RAM.ui}</th>
|
||||
<th style="text-align:center;" data-sort="${ASSET_SCHEMA.STORAGE1.key}">Storage</th>
|
||||
<th style="text-align:center;" data-sort="${ASSET_SCHEMA.PURCHASE_YM.key}">${ASSET_SCHEMA.PURCHASE_YM.ui}</th>
|
||||
<th style="text-align:center;" data-sort="${ASSET_SCHEMA.PRICE.key}">${ASSET_SCHEMA.PRICE.ui}</th>
|
||||
<th style="text-align:center;">${ASSET_SCHEMA.DOC_NAME.ui}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -67,7 +69,7 @@ export function renderPcList(container: HTMLElement) {
|
||||
const keyword = keywordInput ? keywordInput.value.toLowerCase().trim() : '';
|
||||
const corp = corpSelect ? corpSelect.value : '';
|
||||
|
||||
const filtered = fullList.filter(asset => {
|
||||
let filtered = fullList.filter(asset => {
|
||||
const matchKeyword = !keyword ||
|
||||
String(asset[ASSET_SCHEMA.ASSET_CODE.key]||'').toLowerCase().includes(keyword) ||
|
||||
String(asset[ASSET_SCHEMA.USER.key]||'').toLowerCase().includes(keyword) ||
|
||||
@@ -77,6 +79,10 @@ export function renderPcList(container: HTMLElement) {
|
||||
return matchKeyword && matchCorp;
|
||||
});
|
||||
|
||||
if (sortState.key) {
|
||||
filtered = dynamicSort(filtered, sortState.key, sortState.direction);
|
||||
}
|
||||
|
||||
tbody.innerHTML = '';
|
||||
if (filtered.length === 0) {
|
||||
tbody.innerHTML = `<tr><td colspan="14" style="text-align:center; padding: 3rem; color: var(--text-muted);">${UI_TEXT.MESSAGES.NO_DATA}</td></tr>`;
|
||||
@@ -115,6 +121,12 @@ export function renderPcList(container: HTMLElement) {
|
||||
tr.addEventListener('click', () => openHwModal(asset, 'view'));
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
setupTableSorting(table, sortState, (key, dir) => {
|
||||
sortState = { key, direction: dir };
|
||||
updateTable();
|
||||
});
|
||||
|
||||
createIcons({ icons: { Paperclip, RefreshCcw } });
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { state } from '../../core/state';
|
||||
import { openHwModal } from '../../components/Modal/HWModal';
|
||||
import { formatInline, createBadge, sortAssets } from '../../core/utils';
|
||||
import { formatInline, createBadge, sortAssets, dynamicSort } from '../../core/utils';
|
||||
import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema';
|
||||
import { setupTableSorting, SortState } from '../../core/tableHandler';
|
||||
import { createIcons, RefreshCcw } from 'lucide';
|
||||
|
||||
/**
|
||||
@@ -10,6 +11,7 @@ import { createIcons, RefreshCcw } from 'lucide';
|
||||
*/
|
||||
export function renderServerList(container: HTMLElement) {
|
||||
const fullList = sortAssets(state.masterData.server);
|
||||
let sortState: SortState = { key: '', direction: 'asc' };
|
||||
|
||||
const filterBar = document.createElement('div');
|
||||
filterBar.className = 'search-bar';
|
||||
@@ -42,14 +44,14 @@ export function renderServerList(container: HTMLElement) {
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">No</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.CORP.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.ORG.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.ASSET_CODE.ui}</th>
|
||||
<th>용도</th>
|
||||
<th>상세</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.LOCATION.ui}</th>
|
||||
<th class="text-center">담당자(정/부)</th>
|
||||
<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="용도">용도</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>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="dynamic-tbody"></tbody>
|
||||
@@ -68,7 +70,7 @@ export function renderServerList(container: HTMLElement) {
|
||||
const corp = corpSelect ? corpSelect.value : '';
|
||||
const orgUnit = orgSelect ? orgSelect.value : '';
|
||||
|
||||
const filtered = fullList.filter(asset => {
|
||||
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) ||
|
||||
@@ -78,6 +80,10 @@ export function renderServerList(container: HTMLElement) {
|
||||
return matchKeyword && matchCorp && matchOrg;
|
||||
});
|
||||
|
||||
if (sortState.key) {
|
||||
filtered = dynamicSort(filtered, sortState.key, sortState.direction);
|
||||
}
|
||||
|
||||
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>`;
|
||||
@@ -108,6 +114,11 @@ export function renderServerList(container: HTMLElement) {
|
||||
tr.addEventListener('click', () => openHwModal(asset, 'view'));
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
setupTableSorting(table, sortState, (key, dir) => {
|
||||
sortState = { key, direction: dir };
|
||||
updateTable();
|
||||
});
|
||||
};
|
||||
|
||||
document.getElementById('filter-keyword')?.addEventListener('input', updateTable);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { state } from '../../core/state';
|
||||
import { openHwModal } from '../../components/Modal/HWModal';
|
||||
import { formatInline, createBadge, sortAssets } from '../../core/utils';
|
||||
import { formatInline, createBadge, sortAssets, dynamicSort } from '../../core/utils';
|
||||
import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema';
|
||||
import { setupTableSorting, SortState } from '../../core/tableHandler';
|
||||
import { createIcons, RefreshCcw } from 'lucide';
|
||||
|
||||
/**
|
||||
@@ -10,6 +11,7 @@ import { createIcons, RefreshCcw } from 'lucide';
|
||||
*/
|
||||
export function renderStorageList(container: HTMLElement) {
|
||||
const fullList = sortAssets(state.masterData.storage);
|
||||
let sortState: SortState = { key: '', direction: 'asc' };
|
||||
|
||||
const filterBar = document.createElement('div');
|
||||
filterBar.className = 'search-bar';
|
||||
@@ -42,14 +44,14 @@ export function renderStorageList(container: HTMLElement) {
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">No</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.CORP.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.ORG.ui}</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.ASSET_CODE.ui}</th>
|
||||
<th>용도</th>
|
||||
<th>상세</th>
|
||||
<th class="text-center">${ASSET_SCHEMA.LOCATION.ui}</th>
|
||||
<th class="text-center">담당자(정/부)</th>
|
||||
<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="용도">용도</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>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="dynamic-tbody"></tbody>
|
||||
@@ -68,7 +70,7 @@ export function renderStorageList(container: HTMLElement) {
|
||||
const corp = corpSelect ? corpSelect.value : '';
|
||||
const orgUnit = orgSelect ? orgSelect.value : '';
|
||||
|
||||
const filtered = fullList.filter(asset => {
|
||||
let filtered = fullList.filter(asset => {
|
||||
const matchKeyword = !keyword ||
|
||||
String((asset as any)[ASSET_SCHEMA.ASSET_CODE.key]||'').toLowerCase().includes(keyword) ||
|
||||
String((asset as any)[ASSET_SCHEMA.ORG.key]||'').toLowerCase().includes(keyword);
|
||||
@@ -77,6 +79,10 @@ export function renderStorageList(container: HTMLElement) {
|
||||
return matchKeyword && matchCorp && matchOrg;
|
||||
});
|
||||
|
||||
if (sortState.key) {
|
||||
filtered = dynamicSort(filtered, sortState.key, sortState.direction);
|
||||
}
|
||||
|
||||
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>`;
|
||||
@@ -107,6 +113,11 @@ export function renderStorageList(container: HTMLElement) {
|
||||
tr.addEventListener('click', () => openHwModal(asset, 'view'));
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
setupTableSorting(table, sortState, (key, dir) => {
|
||||
sortState = { key, direction: dir };
|
||||
updateTable();
|
||||
});
|
||||
};
|
||||
|
||||
document.getElementById('filter-keyword')?.addEventListener('input', updateTable);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { state } from '../../core/state';
|
||||
import { openSwModal } from '../../components/Modal/SWModal';
|
||||
import { openSwUserModal } from '../../components/Modal/SWUserModal';
|
||||
import { sortAssets, formatPrice } from '../../core/utils';
|
||||
import { sortAssets, dynamicSort, formatPrice } from '../../core/utils';
|
||||
import { setupTableSorting, SortState } from '../../core/tableHandler';
|
||||
import { CORP_LIST } from '../../components/Modal/SharedData';
|
||||
import { generateOptionsHTML } from '../../components/Modal/ModalUtils';
|
||||
import { createIcons, Edit2, Users, RefreshCcw } from 'lucide';
|
||||
@@ -10,6 +11,8 @@ export function renderSwList(container: HTMLElement) {
|
||||
const isSub = state.activeSubTab === '구독SW';
|
||||
const fullList = sortAssets(isSub ? state.masterData.subSw : state.masterData.permSw);
|
||||
|
||||
let sortState: SortState = { key: '', direction: 'asc' };
|
||||
|
||||
const filterBar = document.createElement('div');
|
||||
filterBar.className = 'search-bar';
|
||||
filterBar.innerHTML = `
|
||||
@@ -43,17 +46,17 @@ export function renderSwList(container: HTMLElement) {
|
||||
table.innerHTML = `
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align:center;">No.</th>
|
||||
<th style="text-align:center;">상태</th>
|
||||
<th style="text-align:center;">분야</th>
|
||||
<th style="text-align:center;">법인</th>
|
||||
<th style="text-align:center;">부서</th>
|
||||
<th style="text-align:center;">제품명</th>
|
||||
<th style="text-align:center;">구매일</th>
|
||||
<th style="text-align:center;">시작일</th>
|
||||
<th style="text-align:center;">만료일</th>
|
||||
<th style="text-align:center;">금액</th>
|
||||
<th style="text-align:center;">수량</th>
|
||||
<th style="text-align:center; width: 50px;">No.</th>
|
||||
<th style="text-align:center;" data-sort="상태">상태</th>
|
||||
<th style="text-align:center;" data-sort="분야">분야</th>
|
||||
<th style="text-align:center;" data-sort="법인">법인</th>
|
||||
<th style="text-align:center;" data-sort="부서">부서</th>
|
||||
<th style="text-align:center;" data-sort="제품명">제품명</th>
|
||||
<th style="text-align:center;" data-sort="구매일">구매일</th>
|
||||
<th style="text-align:center;" data-sort="시작일">시작일</th>
|
||||
<th style="text-align:center;" data-sort="만료일">만료일</th>
|
||||
<th style="text-align:center;" data-sort="금액">금액</th>
|
||||
<th style="text-align:center;" data-sort="수량">수량</th>
|
||||
<th style="text-align:center;">사용가능</th>
|
||||
<th style="text-align:center;">사용자</th>
|
||||
</tr>
|
||||
@@ -74,13 +77,17 @@ export function renderSwList(container: HTMLElement) {
|
||||
const field = fieldSelect ? fieldSelect.value : '';
|
||||
const corp = corpSelect ? corpSelect.value : '';
|
||||
|
||||
const filtered = fullList.filter(asset => {
|
||||
let filtered = fullList.filter(asset => {
|
||||
const matchKeyword = !keyword || (asset.제품명 || '').toLowerCase().includes(keyword) || (asset.부서 || '').toLowerCase().includes(keyword);
|
||||
const matchField = !field || asset.분야 === field;
|
||||
const matchCorp = !corp || asset.법인 === corp;
|
||||
return matchKeyword && matchField && matchCorp;
|
||||
});
|
||||
|
||||
if (sortState.key) {
|
||||
filtered = dynamicSort(filtered, sortState.key, sortState.direction);
|
||||
}
|
||||
|
||||
tbody.innerHTML = '';
|
||||
if (filtered.length === 0) {
|
||||
tbody.innerHTML = `<tr><td colspan="13" style="text-align:center; padding: 3rem; color: var(--text-muted);">검색 결과가 없습니다.</td></tr>`;
|
||||
@@ -155,6 +162,12 @@ export function renderSwList(container: HTMLElement) {
|
||||
});
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
setupTableSorting(table, sortState, (key, dir) => {
|
||||
sortState = { key, direction: dir };
|
||||
updateTable();
|
||||
});
|
||||
|
||||
createIcons({ icons: { Edit2, Users, RefreshCcw } });
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user