응답 -> 탭 적용
This commit is contained in:
+5
-2
@@ -46,7 +46,9 @@ public class MockRouteMgmtController {
|
||||
@GetMapping("/create_view.do")
|
||||
public String createView(ModelMap model) {
|
||||
MockRouteDTO defaultRoute = new MockRouteDTO();
|
||||
defaultRoute.getResponses().add(new MockResponseDTO());
|
||||
MockResponseDTO defaultResponse = new MockResponseDTO();
|
||||
defaultResponse.setDefaultResponse(true);
|
||||
defaultRoute.getResponses().add(defaultResponse);
|
||||
model.addAttribute("mockRoute", defaultRoute);
|
||||
return MOCK_ROUTE_EDIT;
|
||||
}
|
||||
@@ -55,7 +57,8 @@ public class MockRouteMgmtController {
|
||||
public String updateView(ModelMap model, @RequestParam("id") Long id) {
|
||||
|
||||
MockRoute found = mockRouteService.findById(id);
|
||||
model.addAttribute("mockRoute", found);
|
||||
|
||||
model.addAttribute("mockRoute", mockRouteMapper.map(found));
|
||||
return MOCK_ROUTE_EDIT;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,11 @@ package com.eactive.httpmockserver.api.dto;
|
||||
import javax.validation.constraints.Min;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MockResponseDTO {
|
||||
|
||||
@Min(100)
|
||||
private int statusCode = 100;
|
||||
private int statusCode = 200;
|
||||
|
||||
private List<MockHeaderDTO> headers = new ArrayList<>();
|
||||
|
||||
@@ -16,6 +15,7 @@ public class MockResponseDTO {
|
||||
|
||||
private long delay = 0; //millisecond
|
||||
|
||||
private boolean defaultResponse = false;
|
||||
|
||||
private List<MockConditionDTO> conditions;
|
||||
public int getStatusCode() {
|
||||
@@ -57,4 +57,12 @@ public class MockResponseDTO {
|
||||
public void setConditions(List<MockConditionDTO> conditions) {
|
||||
this.conditions = conditions;
|
||||
}
|
||||
|
||||
public boolean isDefaultResponse() {
|
||||
return defaultResponse;
|
||||
}
|
||||
|
||||
public void setDefaultResponse(boolean defaultResponse) {
|
||||
this.defaultResponse = defaultResponse;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ public class MockResponse {
|
||||
|
||||
private long delay = 0; //millisecond
|
||||
|
||||
@Column(name = "DEFAULT_RESPONSE", nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean defaultResponse = false;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "ROUTE_ID", nullable = false)
|
||||
private MockRoute route;
|
||||
@@ -89,4 +92,12 @@ public class MockResponse {
|
||||
public void setConditions(List<MockCondition> conditions) {
|
||||
this.conditions = conditions;
|
||||
}
|
||||
|
||||
public boolean isDefaultResponse() {
|
||||
return defaultResponse;
|
||||
}
|
||||
|
||||
public void setDefaultResponse(boolean defaultResponse) {
|
||||
this.defaultResponse = defaultResponse;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,42 +59,7 @@ ul li {
|
||||
border-color: #f5c08d;
|
||||
}
|
||||
|
||||
/*메인페이지 뉴스 패널*/
|
||||
.nav-tabs {
|
||||
margin-top: 6px;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus {
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.nav-tabs > li > a {
|
||||
height: 60px;
|
||||
margin-right: 0;
|
||||
font-size: 16px;
|
||||
line-height: 2.5;
|
||||
color: #888;
|
||||
border-radius: 0;
|
||||
border: 0px;
|
||||
border-bottom: 2px solid #ddd;
|
||||
box-shadow: inset 0px 2px 0px .0px rgba(0, 0, 0, .2);
|
||||
}
|
||||
|
||||
.nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus {
|
||||
color: #222;
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 2px solid #222;
|
||||
box-shadow: inset 0px 1.5px 0px .0px rgba(0, 0, 0, 1);
|
||||
z-index: 999;
|
||||
background: url(../img/bullet01.png) no-repeat 190px center;
|
||||
}
|
||||
|
||||
.nav-tabs .active {
|
||||
border: 0px;
|
||||
}
|
||||
/*사이트소개*/
|
||||
.portal_main_head {
|
||||
position: relative;
|
||||
@@ -291,48 +256,11 @@ ul li {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
div.calen-s {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin-left: 10px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.calen-s span {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
div.calen-s input[type="date"] {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 150px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.signup .idsave {
|
||||
margin: 10px 0 0 95px;
|
||||
}
|
||||
|
||||
/*관리자 페이지 왼쪽 메뉴*/
|
||||
.admin_menu {
|
||||
display: block;
|
||||
position: relative;
|
||||
margin-left: 70px;
|
||||
float: left;
|
||||
top: 30px;
|
||||
padding: 10px 20px 10px 20px;
|
||||
width: 220px; /* box-shadow: 0px 0px 10px 2px rgba(0,0,0,0.08); */
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
clear: both;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.admin_menu ul li div ul li:last-child a {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
|
||||
.b-example-divider {
|
||||
flex-shrink: 0;
|
||||
width: 1.5rem;
|
||||
@@ -343,26 +271,6 @@ div.calen-s input[type="date"] {
|
||||
box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15);
|
||||
}
|
||||
|
||||
.btn-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 20px; /*margin: 10px 0 5px 0;*/
|
||||
height: 30px;
|
||||
background-color: /*transparent*/ #fff8eb;
|
||||
border-radius: 4px;
|
||||
border: 0;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.btn-toggle:hover,
|
||||
.btn-toggle:focus {
|
||||
color: rgba(0, 0, 0, .85);
|
||||
background-color: #fff8eb;
|
||||
}
|
||||
|
||||
/* 화면 스크롤 해도 nav_bar를 상단에 고정 */
|
||||
.fixed_top {
|
||||
position: fixed;
|
||||
@@ -382,97 +290,14 @@ div.calen-s input[type="date"] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.btn-toggle[aria-expanded="true"] {
|
||||
width: 100%;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
background-color: #fd9b00;
|
||||
}
|
||||
|
||||
.btn-toggle[aria-expanded="true"]::before {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.btn-toggle-nav a {
|
||||
display: inline-flex;
|
||||
width: 100%;
|
||||
padding: .1875rem .5rem;
|
||||
margin-top: .125rem;
|
||||
margin-left: 1.25rem;
|
||||
text-decoration: none;
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
|
||||
.scrollarea {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.admin_content {
|
||||
display: block;
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.has-error .form-control {
|
||||
border-color: #dc312d;
|
||||
}
|
||||
|
||||
.explan.error {
|
||||
color: #dc312d;
|
||||
}
|
||||
|
||||
|
||||
/*테스트 등록*/
|
||||
.testregister_wrap {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #ddd;
|
||||
margin: 20px 0 40px 0;
|
||||
}
|
||||
|
||||
.testregister_top {
|
||||
padding: 40px 60px 40px 60px;
|
||||
}
|
||||
|
||||
.testregister_left, .testregister_right {
|
||||
display: inline-block;
|
||||
width: 49.8%;
|
||||
padding: 40px 60px 60px 60px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.testregister_left {
|
||||
border-right: 1px solid #e6e6e6;
|
||||
}
|
||||
|
||||
|
||||
.testregister_wrap h3 {
|
||||
display: block;
|
||||
float: left;
|
||||
margin-top: 10px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.jg-regist {
|
||||
display: block;
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.jg-regist table tr {
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.jsgrid-table {
|
||||
position: relative;
|
||||
margin-left: 15px;
|
||||
@@ -482,103 +307,6 @@ div.calen-s input[type="date"] {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.testregister_wrap h3 span {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
margin-right: 10px;
|
||||
top: -2px;
|
||||
background-color: #222;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.testregister_wrap hr {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
border-color: #ddd;
|
||||
}
|
||||
|
||||
.testregister_result {
|
||||
width: 100%;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 6px;
|
||||
padding: 10px 0 10px 20px;
|
||||
line-height: 1.7;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.testregister_select_tit {
|
||||
float: left;
|
||||
width: 100%;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 6px;
|
||||
padding: 15px 0 15px 20px;
|
||||
line-height: 1.7;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.testregister_select_tit li {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.testregister_select {
|
||||
float: left;
|
||||
width: 100%;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 6px;
|
||||
padding: 10px 20px;
|
||||
background-color: #fafafa;
|
||||
line-height: 1.7;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.testregister_select li {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 46px;
|
||||
line-height: 2.8;
|
||||
text-indent: 20px;
|
||||
}
|
||||
|
||||
.testregister_select li:first-child {
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.testregister_select li:hover {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.testregister_result a, .testregister_select a {
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.testregister_left .pagination {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.testregister_left .pagination ul li a,
|
||||
.testregister_left .pagination ul li.on a,
|
||||
.testregister_left .pagination ul li:hover a {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.testregister_detail {
|
||||
padding: 40px 60px 40px 60px;
|
||||
}
|
||||
|
||||
.testregister_detail label {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.board_content {
|
||||
padding: 10px;
|
||||
line-height: 1.5;
|
||||
@@ -1812,7 +1540,6 @@ figure div span {
|
||||
}
|
||||
|
||||
|
||||
|
||||
.dev {
|
||||
background-color : #f74140 !important;
|
||||
color : white !important;
|
||||
|
||||
@@ -192,7 +192,6 @@
|
||||
|
||||
$('#path').on('input', function(){
|
||||
model.path = $(this).val();
|
||||
//parse querystring from path and set to model.queryParams
|
||||
model.queryParams = [];
|
||||
let queryString = model.path.split('?')[1];
|
||||
if(queryString){
|
||||
|
||||
@@ -10,16 +10,15 @@
|
||||
th:object='${mockRoute}' method="post">
|
||||
<div class="card col-md">
|
||||
<div class="card-header">
|
||||
<h3 th:if="${mockRoute.id == null}">API 정보 등록</h3>
|
||||
<h3 th:if="${mockRoute.id != null}">API 정보 수정</h3>
|
||||
<h5 th:if="${mockRoute.id == null}">API 정보 등록</h5>
|
||||
<h5 th:if="${mockRoute.id != null}">API 정보 수정</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
|
||||
<input type="hidden" name="id" th:value="${mockRoute.id}">
|
||||
<div class="form-floating mt-2">
|
||||
<input type="text" class="form-control"
|
||||
th:classappend="${#fields.hasErrors('name')}? 'is-invalid'" th:field="*{name}"
|
||||
name="username" id="name" required/>
|
||||
th:classappend="${#fields.hasErrors('name')}? 'is-invalid'" th:field="*{name}" required/>
|
||||
<label for="name" class="form-label must" th:text="#{name}">이름</label>
|
||||
<th:block th:each="err : ${#fields.errors('name')}">
|
||||
<div th:text="${err}" class="invalid-feedback"></div>
|
||||
@@ -53,134 +52,45 @@
|
||||
<div class="card mt-2">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<h3>응답</h3>
|
||||
<h5>응답</h5>
|
||||
<button type="button" class="btn btn-sm btn-primary btn_add_case"><i
|
||||
class="fa-sharp fa-solid fa-plus"></i>케이스 추가
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body" id="responses">
|
||||
<div class="card" th:each="response, status: *{responses}">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<span th:text="'조건 ' + ${status.index + 1}"></span>
|
||||
<button type="button" class="btn btn-secondary btn-sm btn_remove_case"
|
||||
th:data-id="${status.index+1}">제거
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>조건 항목</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">종류</th>
|
||||
<th scope="col">키</th>
|
||||
<th scope="col">값</th>
|
||||
<th>
|
||||
<button type="button" class="btn btn-secondary btn-sm">추가
|
||||
</button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="response_conditions">
|
||||
<tr th:each="condition, status: *{responses[__${status.index}__].conditions}">
|
||||
<td>
|
||||
<select>
|
||||
<option value="query"
|
||||
th:selected="${condition.type == 'query'}">Query
|
||||
</option>
|
||||
<option value="header"
|
||||
th:selected="${condition.type == 'header'}">Header
|
||||
</option>
|
||||
<option value="path"
|
||||
th:selected="${condition.type == 'path'}">Path
|
||||
</option>
|
||||
<option value="jsonpath"
|
||||
th:selected="${condition.type == 'jsonpath'}">JSON
|
||||
Path
|
||||
</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" type="text" name="key"
|
||||
th:value="${condition.key}"/>
|
||||
</td>
|
||||
<td><input class="form-control" type="text" name="value"
|
||||
th:value="${condition.value}"/></td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-secondary btn-sm">제거
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md">
|
||||
<div class="card">
|
||||
<div class="card-header">응답 내용</div>
|
||||
<div class="card-body">
|
||||
<div class="form-floating mt-2">
|
||||
<input class="form-control" type="number"
|
||||
th:field="*{responses[__${status.index}__].statusCode}"
|
||||
required/>
|
||||
<label class="form-label must">Status</label>
|
||||
</div>
|
||||
<div class="form-floating mt-2">
|
||||
<input class="form-control" type="number"
|
||||
th:field="*{responses[__${status.index}__].delay}" required/>
|
||||
<label class="form-label must">응답 지연 시간(ms)</label>
|
||||
</div>
|
||||
<div class="form-floating mt-2">
|
||||
<textarea class="form-control" style="height: 200px;"
|
||||
th:field="*{responses[__${status.index}__].body}">
|
||||
</textarea>
|
||||
<label class="form-label must">응답 Body</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Header 이름</th>
|
||||
<th>값</th>
|
||||
<th>
|
||||
<button type="button" class="btn btn-secondary btn-sm">추가
|
||||
</button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="response_headers">
|
||||
<tr th:each="header, status: *{responses[__${status.index}__].headers}">
|
||||
<td>
|
||||
<input class="form-control" type="text" name="key"
|
||||
th:value="${header.key}"/>
|
||||
</td>
|
||||
<td><input class="form-control" type="text" name="value"
|
||||
th:value="${header.value}"/></td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-secondary btn-sm">제거
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body" >
|
||||
<div id="responses">
|
||||
<div class="row" th:each="response, status: *{responses}">
|
||||
<input type="number" th:field="*{responses[__${status.index}__].statusCode}" required/>
|
||||
<textarea th:field="*{responses[__${status.index}__].body}"></textarea>
|
||||
<input type="number" th:field="*{responses[__${status.index}__].delay}" required/>
|
||||
<input type="text" th:field="*{responses[__${status.index}__].defaultResponse}" />
|
||||
<ul class="response_conditions">
|
||||
<li th:each="condition, status: *{responses[__${status.index}__].conditions}">
|
||||
<select>
|
||||
<option value="query" th:selected="${condition.type == 'query'}">Query</option>
|
||||
<option value="header" th:selected="${condition.type == 'header'}">Header</option>
|
||||
<option value="path" th:selected="${condition.type == 'path'}">Path</option>
|
||||
<option value="jsonpath" th:selected="${condition.type == 'jsonpath'}">JSON Path</option>
|
||||
</select>
|
||||
<input type="text" name="key" th:value="${condition.key}"/>
|
||||
<input type="text" name="value" th:value="${condition.value}"/>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="response_headers">
|
||||
<li th:each="header, status: *{responses[__${status.index}__].headers}">
|
||||
<input type="text" name="key" th:value="${header.key}"/>
|
||||
<input type="text" name="value" th:value="${header.value}"/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="nav nav-tabs" id="responseTabTitle" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="responseTabContent">
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="button" class="btn btn-primary btn_list"><i class="fa-solid fa-list"></i> 목록</button>
|
||||
@@ -190,122 +100,129 @@
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div id="template" style="visibility: hidden; height: 0;">
|
||||
<div class="card mt-1">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<span class="condition_name"></span>
|
||||
<button type="button" class="btn btn-secondary btn-sm btn_remove_case">제거</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>조건 항목</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">종류</th>
|
||||
<th scope="col">키</th>
|
||||
<th scope="col">값</th>
|
||||
<th>
|
||||
<button type="button" class="btn btn-secondary btn-sm btn_add_condition">추가</button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="response_conditions">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="template" style="visibility: hidden; height: 0;">
|
||||
<div class="tab-pane" role="tabpanel">
|
||||
<!-- <div class="card mt-1">-->
|
||||
<!-- <div class="card-header">-->
|
||||
<!-- <div class="d-flex justify-content-between">-->
|
||||
<!-- <span class="condition_name"></span>-->
|
||||
<!-- <button type="button" class="btn btn-secondary btn-sm btn_remove_case">제거</button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="card-body">-->
|
||||
<!-- -->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<div class="row mt-1">
|
||||
<div class="col-md">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>조건 항목</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md">
|
||||
<div class="card">
|
||||
<div class="card-header">응답 내용</div>
|
||||
<div class="card-body">
|
||||
<div class="form-floating mt-1">
|
||||
<input class="form-control" type="number" name="statusCode" required/>
|
||||
<label class="form-label must">Status</label>
|
||||
</div>
|
||||
<div class="form-floating mt-1">
|
||||
<input class="form-control" type="number" name="delay" required/>
|
||||
<label class="form-label must">응답 지연 시간(ms)</label>
|
||||
</div>
|
||||
<div class="form-floating mt-1">
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">종류</th>
|
||||
<th scope="col">키</th>
|
||||
<th scope="col">값</th>
|
||||
<th>
|
||||
<button type="button"
|
||||
class="btn btn-secondary btn-sm btn_add_condition">추가
|
||||
</button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="response_conditions">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md">
|
||||
<div class="card">
|
||||
<div class="card-header">응답 내용</div>
|
||||
<div class="card-body">
|
||||
<div class="form-floating mt-1">
|
||||
<input class="form-control" type="number" name="statusCode" required/>
|
||||
<label class="form-label must">Status</label>
|
||||
</div>
|
||||
<div class="form-floating mt-1">
|
||||
<input class="form-control" type="number" name="delay" required/>
|
||||
<label class="form-label must">응답 지연 시간(ms)</label>
|
||||
</div>
|
||||
<div class="form-floating mt-1">
|
||||
<textarea class="form-control" style="height: 200px;" name="body">
|
||||
</textarea>
|
||||
<label class="form-label must">응답 Body</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Header 이름</th>
|
||||
<th>값</th>
|
||||
<th>
|
||||
<button type="button" class="btn btn-secondary btn-sm btn_add_header">추가</button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="response_headers">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<label class="form-label must">응답 Body</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Header 이름</th>
|
||||
<th>값</th>
|
||||
<th>
|
||||
<button type="button" class="btn btn-secondary btn-sm btn_add_header">
|
||||
추가
|
||||
</button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="response_headers">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="conditionTemplate" style="visibility: hidden; height: 0;">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<select class="form-select">
|
||||
<option value="query">Query</option>
|
||||
<option value="header">Header</option>
|
||||
<option value="path">Path</option>
|
||||
<option value="jsonpath">JSON Path</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" type="text" name="key"/>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" type="text" name="value"/>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-secondary btn-sm btn_remove_condition">제거</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="responseHeaderTemplate" style="visibility: hidden; height: 0;">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<input class="form-control" type="text" name="key"/>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" type="text" name="value"/>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-secondary btn-sm btn_remove_header">제거</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div id="conditionTemplate" style="visibility: hidden; height: 0;">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<select class="form-select">
|
||||
<option value="query">Query</option>
|
||||
<option value="header">Header</option>
|
||||
<option value="path">Path Variable</option>
|
||||
<option value="jsonpath">JSON Path</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" type="text" name="key"/>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" type="text" name="value"/>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-secondary btn-sm btn_remove_condition">제거</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="responseHeaderTemplate" style="visibility: hidden; height: 0;">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<input class="form-control" type="text" name="key"/>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" type="text" name="value"/>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-secondary btn-sm btn_remove_header">제거</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
@@ -318,20 +235,23 @@
|
||||
name: '',
|
||||
method: '',
|
||||
pathPattern: '',
|
||||
responses: [
|
||||
]
|
||||
responses: []
|
||||
};
|
||||
|
||||
let view = {
|
||||
currentIdx: 0,
|
||||
init: function () {
|
||||
$('.btn_add_case').on('click', function () {
|
||||
controller.addResponse();
|
||||
});
|
||||
|
||||
$('#responses').on('click', 'button', function () {
|
||||
$('#responseTabTitle').on('click', 'button', function () {
|
||||
if ($(this).hasClass('btn_remove_case')) {
|
||||
controller.removeResponse($(this).attr("data-id"));
|
||||
}
|
||||
});
|
||||
|
||||
$('#responseTabContent').on('click', 'button', function () {
|
||||
if ($(this).hasClass('btn_add_condition')) {
|
||||
controller.addResponseCondition($(this).attr("data-id"));
|
||||
}
|
||||
@@ -349,16 +269,17 @@
|
||||
}
|
||||
});
|
||||
|
||||
$('#responses').children().each(function(){
|
||||
$('#responses').children().each(function () {
|
||||
let response = {
|
||||
conditions: [],
|
||||
headers: []
|
||||
};
|
||||
response.statusCode = $(this).find('input[name$="statusCode"]').val();
|
||||
response.delay = $(this).find('input[name$="delay"]').val();
|
||||
response.defaultResponse = $(this).find('input[name$="defaultResponse"]').val()==='true';
|
||||
response.body = $(this).find('textarea[name$="body"]').val();
|
||||
|
||||
$(this).find('.response_conditions').children().each(function(){
|
||||
$(this).find('.response_conditions').children().each(function () {
|
||||
let condition = {
|
||||
type: $(this).find('select').val(),
|
||||
key: $(this).find('input[name$="key"]').val(),
|
||||
@@ -369,7 +290,7 @@
|
||||
|
||||
model.responses.push(response);
|
||||
|
||||
$(this).find('.response_headers').children().each(function(){
|
||||
$(this).find('.response_headers').children().each(function () {
|
||||
let header = {
|
||||
key: $(this).find('input[name$="key"]').val(),
|
||||
value: $(this).find('input[name$="value"]').val()
|
||||
@@ -378,13 +299,46 @@
|
||||
});
|
||||
|
||||
});
|
||||
$('#responses').empty();
|
||||
this.render();
|
||||
},
|
||||
render: function () {
|
||||
$('#responses').empty();
|
||||
$('#responseTabTitle').empty();
|
||||
$('#responseTabContent').empty();
|
||||
|
||||
for (let i = 0; i < model.responses.length; i++) {
|
||||
let nodeCopy = $('#template').children().clone();
|
||||
nodeCopy.find('.condition_name').text('조건 ' + (i + 1));
|
||||
|
||||
let tabButton = $('<a>').attr('class', 'nav-link'+ (model.responses[i].defaultResponse? ' active' : ''))
|
||||
.attr('data-bs-toggle', 'tab')
|
||||
.attr('type', 'button')
|
||||
.attr('data-bs-target', '#response_tab_' + i)
|
||||
.attr('role', 'tab')
|
||||
.attr('aria-controls', 'response_tab_' + i)
|
||||
.attr('aria-selected', 'false')
|
||||
.text(model.responses[i].defaultResponse?'기본 응답':('조건 ' + (i + 1)));
|
||||
|
||||
// let minusButton = $('<button>').attr('class', 'btn btn-sm btn_remove_case')
|
||||
// .attr('type', 'button')
|
||||
// .attr('data-id', i)
|
||||
// .html('<i class="fa fa-minus-circle"></i>');
|
||||
|
||||
let li = $('<li>').attr('class', 'nav-item')
|
||||
.attr('role','presentation')
|
||||
.append(tabButton);
|
||||
// .append(minusButton);
|
||||
|
||||
$('#responseTabTitle').append(li);
|
||||
|
||||
nodeCopy.attr('id', 'response_tab_' + i);
|
||||
nodeCopy.attr('aria-labelledby', 'response_tab_' + i);
|
||||
nodeCopy.attr('tabindex', i);
|
||||
nodeCopy.attr('class', 'tab-pane fade ' + (model.responses[i].defaultResponse? 'show active' : ''));
|
||||
if (model.responses[i].defaultResponse) {
|
||||
nodeCopy.find('.condition_name').text('기본 응답');
|
||||
}else {
|
||||
nodeCopy.find('.condition_name').text('조건 ' + (i + 1));
|
||||
}
|
||||
nodeCopy.find('.btn_remove_case').attr("data-id", i);
|
||||
nodeCopy.find('.btn_add_condition').attr("data-id", i);
|
||||
nodeCopy.find('.btn_add_header').attr("data-id", i);
|
||||
@@ -396,21 +350,21 @@
|
||||
nodeCopy.find('input[name="responses[' + i + '].delay"]').val(model.responses[i].delay);
|
||||
nodeCopy.find('textarea[name="responses[' + i + '].body"]').val(model.responses[i].body);
|
||||
|
||||
nodeCopy.find('input[name="responses[' + i + '].statusCode"]').on('input', function() {
|
||||
nodeCopy.find('input[name="responses[' + i + '].statusCode"]').on('input', function () {
|
||||
model.responses[i].statusCode = $(this).val();
|
||||
});
|
||||
|
||||
nodeCopy.find('input[name="responses[' + i + '].delay"]').on('input', function() {
|
||||
nodeCopy.find('input[name="responses[' + i + '].delay"]').on('input', function () {
|
||||
model.responses[i].delay = $(this).val();
|
||||
});
|
||||
|
||||
nodeCopy.find('textarea[name="responses[' + i + '].body"]').on('input', function() {
|
||||
nodeCopy.find('textarea[name="responses[' + i + '].body"]').on('input', function () {
|
||||
model.responses[i].body = $(this).val();
|
||||
});
|
||||
|
||||
let conditions = nodeCopy.find('.response_conditions');
|
||||
|
||||
for(let c = 0; c < model.responses[i].conditions.length; c++){
|
||||
for (let c = 0; c < model.responses[i].conditions.length; c++) {
|
||||
let conditionTemplate = $('#conditionTemplate').children().find('tr').clone();
|
||||
conditionTemplate.find('select').attr('name', 'responses[' + i + '].conditions[' + c + '].type');
|
||||
conditionTemplate.find('input[name="key"]').attr('name', 'responses[' + i + '].conditions[' + c + '].key');
|
||||
@@ -422,45 +376,49 @@
|
||||
conditionTemplate.find('input[name="responses[' + i + '].conditions[' + c + '].key"]').val(model.responses[i].conditions[c].key);
|
||||
conditionTemplate.find('input[name="responses[' + i + '].conditions[' + c + '].value"]').val(model.responses[i].conditions[c].value);
|
||||
|
||||
conditionTemplate.find('select').on('change', function() {
|
||||
conditionTemplate.find('select').on('change', function () {
|
||||
model.responses[i].conditions[c].type = $(this).val();
|
||||
});
|
||||
|
||||
conditionTemplate.find('input[name="responses[' + i + '].conditions[' + c + '].key"]').on('input', function() {
|
||||
conditionTemplate.find('input[name="responses[' + i + '].conditions[' + c + '].key"]').on('input', function () {
|
||||
model.responses[i].conditions[c].key = $(this).val();
|
||||
});
|
||||
|
||||
conditionTemplate.find('input[name="responses[' + i + '].conditions[' + c + '].value"]').on('input', function() {
|
||||
conditionTemplate.find('input[name="responses[' + i + '].conditions[' + c + '].value"]').on('input', function () {
|
||||
model.responses[i].conditions[c].value = $(this).val();
|
||||
});
|
||||
|
||||
$(conditions).append(conditionTemplate);
|
||||
}
|
||||
|
||||
for(let j = 0; j < model.responses[i].headers.length; j++){
|
||||
for (let j = 0; j < model.responses[i].headers.length; j++) {
|
||||
let headerTemplate = $('#responseHeaderTemplate').children().find('tr').clone();
|
||||
headerTemplate.find('input[name="key"]').attr('name', 'responses[' + i + '].headers[' + j + '].key');
|
||||
headerTemplate.find('input[name="value"]').attr('name', 'responses[' + i + '].headers[' + j + '].value');
|
||||
headerTemplate.find('button').attr("data-id", i);
|
||||
headerTemplate.find('button').attr("data-row",j);
|
||||
headerTemplate.find('button').attr("data-row", j);
|
||||
|
||||
headerTemplate.find('input[name="responses[' + i + '].headers[' + j + '].key"]').val(model.responses[i].headers[j].key);
|
||||
headerTemplate.find('input[name="responses[' + i + '].headers[' + j + '].value"]').val(model.responses[i].headers[j].value);
|
||||
|
||||
headerTemplate.find('input[name="responses[' + i + '].headers[' + j + '].key"]').on('input', function() {
|
||||
headerTemplate.find('input[name="responses[' + i + '].headers[' + j + '].key"]').on('input', function () {
|
||||
model.responses[i].headers[j].key = $(this).val();
|
||||
});
|
||||
|
||||
headerTemplate.find('input[name="responses[' + i + '].headers[' + j + '].value"]').on('input', function() {
|
||||
headerTemplate.find('input[name="responses[' + i + '].headers[' + j + '].value"]').on('input', function () {
|
||||
model.responses[i].headers[j].value = $(this).val();
|
||||
});
|
||||
|
||||
$(nodeCopy).find('.response_headers').append(headerTemplate);
|
||||
}
|
||||
|
||||
$('#responses').append(nodeCopy);
|
||||
}
|
||||
$('#responseTabContent').append(nodeCopy);
|
||||
|
||||
}
|
||||
console.log('#responseTabTitle li:eq(' + view.currentIdx + ') a');
|
||||
console.log("render: " + view.currentIdx);
|
||||
$('#responseTabTitle li:eq(' + view.currentIdx + ') a').tab('show');
|
||||
// console.log(model);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -479,11 +437,12 @@
|
||||
view.render();
|
||||
},
|
||||
removeResponse: function (idx) {
|
||||
if (model.responses.length === 1) {
|
||||
alert('최소 1개의 응답이 필요합니다.');
|
||||
if (model.responses[idx].defaultResponse) {
|
||||
alert('기본 응답은 삭제할 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
model.responses.splice(idx, 1);
|
||||
view.currentIdx = 0;
|
||||
view.render();
|
||||
},
|
||||
addResponseCondition: function (idx) {
|
||||
@@ -492,21 +451,25 @@
|
||||
key: '',
|
||||
value: ''
|
||||
});
|
||||
view.currentIdx = idx;
|
||||
view.render();
|
||||
},
|
||||
removeResponseCondition: function (idx, conditionIdx) {
|
||||
model.responses[idx].conditions.splice(conditionIdx, 1);
|
||||
view.currentIdx = idx;
|
||||
view.render();
|
||||
},
|
||||
addResponseHeader : function(idx) {
|
||||
addResponseHeader: function (idx) {
|
||||
model.responses[idx].headers.push({
|
||||
key: '',
|
||||
value: ''
|
||||
});
|
||||
view.currentIdx = idx;
|
||||
view.render();
|
||||
},
|
||||
removeResponseHeader : function(idx, headerIdx) {
|
||||
removeResponseHeader: function (idx, headerIdx) {
|
||||
model.responses[idx].headers.splice(headerIdx, 1);
|
||||
view.currentIdx = idx;
|
||||
view.render();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user