`;
}
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 = `
`;
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(``);
$('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 `
${name}
`;
}
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 = $('