컬렉션, 요청 삭제
This commit is contained in:
@@ -30,6 +30,11 @@ public class ApiRequestMgmtService {
|
||||
}
|
||||
|
||||
public void deleteApiCollection(String id) {
|
||||
ApiCollection collection = apiCollectionRepository.findById(id).orElseThrow(() -> new NotFoundException("api collection[" + id + "] not found"));
|
||||
|
||||
if (collection.getApis().size()>0){
|
||||
throw new RuntimeException("api collection[" + id + "] is not empty");
|
||||
}
|
||||
apiCollectionRepository.deleteById(id);
|
||||
}
|
||||
|
||||
|
||||
+9
@@ -21,4 +21,13 @@ public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler
|
||||
return new ResponseEntity<>(errors, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
public ResponseEntity<CustomErrorResponse> customHandleRuntime(Exception ex, WebRequest request) {
|
||||
CustomErrorResponse errors = new CustomErrorResponse();
|
||||
errors.setTimestamp(LocalDateTime.now());
|
||||
errors.setError(ex.getMessage());
|
||||
errors.setStatus(HttpStatus.BAD_REQUEST.value());
|
||||
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1547,4 +1547,19 @@ figure div span {
|
||||
.prod {
|
||||
background-color : #49cc90 !important;
|
||||
color : white !important;
|
||||
}
|
||||
}
|
||||
|
||||
.reset-button {
|
||||
/* Reset button styles */
|
||||
background: none;
|
||||
border: none;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
font: inherit;
|
||||
outline: inherit;
|
||||
|
||||
/* Style the icon */
|
||||
display: inline-block;
|
||||
margin-right: 5px; /* Adjust this value as per your requirement */
|
||||
}
|
||||
|
||||
@@ -40,6 +40,23 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="confirm_delete_modal" tabindex="-1" aria-labelledby="confirm_delete_modal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">컬렉션 삭제</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>삭제 하시겠습니까?</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
|
||||
<button type="button" class="btn btn-primary confirm_delete">삭제</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- menu script -->
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<section layout:fragment="contentFragment">
|
||||
<script>
|
||||
require.config({ paths: { 'vs': '/plugins/vs' }});
|
||||
require.config({paths: {'vs': '/plugins/vs'}});
|
||||
// require(['vs/editor/editor.main'], function(){});
|
||||
</script>
|
||||
<div id="loading-overlay" style="display: none;">
|
||||
@@ -25,7 +25,8 @@
|
||||
<div class="tab-content" id="apiRequestTabContent">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="new_api_request_modal" tabindex="-1" aria-labelledby="new_api_request_modal" aria-hidden="true">
|
||||
<div class="modal fade" id="new_api_request_modal" tabindex="-1" aria-labelledby="new_api_request_modal"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
@@ -61,7 +62,8 @@
|
||||
</div>
|
||||
<div class="form-floating col-md-1 me-1">
|
||||
<select class="form-select server" name="server">
|
||||
<option th:each="server : ${servers}" th:value="${server.id}" th:text="${server.name}" th:data-path="${server.basePath}"></option>
|
||||
<option th:each="server : ${servers}" th:value="${server.id}" th:text="${server.name}"
|
||||
th:data-path="${server.basePath}"></option>
|
||||
</select>
|
||||
<label class="form-label must">Server</label>
|
||||
</div>
|
||||
@@ -71,7 +73,7 @@
|
||||
<label class="must">base path</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group col-md">
|
||||
<div class="input-group col-md me-1">
|
||||
<div class="form-floating col-md">
|
||||
<input type="text" name="path" class="form-control path" placeholder="호출할 경로 (/부터 입력)"
|
||||
required>
|
||||
@@ -79,6 +81,7 @@
|
||||
</div>
|
||||
<button class="btn btn-primary send">Send</button>
|
||||
</div>
|
||||
<button class="btn btn-primary save">저장</button>
|
||||
</div>
|
||||
<ul class="nav nav-tabs mt-1" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
@@ -228,10 +231,14 @@
|
||||
<ul id="collectionTemplate" style="display: none;">
|
||||
<li>
|
||||
<div class="d-flex justify-content-between">
|
||||
<button class="btn d-inline-flex align-items-center rounded new_collection" data-bs-toggle="collapse"
|
||||
<button class="btn d-inline-flex align-items-center rounded new_collection normal"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="" aria-expanded="false" aria-current="false">컬렉션
|
||||
</button>
|
||||
<button class="p-1 hover:text-white delete_collection"><i class="fa fa-trash-can"></i></button>
|
||||
<div class="d-flex justify-content-between">
|
||||
<button class="p-1 reset-button edit_collection"><i class="fa fa-sharp fa-file-edit"></i></button>
|
||||
<button class="p-1 reset-button delete_collection"><i class="fa fa-sharp fa-trash-can"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse">
|
||||
<ul class="list-unstyled fw-normal pb-1 small">
|
||||
@@ -242,7 +249,7 @@
|
||||
<ul id="collectionApiTemplate" style="display: none;">
|
||||
<li class="d-flex justify-content-between">
|
||||
<a href="#" class="d-inline-flex align-items-center rounded"></a>
|
||||
<button class="p-1 hover:text-white delete_api_request"><i class="fa fa-trash-can"></i></button>
|
||||
<button class="p-1 reset-button delete_api_request"><i class="fa fa-trash-can"></i></button>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
@@ -269,18 +276,25 @@
|
||||
});
|
||||
|
||||
$('#new_request').on('click', function () {
|
||||
if (collections.length == 0) {
|
||||
alert('새로운 컬렉션을 추가해 주세요.');
|
||||
return;
|
||||
}
|
||||
$('#new_api_request_modal').modal('show');
|
||||
});
|
||||
|
||||
$('#new_api_request_modal').find('.add_new_request').on('click', function () {
|
||||
controller.addAPIRequest($('#new_api_request_modal').find('select').val());
|
||||
|
||||
});
|
||||
|
||||
$('#new_collection_modal').find('.save').on('click', function () {
|
||||
controller.addCollection($('#new_collection_modal').find('input').val());
|
||||
});
|
||||
|
||||
$('#confirm_delete_modal').find('button.confirm_delete').on('click', function () {
|
||||
controller.removeCollection($(this).data('id'));
|
||||
});
|
||||
|
||||
controller.loadCollections();
|
||||
},
|
||||
renderParam: function (tabIdx) {
|
||||
@@ -293,8 +307,8 @@
|
||||
template.find('input[name="key"]').val(model.queryParams[i].key);
|
||||
template.find('input[name="value"]').val(model.queryParams[i].value);
|
||||
|
||||
if(model.queryParams[i].enabled){
|
||||
template.find('input[name="enabled"]').prop("checked",model.queryParams[i].enabled);
|
||||
if (model.queryParams[i].enabled) {
|
||||
template.find('input[name="enabled"]').prop("checked", model.queryParams[i].enabled);
|
||||
}
|
||||
|
||||
template.find('button').attr("data-id", i);
|
||||
@@ -325,8 +339,8 @@
|
||||
let model = apiRequests[tabIdx];
|
||||
for (let i = 0; i < model.headers.length; i++) {
|
||||
let template = $('#inputTemplate').children().find('tr').clone();
|
||||
if(model.headers[i].enabled){
|
||||
template.find('input[name="enabled"]').prop("checked",model.headers[i].enabled);
|
||||
if (model.headers[i].enabled) {
|
||||
template.find('input[name="enabled"]').prop("checked", model.headers[i].enabled);
|
||||
}
|
||||
template.find('input[name="key"]').val(model.headers[i].key);
|
||||
template.find('input[name="value"]').val(model.headers[i].value);
|
||||
@@ -345,14 +359,14 @@
|
||||
target.find('.request_headers').append(template);
|
||||
}
|
||||
},
|
||||
renderTabHeader : function(){
|
||||
renderTabHeader: function () {
|
||||
let apiRequestTabTitle = $('#apiRequestTabTitle');
|
||||
apiRequestTabTitle.empty();
|
||||
for (let idx = 0; idx < apiRequests.length; idx++) {
|
||||
let $span = $('<span>')
|
||||
.html(' <i class="fa fa-light fa-close" data-id="'+ idx +'"></i>');
|
||||
.html(' <i class="fa fa-light fa-close" data-id="' + idx + '"></i>');
|
||||
|
||||
$span.on('click', function(event) {
|
||||
$span.on('click', function (event) {
|
||||
event.stopPropagation();
|
||||
controller.removeAPIRequest(idx);
|
||||
});
|
||||
@@ -374,7 +388,7 @@
|
||||
apiRequestTabTitle.append(li);
|
||||
}
|
||||
},
|
||||
renderTabContent: function(idx){
|
||||
renderTabContent: function (idx) {
|
||||
let apiRequestTabContent = $('#apiRequestTabContent');
|
||||
|
||||
let model = apiRequests[idx];
|
||||
@@ -384,13 +398,13 @@
|
||||
template.attr('id', 'api_request_' + idx);
|
||||
template.attr("data-id", idx);
|
||||
template.attr('class', 'tab-pane fade mt-1' + (idx === this.currentIdx ? ' show active' : ''));
|
||||
template.find('.btn_request_param_tab').attr('data-bs-target', "#requestParamTab_"+ idx);
|
||||
template.find('.btn_request_header_tab').attr('data-bs-target', "#requestHeaderTab_"+ idx);
|
||||
template.find('.btn_request_body_tab').attr('data-bs-target', "#requestBodyTab_"+ idx);
|
||||
template.find('.btn_request_param_tab').attr('data-bs-target', "#requestParamTab_" + idx);
|
||||
template.find('.btn_request_header_tab').attr('data-bs-target', "#requestHeaderTab_" + idx);
|
||||
template.find('.btn_request_body_tab').attr('data-bs-target', "#requestBodyTab_" + idx);
|
||||
|
||||
template.find('.request_param_tab').attr('id', "requestParamTab_"+ idx);
|
||||
template.find('.request_header_tab').attr('id', "requestHeaderTab_"+ idx);
|
||||
template.find('.request_body_tab').attr('id', "requestBodyTab_"+ idx);
|
||||
template.find('.request_param_tab').attr('id', "requestParamTab_" + idx);
|
||||
template.find('.request_header_tab').attr('id', "requestHeaderTab_" + idx);
|
||||
template.find('.request_body_tab').attr('id', "requestBodyTab_" + idx);
|
||||
|
||||
apiRequestTabContent.append(template);
|
||||
let target = $('#api_request_' + idx);
|
||||
@@ -435,7 +449,7 @@
|
||||
let queryParamArray = queryString.split('&');
|
||||
for (let i = 0; i < queryParamArray.length; i++) {
|
||||
let queryParam = queryParamArray[i].split('=');
|
||||
controller.addQueryParam(idx, queryParam[0], queryParam[1]===undefined?'' : queryParam[1]);
|
||||
controller.addQueryParam(idx, queryParam[0], queryParam[1] === undefined ? '' : queryParam[1]);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -445,7 +459,7 @@
|
||||
});
|
||||
let me = this;
|
||||
|
||||
require(['vs/editor/editor.main'], function() {
|
||||
require(['vs/editor/editor.main'], function () {
|
||||
let requestBodyEditor = monaco.editor.create(target.find(".request_body")[0], {
|
||||
value: '',
|
||||
language: 'json',
|
||||
@@ -503,8 +517,13 @@
|
||||
target.find('.response_headers').empty();
|
||||
target.find(".response_status").empty();
|
||||
|
||||
this.responses[tabIdx].setValue(model.responseModel.body);
|
||||
|
||||
try {
|
||||
const parsedJson = JSON.parse(model.responseModel.body);
|
||||
const formattedJson = JSON.stringify(parsedJson, null, 2);
|
||||
this.responses[tabIdx].setValue(formattedJson);
|
||||
}catch(e){
|
||||
this.responses[tabIdx].setValue(model.responseModel.body);
|
||||
}
|
||||
for (let i = 0; i < model.responseModel.headers.length; i++) {
|
||||
let template = $('#responseHeaderTemplate').children().find('tr').clone();
|
||||
template.find('input[name="key"]').val(model.responseModel.headers[i].key);
|
||||
@@ -512,31 +531,43 @@
|
||||
target.find('.response_headers').append(template);
|
||||
}
|
||||
|
||||
//show response status
|
||||
target.find(".response_status").text("status: " + model.responseModel.status);
|
||||
target.find(".response_time").text("time: " + model.responseModel.time + "ms");
|
||||
target.find(".response_size").text("size: " + model.responseModel.size + "bytes");
|
||||
},
|
||||
renderCollections: function(){
|
||||
renderCollections: function () {
|
||||
let select = $('#modal_collection');
|
||||
let sidemenu = $('#side_menubar');
|
||||
let sidemenu = $('#side_menubar');
|
||||
select.empty();
|
||||
sidemenu.empty();
|
||||
|
||||
for (let i = 0; i < collections.length; i++) {
|
||||
let template = $('#collectionTemplate').children().clone();
|
||||
template.attr('id', 'collection_' + i);
|
||||
template.find('button.new_collection').text(collections[i].name);
|
||||
template.find('button').attr('data-bs-target', '#collection_' + i);
|
||||
template.find('.collapse').attr('id', 'collection_' +i);
|
||||
template.find('button.new_collection').attr('data-bs-target', '#btn_collection_' + i);
|
||||
template.find('button.delete_collection').attr('data-id', collections[i].id);
|
||||
template.find('button.delete_collection').on('click', function () {
|
||||
$('#confirm_delete_modal').find('.confirm_delete').attr('data-id', $(this).attr('data-id'));
|
||||
$('#confirm_delete_modal').modal('show');
|
||||
});
|
||||
|
||||
template.find('.collapse').attr('id', 'btn_collection_' + i);
|
||||
|
||||
for (let j = 0; j < collections[i].apis.length; j++) {
|
||||
let collectionApiTemplate = $('#collectionApiTemplate').children().clone();
|
||||
let link = collectionApiTemplate.find('a');
|
||||
let btn = collectionApiTemplate.find('button.delete_api_request');
|
||||
link.text(collections[i].apis[j].name);
|
||||
link.attr('data-collection', collections[i].id);
|
||||
link.attr('data-id', collections[i].apis[j].id);
|
||||
link.on('click', function(){
|
||||
controller.openApiRequest($(this).attr('data-collection'),$(this).attr('data-id'));
|
||||
link.on('click', function () {
|
||||
controller.openApiRequest($(this).attr('data-collection'), $(this).attr('data-id'));
|
||||
})
|
||||
btn.attr('data-collection', collections[i].id);
|
||||
btn.attr('data-id', collections[i].apis[j].id);
|
||||
btn.on('click', function () {
|
||||
controller.deleteApiRequest($(this).attr('data-collection'), $(this).attr('data-id'));
|
||||
})
|
||||
template.find('.collapse ul').append(collectionApiTemplate);
|
||||
}
|
||||
@@ -586,7 +617,7 @@
|
||||
queryString += '?';
|
||||
}
|
||||
for (let i = 0; i < model.queryParams.length; i++) {
|
||||
if(!model.queryParams[i].enabled){
|
||||
if (!model.queryParams[i].enabled) {
|
||||
continue;
|
||||
}
|
||||
queryString += model.queryParams[i].key + '=' + model.queryParams[i].value;
|
||||
@@ -609,18 +640,28 @@
|
||||
hideLoadingOverlay: function () {
|
||||
$("#loading-overlay").hide();
|
||||
},
|
||||
openApiRequest: function(collectionId, apiId) {
|
||||
openApiRequest: function (collectionId, apiId) {
|
||||
let selectedApi = collections.filter(function (collection) {
|
||||
return collection.id === collectionId;
|
||||
})[0].apis.filter(function (api) {
|
||||
return api.id === apiId;
|
||||
})[0];
|
||||
if (selectedApi !== undefined){
|
||||
let tab = apiRequests.filter(function(api){
|
||||
if (selectedApi !== undefined) {
|
||||
let tab = apiRequests.filter(function (api) {
|
||||
return api.id === selectedApi.id;
|
||||
})[0];
|
||||
|
||||
if (tab === undefined){
|
||||
if (selectedApi.responseModel === undefined) {
|
||||
selectedApi.responseModel = {
|
||||
status: 0,
|
||||
time: 0,
|
||||
size: 0,
|
||||
headers: [],
|
||||
body: ''
|
||||
};
|
||||
}
|
||||
|
||||
if (tab === undefined) {
|
||||
apiRequests.push(selectedApi);
|
||||
view.currentIdx = apiRequests.length - 1;
|
||||
view.renderTabHeader();
|
||||
@@ -628,6 +669,32 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
deleteApiRequest: function (collectionId, apiId) {
|
||||
this.currentAjaxRequest = $.ajax({
|
||||
url: '/mgmt/collections/{id}/apis/delete.do'.replace('{id}', collectionId),
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({id: apiId}),
|
||||
success: function (data) {
|
||||
},
|
||||
error: function (response, textStatus, errorThrown) {
|
||||
controller.hideLoadingOverlay();
|
||||
},
|
||||
complete: function () {
|
||||
controller.hideLoadingOverlay();
|
||||
|
||||
//get the api with apiIdx index from apiRequests
|
||||
let apiIdx = apiRequests.findIndex(function (api) {
|
||||
return api.id === apiId;
|
||||
});
|
||||
|
||||
apiRequests.splice(apiIdx, 1);
|
||||
view.render();
|
||||
$('#apiRequestTabTitle li:eq(0) button').tab('show');
|
||||
controller.loadCollections();
|
||||
}
|
||||
});
|
||||
},
|
||||
send: function (tabIdx) {
|
||||
let model = apiRequests[tabIdx];
|
||||
let target = $('#api_request_' + tabIdx);
|
||||
@@ -648,8 +715,7 @@
|
||||
model.responseModel.headers = data.headers;
|
||||
model.responseModel.size = data.size;
|
||||
},
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
console.error(textStatus, errorThrown);
|
||||
error: function (response, textStatus, errorThrown) {
|
||||
controller.hideLoadingOverlay();
|
||||
},
|
||||
complete: function () {
|
||||
@@ -661,7 +727,7 @@
|
||||
});
|
||||
}
|
||||
},
|
||||
loadCollections: function(){
|
||||
loadCollections: function () {
|
||||
controller.showLoadingOverlay();
|
||||
this.currentAjaxRequest = $.ajax({
|
||||
url: '/mgmt/collections/list.do',
|
||||
@@ -670,8 +736,7 @@
|
||||
success: function (data) {
|
||||
collections = data;
|
||||
},
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
console.error(textStatus, errorThrown);
|
||||
error: function (response, textStatus, errorThrown) {
|
||||
controller.hideLoadingOverlay();
|
||||
},
|
||||
complete: function () {
|
||||
@@ -688,15 +753,15 @@
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({name: collection}),
|
||||
success: function (data) {
|
||||
$('#new_collection_modal').modal('hide');
|
||||
|
||||
},
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
console.error(textStatus, errorThrown);
|
||||
error: function (response, textStatus, errorThrown) {
|
||||
controller.hideLoadingOverlay();
|
||||
},
|
||||
complete: function () {
|
||||
controller.loadCollections();
|
||||
controller.hideLoadingOverlay();
|
||||
$('#new_collection_modal').modal('hide');
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -709,20 +774,23 @@
|
||||
data: JSON.stringify({id: id}),
|
||||
success: function () {
|
||||
},
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
console.error(textStatus, errorThrown);
|
||||
error: function (response, textStatus, errorThrown) {
|
||||
let error = response.responseJSON;
|
||||
controller.hideLoadingOverlay();
|
||||
alert(error.error);
|
||||
},
|
||||
complete: function () {
|
||||
controller.loadCollections();
|
||||
controller.hideLoadingOverlay();
|
||||
$('#confirm_delete_modal').modal('hide');
|
||||
}
|
||||
});
|
||||
},
|
||||
addAPIRequest: function (collectionId) {
|
||||
|
||||
let name = 'New Request';
|
||||
let newApi = {
|
||||
id : '',
|
||||
id: '',
|
||||
server: null,
|
||||
method: 'GET',
|
||||
name: name,
|
||||
@@ -745,24 +813,21 @@
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(newApi),
|
||||
success: function (data) {
|
||||
console.log(data);
|
||||
newApi.id = data.id;
|
||||
newApi.id = data;
|
||||
},
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
console.error(textStatus, errorThrown);
|
||||
error: function (response, textStatus, errorThrown) {
|
||||
controller.hideLoadingOverlay();
|
||||
},
|
||||
complete: function () {
|
||||
controller.loadCollections();
|
||||
controller.hideLoadingOverlay();
|
||||
apiRequests.push(newApi);
|
||||
view.currentIdx = apiRequests.length - 1;
|
||||
|
||||
view.renderTabHeader();
|
||||
view.renderTabContent(view.currentIdx);
|
||||
|
||||
controller.hideLoadingOverlay();
|
||||
$('#new_api_request_modal').modal('hide');
|
||||
controller.loadCollections();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user