"use strict"; /* Codacy comment to notify that baseurl is a read-only global variable. */ /* global baseurl */ // tooltips var thread = null; function setApiInfoBox(isTyping) { clearTimeout(thread); var url = $('#ServerUrl').val(); if (url) { var delay = isTyping ? 200 : 0; var payload = { "url": extractPathFromUrl(url) }; thread = setTimeout( function() { $.ajax({ type: "POST", url: baseurl + '/api/getApiInfo', data: payload, success: function (data) { $('#apiInfo').html(data); addHoverInfo($('#ServerUrl').data('urlWithoutParam')); } }); }, delay ); } else { $('#apiInfo').empty(); } } function loadRestClientHistory(k, data_container) { var data = data_container[k]; $('#ServerMethod').val(data['http_method']); $('#ServerUseFullPath').prop("checked", data['use_full_path']); $('#ServerShowResult').prop("checked", data['show_result']); $('#ServerSkipSslValidation').prop("checked", data['skip_ssl_validation']); $('#ServerUrl').val(data['url']); $('#ServerHeader').val(data['headers']); toggleRestClientBookmark(); cm.setValue(data['body']) var url = extractPathFromUrl(data['url']) $('#TemplateSelect').val(url).trigger("chosen:updated"); updateQueryTool(url, false); $('#querybuilder').find('select').trigger('chosen:updated'); setApiInfoBox(false); } function extractPathFromUrl(url) { var el = document.createElement('a') el.href = url return el.pathname } function populate_rest_history(scope) { if (scope === 'history') { scope = ''; var container_class = 'history_queries'; } else { scope = '1'; var container_class = 'bookmarked_queries'; } $.get(baseurl + "/rest_client_history/index/" + scope, function(data) { $('.' + container_class).html(data); }); } function toggleRestClientBookmark() { if ($('#ServerBookmark').prop("checked") == true) { $('#bookmark-name').css('display', 'block'); } else { $('#bookmark-name').css('display', 'none'); } } function removeRestClientHistoryItem(id) { $.ajax({ data: '[]', success: function () { populate_rest_history('bookmark'); populate_rest_history('history'); }, error:function() { handleGenericAjaxResponse({'saved':false, 'errors':['Request failed due to an unexpected error.']}); }, type:"post", cache: false, url: baseurl + '/rest_client_history/delete/' + id, }); } var allValidApis; var fieldsConstraint; var querybuilderTool; var debounceTimerUpdate; $('form').submit(function(e) { $('#querybuilder').remove(); return true; }); $(function () { $.ajax({ dataType: "json", url: baseurl + '/api/getAllApis', success: function (data) { allValidApis = data['allValidApis']; fieldsConstraint = data['fieldsConstraint']; } }); insertRawRestResponse(); $('.format-toggle-button').bind('click', function() { var type = $(this).data('toggle-type'); if (type === 'Raw') { $('#rest-response-container').empty(); insertRawRestResponse(); } else if (type === 'HTML') { $('#rest-response-container').empty(); insertHTMLRestResponse(); } else if (type === 'JSON') { $('#rest-response-container').empty(); insertJSONRestResponse(); } else if (type === 'Download') { var download_content = $('#rest-response-hidden-container').text(); var extension = 'json'; var export_type = 'json'; var mime = 'application/json'; if ($('#header-X-Response-Format').length != 0) { extension = $('#header-X-Response-Format').text(); } if ($('#header-Content-Type').length != 0) { mime = $('#header-Content-Type').text(); } if ($('#header-X-Export-Module-Used').length != 0) { export_type = $('#header-X-Export-Module-Used').text(); } var filename = export_type + '.result.' + extension; var blob = new Blob([download_content], { type: mime }); saveAs(blob, filename); } }); $('#TemplateSelect').val($('#ServerUrl').val()).trigger("chosen:updated").trigger("change"); $('#ServerUrl').keyup(function(e) { var that = this clearTimeout(debounceTimerUpdate); var c = String.fromCharCode(e.keyCode); var isWordCharacter = c.match(/\w/); if (e.keyCode === undefined || isWordCharacter) { debounceTimerUpdate = setTimeout(function() { $('#TemplateSelect').val($(that).val()).trigger("chosen:updated").trigger("change"); }, 200); } }); $('#TemplateSelect').change(function() { var selected_template = $('#TemplateSelect').val(); var previously_selected_template = $('#ServerUrl').data('urlWithoutParam') if (selected_template !== '' && allValidApis[selected_template] !== undefined) { $('#template_description').show(); $('#ServerMethod').val('POST'); var server_url_changed = $('#ServerUrl').val() != allValidApis[selected_template].url; $('#ServerUrl') .val(allValidApis[selected_template].url) .data('urlWithoutParam', selected_template); var body_value = cm.getValue(); var body_changed = allValidApis[previously_selected_template] !== undefined ? JSON.stringify(allValidApis[previously_selected_template].body, null, 4) !== body_value : true; var refreshBody = (body_value === '' || (server_url_changed && !body_changed)) if (refreshBody) { var body = JSON.stringify(allValidApis[selected_template].body, null, 4); $('#ServerBody').val(body); cm.setValue(body) } setApiInfoBox(false); updateQueryTool(selected_template, refreshBody); } }); $('#showQB').click(function() { $('#qb-div').toggle(); if ($('#TemplateSelect').val() !== '') { $('#ServerUrl').val('') $('#TemplateSelect').trigger("change"); } }); /* Query builder */ // Fix for Bootstrap Datepicker $('#builder-widgets').on('afterUpdateRuleValue.queryBuilder', function(e, rule) { if (rule.filter.plugin === 'datepicker') { rule.$el.find('.rule-value-container input').datepicker('update'); } }); querybuilderTool = $('#querybuilder').queryBuilder({ plugins: { 'filter-description' : { mode: 'inline' }, 'unique-filter': null, 'bt-tooltip-errors': null, 'chosen-selectpicker': null, 'not-group': null }, allow_empty: true, filters: [{ id: 'noValidFilters', label: 'No valid filters, Pick an endpoint first', type: 'string' }], icons: { add_group: 'fa fa-plus-square', add_rule: 'fa fa-plus-circle', remove_group: 'fa fa-minus-square', remove_rule: 'fa fa-minus-circle', error: 'fa fa-exclamation-triangle' } }); querybuilderTool = querybuilderTool[0].queryBuilder; $('#btn-apply').on('click', function() { var result = querybuilderTool.getRules(); if (!$.isEmptyObject(result)) { alert(JSON.stringify(result, null, 2)); } }); $('#btn-inject').on('click', function() { injectQuerybuilterRulesToBody(); }); /* Apply jquery chosen where applicable */ $("#TemplateSelect").chosen(); populate_rest_history('history'); populate_rest_history('bookmark'); toggleRestClientBookmark(); setupCodeMirror(); }); function updateQueryTool(url, isEmpty) { if ($('#qb-div').css('display') == 'none') { return } var apiJson = allValidApis[url]; var filtersJson = fieldsConstraint[url]; isEmpty = isEmpty === undefined ? false : isEmpty; var body = cm.getValue(); if (!isEmpty && body !== undefined && body.length > 0) { try { body = JSON.parse(body); } catch(e) { body = {}; } } else { body = {}; } var filters = []; for (var k in filtersJson) { if (filtersJson.hasOwnProperty(k)) { var filter = filtersJson[k]; var helptext = filter.help; if (helptext !== undefined) { filter.description = helptext; } if (filter.input === 'select') { filter.plugin = 'chosen'; } filter.unique = filter.unique !== undefined ? filter.unique : true; filters.push(filter); } } if (filters.length > 0) { querybuilderTool.setFilters(true, filters); } // add and lock mandatory fields var mandatoryFields = apiJson.mandatory; if (mandatoryFields !== undefined && mandatoryFields.length > 0) { var rules = { "condition": "AND", "rules": [ { "condition": "AND", "rules": [], "not": false, "valid": true, "flags": { "condition_readonly": true, "no_add_rule": true, "no_add_group": true, "no_delete": true } } ], "not": false, "valid": true }; mandatoryFields.forEach(function(mandatory) { var r = filtersJson[mandatory]; var action = r.id.split('.')[1]; if (body[action] !== undefined) { r.value = body[action]; delete body[action]; } r.flags = { no_delete: true, filter_readonly: true }; rules.rules[0].rules.push(r); }) } else { var rules = { "condition": "AND", "rules": [], "not": false, "valid": true }; } Object.keys(body).forEach(function(k) { var values = body[k]; if (Array.isArray(values)) { values.forEach(function(value) { var r = $.extend({}, filtersJson[k], true); r.value = value; if (mandatoryFields !== undefined && mandatoryFields.length > 0) { rules.rules[0].rules.push(r); } else { rules.rules.push(r); } }); } else { var r = filtersJson[k]; if (r !== undefined) { // rule is not defined in the description r.value = values; if (mandatoryFields !== undefined && mandatoryFields.length > 0) { rules.rules[0].rules.push(r); } else { rules.rules.push(r); } } } }); // add Params input field var paramFields = apiJson.params; $('#divAdditionalParamInput').remove(); if (paramFields !== undefined && paramFields.length > 0) { var div = $('.selected-path-container'); var additionalInput = $('
' + '
' + '
' + '' + '
' + '
' + '
'); div.append(additionalInput); } querybuilderTool.setRules(rules, false); } function injectQuerybuilterRulesToBody() { var rules_root = querybuilderTool.getRules(); var result = {}; recursiveInject(result, rules_root, false); var jres = JSON.stringify(result, null, ' '); cm.setValue(jres) // inject param to url var param = $('#paramInput').val(); if (param !== undefined) { var origVal = $('#ServerUrl').val(); var newVal = origVal.replace(/(\[\w+\]){1}/, param); $('#ServerUrl').val(newVal); } } function recursiveInject(result, rules, isNot) { if (rules.rules === undefined) { // add to result var field = rules.field.split(".")[1]; var value = rules.value; var operator_notequal = rules.operator === 'not_equal' ? true : false; var negate = isNot ^ operator_notequal; value = negate ? '!' + value : value; if (result.hasOwnProperty(field)) { if (Array.isArray(result[field])) { result[field].push(value); } else { result[field] = [result[field], value]; } } else { result[field] = value; } } else if (Array.isArray(rules.rules)) { rules.rules.forEach(function(subrules) { recursiveInject(result, subrules, isNot ^ rules.not) ; }); } } function addHoverInfo(url) { if (allValidApis[url] === undefined) { return; } var authorizedParamTypes = ['mandatory', 'optional']; var todisplay = allValidApis[url].controller + '/' + allValidApis[url].action + '/'; $('#selected-path').text(todisplay); authorizedParamTypes.forEach(function(paramtype) { if (allValidApis[url][paramtype] !== undefined) { var validApi = allValidApis[url][paramtype]; if (!Array.isArray(validApi)) { var k = Object.keys(validApi)[0]; if (k === 'AND' || k === 'OR') { validApi = validApi[k]; } else { // not an array, need to generate a new one (some api contain nested arrays: i.e. Org=>Array()) validApi = []; for (var k in allValidApis[url][paramtype]){ if (allValidApis[url][paramtype].hasOwnProperty(k)) { var v = allValidApis[url][paramtype][k]; if (typeof v === 'string') { validApi.push(v); } else { v.forEach(function(v2) { validApi.push(v2); }); } } } } } validApi.forEach(function(field) { if (fieldsConstraint[url][field] !== undefined) { // add icon var apiInfo = fieldsConstraint[url][field].help; if(apiInfo !== undefined && apiInfo !== '') { $('#infofield-'+field).popover({ trigger: 'hover', content: field + ': ' + apiInfo, }); } else { // no help, delete icon $('#infofield-'+field).remove(); } } }); } }); } function findPropertyFromValue(token) { var absoluteIndex = cm.indexFromPos(CodeMirror.Pos(token.line, token.start)) var rawText = cm.getValue() for (var index = absoluteIndex; index > 0; index--) { var ch = rawText[index]; if (ch == ':') { var token = cm.getTokenAt(cm.posFromIndex(index-2)) if (token.type == 'string property') { return token.string.slice(1, token.string.length-1); } } } return false } function findMatchingHints(str, allHints) { allHints = allHints.map(function(str) { var strArray = typeof str === "object" ? String(str.value).split('"') : str.split('"') return { text: strArray.join('\\\"'), // transforms quoted elements into escaped quote renderText: typeof str === "object" ? str.label : strArray.join('\"'), render: function(elem, self, data) { $(elem).append(data.renderText); } } }) if (str.length > 0) { var hints = [] var maxHints = 100 var hint for (var i = 0; hints.length < maxHints && i < allHints.length; i++) { hint = allHints[i]; if (hint.text.startsWith(str)) { hints.push(hint) } } return hints } else { return allHints } } function getCompletions(token, isJSONKey) { var hints = [] var url = $('#TemplateSelect').val() if (allValidApis[url] === undefined) { return hints } if (isJSONKey) { var apiJson = allValidApis[url]; var allHints = (apiJson.mandatory !== undefined ? apiJson.mandatory : []).concat((apiJson.optional !== undefined ? apiJson.optional : [])) hints = findMatchingHints(token.string, allHints) } else { var jsonKey = findPropertyFromValue(token) var filtersJson = fieldsConstraint[url]; if (filtersJson[jsonKey] !== undefined) { var values = filtersJson[jsonKey].values if (values !== undefined) { allHints = Array.isArray(values) ? values : Object.keys(values) hints = findMatchingHints(token.string, allHints) } } } return hints } function jsonHints() { var cur = cm.getCursor() var token = cm.getTokenAt(cur) if (token.type != 'string property' && token.type != 'string') { return } if (cm.getMode().helperType !== "json") return; token.state = cm.state; token.line = cur.line if (/\"([^\"]*)\"/.test(token.string)) { token.end = cur.ch; token.string = token.string.slice(1, cur.ch - token.start); } return { list: getCompletions(token, token.type == 'string property'), from: CodeMirror.Pos(cur.line, token.start+1), to: CodeMirror.Pos(cur.line, token.end) } } var cm; function setupCodeMirror() { var cmOptions = { mode: "application/json", theme:'default', gutters: ["CodeMirror-lint-markers"], lint: true, lineNumbers: true, indentUnit: 4, showCursorWhenSelecting: true, lineWrapping: true, autoCloseBrackets: true, extraKeys: { "Esc": function(cm) { }, "Ctrl-Space": "autocomplete", }, hintOptions: { completeSingle: false, hint: jsonHints }, } cm = CodeMirror.fromTextArea(document.getElementById('ServerBody'), cmOptions); cm.on("keyup", function (cm, event) { if (!cm.state.completionActive && /*Enables keyboard navigation in autocomplete list*/ event.keyCode != 13) { /*Enter - do not open autocomplete list just after item has been selected in it*/ cm.showHint() } }); }