From 4a12635ea5cc7d1e52c3960d4bcdf227916b7d1d Mon Sep 17 00:00:00 2001 From: Molkobain Date: Wed, 20 Nov 2019 11:36:12 +0100 Subject: [PATCH] Portal: Introduce "CombodoPortalToolbox", helpers to ease JS manipulations especially through the iPopupMenuExtension. - CombodoPortalToolbox.CloseAllModals() : Close all modal on the page - CombodoPortalToolbox.OpenUrlInModal(sTargetUrl, bCloseOtherModals) : Open an URL in a modal, typically opening an object form - CombodoPortalToolbox.OpenModal(oOptions) : Generic method to open modals in the portal with various options --- .../portal/public/js/toolbox.js | 200 ++++++++++++++++++ .../portal/templates/layout.html.twig | 1 + 2 files changed, 201 insertions(+) create mode 100644 datamodels/2.x/itop-portal-base/portal/public/js/toolbox.js diff --git a/datamodels/2.x/itop-portal-base/portal/public/js/toolbox.js b/datamodels/2.x/itop-portal-base/portal/public/js/toolbox.js new file mode 100644 index 0000000000..19cc055b83 --- /dev/null +++ b/datamodels/2.x/itop-portal-base/portal/public/js/toolbox.js @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2013-2019 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ + +/** + * A set of helpers to make JS manipulations easier. + * + * @since 2.7.0 + */ +var CombodoPortalToolbox = { + /** + * Close all opened modals on the page + */ + CloseAllModals: function() + { + $('.modal.in').modal('hide'); + }, + /** + * Open a standard modal and put the content of the URL in it. + * + * @param sTargetUrl + * @param bCloseOtherModals + */ + OpenUrlInModal: function(sTargetUrl, bCloseOtherModals){ + // Set default values + if(bCloseOtherModals === undefined) + { + bCloseOtherModals = false; + } + + // Close other modals if necessary + if(bCloseOtherModals) + { + CombodoPortalToolbox.CloseAllModals(); + } + + // Opening modal + CombodoPortalToolbox.OpenModal({ + content: { + endpoint: sTargetUrl, + } + }); + }, + /** + * Generic function to create and open a modal, used by high-levconfiel functions such as "CombodoPortalToolbox.OpenUrlInModal()". + * When developing extensions, you should use them instead. + * + * @param oOptions + * @returns object The jQuery object of the modal element + */ + OpenModal: function(oOptions){ + // Set default options + oOptions = $.extend( + true, + { + id: null, // ID of the created modal + attributes: {}, // HTML attributes + base_modal: { + usage: 'clone', // Either 'clone' or 'replace' + selector: '#modal-for-all' // Either a selector of the modal element used to base this one on or the modal element itself + }, + content: undefined, // Either a string, an object containing the endpoint / data or undefined to keep base modal content as-is + size: 'lg', // Either 'xs' / 'sm' / 'md' / 'lg' + }, + oOptions + ); + + // Compute modal selector + var oSelectorElem = null; + switch(typeof oOptions.base_modal.selector) + { + case 'string': + oSelectorElem = $(oOptions.base_modal.selector); + break; + + case 'object': + oSelectorElem = oOptions.base_modal.selector; + break; + + default: + if (window.console && window.console.warn) + { + console.warn('Could not open modal dialog as the select option was malformed: ', oOptions.content); + } + break; + } + + // Get modal element by either + var oModalElem = null; + // - Create a new modal from template + // Note : This could be better if we check for an existing modal first instead of always creating a new one + if (oOptions.base_modal.usage === 'clone') + { + oModalElem = oSelectorElem.clone(); + oModalElem.attr('id', oOptions.id) + .appendTo('body'); + } + // - Get an existing modal in the DOM + else + { + oModalElem = oSelectorElem; + } + + // Set attributes + for(var sProp in oOptions.attributes) + { + oModalElem.attr(sProp, oOptions.attributes[sProp]); + } + + // Resize to small modal + oModalElem.find('.modal-dialog') + .removeClass('modal-lg') + .addClass('modal-' + oOptions.size); + + // Load content + switch (typeof oOptions.content) + { + case 'string': + oModalElem.find('.modal-content').html(oOptions.content); + + //Manually triggers bootstrap event in order to keep listeners working + oModalElem.trigger('loaded.bs.modal'); + break; + + case 'object': + // Put loader while fetching content + oModalElem.find('.modal-content').html($('#page_overlay .overlay_content').html()); + // Fetch content in background + oModalElem.find('.modal-content').load( + oOptions.content.endpoint, + oOptions.content.data || {}, + function (sResponseText, sStatus) + { + // Hiding modal in case of error as the general AJAX error handler will display a message + if (sStatus === 'error') + { + oModalElem.modal('hide'); + } + + //Manually triggers bootstrap event in order to keep listeners working + oModalElem.trigger('loaded.bs.modal'); + } + ); + break; + + case 'undefined': + // Do nothing, we keep the content as-is + break; + + default: + if (window.console && window.console.warn) + { + console.warn('Could not open modal dialog as the content option was malformed: ', oOptions.content); + } + } + + // Show modal + oModalElem.modal('show'); + + return oModalElem; + }, + /** + * Generic function to call a specific endpoint with callbacks + * + * @param sEndpointUrl + * @param oPostedData + * @param callbackOnSuccess + * @param callbackOnPending + */ + CallEndpoint: function(sEndpointUrl, oPostedData, callbackOnSuccess, callbackOnPending){ + // Call endpoint + $.post(sEndpointUrl, oPostedData, function(oResponse) { + // Call callback on success + if(callbackOnSuccess !== undefined) + { + window[callbackOnSuccess](oResponse); + } + }); + + // Call callback while waiting for response + if(callbackOnPending !== undefined) + { + window[callbackOnPending](); + } + } +}; diff --git a/datamodels/2.x/itop-portal-base/portal/templates/layout.html.twig b/datamodels/2.x/itop-portal-base/portal/templates/layout.html.twig index 777bfa8f15..d6d768a1ab 100644 --- a/datamodels/2.x/itop-portal-base/portal/templates/layout.html.twig +++ b/datamodels/2.x/itop-portal-base/portal/templates/layout.html.twig @@ -92,6 +92,7 @@ +