diff --git a/tools/ws.htm b/tools/ws.htm index a401ffef1..9c7f7eebf 100644 --- a/tools/ws.htm +++ b/tools/ws.htm @@ -5,570 +5,191 @@ Piwigo web API (web-services) explorer + - + + + + + + + - -
-

Piwigo web API (web-services) explorer

-
+
+ + + -
-

Available methods

+
+ +

Piwigo web API (web-services) explorer

+
+ +
+ +
+

Available methods

-
    -
-
- -
- - - -
- - -
-

- API = Application Programming Interface.
- This is the way other applications can communicate with Piwigo. This feature is also know as Web Services. -

- -

Examples:

-
    -
  • Wordpress (web blog software) can display random photos from a Piwigo gallery in its sidebar
  • -
  • Lightroom (photo management software for desktop) can create albums and upload photos to Piwigo
  • -
- -

- This page lists all API methods available on your Piwigo installation, part of the Piwigo core or added by third-party plugins. - For each method you can consult required and optional parameters, and even test them in direct live! -

- -

- For more information you can consult our Wiki Piwigo Web API and our forums. -

-
- - - - -
- - - - - - - +

Examples:

+
    +
  • Wordpress (web blog software) can display random photos from a Piwigo gallery in its sidebar
  • +
  • Lightroom (photo management software for desktop) can create albums and upload photos to Piwigo
  • +
+ +

+ This page lists all API methods available on your Piwigo installation, part of the Piwigo core or added by third-party plugins. + For each method you can consult required and optional parameters, and even test them in direct live! +

+ +

+ For more information you can consult our Wiki Piwigo Web API and our forums. +

