1247 lines
46 KiB
JavaScript
1247 lines
46 KiB
JavaScript
import * as monaco from 'monaco-editor';
|
|
import APIClient from './APIClient';
|
|
import EditableInput from './components/EditableInput';
|
|
import {createPopper} from '@popperjs/core/lib/popper-lite';
|
|
import PropertyTable from './components/PropertyTable';
|
|
import VariableSnippet from './components/VariableSnippet';
|
|
|
|
class APITester {
|
|
|
|
constructor(contextPath) {
|
|
this.servers = [];
|
|
this.apiTabTitleTarget = '#apiRequestTabTitle';
|
|
this.apiTabContentTarget = '#apiRequestTabContent';
|
|
this.collectionTarget = '#side_menubar';
|
|
this.currentIndex = 0;
|
|
this.apiRequests = []; //탭 열린 API
|
|
this.collections = []; //API 컬렉션
|
|
this.requestEditors = []; //API request body editor
|
|
this.responseEditors = []; //API response body editor
|
|
this.consoleEditors = []; //API console editor
|
|
this.preRequestEditors = [];
|
|
this.postRequestEditors = [];
|
|
|
|
this.apiClient = new APIClient();
|
|
this.popperContent = document.getElementById('popperContent');
|
|
this.popperInstance = null;
|
|
this.contextPath = contextPath || '/';
|
|
}
|
|
|
|
getCollectionListURL() {
|
|
return this.contextPath + 'mgmt/collections/list.do';
|
|
}
|
|
|
|
getCollectionCreateURL() {
|
|
return this.contextPath + 'mgmt/collections/create.do';
|
|
}
|
|
|
|
getCollectionUpdateURL() {
|
|
return this.contextPath + 'mgmt/collections/update.do';
|
|
}
|
|
|
|
getCollectionDeleteURL() {
|
|
return this.contextPath + 'mgmt/collections/delete.do';
|
|
}
|
|
|
|
getAPISaveURL(collectionId) {
|
|
return this.contextPath + `mgmt/collections/${collectionId}/apis/save.do`;
|
|
}
|
|
|
|
getAPIDeleteURL(collectionId) {
|
|
return this.contextPath + `mgmt/collections/${collectionId}/apis/delete.do`;
|
|
}
|
|
|
|
renderServers(selectedServer) {
|
|
const optionsHtml = this.servers.map(server => `<option value="${server.id}" ${selectedServer === server.id ? 'selected' : ''} data-path="${server.basePath}">${server.name}</option>`).join('');
|
|
|
|
return `<select class="form-select server" name="server" style="width: 180px; border-radius: 0;" required>
|
|
<option value="">서버 선택</option>
|
|
${optionsHtml}</select>`;
|
|
}
|
|
|
|
basePath(serverId) {
|
|
if (serverId === undefined || serverId === null || serverId === '') {
|
|
return '';
|
|
}
|
|
return this.servers.filter(server => server.id == serverId)[0].basePath; // == : 타입 비교 없이 값만 비교
|
|
}
|
|
|
|
apiRequestTemplate(apiRequest, index) {
|
|
return `
|
|
<div class="tab-pane fade mt-1 api_request" id="api_request_${apiRequest.id}" style="height: 100%;">
|
|
<div><span class="collection_name">${apiRequest.collectionName}</span> > <span class="api_name">${apiRequest.name}</span></div>
|
|
<div class="d-flex api_request_info">
|
|
<div class="form-floating">
|
|
<select name="method" class="form-select method" style="width: 90px; border-bottom-right-radius: 0;border-top-right-radius: 0;">
|
|
<option value="POST" ${apiRequest.method === 'POST' ? 'selected' : ''}>POST</option>
|
|
<option value="GET" ${apiRequest.method === 'GET' ? 'selected' : ''}>GET</option>
|
|
<option value="PUT" ${apiRequest.method === 'PUT' ? 'selected' : ''}>PUT</option>
|
|
<option value="DELETE" ${apiRequest.method === 'DELETE' ? 'selected' : ''}>DELETE</option>
|
|
<option value="CONNECT" ${apiRequest.method === 'CONNECT' ? 'selected' : ''}>CONNECT</option>
|
|
<option value="HEAD" ${apiRequest.method === 'HEAD' ? 'selected' : ''}>HEAD</option>
|
|
<option value="OPTIONS" ${apiRequest.method === 'OPTIONS' ? 'selected' : ''}>OPTIONS</option>
|
|
<option value="TRACE" ${apiRequest.method === 'TRACE' ? 'selected' : ''}>TRACE</option>
|
|
<option value="PATCH" ${apiRequest.method === 'PATCH' ? 'selected' : ''}>PATCH</option>
|
|
</select>
|
|
<label class="form-label must">Method</label>
|
|
</div>
|
|
<div class="form-floating">
|
|
${this.renderServers(apiRequest.server)}
|
|
<label class="form-label must">Server</label>
|
|
</div>
|
|
<div class="form-floating">
|
|
<input type="text" name="basePath" class="form-control" style="width: 180px; border-radius: 0" value="${this.basePath(apiRequest.server)}" readonly>
|
|
<label class="must">기본 경로</label>
|
|
</div>
|
|
<div class="form-floating editableInput me-1 path" data-name="path" data-label="Path">
|
|
<label>Path</label>
|
|
</div>
|
|
<button class="btn btn-primary send me-1">Send</button>
|
|
<button class="btn btn-primary save" data-index="${index}" style="height: 58px;">저장</button>
|
|
</div>
|
|
<div class="api_request d-flex flex-column" style="height:100%;">
|
|
<div class="api_request_body">
|
|
<ul class="nav nav-tabs mt-1" role="tablist">
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link btn_request_body_tab" data-bs-toggle="tab"
|
|
type="button" role="tab" aria-controls="requestBody" data-bs-target="#requestBodyTab_${apiRequest.id}"
|
|
aria-selected="false">Body
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link btn_request_param_tab" data-bs-toggle="tab"
|
|
type="button" role="tab" aria-controls="paramTab" data-bs-target="#requestParamTab_${apiRequest.id}"
|
|
aria-selected="true">Param
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link btn_request_header_tab" data-bs-toggle="tab"
|
|
type="button" role="tab" aria-controls="requestHeader" data-bs-target="#requestHeaderTab_${apiRequest.id}"
|
|
aria-selected="false">Header
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link btn_prerequest_tab" data-bs-toggle="tab"
|
|
type="button" role="tab" aria-controls="preScrit" data-bs-target="#preRequestTab_${apiRequest.id}"
|
|
aria-selected="false">Pre-Request
|
|
</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link btn_postrequest_tab" data-bs-toggle="tab"
|
|
type="button" role="tab" aria-controls="postScript" data-bs-target="#postRequestTab_${apiRequest.id}"
|
|
aria-selected="false">Post-Request
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
<div class="tab-content" style="height: 100%;">
|
|
<div class="tab-pane fade show request_param_tab" role="tabpanel" id="requestParamTab_${apiRequest.id}" aria-labelledby="requestParams-tab">
|
|
<div class="query_params">
|
|
</div>
|
|
</div>
|
|
<div class="tab-pane fade request_header_tab" role="tabpanel" id="requestHeaderTab_${apiRequest.id}"
|
|
aria-labelledby="requestHeader-tab">
|
|
<div class="request_headers">
|
|
</div>
|
|
</div>
|
|
<div class="tab-pane fade request_body_tab" role="tabpanel" id="requestBodyTab_${apiRequest.id}" aria-labelledby="requestBody-tab">
|
|
<div class="d-flex flex-column">
|
|
<select class="form-select mt-1 request_body_type" name="request_type">
|
|
<option value="json">json</option>
|
|
<option value="xml">xml</option>
|
|
<option value="">text/plain</option>
|
|
</select>
|
|
<div class="request_body mt-1" style="width:100%;height: 300px; border:1px solid grey;"></div>
|
|
</div>
|
|
</div>
|
|
<div class="tab-pane fade pre_script_tab" role="tabpanel" id="preRequestTab_${apiRequest.id}" aria-labelledby="preScrit-tab">
|
|
<div class="d-flex flex-row">
|
|
<div style="width:calc(100% - 200px);">
|
|
<div class="pre-request mt-1" style="height:300px;border:1px solid grey;"></div>
|
|
</div>
|
|
<div style="width: 200px;">
|
|
<div class="pre-request-variable">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="tab-pane fade post_script_tab" role="tabpanel" id="postRequestTab_${apiRequest.id}"
|
|
aria-labelledby="postScrit-tab">
|
|
<div class="d-flex flex-row">
|
|
<div style="width:calc(100% - 200px);">
|
|
<div class="post-request mt-1" style="height:300px;border:1px solid grey;"></div>
|
|
</div>
|
|
<div style="width: 200px;">
|
|
<div class="post-request-variable">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- <div class="resizer" data-direction="vertical"></div>-->
|
|
<div class="api_response" style="flex: 1">
|
|
<div class="mt-1">
|
|
<span>Response</span>
|
|
<span class="response_status"></span>
|
|
<span class="response_time"></span>
|
|
<span class="response_size"></span>
|
|
</div>
|
|
<ul class="nav nav-tabs mt-1" role="tablist">
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#responseBodyTab_${apiRequest.id}" type="button" role="tab" aria-controls="responseBody" aria-selected="false">Body</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#responseHeaderTab_${apiRequest.id}" type="button" role="tab" aria-controls="responseHeader" aria-selected="false">Header</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#consoleTab_${apiRequest.id}" type="button" role="tab" aria-controls="consoleTab" aria-selected="false">Console</button>
|
|
</li>
|
|
</ul>
|
|
<div class="tab-content border-bottom" style="min-height: 250px;">
|
|
<div class="tab-pane fade show active" id="responseBodyTab_${apiRequest.id}" role="tabpanel"
|
|
aria-labelledby="responseParams-tab">
|
|
<div class="response_body mt-1" style="width:100%;height:250px;border:1px solid grey;"></div>
|
|
</div>
|
|
<div class="tab-pane fade" id="responseHeaderTab_${apiRequest.id}" role="tabpanel"
|
|
aria-labelledby="responseParams-tab">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th scope="col">이름</th>
|
|
<th scope="col">값</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="response_headers">
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="tab-pane fade" id="consoleTab_${apiRequest.id}" role="tabpanel"
|
|
aria-labelledby="console-tab">
|
|
<div class="console mt-1" style="width:100%;height:250px;border:1px solid grey;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
`;
|
|
}
|
|
|
|
headerTemplate(header, index) {
|
|
return `
|
|
<tr data-index="${index}">
|
|
<td>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" name="headers[${index}].enabled" ${header.enabled ? 'checked' : ''} />
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<input class="form-control" type="text" name="headers[${index}].key" value="${header.key}"/>
|
|
</td>
|
|
<td>
|
|
<input class="form-control" type="text" name="headers[${index}].value" value="${header.value}"/>
|
|
</td>
|
|
<td>
|
|
<button type="button" class="btn btn-secondary btn-sm btn_remove_header">제거</button>
|
|
</td>
|
|
</tr>
|
|
`;
|
|
}
|
|
|
|
responseHeaderTemplate(key, value) {
|
|
return `
|
|
<tr>
|
|
<td>
|
|
<input class="form-control" type="text" value="${key}" readonly/>
|
|
</td>
|
|
<td>
|
|
<input class="form-control" type="text" value="${value}" readonly/>
|
|
</td>
|
|
</tr>
|
|
`;
|
|
}
|
|
|
|
collectionTemplate(collection, index) {
|
|
return `
|
|
<li id="collection_${index}" class="collection api_scenario_item" data-index="${index}">
|
|
<div class="d-flex justify-content-between">
|
|
<button class="btn d-inline-flex align-items-center rounded normal"
|
|
data-bs-toggle="collapse"
|
|
data-bs-target="#btn_collection_${index}" aria-expanded="false" aria-current="false">${collection.name}
|
|
</button>
|
|
<div class="d-flex justify-content-between">
|
|
<button class="p-1 reset-button edit_collection" data-collection="${collection.id}"><i class="fa fa-sharp fa-file-edit"></i></button>
|
|
<button class="p-1 reset-button delete_collection" data-collection="${collection.id}"><i class="fa fa-sharp fa-trash-can"></i></button>
|
|
</div>
|
|
</div>
|
|
<div class="collapse" id="btn_collection_${index}">
|
|
<ul class="list-unstyled fw-normal pb-1 small">
|
|
${collection.apis.map((api, apiIndex) => this.collectionApiTemplate(api, apiIndex, collection.id)).join('')}
|
|
</ul>
|
|
</div>
|
|
</li>
|
|
`;
|
|
}
|
|
|
|
collectionApiTemplate(api, apiIndex, collectionId) {
|
|
return `
|
|
<li class="d-flex justify-content-between api_request_sortable " draggable="true" data-collection="${collectionId}" data-id="${api.id}" data-index="${apiIndex}" data-node-type="api" data-name="${api.name}">
|
|
<a href="#" class="d-inline-flex align-items-center rounded open_api_request" data-node-type="api">${api.name}</a>
|
|
<div class="d-flex justify-content-between">
|
|
<button class="p-1 reset-button edit_api_request"><i class="fa fa-sharp fa-file-edit"></i></button>
|
|
<button class="p-1 reset-button delete_api_request"><i class="fa fa-trash-can"></i></button>
|
|
</div>
|
|
</li>
|
|
`;
|
|
}
|
|
|
|
init(servers) {
|
|
if (servers) {
|
|
this.servers = servers;
|
|
if (this.servers.length === 0) {
|
|
$('.toast-body').text('서버관리에서 서버를 등록해주세요.');
|
|
$('.toast').toast('show');
|
|
}
|
|
}
|
|
this.bindEvents();
|
|
this.loadCollections();
|
|
}
|
|
|
|
bindEvents() {
|
|
const events = [
|
|
{selector: '.btn_add_header', action: this.addHeader.bind(this)},
|
|
{selector: '.btn_remove_header', action: this.removeHeader.bind(this)},
|
|
{selector: '.send', action: this.handleSendAPIRequest.bind(this)},
|
|
{selector: '.save', action: this.saveAPIRequest.bind(this)},
|
|
{selector: '.save_collection', action: this.addCollection.bind(this)},
|
|
{selector: '#cancel-ajax', action: this.cancelAjaxRequest.bind(this)},
|
|
{selector: '#new_collection', action: this.showNewCollectionModal.bind(this)},
|
|
{selector: '#new_request', action: this.showNewApiRequestModal.bind(this)},
|
|
{selector: '.edit_collection', action: this.showCollectionEditModal.bind(this)},
|
|
{selector: '.delete_collection', action: this.showCollectionDeleteModal.bind(this)},
|
|
{selector: '.confirm_delete', action: this.removeCollection.bind(this)},
|
|
{selector: '.add_new_request', action: this.addAPIRequest.bind(this)},
|
|
{selector: '.edit_api_request', action: this.showEditNameModal.bind(this)},
|
|
{selector: '.delete_api_request', action: this.showDeleteApiRequestModal.bind(this)},
|
|
{selector: '.open_api_request', action: this.openApiRequest.bind(this)},
|
|
{selector: '.confirm_delete_api', action: this.deleteApiRequest.bind(this)},
|
|
{selector: '.close_tab', action: this.closeTab.bind(this)}
|
|
];
|
|
|
|
for (let event of events) {
|
|
$(document).on('click', event.selector, event.action);
|
|
}
|
|
|
|
$(document).on('change', '.path', this.parseParam.bind(this));
|
|
$(document).on('change', '.request_headers input', this.handleUIUpdate.bind(this));
|
|
$(document).on('change', '.api_request_info select, .api_request_info input', this.handleUIUpdate.bind(this));
|
|
$(document).on('change', '.api_request_info select', this.handleUpdateServer.bind(this));
|
|
|
|
window.addEventListener('resize', this.resizeEditor.bind(this));
|
|
|
|
}
|
|
|
|
resizeEditor() {
|
|
//FIXME: 창 크기 변경시 자동으로 editor 크기가 조정되지 않아서, 0으로 강제 변경후 다시 layout() 호출
|
|
|
|
for (let i = 0; i < this.requestEditors.length; i++) {
|
|
this.requestEditors[i].layout({
|
|
width: 0
|
|
});
|
|
}
|
|
for (let i = 0; i < this.responseEditors.length; i++) {
|
|
this.responseEditors[i].layout({
|
|
width: 0
|
|
});
|
|
}
|
|
for (let i = 0; i < this.preRequestEditors.length; i++) {
|
|
this.preRequestEditors[i].layout({
|
|
width: 0
|
|
});
|
|
}
|
|
for (let i = 0; i < this.postRequestEditors.length; i++) {
|
|
this.postRequestEditors[i].layout({
|
|
width: 0
|
|
});
|
|
}
|
|
|
|
for (let i = 0; i < this.requestEditors.length; i++) {
|
|
this.requestEditors[i].layout({});
|
|
}
|
|
for (let i = 0; i < this.responseEditors.length; i++) {
|
|
this.responseEditors[i].layout({});
|
|
}
|
|
for (let i = 0; i < this.preRequestEditors.length; i++) {
|
|
this.preRequestEditors[i].layout({});
|
|
}
|
|
for (let i = 0; i < this.postRequestEditors.length; i++) {
|
|
this.postRequestEditors[i].layout({});
|
|
}
|
|
|
|
}
|
|
|
|
showCollectionDeleteModal(event) {
|
|
const collectionId = $(event.currentTarget).closest('button').data('collection');
|
|
$('#confirm_delete_modal').find('.confirm_delete').data('id', collectionId);
|
|
$('#confirm_delete_modal').modal('show');
|
|
}
|
|
|
|
getApiRequestModel(apiId) {
|
|
let foundApi = null;
|
|
this.collections.forEach(function(collection) {
|
|
collection.apis.forEach(function(api) {
|
|
if (api.id === apiId) {
|
|
foundApi = api;
|
|
}
|
|
});
|
|
});
|
|
|
|
return foundApi;
|
|
}
|
|
|
|
showCollectionEditModal(event) {
|
|
const me = this;
|
|
const collectionId = $(event.currentTarget).closest('button').data('collection');
|
|
const collection = this.collections.filter(function(collection) {
|
|
return collection.id === collectionId;
|
|
})[0];
|
|
|
|
$('#edit_name_modal').find('input').val('');
|
|
$('#edit_name_modal').modal('show');
|
|
|
|
let saveBtn = $('#edit_name_modal').find('button.change_name');
|
|
saveBtn.off('click');
|
|
|
|
saveBtn.on('click', function() {
|
|
collection.name = $('#edit_name_modal').find('input').val();
|
|
me.saveCollection(collection.id, collection.name);
|
|
me.renderCollections();
|
|
$('#edit_name_modal').modal('hide');
|
|
});
|
|
}
|
|
|
|
showDeleteApiRequestModal(event) {
|
|
let collectionId = $(event.currentTarget).closest('li').data('collection');
|
|
let apiId = $(event.currentTarget).closest('li').data('id');
|
|
$('#confirm_delete_api_modal').find('.confirm_delete_api').data('id', apiId);
|
|
$('#confirm_delete_api_modal').find('.confirm_delete_api').data('collection', collectionId);
|
|
$('#confirm_delete_api_modal').modal('show');
|
|
}
|
|
|
|
showNewApiRequestModal(event) {
|
|
if (this.collections.length == 0) {
|
|
$('.toast-body').text('새로운 컬렉션을 추가해 주세요.');
|
|
$('.toast').toast('show');
|
|
return;
|
|
}
|
|
$('#new_api_request_modal').modal('show');
|
|
}
|
|
|
|
showNewCollectionModal(event) {
|
|
$('#new_collection_modal').find('input').val('');
|
|
$('#new_collection_modal').modal('show');
|
|
}
|
|
|
|
showEditNameModal(event) {
|
|
const me = this;
|
|
const apiId = $(event.currentTarget).closest('li').data('id');
|
|
const collectionId = $(event.currentTarget).closest('li').data('collection');
|
|
|
|
const collection = this.collections.filter(function(collection) {
|
|
return collection.id === collectionId;
|
|
})[0];
|
|
|
|
let apiRequest = collection.apis.filter(function(api) {
|
|
return api.id === apiId;
|
|
})[0];
|
|
|
|
apiRequest.collectionId = collectionId;
|
|
|
|
let saveBtn = $('#edit_name_modal').find('button.change_name');
|
|
saveBtn.off('click');
|
|
saveBtn.on('click', function() {
|
|
apiRequest.name = $('#edit_name_modal').find('input').val();
|
|
me.changeAPIName(apiRequest);
|
|
me.renderCollections();
|
|
$('#edit_name_modal').modal('hide');
|
|
|
|
//탭이 열려 있으면, 닫았다가 다시 열어야 함.
|
|
me.renderTabHeader();
|
|
me.renderTabContent(apiRequest.index);
|
|
|
|
});
|
|
$('#edit_name_modal').find('input').val('');
|
|
$('#edit_name_modal').modal('show');
|
|
}
|
|
|
|
getFieldValue(element) {
|
|
if ($(element).is('select') || $(element).is('input[type="text"]')) {
|
|
return $(element).val();
|
|
}
|
|
if ($(element).is('input[type="checkbox"]')) {
|
|
return $(element).is(':checked');
|
|
}
|
|
}
|
|
|
|
handleUIUpdate(event) {
|
|
if (event) {
|
|
event.preventDefault();
|
|
const element = event.currentTarget;
|
|
const fieldName = $(element).attr('name');
|
|
const newValue = this.getFieldValue(element);
|
|
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
|
let model = this.apiRequests[tabIndex];
|
|
|
|
if (fieldName !== '') {
|
|
_.set(model, fieldName, newValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
handleUpdateServer(event) {
|
|
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
|
let model = this.apiRequests[tabIndex];
|
|
let target = $('#api_request_' + model.id);
|
|
target.find('input[name="basePath"]').val(this.basePath(model.server));
|
|
}
|
|
|
|
renderHeaders(headers) {
|
|
return headers.map((header, index) => this.headerTemplate(header, index)).join('');
|
|
}
|
|
|
|
renderTabHeader() {
|
|
let apiRequestTabTitle = $(this.apiTabTitleTarget);
|
|
apiRequestTabTitle.empty();
|
|
|
|
for (let idx = 0; idx < this.apiRequests.length; idx++) {
|
|
let li = `<li class="nav-item" role="presentation">
|
|
<button class="nav-link" id="api_request_tab_${this.apiRequests[idx].id}" data-bs-toggle="tab" type="button" role="tab" aria-controls="api_request_${this.apiRequests[idx].id}" data-bs-target="#api_request_${this.apiRequests[idx].id}" aria-selected="false">${this.apiRequests[idx].name}
|
|
<span class="close_tab"><i class="fa fa-light fa-close"></i></span>
|
|
</button>
|
|
</li>`;
|
|
apiRequestTabTitle.append(li);
|
|
}
|
|
}
|
|
|
|
showPopper(element, text) {
|
|
const variable = text.replace(/{{|}}/g, '');
|
|
this.popperContent.style.display = 'block';
|
|
|
|
const innerDiv = this.popperContent.querySelector('.variable_popper');
|
|
innerDiv.textContent = '{{' + variable + '}} = ' + (window.globals[variable] === undefined ? '' : window.globals[variable]);
|
|
|
|
this.popperInstance = createPopper(element, this.popperContent, {
|
|
placement: 'bottom', // Popper below the element
|
|
modifiers: [
|
|
{
|
|
name: 'offset',
|
|
options: {
|
|
offset: [0, 8] // Adjust the position if needed
|
|
}
|
|
}
|
|
]
|
|
});
|
|
}
|
|
|
|
hidePopper(element) {
|
|
if (this.popperInstance) {
|
|
this.popperInstance.destroy();
|
|
this.popperInstance = null;
|
|
}
|
|
this.popperContent.style.display = 'none';
|
|
}
|
|
|
|
renderTabContent(index) {
|
|
var me = this;
|
|
let apiRequestTabContent = $(this.apiTabContentTarget);
|
|
let model = this.apiRequests[index];
|
|
|
|
apiRequestTabContent.append(this.apiRequestTemplate(model, index));
|
|
|
|
let editableInput = new EditableInput({
|
|
name: 'path',
|
|
value: model.path
|
|
});
|
|
|
|
let queryParamTable = new PropertyTable({
|
|
propertyName: 'queryParams',
|
|
properties: model.queryParams
|
|
});
|
|
|
|
let headerTable = new PropertyTable({
|
|
propertyName: 'headers',
|
|
properties: model.headers
|
|
});
|
|
|
|
queryParamTable.init(apiRequestTabContent.find(`#api_request_${model.id}`).find('.query_params')[0], (properties) => {
|
|
model.queryParams = properties;
|
|
console.log(model.queryParams);
|
|
this.buildPath(model);
|
|
editableInput.setValue(model.path);
|
|
$('span.variable').off('mouseover');
|
|
$('span.variable').off('mouseout');
|
|
document.querySelectorAll('span.variable').forEach(element => {
|
|
let text = element.innerText;
|
|
element.addEventListener('mouseover', () => me.showPopper(element, text));
|
|
element.addEventListener('mouseout', () => me.hidePopper(element));
|
|
});
|
|
});
|
|
|
|
headerTable.init(apiRequestTabContent.find(`#api_request_${model.id}`).find('.request_headers')[0], (properties) => {
|
|
model.headers = properties;
|
|
$('span.variable').off('mouseover');
|
|
$('span.variable').off('mouseout');
|
|
document.querySelectorAll('span.variable').forEach(element => {
|
|
let text = element.innerText;
|
|
element.addEventListener('mouseover', () => me.showPopper(element, text));
|
|
element.addEventListener('mouseout', () => me.hidePopper(element));
|
|
});
|
|
});
|
|
|
|
apiRequestTabContent.find(`#api_request_${model.id}`).find('.api_request_info').find('.path').each(function() {
|
|
editableInput.init(this, (value) => {
|
|
model.path = value;
|
|
model.queryParams = me.parseParam(model.path);
|
|
queryParamTable.setProperties(model.queryParams);
|
|
$('span.variable').off('mouseover');
|
|
$('span.variable').off('mouseout');
|
|
document.querySelectorAll('span.variable').forEach(element => {
|
|
let text = element.innerText;
|
|
element.addEventListener('mouseover', () => me.showPopper(element, text));
|
|
element.addEventListener('mouseout', () => me.hidePopper(element));
|
|
});
|
|
});
|
|
|
|
$(this).append(`<label>Path</label>`);
|
|
|
|
$('span.variable').off('mouseover');
|
|
$('span.variable').off('mouseout');
|
|
});
|
|
|
|
document.querySelectorAll('.variable').forEach(element => {
|
|
|
|
let text = element.innerText;
|
|
element.addEventListener('mouseover', () => me.showPopper(element, text));
|
|
element.addEventListener('mouseout', () => me.hidePopper(element));
|
|
});
|
|
|
|
this.openTab(model.id);
|
|
let target = $('#api_request_' + model.id);
|
|
|
|
let requestBodyEditor = monaco.editor.create(target.find('.request_body')[0], {
|
|
value: model.requestBody,
|
|
language: 'json',
|
|
automaticLayout: true
|
|
});
|
|
|
|
requestBodyEditor.onMouseMove((e) => {
|
|
let position = e.target.position;
|
|
if (position) {
|
|
let model = requestBodyEditor.getModel();
|
|
let word = model.getWordAtPosition(position);
|
|
let lineContent = model.getLineContent(position.lineNumber);
|
|
if (word) {
|
|
if (lineContent.indexOf('{{' + word.word + '}}') > -1) {
|
|
me.showPopper(e.target.element, word.word);
|
|
}
|
|
} else {
|
|
me.hidePopper(e.target.element);
|
|
}
|
|
}
|
|
});
|
|
|
|
me.requestEditors.push(requestBodyEditor);
|
|
target.find('.request_body')[0].addEventListener('shown.bs.tab', () => {
|
|
me.requestEditors[index].layout();
|
|
});
|
|
|
|
me.requestEditors[index].onDidChangeModelContent((e) => {
|
|
model.requestBody = requestBodyEditor.getValue();
|
|
});
|
|
|
|
target.find('.request_body_type').on('change', function() {
|
|
let model = requestBodyEditor.getModel();
|
|
monaco.editor.setModelLanguage(model, $(this).val());
|
|
});
|
|
|
|
let responseBodyEditor = monaco.editor.create(target.find('.response_body')[0], {
|
|
value: '',
|
|
language: 'json',
|
|
automaticLayout: true,
|
|
quickSuggestions: false
|
|
});
|
|
|
|
me.responseEditors.push(responseBodyEditor);
|
|
|
|
let consoleEditor = monaco.editor.create(target.find('.console')[0], {
|
|
value: '',
|
|
automaticLayout: true,
|
|
quickSuggestions: false
|
|
});
|
|
|
|
me.consoleEditors.push(consoleEditor);
|
|
|
|
let preRequestEditor = monaco.editor.create(target.find('.pre-request')[0], {
|
|
value: model.preRequestScript,
|
|
language: 'javascript',
|
|
automaticLayout: true,
|
|
quickSuggestions: false
|
|
});
|
|
|
|
const snippet1 = new VariableSnippet();
|
|
snippet1.init(target.find('.pre-request-variable')[0], preRequestEditor);
|
|
|
|
me.preRequestEditors.push(preRequestEditor);
|
|
target.find('.pre-request')[0].addEventListener('shown.bs.tab', () => {
|
|
me.preRequestEditors[index].layout();
|
|
});
|
|
|
|
me.preRequestEditors[index].onDidChangeModelContent((e) => {
|
|
model.preRequestScript = preRequestEditor.getValue();
|
|
});
|
|
|
|
let postRequestEditor = monaco.editor.create(target.find('.post-request')[0], {
|
|
value: model.postRequestScript,
|
|
language: 'javascript',
|
|
automaticLayout: true,
|
|
quickSuggestions: false
|
|
});
|
|
|
|
const snippet2 = new VariableSnippet();
|
|
snippet2.init(target.find('.post-request-variable')[0], postRequestEditor);
|
|
|
|
me.postRequestEditors.push(postRequestEditor);
|
|
target.find('.post-request')[0].addEventListener('shown.bs.tab', () => {
|
|
me.postRequestEditors[index].layout();
|
|
});
|
|
|
|
me.postRequestEditors[index].onDidChangeModelContent((e) => {
|
|
model.postRequestScript = postRequestEditor.getValue();
|
|
});
|
|
|
|
// apiRequestTabContent.find('.resizer').each(function(index, ele) {
|
|
// resizable(ele, () => {this.resizeEditor();});
|
|
// });
|
|
}
|
|
|
|
renderResponse(tabIndex) {
|
|
let model = this.apiRequests[tabIndex];
|
|
let target = $('#api_request_' + model.id);
|
|
target.find('.response_headers').empty();
|
|
target.find('.response_status').empty();
|
|
|
|
try {
|
|
const parsedJson = JSON.parse(model.responseModel.body);
|
|
const formattedJson = JSON.stringify(parsedJson, null, 2);
|
|
this.responseEditors[tabIndex].setValue(formattedJson);
|
|
} catch (e) {
|
|
this.responseEditors[tabIndex].setValue(model.responseModel.body);
|
|
}
|
|
if (model.responseModel && model.responseModel.headers) {
|
|
const headers = model.responseModel.headers;
|
|
Object.entries(headers).forEach(([key, value]) => {
|
|
target.find('.response_headers').append(this.responseHeaderTemplate(key, value));
|
|
});
|
|
}
|
|
|
|
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');
|
|
|
|
}
|
|
|
|
customHelper(event) {
|
|
// Create and return the custom helper element
|
|
let name = $(event.target).closest('.api_request_sortable').find('.open_api_request').text().trim();
|
|
let apiId = $(event.target).closest('.api_request_sortable').data('id');
|
|
return `<div style="display: flex; flex-direction: column; flex: 1; border: 2px dashed #333; padding: 10px;" data-id="${apiId}">
|
|
<div>${name}</div>
|
|
</div>`;
|
|
}
|
|
|
|
renderCollections() {
|
|
let select = $('#modal_collection');
|
|
let sidemenu = $(this.collectionTarget);
|
|
select.empty();
|
|
sidemenu.empty();
|
|
|
|
for (let i = 0; i < this.collections.length; i++) {
|
|
sidemenu.append(this.renderCollection(this.collections[i], i));
|
|
let option = $('<option>');
|
|
option.attr('value', this.collections[i].id);
|
|
option.text(this.collections[i].name);
|
|
select.append(option);
|
|
}
|
|
|
|
$('li .api_request_sortable').draggable({
|
|
helper: this.customHelper,
|
|
start: function(event, ui) {
|
|
// You can add any additional data or styles you want when dragging starts
|
|
$(this).addClass('dragging');
|
|
},
|
|
stop: function(event, ui) {
|
|
// Clean up, e.g., remove styles or data
|
|
$(this).removeClass('dragging');
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
renderCollection(collection, index) {
|
|
return this.collectionTemplate(collection, index);
|
|
}
|
|
|
|
openTab(id) {
|
|
try {
|
|
$(`#api_request_tab_${id}`).tab('show'); // API request 탭 활성화
|
|
} catch (e) {
|
|
}
|
|
|
|
try {
|
|
$(`#api_request_${id}`).find('.btn_request_body_tab').tab('show'); // Body 탭 활성화
|
|
} catch (e) {
|
|
}
|
|
}
|
|
|
|
addHeader(event) {
|
|
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
|
let model = this.apiRequests[tabIndex];
|
|
model.headers.push({
|
|
enabled: true,
|
|
key: '',
|
|
value: ''
|
|
});
|
|
this.renderHeaderView(tabIndex);
|
|
}
|
|
|
|
removeHeader(event) {
|
|
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
|
const index = $(event.currentTarget).closest('tr').data('index');
|
|
let model = this.apiRequests[tabIndex];
|
|
model.headers.splice(index, 1);
|
|
this.renderHeaderView(tabIndex);
|
|
}
|
|
|
|
renderHeaderView(tabIndex) {
|
|
let model = this.apiRequests[tabIndex];
|
|
let target = $('#api_request_' + model.id);
|
|
target.find('.request_headers').empty();
|
|
target.find('.request_headers').append(this.renderHeaders(model.headers));
|
|
}
|
|
|
|
parseParam(path) {
|
|
let queryParams = [];
|
|
let queryString = path.split('?')[1];
|
|
if (queryString) {
|
|
let queryParamArray = queryString.split('&');
|
|
for (let i = 0; i < queryParamArray.length; i++) {
|
|
let queryParam = queryParamArray[i].split('=');
|
|
|
|
queryParams.push({
|
|
enabled: true,
|
|
key: queryParam[0],
|
|
value: (queryParam[1] === undefined ? '' : queryParam[1])
|
|
});
|
|
}
|
|
}
|
|
return queryParams;
|
|
}
|
|
|
|
buildPath(model) {
|
|
let queryString = model.path.split('?')[0];
|
|
if (model.queryParams.length > 0) {
|
|
queryString += '?';
|
|
}
|
|
for (let i = 0; i < model.queryParams.length; i++) {
|
|
if (!model.queryParams[i].enabled) {
|
|
continue;
|
|
}
|
|
queryString += model.queryParams[i].key + '=' + model.queryParams[i].value;
|
|
if (i < model.queryParams.length - 1) {
|
|
queryString += '&';
|
|
}
|
|
}
|
|
model.path = queryString;
|
|
}
|
|
|
|
showLoadingOverlay() {
|
|
$('#loading-overlay').show();
|
|
}
|
|
|
|
hideLoadingOverlay() {
|
|
$('#loading-overlay').hide();
|
|
}
|
|
|
|
handleSendAPIRequest(event) {
|
|
const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
|
|
|
let model = this.apiRequests[tabIndex];
|
|
|
|
if (!model.server) {
|
|
$('.toast-body').text('서버를 등록해주세요.');
|
|
$('.toast').toast('show');
|
|
return;
|
|
}
|
|
|
|
let target = $('#api_request_' + model.id);
|
|
target.find('.response_headers').empty();
|
|
this.responseEditors[tabIndex].setValue('');
|
|
let console = this.consoleEditors[tabIndex];
|
|
model.responseModel = {};
|
|
this.showLoadingOverlay();
|
|
|
|
let startTime = new Date().getTime();
|
|
this.currentAjaxRequest = this.apiClient.sendAPIRequest(model, null, this.consoleOutput.bind(this, console)).then(response => {
|
|
if (response) {
|
|
model.responseModel = response;
|
|
let endTime = new Date().getTime();
|
|
model.responseModel.time = endTime - startTime;
|
|
} else {
|
|
model.responseModel = {
|
|
status: 0,
|
|
time: 0,
|
|
size: 0,
|
|
headers: [],
|
|
body: ''
|
|
};
|
|
}
|
|
|
|
this.renderResponse(tabIndex);
|
|
this.hideLoadingOverlay();
|
|
}).catch(error => {
|
|
$('.toast-body').text(error);
|
|
$('.toast').toast('show');
|
|
this.hideLoadingOverlay();
|
|
});
|
|
}
|
|
|
|
consoleOutput(console, message) {
|
|
var range = new monaco.Range(console.getModel().getLineCount(), 1, console.getModel().getLineCount(), 1);
|
|
var id = {major: 1, minor: 1};
|
|
if (typeof message === 'object') {
|
|
message = JSON.stringify(message, null, 2);
|
|
}
|
|
var op = {
|
|
identifier: id,
|
|
range: range,
|
|
text: message + '\n',
|
|
forceMoveMarkers: true
|
|
};
|
|
console.executeEdits('my-source', [op]);
|
|
}
|
|
|
|
loadCollections() {
|
|
const me = this;
|
|
this.currentAjaxRequest = $.ajax({
|
|
url: this.getCollectionListURL(),
|
|
type: 'GET',
|
|
contentType: 'application/json',
|
|
success: function(data) {
|
|
me.collections = data.map(collection => {
|
|
if (collection.apis) {
|
|
collection.apis = collection.apis.map(api => ({...api, collectionId: collection.id}));
|
|
}
|
|
return collection;
|
|
});
|
|
},
|
|
error: function(response, textStatus, errorThrown) {
|
|
me.hideLoadingOverlay();
|
|
$('.toast-body').text(response.responseJSON.error);
|
|
$('.toast').toast('show');
|
|
},
|
|
complete: function() {
|
|
me.renderCollections();
|
|
me.hideLoadingOverlay();
|
|
}
|
|
});
|
|
}
|
|
|
|
addCollection(event) {
|
|
const name = $('#new_collection_name').val();
|
|
const me = this;
|
|
me.showLoadingOverlay();
|
|
this.currentAjaxRequest = $.ajax({
|
|
url: this.getCollectionCreateURL(),
|
|
type: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify({name: name}),
|
|
error: function(response, textStatus, errorThrown) {
|
|
me.hideLoadingOverlay();
|
|
$('.toast-body').text(response.responseJSON.error);
|
|
$('.toast').toast('show');
|
|
},
|
|
complete: function() {
|
|
me.loadCollections();
|
|
me.hideLoadingOverlay();
|
|
$('#new_collection_modal').modal('hide');
|
|
}
|
|
});
|
|
}
|
|
|
|
saveCollection(id, name) {
|
|
const me = this;
|
|
me.showLoadingOverlay();
|
|
this.currentAjaxRequest = $.ajax({
|
|
url: this.getCollectionUpdateURL(),
|
|
type: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify({id: id, name: name}),
|
|
error: function(response, textStatus, errorThrown) {
|
|
me.hideLoadingOverlay();
|
|
$('.toast-body').text(response.responseJSON.error);
|
|
$('.toast').toast('show');
|
|
},
|
|
complete: function() {
|
|
me.loadCollections();
|
|
me.hideLoadingOverlay();
|
|
$('#new_collection_modal').modal('hide');
|
|
}
|
|
});
|
|
}
|
|
|
|
removeCollection(event) {
|
|
let collectionId = $(event.currentTarget).closest('button').data('id');
|
|
const me = this;
|
|
me.showLoadingOverlay();
|
|
this.currentAjaxRequest = $.ajax({
|
|
url: this.getCollectionDeleteURL(),
|
|
type: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify({id: collectionId}),
|
|
success: function() {
|
|
},
|
|
error: function(response, textStatus, errorThrown) {
|
|
me.hideLoadingOverlay();
|
|
$('.toast-body').text(response.responseJSON.error);
|
|
$('.toast').toast('show');
|
|
},
|
|
complete: function() {
|
|
me.loadCollections();
|
|
me.hideLoadingOverlay();
|
|
$('#confirm_delete_modal').modal('hide');
|
|
}
|
|
});
|
|
}
|
|
|
|
changeAPIName(model) {
|
|
const me = this;
|
|
me.showLoadingOverlay();
|
|
this.currentAjaxRequest = $.ajax({
|
|
url: this.getAPISaveURL(model.collectionId),
|
|
type: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify(model),
|
|
success: function(data) {
|
|
let message = '저장되었습니다.';
|
|
$('.toast-body').text(message);
|
|
$('.toast').toast('show');
|
|
},
|
|
error: function(response, textStatus, errorThrown) {
|
|
me.hideLoadingOverlay();
|
|
$('.toast-body').text(response.responseJSON.error);
|
|
$('.toast').toast('show');
|
|
},
|
|
complete: function() {
|
|
me.hideLoadingOverlay();
|
|
}
|
|
});
|
|
}
|
|
|
|
saveAPIRequest(event) {
|
|
const me = this;
|
|
const index = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request'));
|
|
let model = this.apiRequests[index];
|
|
me.showLoadingOverlay();
|
|
|
|
this.currentAjaxRequest = $.ajax({
|
|
url: this.getAPISaveURL(model.collectionId),
|
|
type: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify(model),
|
|
success: function(data) {
|
|
let message = '저장되었습니다.';
|
|
$('.toast-body').text(message);
|
|
$('.toast').toast('show');
|
|
},
|
|
error: function(response, textStatus, errorThrown) {
|
|
me.hideLoadingOverlay();
|
|
$('.toast-body').text(response.responseJSON.error);
|
|
$('.toast').toast('show');
|
|
},
|
|
complete: function() {
|
|
me.hideLoadingOverlay();
|
|
}
|
|
});
|
|
}
|
|
|
|
addAPIRequest(event) {
|
|
const collectionId = $('#modal_collection').val();
|
|
let newApiName = $('#new_api_name').val();
|
|
if (newApiName === '') {
|
|
newApiName = '새로운 API';
|
|
}
|
|
|
|
const collection = this.collections.filter(function(collection) {
|
|
return collection.id === collectionId;
|
|
})[0];
|
|
let me = this;
|
|
let newApi = {
|
|
id: '',
|
|
server: null,
|
|
method: 'GET',
|
|
name: newApiName,
|
|
path: '',
|
|
headers: [],
|
|
queryParams: [],
|
|
requestBody: '',
|
|
preRequestScript: '',
|
|
postRequestScript: '',
|
|
collectionId: collectionId,
|
|
responseModel: {
|
|
status: 0,
|
|
time: 0,
|
|
size: 0,
|
|
headers: [],
|
|
ody: ''
|
|
}
|
|
};
|
|
newApi.collectionName = collection.name;
|
|
|
|
this.currentAjaxRequest = $.ajax({
|
|
url: this.getAPISaveURL(collectionId),
|
|
type: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify(newApi),
|
|
success: function(data) {
|
|
newApi.id = data;
|
|
},
|
|
error: function(response, textStatus, errorThrown) {
|
|
me.hideLoadingOverlay();
|
|
$('.toast-body').text(response.responseJSON.error);
|
|
$('.toast').toast('show');
|
|
},
|
|
complete: function() {
|
|
me.loadCollections();
|
|
me.apiRequests.push(newApi);
|
|
me.currentIndex = me.apiRequests.length - 1;
|
|
|
|
me.renderTabHeader();
|
|
me.renderTabContent(me.currentIndex);
|
|
$('#new_api_name').val('');
|
|
me.hideLoadingOverlay();
|
|
$('#new_api_request_modal').modal('hide');
|
|
}
|
|
});
|
|
}
|
|
|
|
cancelAjaxRequest() {
|
|
if (this.currentAjaxRequest) {
|
|
try {
|
|
|
|
this.currentAjaxRequest.abort();
|
|
} catch (e) {
|
|
this.apiClient.abort();
|
|
}
|
|
}
|
|
this.hideLoadingOverlay();
|
|
}
|
|
|
|
openApiRequest(event) {
|
|
const collectionId = $(event.currentTarget).closest('li').data('collection');
|
|
const apiId = $(event.currentTarget).closest('li').data('id');
|
|
|
|
const collection = this.collections.filter(function(collection) {
|
|
return collection.id === collectionId;
|
|
})[0];
|
|
let selectedApi = collection.apis.filter(function(api) {
|
|
return api.id === apiId;
|
|
})[0];
|
|
|
|
if (selectedApi) {
|
|
selectedApi.collectionId = collectionId;
|
|
selectedApi.collectionName = collection.name;
|
|
let tab = this.apiRequests.filter(function(api) {
|
|
return api.id === selectedApi.id;
|
|
})[0];
|
|
|
|
if (!selectedApi.responseModel) {
|
|
selectedApi.responseModel = {
|
|
status: 0,
|
|
time: 0,
|
|
size: 0,
|
|
headers: [],
|
|
body: ''
|
|
};
|
|
}
|
|
|
|
if (tab) {
|
|
this.currentIndex = this.apiRequests.findIndex(function(api) {
|
|
return api.id === selectedApi.id;
|
|
});
|
|
this.openTab(selectedApi.id);
|
|
|
|
} else {
|
|
this.apiRequests.push(selectedApi);
|
|
this.currentIndex = this.apiRequests.length - 1;
|
|
this.renderTabHeader();
|
|
this.renderTabContent(this.currentIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
deleteApiRequest(event) {
|
|
let collectionId = $(event.currentTarget).closest('button').data('collection');
|
|
let apiId = $(event.currentTarget).closest('.confirm_delete_api').data('id');
|
|
let apiIndex = this.apiRequests.findIndex(function(api) {
|
|
return api.id === apiId;
|
|
});
|
|
if (apiIndex >= 0) {
|
|
this.closeTabWithApiIndex(apiIndex);
|
|
}
|
|
const me = this;
|
|
this.currentAjaxRequest = $.ajax({
|
|
url: this.getAPIDeleteURL(collectionId),
|
|
type: 'POST',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify({id: apiId}),
|
|
success: function(data) {
|
|
},
|
|
error: function(response, textStatus, errorThrown) {
|
|
$('.toast-body').text(response.responseJSON.error);
|
|
me.hideLoadingOverlay();
|
|
},
|
|
complete: function() {
|
|
me.hideLoadingOverlay();
|
|
me.loadCollections();
|
|
$('#confirm_delete_api_modal').modal('hide');
|
|
}
|
|
});
|
|
}
|
|
|
|
closeTabWithApiIndex(index) {
|
|
if (index !== undefined) {
|
|
const model = this.apiRequests[index];
|
|
this.apiRequests.splice(index, 1);
|
|
|
|
this.requestEditors.splice(index, 1);
|
|
this.responseEditors.splice(index, 1);
|
|
this.consoleEditors.splice(index, 1);
|
|
this.preRequestEditors.splice(index, 1);
|
|
this.postRequestEditors.splice(index, 1);
|
|
|
|
this.renderTabHeader();
|
|
$(`#api_request_${model.id}`).remove();
|
|
// $(`#apiRequestTabTitle li:eq(${this.apiRequests.length - 1}) button`).tab('show');
|
|
|
|
$(`#apiRequestTabTitle li:last button`).tab('show');
|
|
}
|
|
}
|
|
|
|
closeTab(event) {
|
|
const index = $('#apiRequestTabTitle').children().index($(event.currentTarget).closest('.nav-item'));
|
|
this.closeTabWithApiIndex(index);
|
|
}
|
|
}
|
|
|
|
export default APITester;
|