TCP 서버 모드 추가
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
class ApiLayoutItemTreeBuilder {
|
||||
static createTree(layoutItems) {
|
||||
layoutItems.sort((a, b) => a.loutItemSerno - b.loutItemSerno);
|
||||
const rootId = layoutItems.length === 0 ? 0 : parseInt(layoutItems[0].parent);
|
||||
const root = {id: rootId, children: [], loutItemSerno: 0, loutItemName: 'Root', loutItemDesc: 'Root', loutItemType: '', loutItemDepth: 0, parent: null};
|
||||
|
||||
const nodeMap = new Map();
|
||||
nodeMap.set(rootId, root);
|
||||
|
||||
for (const item of layoutItems) {
|
||||
if (['Grid', 'Group'].includes(item.loutItemType)) {
|
||||
if (item.loutItemOccCnt !== null) {
|
||||
if (item.loutItemOccCnt === '*') {
|
||||
let refItem = layoutItems.find(p => p.loutItemName === item.loutItemOccRef);
|
||||
if (refItem) {
|
||||
item.childOccCnt = parseInt(refItem.value, 10);
|
||||
}
|
||||
} else {
|
||||
item.childOccCnt = parseInt(item.loutItemOccCnt, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nodeMap.has(parseInt(item.parent))) {
|
||||
nodeMap.get(parseInt(item.parent)).children.push(item);
|
||||
// console.log(item.id + ' to ' + item.parent);
|
||||
} else {
|
||||
console.log('Parent not found: ' + item.parent);
|
||||
}
|
||||
|
||||
nodeMap.set(item.id, item);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
static moveNode(root, node, moveUp) {
|
||||
const parent = this.getParentNode(root, node);
|
||||
if (parent === null) {
|
||||
// Node is the root node, cannot be moved
|
||||
return;
|
||||
}
|
||||
|
||||
const siblings = parent.children;
|
||||
const currentIndex = siblings.indexOf(node);
|
||||
if (currentIndex === -1) {
|
||||
// Node not found in parent's children list
|
||||
return;
|
||||
}
|
||||
|
||||
const newIndex = moveUp ? currentIndex - 1 : currentIndex + 1;
|
||||
if (newIndex >= 0 && newIndex < siblings.length) {
|
||||
// Swap the positions of the current node and the node at the new index
|
||||
[siblings[currentIndex], siblings[newIndex]] = [siblings[newIndex], siblings[currentIndex]];
|
||||
}
|
||||
}
|
||||
|
||||
static getParentNode(root, node) {
|
||||
if (node.parent === null) {
|
||||
return null; // Node is the root node
|
||||
}
|
||||
|
||||
return this.getNodeById(root, node.parent);
|
||||
}
|
||||
|
||||
static getNodeIndex(parent, node) {
|
||||
return parent.children.indexOf(node);
|
||||
}
|
||||
|
||||
static getNodeById(node, id) {
|
||||
if (node.id == id) {
|
||||
return node;
|
||||
}
|
||||
|
||||
for (const child of node.children) {
|
||||
const found = this.getNodeById(child, id);
|
||||
if (found !== null) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static findParent(root, node) {
|
||||
if (root === null || node === null) {
|
||||
return null; // Invalid input
|
||||
}
|
||||
|
||||
if (root.children.includes(node)) {
|
||||
return root; // The root is the parent of the node
|
||||
}
|
||||
|
||||
for (const child of root.children) {
|
||||
const parent = this.findParent(child, node);
|
||||
if (parent !== null) {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
|
||||
return null; // Node not found in the tree
|
||||
}
|
||||
|
||||
static printTree(root) {
|
||||
console.log('====================================');
|
||||
this.printNode(root, 0);
|
||||
console.log('====================================');
|
||||
}
|
||||
|
||||
static printNode(node, level) {
|
||||
if (node === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Print indentation based on the level
|
||||
let indent = '';
|
||||
for (let i = 0; i < level; i++) {
|
||||
indent += ' ';
|
||||
}
|
||||
|
||||
// Print the node information
|
||||
console.log(`${indent}${node.id}: ${node.loutName}[${node.loutItemType}, Level: ${node.loutItemDepth}, Serno: ${node.loutItemSerno}]`);
|
||||
|
||||
// Recursively print the children
|
||||
if (node.children.length > 0) {
|
||||
for (const child of node.children) {
|
||||
this.printNode(child, level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static moveNodeDepth(root, node, newDepth) {
|
||||
if (node === null || root === null || newDepth < 0) {
|
||||
// Invalid input
|
||||
return;
|
||||
}
|
||||
|
||||
const parent = this.getParentNode(root, node);
|
||||
if (parent === null) {
|
||||
// Node is the root node, cannot be moved to a different level
|
||||
return;
|
||||
}
|
||||
|
||||
const currentDepth = node.loutItemDepth;
|
||||
const nodeIndex = this.getNodeIndex(parent, node);
|
||||
const nextSibling = this.findClosestSibling(parent.children, nodeIndex);
|
||||
parent.children.splice(nodeIndex, 1);
|
||||
|
||||
if (newDepth > currentDepth) {
|
||||
// Moving to a higher depth
|
||||
if (nextSibling !== null) {
|
||||
nextSibling.children.push(node);
|
||||
node.parent = nextSibling.id;
|
||||
node.loutItemDepth = newDepth;
|
||||
this.adjustChildrenDepth(node, newDepth + 1);
|
||||
} else {
|
||||
// No next sibling found, add the node back to the original parent
|
||||
parent.children.push(node);
|
||||
}
|
||||
} else {
|
||||
// Moving to a lower depth
|
||||
const newParent = this.findParent(root, parent);
|
||||
if (newParent !== null) {
|
||||
newParent.children.push(node);
|
||||
node.parent = newParent.id;
|
||||
node.loutItemDepth = newDepth;
|
||||
this.adjustChildrenDepth(node, newDepth + 1);
|
||||
} else {
|
||||
// No parent found at the desired level, add the node back to the original parent
|
||||
parent.children.push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static adjustChildrenDepth(node, depth) {
|
||||
for (const child of node.children) {
|
||||
child.loutItemDepth = depth;
|
||||
this.adjustChildrenDepth(child, depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static findNextSibling(siblings) {
|
||||
if (siblings === null || siblings.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return siblings[0];
|
||||
}
|
||||
|
||||
static findClosestSibling(siblings, nodeIndex) {
|
||||
if (siblings === null || siblings.length === 0) {
|
||||
return null;
|
||||
}
|
||||
if (nodeIndex < 1 || nodeIndex >= siblings.length) {
|
||||
return this.findNextSibling(siblings);
|
||||
}
|
||||
return siblings[nodeIndex - 1];
|
||||
}
|
||||
}
|
||||
|
||||
export default ApiLayoutItemTreeBuilder;
|
||||
@@ -0,0 +1,51 @@
|
||||
class ApiLayoutItemTreeDataBuilder {
|
||||
constructor(startId = 10000) {
|
||||
this.idCounter = this.generateId(startId);
|
||||
this.nodeMap = new Map();
|
||||
}
|
||||
|
||||
* generateId(start) {
|
||||
let id = start;
|
||||
while (true) {
|
||||
yield id++;
|
||||
}
|
||||
}
|
||||
|
||||
cloneNode(node, parent) {
|
||||
|
||||
// Create a shallow copy of the node, except for the children array
|
||||
let newNode = {
|
||||
...node,
|
||||
id: this.idCounter.next().value, // Update with a new unique ID
|
||||
parent: parent ? parent.id : undefined // Set the new parent's ID if parent exists
|
||||
};
|
||||
|
||||
// Remove children property to handle it separately
|
||||
delete newNode.children;
|
||||
this.nodeMap.set(newNode.id, newNode);
|
||||
return newNode;
|
||||
}
|
||||
|
||||
replicateTree(node, parent = null) {
|
||||
const newNode = this.cloneNode(node, parent);
|
||||
newNode.children = []; // Initialize children array
|
||||
if (node.children && node.children.length > 0) {
|
||||
node.children.forEach(child => {
|
||||
const childCount = node.childOccCnt || 1;
|
||||
for (let i = 0; i < childCount; i++) {
|
||||
const childReplicas = this.replicateTree(child, newNode);
|
||||
newNode.children = newNode.children.concat(childReplicas);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return [newNode]; // Return an array containing only the new singular parent node with replicated children
|
||||
}
|
||||
|
||||
createReplicatedTree(originalTree) {
|
||||
// console.log({originalTree});
|
||||
return this.replicateTree(originalTree)[0]; // Return the first element to maintain the tree structure
|
||||
}
|
||||
}
|
||||
|
||||
export default ApiLayoutItemTreeDataBuilder;
|
||||
@@ -0,0 +1,272 @@
|
||||
export const fillPadding = async (apiRequest, value, dataLength) => {
|
||||
let paddedValue = value; // In real app, this would be processed by APIClient
|
||||
while (paddedValue.length < dataLength) {
|
||||
paddedValue = ' ' + paddedValue;
|
||||
}
|
||||
return paddedValue;
|
||||
};
|
||||
|
||||
class APIClient {
|
||||
constructor() {
|
||||
// Initialize global variables store
|
||||
window.globals = window.globals || {};
|
||||
this.abortController = null;
|
||||
this.contextPath = document.querySelector('meta[name="context-path"]')?.getAttribute('content') || '/';
|
||||
|
||||
if (!this.contextPath.endsWith('/')) {
|
||||
this.contextPath += '/';
|
||||
}
|
||||
}
|
||||
|
||||
getClientUrl() {
|
||||
return `${this.contextPath}mgmt/api/test.do`;
|
||||
}
|
||||
|
||||
// Format response for consistency
|
||||
formatResponse(data) {
|
||||
return {
|
||||
body: data.body,
|
||||
status: data.status,
|
||||
headers: data.headers.reduce((acc, header) => {
|
||||
acc[header.key] = header.value;
|
||||
return acc;
|
||||
}, {}),
|
||||
size: data.size
|
||||
};
|
||||
}
|
||||
|
||||
// Abort ongoing requests
|
||||
abort() {
|
||||
if (this.abortController) {
|
||||
this.abortController.abort();
|
||||
this.abortController = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Make the actual API request
|
||||
async makeAjaxRequest(processedRequest) {
|
||||
this.abortController = new AbortController();
|
||||
|
||||
try {
|
||||
const response = await fetch(this.getClientUrl(), {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-XSRF-TOKEN': document.querySelector('meta[name="_csrf"]')?.getAttribute('content')
|
||||
},
|
||||
body: JSON.stringify(processedRequest),
|
||||
signal: this.abortController.signal
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Network request failed');
|
||||
}
|
||||
|
||||
return response;
|
||||
|
||||
} catch (error) {
|
||||
if (error.name === 'AbortError') {
|
||||
// Handle abort silently
|
||||
return null;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Process pre-script and variables
|
||||
async processPreScriptAndVariables(model, value, consoleOutput) {
|
||||
const variables = {};
|
||||
const updatedModel = await this.executePreRequestScript(model, variables, consoleOutput);
|
||||
return this.replacePlaceholderValueWithVariables(updatedModel, value, variables);
|
||||
}
|
||||
|
||||
// Replace placeholder values with actual variables
|
||||
replacePlaceholderValueWithVariables(model, originalValue, variables = {}) {
|
||||
const mergedVariables = {
|
||||
...window.globals,
|
||||
...variables
|
||||
};
|
||||
|
||||
return Object.entries(mergedVariables).reduce((value, [key, replacement]) => {
|
||||
const placeholder = `{{${key}}}`;
|
||||
return value.replace(new RegExp(placeholder, 'g'), replacement);
|
||||
}, originalValue);
|
||||
}
|
||||
|
||||
// Main method to send API requests
|
||||
async sendAPIRequest(model, preProcessCallback, consoleOutput) {
|
||||
try {
|
||||
// Execute pre-request script and get variables
|
||||
const variables = {};
|
||||
const updatedModel = await this.executePreRequestScript(model, variables, consoleOutput);
|
||||
|
||||
// Process request with variables
|
||||
const processedRequest = this.replacePlaceholdersWithVariables(updatedModel, variables);
|
||||
|
||||
// Allow pre-processing if callback provided
|
||||
if (preProcessCallback) {
|
||||
preProcessCallback(processedRequest);
|
||||
}
|
||||
|
||||
// Make the request
|
||||
const response = await this.makeAjaxRequest(processedRequest, consoleOutput);
|
||||
if (!response) return null;
|
||||
|
||||
const responseData = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(responseData.error || 'Unknown error');
|
||||
}
|
||||
|
||||
// Format response
|
||||
const finalResponse = this.formatResponse(responseData);
|
||||
|
||||
// Execute post-request script
|
||||
return this.executePostRequestScript(
|
||||
model.postRequestScript,
|
||||
variables,
|
||||
processedRequest,
|
||||
finalResponse,
|
||||
consoleOutput
|
||||
).catch(error => {
|
||||
console.error('Post-request script error:', error);
|
||||
return finalResponse;
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
throw new Error(`API 호출 중 오류가 발생했습니다. 사유[${error.message}]`);
|
||||
}
|
||||
}
|
||||
|
||||
// Replace placeholders in request with variables
|
||||
replacePlaceholdersWithVariables(original, variables = {}) {
|
||||
const request = JSON.parse(JSON.stringify(original));
|
||||
const mergedVariables = {
|
||||
...window.globals,
|
||||
...variables
|
||||
};
|
||||
|
||||
Object.entries(mergedVariables).forEach(([key, value]) => {
|
||||
const placeholder = new RegExp(`{{${key}}}`, 'g');
|
||||
|
||||
// Replace in path
|
||||
request.path = request.path.replace(placeholder, value);
|
||||
|
||||
// Replace in request body
|
||||
if (request.requestBody) {
|
||||
request.requestBody = request.requestBody.replace(placeholder, value);
|
||||
}
|
||||
|
||||
// Replace in headers
|
||||
if (request.headers?.length) {
|
||||
request.headers = JSON.parse(
|
||||
JSON.stringify(request.headers).replace(placeholder, value)
|
||||
);
|
||||
}
|
||||
|
||||
// Replace in query params
|
||||
if (request.queryParams?.length) {
|
||||
request.queryParams = JSON.parse(
|
||||
JSON.stringify(request.queryParams).replace(placeholder, value)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
// Execute pre-request script in an iframe
|
||||
executePreRequestScript(model, variables, consoleOutput) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const resultFrame = document.getElementById('preRequest');
|
||||
if (!resultFrame) {
|
||||
console.warn('preRequest iframe not found');
|
||||
resolve(model);
|
||||
return;
|
||||
}
|
||||
|
||||
window.preRequestComplete = (updatedModel, error) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(updatedModel);
|
||||
}
|
||||
};
|
||||
|
||||
window.temp_variable = variables;
|
||||
window.currentRequest = model;
|
||||
window.consoleOutput = consoleOutput;
|
||||
|
||||
resultFrame.srcdoc = `
|
||||
<script>
|
||||
var oldLog = console.log;
|
||||
console.log = function(message) {
|
||||
if(window.parent.consoleOutput)
|
||||
window.parent.consoleOutput(message);
|
||||
oldLog.apply(console, arguments);
|
||||
};
|
||||
|
||||
window.globals = window.parent.globals;
|
||||
window.variables = window.parent.temp_variable;
|
||||
window.request = window.parent.currentRequest;
|
||||
|
||||
try {
|
||||
${model.preRequestScript || ''}
|
||||
window.parent.preRequestComplete(window.request, null);
|
||||
} catch (error) {
|
||||
window.parent.preRequestComplete(null, error);
|
||||
}
|
||||
</script>
|
||||
`;
|
||||
});
|
||||
}
|
||||
|
||||
// Execute post-request script in an iframe
|
||||
executePostRequestScript(script, variables, request, response, consoleOutput) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const resultFrame = document.getElementById('postRequest');
|
||||
if (!resultFrame) {
|
||||
console.warn('postRequest iframe not found');
|
||||
resolve(response);
|
||||
return;
|
||||
}
|
||||
|
||||
window.request = request;
|
||||
window.response = response;
|
||||
window.temp_variable = variables;
|
||||
window.postRequestComplete = (response, error) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(response);
|
||||
}
|
||||
};
|
||||
window.consoleOutput = consoleOutput;
|
||||
|
||||
resultFrame.srcdoc = `
|
||||
<script>
|
||||
var oldLog = console.log;
|
||||
console.log = function(message) {
|
||||
if(window.parent.consoleOutput)
|
||||
window.parent.consoleOutput(message);
|
||||
oldLog.apply(console, arguments);
|
||||
};
|
||||
|
||||
window.globals = window.parent.globals;
|
||||
window.variables = window.parent.temp_variable;
|
||||
window.request = window.parent.request;
|
||||
window.response = window.parent.response;
|
||||
|
||||
try {
|
||||
${script || ''}
|
||||
window.parent.postRequestComplete(window.response, null);
|
||||
} catch (error) {
|
||||
window.parent.postRequestComplete(window.response, error.toString());
|
||||
}
|
||||
</script>
|
||||
`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default APIClient;
|
||||
@@ -0,0 +1,6 @@
|
||||
import { clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
export const basePath = (servers, serverId) => {
|
||||
if (!serverId) return '';
|
||||
return servers.find(server => server.id == serverId)?.basePath || '';
|
||||
};
|
||||
|
||||
export const getServer = (servers, serverId) => {
|
||||
return servers.find(server => server.id == serverId);
|
||||
};
|
||||
|
||||
export const getHeader = (headers = [], key) => {
|
||||
const header = headers.find(header => header.key === key);
|
||||
if (!header) {
|
||||
const newHeader = { key, value: '', enabled: true };
|
||||
headers.push(newHeader);
|
||||
return newHeader;
|
||||
}
|
||||
return header;
|
||||
};
|
||||
Reference in New Issue
Block a user