socket client
This commit is contained in:
@@ -3,143 +3,146 @@
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/default_layout}">
|
||||
<body>
|
||||
<section layout:fragment="contentFragment">
|
||||
<div class="container-fluid">
|
||||
<div class="card mt-2">
|
||||
<div class="card-header">
|
||||
<h3 th:if="${server.id == null}">서버 등록</h3>
|
||||
<h3 th:if="${server.id != null}">서버 수정</h3>
|
||||
<div class="container-fluid">
|
||||
<div class="card mt-2">
|
||||
<div class="card-header">
|
||||
<h3 th:if="${server.id == null}">서버 등록</h3>
|
||||
<h3 th:if="${server.id != null}">서버 수정</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form name="serverForm" id="serverForm"
|
||||
th:action="${server.id==null}?@{/mgmt/servers/register.do}:@{/mgmt/servers/update.do}"
|
||||
th:object='${server}' method="post">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
|
||||
<input type="hidden" th:name="id" th:value="${server.id}">
|
||||
<div class="form-floating mt-2">
|
||||
<input type="text" class="form-control" th:field="*{name}" placeholder="서버명" required>
|
||||
<label for="name">서버명</label>
|
||||
<th:block th:each="err : ${#fields.errors('name')}">
|
||||
<div th:text="${err}" class="invalid-feedback"></div>
|
||||
</th:block>
|
||||
</div>
|
||||
<div class="input-group col-md mt-2">
|
||||
<div class="form-floating">
|
||||
<select class="form-select" th:field="*{scheme}" style="border-top-right-radius: 0; border-bottom-right-radius: 0;">
|
||||
<option value="http" th:selected="${server.scheme =='http'}">http</option>
|
||||
<option value="https" th:selected="${server.scheme =='https'}">https</option>
|
||||
<option value="tcp" th:selected="${server.scheme =='tcp'}">tcp</option>
|
||||
</select>
|
||||
<label for="scheme">Scheme</label>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form name="serverForm" id="serverForm"
|
||||
th:action="${server.id==null}?@{/mgmt/servers/register.do}:@{/mgmt/servers/update.do}"
|
||||
th:object='${server}' method="post">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
|
||||
<input type="hidden" th:name="id" th:value="${server.id}">
|
||||
<div class="form-floating mt-2">
|
||||
<input type="text" class="form-control" th:field="*{name}" placeholder="서버명" required>
|
||||
<label for="name">서버명</label>
|
||||
<th:block th:each="err : ${#fields.errors('name')}">
|
||||
<div th:text="${err}" class="invalid-feedback"></div>
|
||||
</th:block>
|
||||
</div>
|
||||
<div class="input-group col-md mt-2">
|
||||
<div class="form-floating">
|
||||
<select class="form-select" th:field="*{scheme}" style="border-top-right-radius: 0; border-bottom-right-radius: 0;">
|
||||
<option value="http" th:selected="${server.scheme =='http'}">http</option>
|
||||
<option value="https" th:selected="${server.scheme =='https'}">https</option>
|
||||
<option value="tcp" th:selected="${server.scheme =='tcp'}">tcp</option>
|
||||
</select>
|
||||
<label for="scheme">Scheme</label>
|
||||
</div>
|
||||
<span class="input-group-text" id="inputGroup-sizing-sm">://</span>
|
||||
<div class="form-floating">
|
||||
<input type="text" class="form-control" style="border-radius: 0;" th:field="*{hostname}" placeholder="서버 주소" required>
|
||||
<label for="hostname">서버 주소</label>
|
||||
<th:block th:each="err : ${#fields.errors('hostname')}">
|
||||
<div th:text="${err}" class="invalid-feedback"></div>
|
||||
</th:block>
|
||||
</div>
|
||||
<span class="input-group-text" id="inputGroup-sizing-sm">:</span>
|
||||
<div class="form-floating">
|
||||
<input type="text" class="form-control" style="border-radius: 0;" th:field="*{port}" placeholder="포트" required>
|
||||
<label for="port">포트</label>
|
||||
<th:block th:each="err : ${#fields.errors('port')}">
|
||||
<div th:text="${err}" class="invalid-feedback"></div>
|
||||
</th:block>
|
||||
</div>
|
||||
<div class="form-floating">
|
||||
<input type="text" class="form-control" style="border-top-left-radius: 0; border-bottom-left-radius: 0;" th:field="*{basePath}" placeholder="기본 경로" required>
|
||||
<label for="basePath">기본 경로</label>
|
||||
<th:block th:each="err : ${#fields.errors('basePath')}">
|
||||
<div th:text="${err}" class="invalid-feedback"></div>
|
||||
</th:block>
|
||||
</div>
|
||||
</div>
|
||||
<!-- TCP-specific fields -->
|
||||
<div id="tcpFields" style="display: none;">
|
||||
<div class="input-group">
|
||||
<div class="form-floating mt-2 me-2">
|
||||
<input type="text" class="form-control" th:field="*{lengthFieldOffset}" placeholder="Length Field Offset">
|
||||
<label for="lengthFieldOffset">길이 필드 시작 위치</label>
|
||||
</div>
|
||||
<div class="form-floating mt-2 me-2">
|
||||
<input type="text" class="form-control" th:field="*{lengthFieldLength}" placeholder="Length Field Length">
|
||||
<label for="lengthFieldLength">길이 필드 길이</label>
|
||||
</div>
|
||||
<div class="form-check mt-2">
|
||||
<input class="form-check-input" type="checkbox" th:field="*{lengthFieldInclude}" id="lengthFieldInclude">
|
||||
<label class="form-check-label" for="lengthFieldInclude">길이 필드 포함</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<div class="form-floating mt-2 me-2">
|
||||
<input type="text" class="form-control" th:field="*{messageKeyOffset}" placeholder="Message Key Offset">
|
||||
<label for="messageKeyOffset">메시지 키 시작 위치</label>
|
||||
</div>
|
||||
<div class="form-floating mt-2 me-2">
|
||||
<input type="text" class="form-control" th:field="*{messageKeyLength}" placeholder="Message Key Length">
|
||||
<label for="messageKeyLength">메시지 키 길이</label>
|
||||
</div>
|
||||
<div class="form-check mt-2">
|
||||
<input class="form-check-input" type="checkbox" th:field="*{messageKeyInclude}" id="messageKeyInclude">
|
||||
<label class="form-check-label" for="messageKeyInclude">메시지 키 포함</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-check mt-2">
|
||||
<input type="checkbox" class="form-check-input" th:field="*{enabled}" placeholder="사용 여부">
|
||||
<label class="form-check-label" for="enabled">사용?</label>
|
||||
</div>
|
||||
</form>
|
||||
<span class="input-group-text" id="inputGroup-sizing-sm">://</span>
|
||||
<div class="form-floating">
|
||||
<input type="text" class="form-control" style="border-radius: 0;" th:field="*{hostname}" placeholder="서버 주소" required>
|
||||
<label for="hostname">서버 주소</label>
|
||||
<th:block th:each="err : ${#fields.errors('hostname')}">
|
||||
<div th:text="${err}" class="invalid-feedback"></div>
|
||||
</th:block>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="button" class="btn btn-primary btn_list"><i class="fa-solid fa-list"></i> 목록</button>
|
||||
<button type="button" class="btn btn-primary btn_register"><i class="fa-sharp fa-solid fa-floppy-disk"></i> 저장</button>
|
||||
<span class="input-group-text" id="inputGroup-sizing-sm">:</span>
|
||||
<div class="form-floating">
|
||||
<input type="text" class="form-control" style="border-radius: 0;" th:field="*{port}" placeholder="포트" required>
|
||||
<label for="port">포트</label>
|
||||
<th:block th:each="err : ${#fields.errors('port')}">
|
||||
<div th:text="${err}" class="invalid-feedback"></div>
|
||||
</th:block>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-floating">
|
||||
<input type="text" class="form-control" style="border-top-left-radius: 0; border-bottom-left-radius: 0;" th:field="*{basePath}" placeholder="기본 경로" required>
|
||||
<label for="basePath">기본 경로</label>
|
||||
<th:block th:each="err : ${#fields.errors('basePath')}">
|
||||
<div th:text="${err}" class="invalid-feedback"></div>
|
||||
</th:block>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-check mt-2">
|
||||
<input type="checkbox" class="form-check-input" th:field="*{enabled}" placeholder="사용 여부">
|
||||
<label class="form-check-label" for="enabled">사용?</label>
|
||||
</div>
|
||||
<!-- Server Option fields -->
|
||||
<div id="serverOptionsContainer">
|
||||
<div class="mt-1">
|
||||
<span>서버 메시지 옵션</span>
|
||||
<button type="button" class="btn btn-primary add-option"><i class="fas fa-plus"></i></button>
|
||||
</div>
|
||||
<!-- header for options fields -->
|
||||
<div class="input-group mt-2">
|
||||
<span style="width: 120px;">키</span>
|
||||
<span style="width: 160px;">이름</span>
|
||||
<span style="width: 160px;">메시지 위치</span>
|
||||
<span style="width: 160px;">메시지 길이</span>
|
||||
<span style="width: 160px;">기본 값</span>
|
||||
</div>
|
||||
<th:block th:each="option, optionStat : *{serverOptions}">
|
||||
<div class="input-group mb-3" style="width: 800px" th:id="'option-' + ${optionStat.index}">
|
||||
<input type="text" style="width: 120px;" class="form-control" th:field="*{serverOptions[__${optionStat.index}__].optionKey}" placeholder="키">
|
||||
<input type="text" style="width: 160px;" class="form-control" th:field="*{serverOptions[__${optionStat.index}__].optionName}" placeholder="이름">
|
||||
<input type="number" style="width: 160px;" class="form-control" th:field="*{serverOptions[__${optionStat.index}__].offset}" placeholder="메시지 위치">
|
||||
<input type="number" style="width: 160px;" class="form-control" th:field="*{serverOptions[__${optionStat.index}__].length}" placeholder="메시지 길이">
|
||||
<input type="text" style="width: 160px;" class="form-control" th:field="*{serverOptions[__${optionStat.index}__].defaultValue}" placeholder="기본 값">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary remove-option" type="button"><i class="fas fa-trash-alt"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="button" class="btn btn-primary btn_list"><i class="fa-solid fa-list"></i> 목록</button>
|
||||
<button type="button" class="btn btn-primary btn_register"><i class="fa-sharp fa-solid fa-floppy-disk"></i> 저장</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
<th:block layout:fragment="contentScript">
|
||||
<script>
|
||||
$(function () {
|
||||
<script>
|
||||
$(function() {
|
||||
|
||||
function toggleTcpFields() {
|
||||
let scheme = document.querySelector('select[name="scheme"]').value;
|
||||
console.log(scheme)
|
||||
let tcpFields = document.getElementById('tcpFields');
|
||||
if (scheme === 'tcp') {
|
||||
tcpFields.style.display = 'block';
|
||||
} else {
|
||||
tcpFields.style.display = 'none';
|
||||
}
|
||||
}
|
||||
const optionsContainer = document.getElementById('serverOptionsContainer');
|
||||
const addOptionButton = document.querySelector('.add-option');
|
||||
|
||||
// Run on page load
|
||||
toggleTcpFields();
|
||||
addOptionButton.addEventListener('click', function() {
|
||||
const index = document.querySelectorAll('.input-group').length;
|
||||
const optionHtml = `<div class="input-group mb-3">
|
||||
<input type="text" class="form-control" name="serverOptions[${index}].optionKey" placeholder="키">
|
||||
<input type="text" class="form-control" name="serverOptions[${index}].optionName" placeholder="이름">
|
||||
<input type="number" class="form-control" name="serverOptions[${index}].offset" placeholder="메시지 위치">
|
||||
<input type="number" class="form-control" name="serverOptions[${index}].length" placeholder="메시지 길이">
|
||||
<input type="text" class="form-control" name="serverOptions[${index}].defaultValue" placeholder="기본 값">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary remove-option" type="button"><i class="fas fa-trash-alt"></i></button>
|
||||
</div>
|
||||
</div>`;
|
||||
optionsContainer.insertAdjacentHTML('beforeend', optionHtml);
|
||||
});
|
||||
|
||||
// Attach event listener to scheme select element
|
||||
document.querySelector('select[name="scheme"]').addEventListener('change', toggleTcpFields);
|
||||
optionsContainer.addEventListener('click', function(event) {
|
||||
if (event.target.closest('button').classList.contains('remove-option')) {
|
||||
event.target.closest('.input-group').remove();
|
||||
}
|
||||
});
|
||||
|
||||
let fnRegister = document.querySelector('.btn_register');
|
||||
fnRegister.addEventListener('click', function(event) {
|
||||
let form = document.getElementById('serverForm');
|
||||
if (!form.checkValidity()) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
} else {
|
||||
form.submit();
|
||||
}
|
||||
form.classList.add('was-validated');
|
||||
});
|
||||
|
||||
let fnRegister = document.querySelector(".btn_register");
|
||||
fnRegister.addEventListener("click", function (event) {
|
||||
let form = document.getElementById("serverForm");
|
||||
if (!form.checkValidity()) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
} else {
|
||||
form.submit();
|
||||
}
|
||||
form.classList.add('was-validated');
|
||||
});
|
||||
let fnList = document.querySelector('.btn_list');
|
||||
|
||||
let fnList = document.querySelector(".btn_list");
|
||||
|
||||
fnList.addEventListener("click", function () {
|
||||
location.href = "[[@{/mgmt/servers/list_view.do}]]";
|
||||
});
|
||||
});
|
||||
</script>
|
||||
fnList.addEventListener('click', function() {
|
||||
location.href = '[[@{/mgmt/servers/list_view.do}]]';
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</th:block>
|
||||
</html>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
fetch('[[@{/mgmt/servers/list.do}]]').then(response => response.json()).then(data => {
|
||||
fetch('[[@{/servers/list.do}]]').then(response => response.json()).then(data => {
|
||||
let options = {};
|
||||
options.contextPath = '[[@{/}]]';
|
||||
options.servers = data;
|
||||
|
||||
@@ -73,9 +73,8 @@
|
||||
</body>
|
||||
|
||||
<th:block layout:fragment="contentScript">
|
||||
<link th:href="@{/css/goldenlayout-base.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/css/goldenlayout-light-theme.css}" rel="stylesheet"/>
|
||||
<link rel="stylesheet" th:href="@{/css/xspreadsheet.css}">
|
||||
<!-- <link th:href="@{/css/goldenlayout-base.css}" rel="stylesheet"/>-->
|
||||
<!-- <link th:href="@{/css/goldenlayout-light-theme.css}" rel="stylesheet"/>-->
|
||||
<script th:src="@{/plugins/apitestmanager/app.bundle.js}"></script>
|
||||
<script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user