Files
elink-test-master/ApiTestManager/src/components/LayoutGrid.js
T
2024-05-07 13:43:48 +09:00

288 lines
11 KiB
JavaScript

import EditableInput from './EditableInput';
class LayoutGridModel {
constructor(items) {
this.items = items;
}
}
class LayoutGridView {
constructor(model, controller) {
this.model = model;
this.controller = controller;
}
render() {
this.renderApiLayout();
}
renderApiLayout() {
const requestContainer = this.targetContent.find('.request_layout');
requestContainer.empty();
const headerHtml = `
<table class="layout_table" style="border-collapse: collapse; border: 1px gray solid;">
<colgroup>
<col style="width: 50px;">
<col style="width: 80px;">
<col style="width: 80px;">
<col style="width: 120px;">
<col style="width: 150px;">
<col style="width: 60px;">
<col style="width: 110px;">
<col style="width: 80px;">
<col style="width: 100px;">
<col style="width: 80px;">
<col style="width: 120px;">
<col style="width: 120px;">
</colgroup>
<thead>
<tr>
<th scope="col" style="border: 1px gray solid; text-align: center;width: 80px;">#</th>
<th scope="col" style="border: 1px gray solid; text-align: center;width: 40px;">ID</th>
<th scope="col" style="border: 1px gray solid; text-align: center;width: 40px;">Parent</th>
<th scope="col" style="border: 1px gray solid; text-align: center;width: 120px;">항목명(영문)</th>
<th scope="col" style="border: 1px gray solid; text-align: center;width: 150px;">항목설명</th>
<th scope="col" style="border: 1px gray solid; text-align: center;width: 60px;">깊이</th>
<th scope="col" style="border: 1px gray solid; text-align: center;width: 110px;">아이템 유형</th>
<th scope="col" style="border: 1px gray solid; text-align: center;width: 80px;">반복 횟수 </th>
<th scope="col" style="border: 1px gray solid; text-align: center;width: 100px;">반복 참조 필드</th>
<th scope="col" style="border: 1px gray solid; text-align: center;width: 80px;">데이터 길이</th>
<th scope="col" style="border: 1px gray solid; text-align: center;width: 120px;">값</th>
<th scope="col" style="border: 1px gray solid; text-align: center;width: 120px;">비고 <button type="button" class="btn btn-sm btn-outline-secondary add-layout-item"><i class="fas fa-plus"></i></button></th>
</tr>
</thead>
<tbody>
`;
const footerHtml = `
</tbody>
</table>
`;
const fieldsHtml = this.model.items ? this.model.items.map((item, index) => {
return this.renderApiLayoutItem(item, index);
}).join('') : '';
requestContainer.append(headerHtml + fieldsHtml + footerHtml);
requestContainer.find('.editable').each((index, editableElement) => {
const editableInput = new EditableInput({
name: editableElement.dataset.name,
value: editableElement.dataset.value,
style : {width : '120px'}
});
editableInput.init(editableElement, async (value) => {
_.set(this.model, editableElement.dataset.name, value);
await this.controller.additionalCallback(this.model);
});
});
let totalLength = 0;
this.model.items.forEach(item => {
totalLength += parseInt(item.loutItemLength);
});
this.setupListeners();
}
getFieldValue(element) {
if ($(element).is('select') || $(element).is('input[type="text"]') || $(element).is('input[type="number"]')) {
return $(element).val();
}
if ($(element).is('input[type="checkbox"]')) {
return $(element).is(':checked');
}
}
recalculateSerno() {
// Reassign loutItemSerno sequentially based on the current order
this.model.items.forEach((item, index) => {
item.loutItemSerno = index + 1; // Assuming you want to start numbering from 1
});
}
async handleUIUpdate(event) {
if (event) {
event.preventDefault();
const element = event.currentTarget;
const fieldName = $(element).attr('name');
const newValue = this.getFieldValue(element);
if (fieldName !== '') {
_.set(this.model, fieldName, newValue);
await this.controller.additionalCallback(this.model);
}
}
let totalLength = 0;
this.model.items.forEach(item => {
totalLength += parseInt(item.loutItemLength);
});
}
getLastId (){
let lastId = 0;
this.model.items.forEach(item => {
if (item.id > lastId) {
lastId = item.id;
}
});
return lastId + 1;
}
setupListeners() {
const table = this.targetContent.find('.layout_table');
table.on('change', 'select.field, input.field', this.handleUIUpdate.bind(this));
table.on('click', '.add-layout-item', async(event) => {
let item = {
'id' : this.getLastId(),
'parent': 0,
'level': 1,
'loutName': '',
'loutItemName': '',
'loutItemDesc': '',
'loutItemDepth': 1,
'loutItemType': 'Field',
'loutItemOccCnt': '',
'loutItemOccRef': '',
'loutItemDataType': 'String',
'loutItemLength': 1,
'loutItemDecimal': 0,
'loutItemDefault': '',
'loutItemMaskYn': 'N',
'loutItemMaskOffset': 0,
'loutItemMaskLength': 0,
'parentLoutItemIndex': 0,
'expanded': true,
'isLeaf': true,
'LOUTITEMPATH': '',
'value': '',
'loutItemSerno': 0
};
this.model.items.push(item);
this.recalculateSerno();
this.renderApiLayout();
await this.controller.additionalCallback(this.model);
});
table.on('click', '.move-up', async (event) => {
const index = $(event.currentTarget).data('index');
if (index > 0) {
const temp = this.model.items[index];
this.model.items[index] = this.model.items[index - 1];
this.model.items[index - 1] = temp;
this.recalculateSerno();
this.renderApiLayout();
await this.controller.additionalCallback(this.model);
}
});
table.on('click', '.move-down', async (event) => {
const index = $(event.currentTarget).data('index');
if (index < this.model.items.length - 1) {
const temp = this.model.items[index];
this.model.items[index] = this.model.items[index + 1];
this.model.items[index + 1] = temp;
this.recalculateSerno();
this.renderApiLayout();
await this.controller.additionalCallback(this.model);
}
});
table.on('click', '.delete', async (event) => {
const index = $(event.currentTarget).data('index');
this.model.items.splice(index, 1);
this.recalculateSerno();
this.renderApiLayout();
await this.controller.additionalCallback(this.model);
});
}
renderApiLayoutItem(item, index) {
if (item.value === null) {
item.value = '';
}
return `
<tr class="layout-grid-row">
<td class="layout-grid-cell" style="width: 80px; text-align: center;">
<span style="width: 80px; text-align: center;">${item.loutItemSerno}</span>
</td>
<td class="layout-grid-cell">
<input type="text" class="form-control" name="items[${index}].id" value="${item.id}">
</td>
<td class="layout-grid-cell">
<input type="text" class="form-control" name="items[${index}].parent" value="${item.parent}">
</td>
<td class="layout-grid-cell">
<input type="text" class="form-control" name="items[${index}].loutItemName" value="${item.loutItemName}">
</td>
<td class="layout-grid-cell">
<input type="text" class="form-control" name="items[${index}].loutItemDesc" value="${item.loutItemDesc}">
</td>
<td class="layout-grid-cell">
<input type="number" class="form-control" style="width: 60px;" name="items[${index}].loutItemDepth" min="1" value="${item.loutItemDepth}">
</td>
<td class="layout-grid-cell">
<select name="items[${index}].loutItemType" class="form-select">
<option value="Field" ${item.loutItemType === 'Field' ? 'selected' : ''}>Field</option>
<option value="Grid" ${item.loutItemType === 'Grid' ? 'selected' : ''}>Grid</option>
<option value="Group" ${item.loutItemType === 'Group' ? 'selected' : ''}>Group</option>
<option value="Attr" ${item.loutItemType === 'Attr' ? 'selected' : ''}>Attr</option>
</select>
</td>
<td class="layout-grid-cell">
<input type="text" class="form-control" style="width: 80px;" name="items[${index}].loutItemOccCnt" min="0" value="${item.loutItemOccCnt}">
</td>
<td class="layout-grid-cell">
<input type="text" class="form-control" name="items[${index}].loutItemOccRef" value="${item.loutItemOccRef}"></td>
<td class="layout-grid-cell">
<input type="number" class="form-control" style="width: 80px;" name="items[${index}].loutItemLength" min="1" value="${item.loutItemLength}">
</td>
<td class="layout-grid-cell">
${ item.loutItemType ==='Field'? `<div class="editable" data-name="items[${index}].value" data-value="${item.value}"></div>`:''}
</td>
<td class="layout-grid-cell" style="width: 120px; text-align: center;">
<div style="width: 120px !important;">
<button type="button" class="btn btn-sm btn-outline-secondary move-up" data-index="${index}"><i class="fas fa-arrow-up"></i></button>
<button type="button" class="btn btn-sm btn-outline-secondary move-down" data-index="${index}"><i class="fas fa-arrow-down"></i></button>
<button type="button" class="btn btn-sm btn-outline-secondary delete" data-index="${index}"><i class="fas fa-trash-alt"></i></button>
</div>
</td>
</tr>
`;
}
}
class LayoutGridController {
constructor(model) {
this.model = model;
this.view = new LayoutGridView(this.model, this);
}
init(targetContent, callback) {
this.additionalCallback = callback;
this.view.targetContent = targetContent;
this.view.render();
}
}
class LayoutGrid {
constructor(layout) {
this.model = new LayoutGridModel(layout.layoutItems);
this.controller = new LayoutGridController(this.model);
}
init(targetContent, callback) {
this.controller.init(targetContent, callback);
}
}
export default LayoutGrid;