+
+
+ + + + + + + +
+ +
+ + + + + diff --git a/tools/ws/jquery.json-viewer.css b/tools/ws/jquery.json-viewer.css new file mode 100644 index 000000000..6624afaf5 --- /dev/null +++ b/tools/ws/jquery.json-viewer.css @@ -0,0 +1,57 @@ +/* Root element */ +.json-document { + padding: 1em 2em; +} + +/* Syntax highlighting for JSON objects */ +ul.json-dict, ol.json-array { + list-style-type: none; + margin: 0 0 0 1px; + border-left: 1px dotted #ccc; + padding-left: 2em; +} +.json-string { + color: #0B7500; +} +.json-literal { + color: #4B31FF; + font-weight: bold; +} + +/* Toggle button */ +a.json-toggle { + position: relative; + color: inherit; + text-decoration: none; +} +a.json-toggle:focus { + outline: none; +} +a.json-toggle:before { + font-size: 1.1em; + color: #c0c0c0; + content: "\25BC"; /* down arrow */ + position: absolute; + display: inline-block; + width: 1em; + text-align: center; + line-height: 1em; + left: -1.2em; +} +a.json-toggle:hover:before { + color: #aaa; +} +a.json-toggle.collapsed:before { + /* Use rotated down arrow, prevents right arrow appearing smaller than down arrow in some browsers */ + transform: rotate(-90deg); +} + +/* Collapsable placeholder links */ +a.json-placeholder { + color: #aaa; + padding: 0 1em; + text-decoration: none; +} +a.json-placeholder:hover { + text-decoration: underline; +} diff --git a/tools/ws/jquery.json-viewer.js b/tools/ws/jquery.json-viewer.js new file mode 100644 index 000000000..611411bc7 --- /dev/null +++ b/tools/ws/jquery.json-viewer.js @@ -0,0 +1,158 @@ +/** + * jQuery json-viewer + * @author: Alexandre Bodelot + * @link: https://github.com/abodelot/jquery.json-viewer + */ +(function($) { + + /** + * Check if arg is either an array with at least 1 element, or a dict with at least 1 key + * @return boolean + */ + function isCollapsable(arg) { + return arg instanceof Object && Object.keys(arg).length > 0; + } + + /** + * Check if a string represents a valid url + * @return boolean + */ + function isUrl(string) { + var urlRegexp = /^(https?:\/\/|ftps?:\/\/)?([a-z0-9%-]+\.){1,}([a-z0-9-]+)?(:(\d{1,5}))?(\/([a-z0-9\-._~:/?#[\]@!$&'()*+,;=%]+)?)?$/i; + return urlRegexp.test(string); + } + + /** + * Transform a json object into html representation + * @return string + */ + function json2html(json, options) { + var html = ''; + if (typeof json === 'string') { + // Escape tags and quotes + json = json + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/'/g, ''') + .replace(/"/g, '"'); + + if (options.withLinks && isUrl(json)) { + html += '' + json + ''; + } else { + // Escape double quotes in the rendered non-URL string. + json = json.replace(/"/g, '\\"'); + html += '"' + json + '"'; + } + } else if (typeof json === 'number') { + html += '' + json + ''; + } else if (typeof json === 'boolean') { + html += '' + json + ''; + } else if (json === null) { + html += 'null'; + } else if (json instanceof Array) { + if (json.length > 0) { + html += '[
    '; + for (var i = 0; i < json.length; ++i) { + html += '
  1. '; + // Add toggle button if item is collapsable + if (isCollapsable(json[i])) { + html += ''; + } + html += json2html(json[i], options); + // Add comma if item is not last + if (i < json.length - 1) { + html += ','; + } + html += '
  2. '; + } + html += '
]'; + } else { + html += '[]'; + } + } else if (typeof json === 'object') { + var keyCount = Object.keys(json).length; + if (keyCount > 0) { + html += '{}'; + } else { + html += '{}'; + } + } + return html; + } + + /** + * jQuery plugin method + * @param json: a javascript object + * @param options: an optional options hash + */ + $.fn.jsonViewer = function(json, options) { + // Merge user options with default options + options = Object.assign({}, { + collapsed: false, + rootCollapsable: true, + withQuotes: false, + withLinks: true + }, options); + + // jQuery chaining + return this.each(function() { + + // Transform to HTML + var html = json2html(json, options); + if (options.rootCollapsable && isCollapsable(json)) { + html = '' + html; + } + + // Insert HTML in target DOM element + $(this).html(html); + $(this).addClass('json-document'); + + // Bind click on toggle buttons + $(this).off('click'); + $(this).on('click', 'a.json-toggle', function() { + var target = $(this).toggleClass('collapsed').siblings('ul.json-dict, ol.json-array'); + target.toggle(); + if (target.is(':visible')) { + target.siblings('.json-placeholder').remove(); + } else { + var count = target.children('li').length; + var placeholder = count + (count > 1 ? ' items' : ' item'); + target.after('' + placeholder + ''); + } + return false; + }); + + // Simulate click on toggle button when placeholder is clicked + $(this).on('click', 'a.json-placeholder', function() { + $(this).siblings('a.json-toggle').click(); + return false; + }); + + if (options.collapsed == true) { + // Trigger click to collapse all nodes + $(this).find('a.json-toggle').click(); + } + }); + }; +})(jQuery); diff --git a/tools/ws/piwigo-logo-minimal.svg b/tools/ws/piwigo-logo-minimal.svg new file mode 100644 index 000000000..15b0471f9 --- /dev/null +++ b/tools/ws/piwigo-logo-minimal.svg @@ -0,0 +1,66 @@ + +image/svg+xml + + + + + + + + + diff --git a/tools/ws/ws.css b/tools/ws/ws.css new file mode 100644 index 000000000..58ce93bf4 --- /dev/null +++ b/tools/ws/ws.css @@ -0,0 +1,601 @@ + +/* BEGIN CSS RESET +http://meyerweb.com/eric/tools/css/reset +v2.0 | 20110126 | License: none (public domain) */ +html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video +{margin:0;padding:0;border:0;font-size:100%;vertical-align:baseline;} + +article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {display:block;} +body {line-height:1.1;} +blockquote, q {quotes:none;} +blockquote:before, blockquote:after, q:before, q:after {content:'';content:none;} +table {border-collapse:collapse;border-spacing:0;} +/* END CSS RESET */ + +#the_body, body { + --color-bg: #E5E5E5; + --color-bg-secondary: #FFFFFF; + --color-text: #434343; + --color-action: #FF7700; + --color-action-text: #FFF; + --color-action-hover: #ee4b00; + --color-action-secondary: #eee; + --color-action-secondary-text: var(--color-text); + --color-action-secondary-hover: #ddd; + --color-bg-nuance:#f7f7f7; + + --border-radius: 5px; + --box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.25); + + --header-heigth: 50px; + --footer-heigth: 20px; + --container-heigth: calc(100vh - var(--header-heigth) - var(--footer-heigth)); + + background: var(--color-bg); +} + +#the_body.dark-mode { + --color-bg: #393939; + --color-bg-secondary: #242424; + --color-text: #fff; + --color-action: #FF7700; + --color-action-text: #FFF; + --color-action-hover: #ee4b00; + --color-action-secondary: #181818; + --color-action-secondary-text: #fff; + --color-action-secondary-hover: #292929; + --color-bg-nuance:#1e1e1e; + + --box-shadow: none; +} + +li { + list-style: none; +} + +html {font-family:"Corbel","Lucida Grande","Verdana",sans-serif;color:#434343;font-size:14px;} + +#the_body { + display: flex; + flex-direction: column; +} + +#the_container { + display: grid; + grid-template-columns: 250px auto; +} + +#the_header, #the_footer { + display: flex; + align-items: center; + z-index: 10; + overflow: hidden; + background: var(--color-bg-secondary); + color: var(--color-text); +} + +a { + color:var(--color-action); + text-decoration:none; +} +a:hover { + color:var(--color-action-hover); + border-bottom-width:1px; +} + +blockquote { + padding:8px; +} +hr { + margin:10px 30px; +} +ul { + margin-left:25px; +} +p {margin: 8px 0;} + +h1 { + font-size:20px; + padding-left:10px; +} + +h2 { + font-size:16px; + padding: 10px 10px 5px 10px; +} + +h2#errorWrapper { + color:#F42C00; + font-weight:normal; +} + +h3 { + display:inline-block; + font-weight:bold; +} + +input[type="text"] { + border: 2px solid var(--color-action-secondary); + border-radius: var(--border-radius); + color: var(--color-text); + background: var(--color-bg-secondary); + width: 100%; + padding: 5px; +} + +#the_header { + height: var(--header-heigth); + box-shadow: var(--box-shadow); +} + +#the_header img { + width: 30px; + opacity: 1; + margin-left: 10px; +} + +#the_body:not(.dark-mode) #the_header img { + filter: brightness(80%);; +} + +#the_footer { + height: var(--footer-heigth); + justify-content: center; + background: var(--color-bg-secondary); + opacity: 0.7; +} + +#the_footer a { + margin-left: 5px; +} + +#the_methods, #the_page { + height: var(--container-heigth); + overflow-y: auto; + overflow-x: hidden; + + /* ScrollBar customization for firefox */ + scrollbar-width: thin; +} + +#the_methods { + background-color: var(--color-bg-secondary); + color: var(--color-text); + box-shadow: var(--box-shadow); + z-index: 5; +} + +#methodsList, #search { + font-size:1.1em; + margin:5px 10px; + position: relative; +} + +#search { + display: flex; +} + +#search i { + position:absolute; + top:50%; + left:5px; + transform: translateY(-50%); +} + +#search input { + padding-left: 25px; +} + +.method-node { + position: relative; + display: flex; + flex-direction: column; +} + +.method-node input { + opacity: 0; + position: absolute; + width: 0; + height: 0; +} + +.method-node-content { + padding-left: 30px; + display: flex; + flex-direction: column; + overflow: hidden; +} + +.method-node label, .method-link { + margin: 5px 0px; + overflow-x: hidden; + white-space: nowrap; + text-overflow: ellipsis; + cursor: pointer; + overflow-y: clip; +} + +.method-link { + order: 1; +} + +.method-node label { + background: var(--color-action-secondary); + color: var(--color-action-secondary-text); + padding: 6px; + border-radius: var(--border-radius); + font-weight: bold; +} + +.onSearch .method-node label { + pointer-events: none; + padding-left: 10px; +} + +.onSearch .method-node label i { + display: none; +} + +.method-node label i::before { + font-size: 12px; + transform: rotate(-90deg); + transition: 0.2s ease-in-out; +} + +.method-node > input:checked ~ label i::before { + transform: rotate(0deg); +} + +.method-node label:hover { + background-color: var(--color-action-secondary-hover); +} + +#methodsList > .method-node > label { + background: var(--color-action); + color: var(--color-action-text); +} + +#methodsList > .method-node > label:hover { + background: var(--color-action-hover); +} + +#the_page { + background-color: var(--color-bg); + color: var(--color-text); +} + +#the_title { + display: flex; + align-items: baseline; +} + +#the_title #onlys .only { + border-radius: var(--border-radius); + background: var(--color-action-secondary); + color: var(--color-text); + padding: 5px; + margin-right: 10px; +} + +#the_content { + padding:10px; + padding-top: 0px; +} + +#methodWrapper { + display: flex; + flex-direction: column; +} + +#methodControl { + display: grid; + grid-template-columns: 66% 34%; +} + +.card, .card-2 { + margin: 10px; + background-color: var(--color-bg-secondary); + border-radius: var(--border-radius); + position: relative; +} + +.card { + padding:10px; +} + +.card-2 { + border: 2px solid var(--color-action); + margin-top: 25px; +} + +.card .card-title { + font-size: 16px; +} + +.card-2 .card-title { + font-size: 14px; + color: var(--color-action); + position: absolute; + top: 0; + transform: translateY(calc(-100% - 5px)); +} + +.card-2 .card-content { + overflow-y: auto; + + /* firefox scrollbar customization */ + scrollbar-width: thin; +} + +.card .card-title i { + color: var(--color-action); + font-size: 20px; + margin-right: 5px; +} + +.card .card-content { + padding: 10px; + position: relative; +} + +/* #requestResultDisplay { + background: white; +} */ + +#methodParams table { + width: 100%; +} + +#methodParams td .methodParameterSend{ + opacity: 0; + position: absolute; + width: 0; + height: 0; +} + +#methodParams td .methodParameterSendCheckbox { + padding: 10px; + position: relative; + border: 2px solid var(--color-action); + border-radius: var(--border-radius); + line-height: 0; + box-sizing: border-box; + cursor: pointer; +} + +#methodParams td .methodParameterSendCheckbox i { + color: var(--color-action-text); + position:absolute; + top:50%; + left:50%; + transform: translate(-50%,-50%); +} + +#methodParams td .methodParameterSend:checked ~ .methodParameterSendCheckbox { + background: var(--color-action); +} + +#methodParams td .methodParameterSend:not(:checked) ~ .methodParameterSendCheckbox i { + display: none; + transform: translate(-50%,-50%); +} + +#methodParams tr { + display: flex; + border-radius: var(--border-radius); + align-items: center; + height: 38px; +} + +#methodParams tr td { + display: flex; + flex-wrap: nowrap; + padding: 0px 12px; +} + +#methodParams tr .required { + color: var(--color-action); + font-size: 20px; +} + +#methodParams tr td:nth-child(1){width: calc(50% - 100px);} +#methodParams tr td:nth-child(2){width: 100px;} +#methodParams tr td:nth-child(3){width: calc(50% - 30px);} +#methodParams tr td:nth-child(4){width: 30px; justify-content: center;} + +#methodParams thead tr { + background: var(--color-action); + color: var(--color-action-text); + font-weight: bold; +} + +#methodParams tbody tr:nth-child(even) { + background-color: var(--color-bg-nuance); +} + +#methodParams .type-badge { + display:flex; + overflow: hidden; + align-items: center; + justify-content: center; + width:20px; + height:20px; + font-size: 20px; + font-weight: bold; + line-height:16px; + border-radius: 100%; + background: var(--color-action); + color: var(--color-action-text); + margin-right: 2px; +} + +#methodParams .type-badge::before { + font-size: 12px; +} + +#testForm .card-content .select-group { + margin-bottom: 10px; + display: flex; + align-items: baseline; + flex-direction: column; +} + +#testForm .testAction { + display:flex; + justify-content: flex-end; +} + +#testForm .testAction .button { + margin-left: 10px; +} + +#testForm select, #testForm select::before, #testForm select::after { + box-sizing: border-box; +} + +select { + appearance: none; + background-color: transparent; + border: none; + padding: 0 1em 0 0; + margin: 0; + width: 100%; + font-family: inherit; + font-size: inherit; + cursor: inherit; + line-height: inherit; + color: var(--color-text); +} + +#testForm .select { + width: 100%; + outline: none; + min-width: 15ch; + max-width: 30ch; + border: 2px solid var(--color-action-secondary); + border-radius: var(--border-radius); + padding: 5px; + cursor: pointer; + font-weight: bold; + position: relative; +} + +#testForm .select::after { + content: '\e835'; + font-family: 'fontello'; + font-size: 12px; + color: var(--color-text); + position:absolute; + top:50%; + right: 10px; + transform: translateY(-50%); + pointer-events: none; +} + +/* Remove arrow from select */ +#testForm select::-ms-expand { + display: none; +} + +#introMessage { + font-size:1.1em; +} + +#introMessage .card-content { + padding: 0 10px; +} + +#urlForm { + margin-bottom:10px; +} + +a.button { + padding: 10px; + border-radius: var(--border-radius); + background: var(--color-action); + color: var(--color-action-text); + display: flex; + align-items: center; +} + +a.button:hover { + background-color: var(--color-action-hover); +} + +#tiptip_content { + font-size:12px; +} + +#resultWrapper { + width:100%; + height:300px; + padding: 0; + position:relative; +} +iframe {width:100%;height:100%; background-color: white;} + +#iframeAction { + position: absolute; + bottom: 0; + transform: translateY(calc(100% + 5px)); +} + +#decreaseIframe i::before { + transform: rotate(180deg); +} + +div.onlys {padding:.25em .5em;display:table;border-radius:4px;margin-bottom:0.5em;} + +.darkModeButton { + position: absolute; + z-index: 11; + top: 0px; + right: 0px; + width: var(--header-heigth); + height: var(--header-heigth); + display: flex; + justify-content: center; + align-items: center; + font-size: 20px; + opacity: 0.7; + cursor: pointer; +} + +.darkModeButton:hover { + opacity: 1; +} + +/* -- Tiptip customization -- */ +#tiptip_content { + color: var(--color-action-text) !important; + background: var(--color-action) !important; + text-shadow: none; +} + +#tiptip_holder.tip_bottom #tiptip_arrow_inner { + border-bottom-color: var(--color-action) !important; +} + +/* -- Chrome ScrollBar customization -- */ +::-webkit-scrollbar { + width: 8px; +} + +/* Track */ +::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.11); +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: var(--color-action); + border-radius:5px; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: var(--color-action); +} \ No newline at end of file diff --git a/tools/ws/ws.js b/tools/ws/ws.js new file mode 100644 index 000000000..38e902edd --- /dev/null +++ b/tools/ws/ws.js @@ -0,0 +1,492 @@ +$(() => { + // global lets + let cachedMethods = new Array; + let ws_url = "http://"; + + // automatic detection of ws_url + match = document.location.toString().match(/^(https?.*\/)tools\/ws\.html?/); + if (match == null) { + askForUrl(); + } + else { + ws_url = match[1] + 'ws.php'; + getMethodList(); + } + + // manual set of ws_url + $("#urlForm").submit(function () { + ws_url = $(this).children("input[name='ws_url']").val(); + getMethodList(); + return false; + }); + + // invoke buttons + $("#invokeMethod").click(function () { + invokeMethod($("#methodName").html(), false); + return false; + }); + $("#invokeMethodBlank").click(function () { + invokeMethod($("#methodName").html(), true); + return false; + }); + + // resizable iframe + $("#increaseIframe").click(function () { + $("#resultWrapper").css('height', $("#resultWrapper").height() + 100); + }); + $("#decreaseIframe").click(function () { + if ($("#resultWrapper").height() > 200) { + $("#resultWrapper").css('height', $("#resultWrapper").height() - 100); + } + }); + + // mask all wrappers + function resetDisplay() { + $("#errorWrapper").hide(); + $("#methodWrapper").hide(); + $("#methodName").hide(); + $("#urlForm").hide(); + $("#methodDescription blockquote").empty(); + $("#methodDescription").hide(); + $("#requestURLDisplay").hide(); + $("#requestResultDisplay").hide(); + $("#invokeFrame").attr('src', ''); + } + + // display error wrapper + function displayError(error) { + resetDisplay(); + $("#errorWrapper").html("Error: " + error).show(); + } + + // display ws_url form + function askForUrl() { + displayError("can't contact web-services, please give absolute url to 'ws.php'"); + if ($("#urlForm input[name='ws_url']").val() == "") { + $("#urlForm input[name='ws_url']").val(ws_url); + } + $("#urlForm").show(); + } + + // parse Piwigo JSON + function parsePwgJSON(json) { + try { + resp = jQuery.parseJSON(json); + if (resp == null | resp.result == null | resp.stat == null | resp.stat != 'ok') { + throw new Error(); + } + } + catch (e) { + displayError("unable to parse JSON string"); + resp = { "stat": "ko", "result": "null" }; + } + + return resp.result; + } + + // fetch methods list + function getMethodList() { + resetDisplay(); + + $.ajax({ + type: "GET", + url: ws_url, + data: { format: "json", method: "reflection.getMethodList" } + }).done(function (result) { + result = parsePwgJSON(result); + + if (result != null) { + methods = result.methods; + + let methodTree = {}; + for (let i = 0; i < methods.length; i++) { + addMethodToNode(methodTree, methods[i].split('.')) + } + + $("#methodsList").html(displayMethodNode(methodTree, [])).show(); + + // trigger method selection + $("#methodsList .method-link").click(function () { + selectMethod($(this).data('method')); + }); + + if ($.cookie('wse-menu-state')) { + $.cookie('wse-menu-state').split(',').forEach(id => $(`input[id="${id}"]`).attr('checked', true)); + } + + setStateMenu(); + + $('.method-node-content').each((i, node) => { + let content = $(node); + let checkbox = content.parent().children('input'); + + checkbox.on('change', function() { + + let id = checkbox.attr('id'); + + let menustate = $.cookie('wse-menu-state')?.split(',') ?? []; + + if (this.checked) { + content.slideDown(200); + + menustate.push(id) + } else { + content.slideUp(200); + menustate = menustate.filter(str => str !== id); + } + + $.cookie('wse-menu-state', menustate.join(',')) + + }) + }) + } + }).error(function (jqXHR, textStatus, errorThrown) { + askForUrl(); + }); + } + + function addMethodToNode(methodNode, methodRoute) { + if (methodRoute.length > 1) { + let node = methodRoute.shift(); + if (!methodNode[node]) + methodNode[node] = {}; + addMethodToNode(methodNode[node], methodRoute); + } else + methodNode[methodRoute[0]] = 1; + } + + function displayMethodNode(methodNode, route) { + let html = ''; + + if (methodNode === 1) { + html = ` + ${route[route.length - 1]} + ` + } else { + html = route.length === 0 ? '' : `
+ + +
`; + + for (const node in methodNode) { + html += displayMethodNode(methodNode[node], [...route, node]); + } + + html += route.length === 0 ? '' :'
'; + } + + return html; + } + + function setStateMenu() { + $('.method-node').each((i, n) => { + let node = $(n); + let content = node.children('.method-node-content') + let checkbox = node.children('input'); + + if (checkbox.prop('checked')) { + content.show(); + } else { + content.hide(); + } + }) + } + + // select method + function selectMethod(methodName) { + $("#introMessage").hide(); + $("#tiptip_holder").fadeOut(200); + + if (cachedMethods[methodName]) { + fillNewMethod(methodName); + } + else { + $.ajax({ + type: "GET", + url: ws_url, + data: { format: "json", method: "reflection.getMethodDetails", methodName: methodName } + }).done(function (result) { + result = parsePwgJSON(result); + + if (result != null) { + let onlys = []; + if (result.options.post_only || result.options.admin_only) { + if (result.options.post_only) { + onlys.push('POST only'); + } + if (result.options.admin_only) { + onlys.push('Admin only'); + } + + } + result.onlys = onlys; + cachedMethods[methodName] = result; + fillNewMethod(methodName); + } + }).error(function (jqXHR, textStatus, errorThrown) { + displayError("unknown error"); + }); + } + } + + // display method details + function fillNewMethod(methodName) { + resetDisplay(); + + method = cachedMethods[methodName]; + + $("#methodName").html(method.name).show(); + + $('#onlys').html(''); + method.onlys.forEach((text) => { + $('#onlys').append($(`${text}`)); + }) + + if (method.description != "") { + $("#methodDescription blockquote").html(method.description); + $("#methodDescription").show(); + } + + $("#requestFormat").val(method.options.post_only ? 'post' : 'get'); + + let methodParams = ''; + if (method.params && method.params.length > 0) { + + $('.no-params').hide(); + $("#methodParams table").show(); + + for (let i = 0; i < method.params.length; i++) { + let param = method.params[i], + isOptional = param.optional, + acceptArray = param.acceptArray, + defaultValue = param.defaultValue == null ? '' : param.defaultValue, + info = param.info == null ? '' : '', + type = '', + subtype = '', + optional = '*', + array = ''; + + if (param.type.match(/bool/)) type += 'B'; + if (param.type.match(/int/)) type += 'I'; + if (param.type.match(/float/)) type += 'F'; + + if (param.type.match(/positive/)) subtype += ''; + if (param.type.match(/notnull/)) subtype += 'ø'; + + + // if an array is direclty printed, the delimiter is a comma where we use a pipe + if (typeof defaultValue == 'object') { + defaultValue = defaultValue.join('|'); + } + + methodParams += ` + ${param.name + (isOptional ? '' : optional ) + info } + ${(acceptArray ? array : '') + type + subtype} + + + + + + `; + } + $("#methodParams tbody").html(methodParams); + } + else { + $('.no-params').show(); + $("#methodParams table").hide(); + } + + $("#methodWrapper").show(); + + // trigger field modification + $("input.methodParameterValue").change(function () { + $("input.methodParameterSend[data-id='" + $(this).data('id') + "']").attr('checked', 'checked'); + }); + + // tiptip + $(".methodInfo").tipTip({ + maxWidth: "300px", + defaultPosition: "bottom", + delay: 0 + }); + + $(".required, .type-badge").tipTip({ + maxWidth: "100px", + defaultPosition: "bottom", + delay: 0 + }); + } + + // invoke method + function invokeMethod(methodName, newWindow) { + + $('#requestURLDisplay').show(); + $('#requestResultDisplay').show(); + + let method = cachedMethods[methodName]; + + let reqUrl = ws_url + "?format=" + $("#responseFormat").val(); + + // GET + if ($("#requestFormat").val() == 'get') { + reqUrl += "&method=" + methodName; + + for (let i = 0; i < method.params.length; i++) { + if (!$("input.methodParameterSend[data-id='" + i + "']").is(":checked")) { + continue; + } + + let paramValue = $("input.methodParameterValue[data-id='" + i + "']").val(); + + let paramSplitted = paramValue.split('|'); + if (method.params[i].acceptArray && paramSplitted.length > 1) { + $.each(paramSplitted, function (v) { + reqUrl += '&' + method.params[i].name + '[]=' + paramSplitted[v]; + }); + } + else { + reqUrl += '&' + method.params[i].name + '=' + paramValue; + } + } + + if (newWindow) { + window.open(reqUrl); + } + else { + if ($("#responseFormat").val() === 'json') { + $("#invokeFrame").hide(); + $('#json-viewer').show(); + fetch(reqUrl) + .then(data => data.json()) + .then(json => { + $('#json-viewer').jsonViewer(json); + }) + } else { + $("#invokeFrame").show(); + $('#json-viewer').hide(); + $("#invokeFrame").attr('src', reqUrl); + } + } + + $('#requestURLDisplay').find('.url').html(reqUrl).end() + .find('.params').hide(); + } + // POST + else { + let params = {}; + + let form = $("#invokeForm"); + form.attr('action', reqUrl); + + let t = ''; + + for (let i = 0; i < method.params.length; i++) { + if (!$("input.methodParameterSend[data-id='" + i + "']").is(":checked")) { + continue; + } + + let paramValue = $("input.methodParameterValue[data-id='" + i + "']").val(), + paramName = method.params[i].name, + paramSplitted = paramValue.split('|'); + + if (method.params[i].acceptArray && paramSplitted.length > 1) { + params[paramName] = []; + + $.each(paramSplitted, function (i, value) { + params[paramName].push(value); + t += ''; + }); + } + else { + params[paramName] = paramValue; + t += ''; + } + } + + + if (!newWindow && $("#responseFormat").val() === 'json') { + $("#invokeFrame").hide(); + $('#json-viewer').show(); + jQuery.ajax({ + url: reqUrl, + type: 'POST', + dataType: 'json', + data: { + "method": methodName, + ...params + }, + success : function(data) { + $('#json-viewer').jsonViewer(data); + } + }) + } else { + $("#invokeFrame").show(); + $('#json-viewer').hide(); + + form.html(t); + form.attr('target', newWindow ? "_blank" : "invokeFrame"); + form.submit(); + } + + $('#requestURLDisplay').find('.url').html(reqUrl).end() + .find('.params').show().html(JSON.stringify(params, null, 4)); + } + + return false; + } + + $('#search input').val(''); + + $('#search input').on('input', function () { + if ($(this).val()) { + $('.method-node, .method-link').hide(); + if (!$('#methodsList').hasClass('onSearch')) { + $('#methodsList').addClass('onSearch'); + $('.method-node-content').show(); + } + + function showBranch(methodNode) { + methodNode.show(); + while (methodNode.parent().parent().hasClass("method-node")) { + methodNode = methodNode.parent().parent(); + methodNode.show(); + } + } + + $('.method-link').each((i, n) => { + if ($(n).data('method').toLowerCase().search($(this).val().toLowerCase())!= -1) { + showBranch($(n)); + } + }) + + } else { + $('.method-node, .method-link').show(); + $('#methodsList').removeClass('onSearch'); + setStateMenu() + } + }) + + if ($.cookie('wse-dark-mode')) { + $('#the_body').addClass('dark-mode'); + $('.darkModeButton').addClass('icon-sun-inv'); + } + + $('.darkModeButton').click(() => { + if ($.cookie('wse-dark-mode')) { + $('.darkModeButton').removeClass('icon-sun-inv').addClass('icon-moon-inv'); + $.removeCookie('wse-dark-mode'); + $('#the_body').removeClass('dark-mode'); + } else { + $('.darkModeButton').removeClass('icon-moon-inv').addClass('icon-sun-inv'); + $.cookie('wse-dark-mode', true); + $('#the_body').addClass('dark-mode'); + } + }) +}) \ No newline at end of file