diff --git a/pandora_console/include/javascript/pandora_visual_console.js b/pandora_console/include/javascript/pandora_visual_console.js index 8cf061f3dd..df6fadc01f 100755 --- a/pandora_console/include/javascript/pandora_visual_console.js +++ b/pandora_console/include/javascript/pandora_visual_console.js @@ -175,7 +175,7 @@ function createVisualConsole( switch (identifier) { case "parent": - var options = visualConsole.elements + var data = visualConsole.elements .filter(function(item) { return item.props.id !== params.id; }) @@ -186,7 +186,57 @@ function createVisualConsole( }; }); - done(null, options); + done(null, data); + break; + case "acl-group": + asyncTaskManager + .add(identifier + "-" + params.id, function(doneAsyncTask) { + var abortable = getGroupsVisualConsoleItem( + baseUrl, + visualConsole.props.id, + function(error, data) { + if (error || !data) { + console.log( + "[ERROR]", + "[VISUAL-CONSOLE-CLIENT]", + "[API]", + error ? error.message : "Invalid response" + ); + + done(error); + doneAsyncTask(); + return; + } + + if (typeof data === "string") { + try { + data = JSON.parse(data); + } catch (error) { + console.log( + "[ERROR]", + "[VISUAL-CONSOLE-CLIENT]", + "[API]", + error ? error.message : "Invalid response" + ); + + done(error); + doneAsyncTask(); + return; // Stop task execution. + } + } + + done(null, data); + doneAsyncTask(); + } + ); + + return { + cancel: function() { + abortable.abort(); + } + }; + }) + .init(); break; default: done(new Error("identifier not found")); @@ -237,7 +287,7 @@ function createVisualConsole( if (typeof data === "string") { try { data = JSON.parse(data); - } catch (e) { + } catch (error) { console.log( "[ERROR]", "[VISUAL-CONSOLE-CLIENT]", @@ -358,7 +408,7 @@ function createVisualConsole( if (typeof data === "string") { try { data = JSON.parse(data); - } catch (e) { + } catch (error) { console.log( "[ERROR]", "[VISUAL-CONSOLE-CLIENT]", @@ -655,7 +705,6 @@ function getVisualConsoleItem(baseUrl, vcId, vcItemId, callback) { // Failed request handler. var handleFail = function(jqXHR, textStatus, errorThrown) { - abort(); // Manually aborted or not. if (textStatus === "abort") { callback(); @@ -760,6 +809,68 @@ function removeVisualConsoleItem(baseUrl, vcId, vcItemId, callback) { }; } +/** + * Fetch groups access user. + * @param {string} baseUrl Base URL to build the API path. + * @param {function} callback Function to be executed on request success or fail. + * @return {Object} Cancellable. Object which include and .abort([statusText]) function. + */ +// eslint-disable-next-line no-unused-vars +function getGroupsVisualConsoleItem(baseUrl, vcId, callback) { + var apiPath = baseUrl + "/ajax.php"; + var jqXHR = null; + + // Cancel the ajax requests. + var abort = function(textStatus) { + if (textStatus == null) textStatus = "abort"; + + // -- XMLHttpRequest.readyState -- + // Value State Description + // 0 UNSENT Client has been created. open() not called yet. + // 4 DONE The operation is complete. + + if (jqXHR.readyState !== 0 && jqXHR.readyState !== 4) + jqXHR.abort(textStatus); + }; + + // Failed request handler. + var handleFail = function(jqXHR, textStatus, errorThrown) { + abort(); + // Manually aborted or not. + if (textStatus === "abort") { + callback(); + } else { + var error = new Error(errorThrown); + error.request = jqXHR; + callback(error); + } + }; + + // Function which handle success case. + var handleSuccess = function(data) { + callback(null, data); + }; + + // Visual Console container request. + jqXHR = jQuery + .get( + apiPath, + { + page: "include/rest-api/index", + getGroupsVisualConsoleItem: 1, + visualConsoleId: vcId + }, + "json" + ) + .done(handleSuccess) + .fail(handleFail); + + // Abortable. + return { + abort: abort + }; +} + // TODO: Delete the functions below when you can. /************************************** These functions require jQuery library diff --git a/pandora_console/include/rest-api/index.php b/pandora_console/include/rest-api/index.php index 4f89f4dabf..1eaa66c2c9 100644 --- a/pandora_console/include/rest-api/index.php +++ b/pandora_console/include/rest-api/index.php @@ -2,6 +2,7 @@ global $config; + if (!is_ajax()) { return; } @@ -16,6 +17,7 @@ $getVisualConsoleItems = (bool) get_parameter('getVisualConsoleItems'); $updateVisualConsoleItem = (bool) get_parameter('updateVisualConsoleItem'); $getVisualConsoleItem = (bool) get_parameter('getVisualConsoleItem'); $removeVisualConsoleItem = (bool) get_parameter('removeVisualConsoleItem'); +$getGroupsVisualConsoleItem = (bool) get_parameter('getGroupsVisualConsoleItem'); ob_clean(); @@ -141,6 +143,26 @@ if ($getVisualConsole === true) { $result = $item::delete($itemId); echo $result; return; +} else if ($getGroupsVisualConsoleItem === true) { + $data = users_get_groups_for_select( + $config['id_user'], + 'AR', + true, + true + ); + + $result = array_map( + function ($id) use ($data) { + return [ + 'value' => $id, + 'text' => $data[$id], + ]; + }, + array_keys($data) + ); + + echo json_encode($result); + return; } exit; diff --git a/visual_console_client/src/Item.ts b/visual_console_client/src/Item.ts index e309bf3325..3fccd1dc8b 100644 --- a/visual_console_client/src/Item.ts +++ b/visual_console_client/src/Item.ts @@ -240,9 +240,9 @@ class SizeInputGroup extends InputGroup> { } /** - * Class to add item to the static Graph item form + * Class to add item to the general items form * This item consists of a label and a color type select. - * Show Last Value is stored in the showLastValueTooltip property + * Parent is stored in the parentId property */ class ParentInputGroup extends InputGroup> { protected createContent(): HTMLElement | HTMLElement[] { @@ -284,6 +284,62 @@ class ParentInputGroup extends InputGroup> { } } +/** + * Class to add item to the general items form + * This item consists of a label and a color type select. + * Parent is stored in the parentId property + */ +class AclGroupInputGroup extends InputGroup> { + protected createContent(): HTMLElement | HTMLElement[] { + const aclGroupLabel = document.createElement("label"); + aclGroupLabel.textContent = t("Restrict access to group"); + + const divSpinner = document.createElement("div"); + divSpinner.className = "visual-console-spinner small"; + aclGroupLabel.appendChild(divSpinner); + + this.requestData("acl-group", {}, (error, data) => { + // Remove Spinner. + divSpinner.remove(); + if (error) { + const errorSelect = document.createElement("img"); + errorSelect.src = ""; + errorSelect.alt = "image-error"; + aclGroupLabel.appendChild(errorSelect); + } + + if (data instanceof Array) { + const aclGroupSelect = document.createElement("select"); + aclGroupSelect.required = true; + + data.forEach(option => { + const optionElement = document.createElement("option"); + optionElement.value = option.value; + // Dangerous because injection sql. + // Use textContent for innerHTML. + // Here it is used to show the depth of the groups. + optionElement.innerHTML = option.text; + aclGroupSelect.appendChild(optionElement); + }); + + aclGroupSelect.addEventListener("change", event => { + this.updateData({ + aclGroupId: parseIntOr((event.target as HTMLSelectElement).value, 0) + }); + }); + + aclGroupSelect.value = `${this.currentData.aclGroupId || + this.initialData.aclGroupId || + 0}`; + + aclGroupLabel.appendChild(aclGroupSelect); + } + }); + + return aclGroupLabel; + } +} + /** * Extract a valid enum value from a raw label position value. * @param labelPosition Raw value. @@ -1184,9 +1240,10 @@ abstract class VisualConsoleItem { new SizeInputGroup("size", this.props), new LinkInputGroup("link", this.props), new OnTopInputGroup("show-on-top", this.props), - new ParentInputGroup("parent", this.props) + new ParentInputGroup("parent", this.props), + new AclGroupInputGroup("acl-group", this.props) ], - ["position", "size", "link", "show-on-top", "parent"] + ["position", "size", "link", "show-on-top", "parent", "acl-group"] ); //return VisualConsoleItem.getFormContainer(this.props); @@ -1201,9 +1258,10 @@ abstract class VisualConsoleItem { new SizeInputGroup("size", props), new LinkInputGroup("link", props), new OnTopInputGroup("show-on-top", props), - new ParentInputGroup("parent", props) + new ParentInputGroup("parent", props), + new AclGroupInputGroup("acl-group", props) ], - ["position", "size", "link", "show-on-top", "parent"] + ["position", "size", "link", "show-on-top", "parent", "acl-group"] ); } } diff --git a/visual_console_client/src/main.css b/visual_console_client/src/main.css index f8216481b5..5c663da819 100644 --- a/visual_console_client/src/main.css +++ b/visual_console_client/src/main.css @@ -40,13 +40,15 @@ pointer-events: none; } -.visual-console-spinner, -.visual-console-spinner :after { - display: block; - width: 32px; - height: 32px; - border-radius: 50%; +@keyframes spinner-loading { + 0% { + transform: rotate(0deg); + } + to { + transform: rotate(1turn); + } } + .visual-console-spinner { background-color: transparent; margin: 0px auto; @@ -60,13 +62,19 @@ animation-iteration-count: infinite; animation-timing-function: linear; } -@keyframes spinner-loading { - 0% { - transform: rotate(0deg); - } - to { - transform: rotate(1turn); - } + +.visual-console-spinner, +.visual-console-spinner :after { + display: block; + width: 32px; + height: 32px; + border-radius: 50%; +} + +.visual-console-spinner.small, +.visual-console-spinner.small :after { + width: 12px; + height: 12px; } .div-visual-console-spinner {