diff --git a/css/backoffice/components/_datatable.scss b/css/backoffice/components/_datatable.scss
index 08ae5d00a..fb644ca0e 100644
--- a/css/backoffice/components/_datatable.scss
+++ b/css/backoffice/components/_datatable.scss
@@ -151,17 +151,3 @@ $ibo-fieldsorter--selected--background-color: $ibo-color-blue-200 !default;
}
-
-#table-row-action-confirmation-dialog{
-
- .ibo-row-action--confirmation--explanation{
- margin-bottom: 16px;
- }
-
- .ibo-row-action--confirmation--do-not-show-again--checkbox{
- height: auto;
- display: inline-block;
- width: auto;
- }
-
-}
\ No newline at end of file
diff --git a/css/backoffice/components/_modal.scss b/css/backoffice/components/_modal.scss
index 6054677e4..0cb0f44de 100644
--- a/css/backoffice/components/_modal.scss
+++ b/css/backoffice/components/_modal.scss
@@ -1,4 +1,18 @@
/*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
- */
\ No newline at end of file
+ */
+
+/* SCSS variables */
+$ibo-modal-option--do-not-show-again--margin-top: $ibo-spacing-500 !default;
+
+// Modal Option - Do not show again
+.ibo-modal-option--do-not-show-again{
+ margin-top: $ibo-modal-option--do-not-show-again--margin-top;
+
+ .ibo-modal-option--do-not-show-again--checkbox{
+ height: auto;
+ display: inline-block;
+ width: auto;
+ }
+}
\ No newline at end of file
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
index 9714a3c79..e6a1afaed 100644
--- a/datamodels/2.x/itop-portal-base/portal/public/js/toolbox.js
+++ b/datamodels/2.x/itop-portal-base/portal/public/js/toolbox.js
@@ -126,7 +126,7 @@ CombodoModal._InstantiateModal = function(oModalElem, oOptions) {
oModalElem.find('.modal-content').html(oOptions.content);
// Internal callbacks
- this._OnContentLoaded(oModalElem, oOptions.callbackOnContentLoaded);
+ this._OnContentLoaded(oModalElem, oOptions.callback_on_content_loaded);
// Manually triggers bootstrap event in order to keep listeners working
oModalElem.trigger('loaded.bs.modal');
@@ -148,7 +148,7 @@ CombodoModal._InstantiateModal = function(oModalElem, oOptions) {
}
// Internal callbacks
- me._OnContentLoaded(oModalElem, oOptions.callbackOnContentLoaded);
+ me._OnContentLoaded(oModalElem, oOptions.callback_on_content_loaded);
//Manually triggers bootstrap event in order to keep listeners working
oModalElem.trigger('loaded.bs.modal');
diff --git a/dictionaries/ui/components/modal/en.dictionary.itop.modal.php b/dictionaries/ui/components/modal/en.dictionary.itop.modal.php
new file mode 100644
index 000000000..52f8a3cb2
--- /dev/null
+++ b/dictionaries/ui/components/modal/en.dictionary.itop.modal.php
@@ -0,0 +1,22 @@
+ 'Confirmation',
+));
\ No newline at end of file
diff --git a/dictionaries/ui/components/modal/fr.dictionary.itop.modal.php b/dictionaries/ui/components/modal/fr.dictionary.itop.modal.php
new file mode 100644
index 000000000..60a3ffb7b
--- /dev/null
+++ b/dictionaries/ui/components/modal/fr.dictionary.itop.modal.php
@@ -0,0 +1,22 @@
+ 'Confirmation',
+));
\ No newline at end of file
diff --git a/js/dataTables.row-actions.js b/js/dataTables.row-actions.js
index a7993a5e2..98f6c12fd 100644
--- a/js/dataTables.row-actions.js
+++ b/js/dataTables.row-actions.js
@@ -3,9 +3,6 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
-const TABLE_ACTION_CONFIRMATION_PREFIX = 'table_action_row';
-const TABLE_ACTION_CONFIRMATION_DIALOG_SELECTOR = '#table-row-action-confirmation-dialog';
-
/**
* Return column JSON declaration for row actions.
* Could be part of column or columnDefs declaration of datatable.js.
@@ -30,77 +27,4 @@ function getRowActionsColumnDefinition(sTableId, iColumnTargetIndex = -1)
}
return aColumn;
-}
-
-
-/**
- * HandleActionRowConfirmation.
- *
- * @param sTitle title for confirmation dialog
- * @param sMessage message of the confirmation dialog
- * @param sDoNotShowAgainPreferenceKey iTop preference key to store "do not show again" flag
- * @param oConfirmHandler confirm button handler
- * @param aConfirmHandlerData confirm button handler data
- * @constructor
- */
-const HandleActionRowConfirmation = function (sTitle, sMessage, sDoNotShowAgainPreferenceKey, oConfirmHandler, aConfirmHandlerData){
-
- // confirmation preference
- if(sDoNotShowAgainPreferenceKey != null){
-
- // retrieve need confirmation user preference
- let bNeedConfirmation = GetUserPreferenceAsBoolean(`${TABLE_ACTION_CONFIRMATION_PREFIX}.${sDoNotShowAgainPreferenceKey}`, true);
-
- // confirm handler if no confirmation requested
- if(!bNeedConfirmation){
- oConfirmHandler(aConfirmHandlerData.datatable, aConfirmHandlerData.tr_element, aConfirmHandlerData.action_id, aConfirmHandlerData.row_data);
- return;
- }
- }
-
- // fill confirmation dialog
- $('.ibo-row-action--confirmation--explanation', $(TABLE_ACTION_CONFIRMATION_DIALOG_SELECTOR)).html(sMessage);
- $('.ibo-row-action--confirmation--do-not-show-again', $(TABLE_ACTION_CONFIRMATION_DIALOG_SELECTOR)).toggle(sDoNotShowAgainPreferenceKey != null);
-
- // open confirmation dialog
- $(TABLE_ACTION_CONFIRMATION_DIALOG_SELECTOR).dialog({
- autoOpen: false,
- minWidth: 400,
- modal: true,
- title: sTitle,
- autoOpen: true,
- position: {my: "center center", at: "center center", of: $('body')},
- close: function () {
- // destroy dialog object
- $(TABLE_ACTION_CONFIRMATION_DIALOG_SELECTOR).dialog( "destroy" );
- },
- buttons: [
- {
- text: Dict.S('UI:Button:Cancel'),
- class: 'ibo-is-alternative',
- click: function () {
- // close dialog
- $(TABLE_ACTION_CONFIRMATION_DIALOG_SELECTOR).dialog('close');
- }
- },
- {
- text: Dict.S('UI:Button:Ok'),
- class: 'ibo-is-primary',
- click: function () {
- // handle "do not show again" user preference
- if(sDoNotShowAgainPreferenceKey != null){
- // save preference
- const bDoNotShowAgain = $(this).find($('.ibo-row-action--confirmation--do-not-show-again--checkbox')).prop('checked');
- if (bDoNotShowAgain) {
- SetUserPreference(`${TABLE_ACTION_CONFIRMATION_PREFIX}.${sDoNotShowAgainPreferenceKey}`, 'false', true);
- }
- }
- // call confirm handler and close dialog
- if(oConfirmHandler(aConfirmHandlerData.datatable, aConfirmHandlerData.tr_element, aConfirmHandlerData.action_id, aConfirmHandlerData.row_data)){
- $(TABLE_ACTION_CONFIRMATION_DIALOG_SELECTOR).dialog('close');
- }
- }
- },
- ],
- });
-}
+}
\ No newline at end of file
diff --git a/js/dataTables.settings.js b/js/dataTables.settings.js
index 52754a972..335012933 100644
--- a/js/dataTables.settings.js
+++ b/js/dataTables.settings.js
@@ -111,6 +111,13 @@ $(function () {
}
});
+ // Append row actions column
+ if (me.options.bHasRowActions) {
+ sThead += "
| ";
+ let iColumnCount = aOptions['columns'].length;
+ aOptions["columns"][iColumnCount] = getRowActionsColumnDefinition(oParams.list_id);
+ }
+
parentElt.append("");
aOptions["lengthMenu"] = [[oParams.end, oParams.end * 2, oParams.end * 3, oParams.end * 4, -1], [oParams.end, oParams.end * 2, oParams.end * 3, oParams.end * 4, aOptions["lengthMenu"]]];
diff --git a/js/pages/backoffice/toolbox.js b/js/pages/backoffice/toolbox.js
index 8f72a08f2..3398b5bdf 100644
--- a/js/pages/backoffice/toolbox.js
+++ b/js/pages/backoffice/toolbox.js
@@ -201,7 +201,10 @@ CombodoModal._InstantiateModal = function(oModalElem, oOptions) {
width: 'auto',
height: 'auto',
modal: oOptions.extra_options.modal ?? true,
+ close: oOptions.extra_options.callback_on_modal_close,
autoOpen: oOptions.auto_open,
+ title: oOptions.title,
+ buttons: this._ConvertButtonDefinition(oOptions.buttons)
};
// Resize to desired size
@@ -245,7 +248,7 @@ CombodoModal._InstantiateModal = function(oModalElem, oOptions) {
{
case 'string':
oModalElem.html(oOptions.content);
- this._OnContentLoaded(oModalElem, oOptions.callbackOnContentLoaded);
+ this._OnContentLoaded(oModalElem, oOptions.callback_on_content_loaded);
break;
case 'object':
@@ -274,7 +277,7 @@ CombodoModal._InstantiateModal = function(oModalElem, oOptions) {
me._CenterModalInViewport(oModalElem);
}, 500);
- me._OnContentLoaded(oModalElem, oOptions.callbackOnContentLoaded);
+ me._OnContentLoaded(oModalElem, oOptions.callback_on_content_loaded);
}
);
break;
@@ -313,6 +316,28 @@ CombodoModal._InstantiateModal = function(oModalElem, oOptions) {
return true;
};
+
+/**
+ * Convert generic buttons definitions to jquery ui dialog definitions.
+ *
+ * @param aButtonsDefinitions
+ * @returns {*[]}
+ * @constructor
+ */
+CombodoModal._ConvertButtonDefinition = function(aButtonsDefinitions){
+ const aConverted = [];
+ aButtonsDefinitions.forEach(element => {
+ const aButton = {
+ text: element.text,
+ class: element.class,
+ click: element.callback_on_click
+ }
+ aConverted.push(aButton);
+ }
+ );
+ return aConverted;
+}
+
/**
* @override
* @inheritDoc
@@ -323,6 +348,85 @@ CombodoModal._CenterModalInViewport = function (oModalElem) {
});
};
+/**
+ * Open a standard confirmation modal and put the content into it.
+ *
+ * @param oOptions array @see CombodoModal.OpenModal + {do_not_show_again_pref_key: string, callback_on_confirm: function, callback_on_cancel}
+ * @param aData data passed to callbacks
+ * @returns object The jQuery object of the modal element
+ */
+CombodoModal.OpenConfirmationModal = function(oOptions, aData) {
+
+ // Check do not show again preference key
+ if(oOptions.do_not_show_again_pref_key !== null){
+ if(GetUserPreference(oOptions.do_not_show_again_pref_key, false)){
+ if(oOptions.callback_on_confirm !== null){
+ oOptions.callback_on_confirm(...aData);
+ }
+ return;
+ }
+ }
+ // Merge external options with confirmation modal default options
+ oOptions = $.extend({
+ title: Dict.S('UI:Modal:DefaultConfirmationTitle'),
+ content: '',
+ do_not_show_again_pref_key: null,
+ callback_on_confirm: null,
+ callback_on_cancel: null,
+ extra_options: {
+ callback_on_modal_close: function () {
+ $(this).dialog( "destroy" ); // destroy dialog object
+ }
+ },
+ buttons: [
+ {
+ text: Dict.S('UI:Button:Cancel'),
+ class: 'ibo-is-alternative',
+ callback_on_click: function () {
+ // call confirm handler and close dialog
+ let bCanClose = true;
+ if(oOptions.callback_on_cancel != null){
+ bCanClose = oOptions.callback_on_cancel(...aData) !== false;
+ }
+ if(bCanClose){
+ $(this).dialog('close'); // close dialog
+ }
+ }
+ },
+ {
+ text: Dict.S('UI:Button:Ok'),
+ class: 'ibo-is-primary',
+ callback_on_click: function () {
+ // Call confirm handler and close dialog
+ let bCanClose = true;
+ if(oOptions.callback_on_confirm != null){
+ bCanClose = oOptions.callback_on_confirm(...aData) !== false;
+ }
+ if(bCanClose){
+ $(this).dialog('close'); // close dialog
+ // Handle "do not show again" user preference
+ let bDoNotShowAgain = oOptions.do_not_show_again_pref_key !== null ?
+ $('[name="do_not_show_again"]', $(this)).prop('checked') :
+ false;
+ if (bDoNotShowAgain) {
+ SetUserPreference(oOptions.do_not_show_again_pref_key, true, true);
+ }
+ }
+ }
+ }
+ ],
+ callback_on_content_loaded: function(oModalContentElement){
+ // Add option do not show again from template
+ if(oOptions.do_not_show_again_pref_key !== null) {
+ oModalContentElement.append($('#ibo-modal-option--do-not-show-again-template').html());
+ }
+ }
+ }, oOptions);
+
+ // Open modal
+ CombodoModal.OpenModal(oOptions);
+}
+
// Processing on each pages of the backoffice
$(document).ready(function(){
// Initialize global keyboard shortcuts
diff --git a/js/utils.js b/js/utils.js
index 923f63d36..c42ad1a14 100644
--- a/js/utils.js
+++ b/js/utils.js
@@ -1121,6 +1121,7 @@ let CombodoModal = {
*
* @param sTargetUrl {String}
* @param bCloseOtherModals {String}
+ * @param callbackOnContentLoaded {function}
* @return {Object} The jQuery object representing the modal element
* @api
*/
@@ -1145,7 +1146,7 @@ let CombodoModal = {
};
if (callbackOnContentLoaded !== undefined) {
- oOptions.callbackOnContentLoaded = callbackOnContentLoaded;
+ oOptions.callback_on_content_loaded = callbackOnContentLoaded;
}
// Opening modal
@@ -1170,10 +1171,12 @@ let CombodoModal = {
usage: 'clone', // Either 'clone' or 'replace'
selector: this._GetDefaultBaseModalSelector() // Either a selector of the modal element used to base this one on or the modal element itself
},
+ title: undefined, // Title of the modal
content: undefined, // Either a string, an object containing the endpoint / data or undefined to keep base modal content as-is
+ buttons: null,
size: 'auto', // Either 'auto' / 'xs' / 'sm' / 'md' / 'lg' or specific height & width via {width: '80px', height: '100px'}
auto_open: true, // true for the modal to open automatically on instantiation
- callbackOnContentLoaded: null, // Callback to call once the content is loaded. Arguments will be oModalElem (the jQuery object representing the modal)
+ callback_on_content_loaded: null, // Callback to call once the content is loaded. Arguments will be oModalElem (the jQuery object representing the modal) callback_on_content_loaded
extra_options: {}, // Extra options to pass to the modal lib directly if they are not handled by the CombodoModal widget yet
},
oOptions
@@ -1206,7 +1209,7 @@ let CombodoModal = {
if (oOptions.base_modal.usage === 'clone') {
// Clone modal using a real template
if (oSelectorElem[0].tagName === 'TEMPLATE') {
- oModalElem = $(oSelectorElem[0].content.firstElementChild.cloneNode(true));
+ oModalElem = $(oSelectorElem.html());
}
// Clone modal using an existing element
else {
@@ -1216,8 +1219,7 @@ let CombodoModal = {
// Force modal to have an HTML ID, otherwise it can lead to complications, especially with the portal_leave_handle.js
// See N°3469
let sModalID = (oOptions.id !== null) ? oOptions.id : 'modal-with-generated-id-'+Date.now();
- oModalElem.attr('id', sModalID)
- .appendTo('body');
+ oModalElem.attr('id', sModalID);
}
// - Get an existing modal in the DOM
else {
@@ -1291,5 +1293,16 @@ let CombodoModal = {
callback(oModalElem);
}
}
+ },
+
+ /**
+ * Open a standard confirmation modal and put the content into it.
+ *
+ * @param oOptions
+ * @returns object The jQuery object of the modal element
+ */
+ OpenConfirmationModal: function(oOptions) {
+ // Meant for overlaoding
+ CombodoJSConsole.Debug('CombodoModal.OpenConfirmationModal not implemented');
}
};
\ No newline at end of file
diff --git a/lib/composer/InstalledVersions.php b/lib/composer/InstalledVersions.php
index 7c5502ca4..d50e0c9fc 100644
--- a/lib/composer/InstalledVersions.php
+++ b/lib/composer/InstalledVersions.php
@@ -24,8 +24,21 @@ use Composer\Semver\VersionParser;
*/
class InstalledVersions
{
+ /**
+ * @var mixed[]|null
+ * @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array}|array{}|null
+ */
private static $installed;
+
+ /**
+ * @var bool|null
+ */
private static $canGetVendors;
+
+ /**
+ * @var array[]
+ * @psalm-var array}>
+ */
private static $installedByVendor = array();
/**
diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php
index c74acc1c2..715cc6475 100644
--- a/lib/composer/autoload_classmap.php
+++ b/lib/composer/autoload_classmap.php
@@ -145,10 +145,6 @@ return array(
'CAS_Request_Exception' => $vendorDir . '/apereo/phpcas/source/CAS/Request/Exception.php',
'CAS_Request_MultiRequestInterface' => $vendorDir . '/apereo/phpcas/source/CAS/Request/MultiRequestInterface.php',
'CAS_Request_RequestInterface' => $vendorDir . '/apereo/phpcas/source/CAS/Request/RequestInterface.php',
- 'CAS_ServiceBaseUrl_AllowedListDiscovery' => $vendorDir . '/apereo/phpcas/source/CAS/ServiceBaseUrl/AllowedListDiscovery.php',
- 'CAS_ServiceBaseUrl_Base' => $vendorDir . '/apereo/phpcas/source/CAS/ServiceBaseUrl/Base.php',
- 'CAS_ServiceBaseUrl_Interface' => $vendorDir . '/apereo/phpcas/source/CAS/ServiceBaseUrl/Interface.php',
- 'CAS_ServiceBaseUrl_Static' => $vendorDir . '/apereo/phpcas/source/CAS/ServiceBaseUrl/Static.php',
'CAS_Session_PhpSession' => $vendorDir . '/apereo/phpcas/source/CAS/Session/PhpSession.php',
'CAS_TypeMismatchException' => $vendorDir . '/apereo/phpcas/source/CAS/TypeMismatchException.php',
'CLILikeWebPage' => $baseDir . '/sources/Application/WebPage/CLILikeWebPage.php',
@@ -233,8 +229,6 @@ return array(
'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\StaticTable\\FormTable\\FormTable' => $baseDir . '/sources/Application/UI/Base/Component/DataTable/StaticTable/FormTable/FormTable.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\StaticTable\\StaticTable' => $baseDir . '/sources/Application/UI/Base/Component/DataTable/StaticTable/StaticTable.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\tTableRowActions' => $baseDir . '/sources/Application/UI/Base/Component/DataTable/tTableRowActions.php',
- 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Dialog\\Dialog' => $baseDir . '/sources/Application/UI/Base/Component/Dialog/Dialog.php',
- 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Dialog\\DialogUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Dialog/DialogUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\FieldBadge\\FieldBadge' => $baseDir . '/sources/Application/UI/Base/Component/FieldBadge/FieldBadge.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\FieldBadge\\FieldBadgeUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/FieldBadge/FieldBadgeUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\FieldSet\\FieldSet' => $baseDir . '/sources/Application/UI/Base/Component/FieldSet/FieldSet.php',
@@ -262,6 +256,7 @@ return array(
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\TextArea' => $baseDir . '/sources/Application/UI/Base/Component/Input/TextArea.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\tInputLabel' => $baseDir . '/sources/Application/UI/Base/Component/Input/tInputLabel.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\MedallionIcon\\MedallionIcon' => $baseDir . '/sources/Application/UI/Base/Component/MedallionIcon/MedallionIcon.php',
+ 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Modal\\DoNotShowAgainOptionBlock' => $baseDir . '/sources/Application/UI/Base/Component/Modal/DoNotShowAgainOptionBlock.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Panel\\Panel' => $baseDir . '/sources/Application/UI/Base/Component/Panel/Panel.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Panel\\PanelUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Panel/PanelUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Pill\\Pill' => $baseDir . '/sources/Application/UI/Base/Component/Pill/Pill.php',
diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php
index d89144835..67161ae8a 100644
--- a/lib/composer/autoload_static.php
+++ b/lib/composer/autoload_static.php
@@ -510,10 +510,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'CAS_Request_Exception' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/Exception.php',
'CAS_Request_MultiRequestInterface' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/MultiRequestInterface.php',
'CAS_Request_RequestInterface' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Request/RequestInterface.php',
- 'CAS_ServiceBaseUrl_AllowedListDiscovery' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ServiceBaseUrl/AllowedListDiscovery.php',
- 'CAS_ServiceBaseUrl_Base' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ServiceBaseUrl/Base.php',
- 'CAS_ServiceBaseUrl_Interface' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ServiceBaseUrl/Interface.php',
- 'CAS_ServiceBaseUrl_Static' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/ServiceBaseUrl/Static.php',
'CAS_Session_PhpSession' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/Session/PhpSession.php',
'CAS_TypeMismatchException' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS/TypeMismatchException.php',
'CLILikeWebPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/CLILikeWebPage.php',
@@ -598,8 +594,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\StaticTable\\FormTable\\FormTable' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/DataTable/StaticTable/FormTable/FormTable.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\StaticTable\\StaticTable' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/DataTable/StaticTable/StaticTable.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\DataTable\\tTableRowActions' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/DataTable/tTableRowActions.php',
- 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Dialog\\Dialog' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Dialog/Dialog.php',
- 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Dialog\\DialogUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Dialog/DialogUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\FieldBadge\\FieldBadge' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/FieldBadge/FieldBadge.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\FieldBadge\\FieldBadgeUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/FieldBadge/FieldBadgeUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\FieldSet\\FieldSet' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/FieldSet/FieldSet.php',
@@ -627,6 +621,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\TextArea' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/TextArea.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\tInputLabel' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/tInputLabel.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\MedallionIcon\\MedallionIcon' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/MedallionIcon/MedallionIcon.php',
+ 'Combodo\\iTop\\Application\\UI\\Base\\Component\\Modal\\DoNotShowAgainOptionBlock' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Modal/DoNotShowAgainOptionBlock.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Panel\\Panel' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Panel/Panel.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Panel\\PanelUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Panel/PanelUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Pill\\Pill' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Pill/Pill.php',
diff --git a/lib/composer/installed.php b/lib/composer/installed.php
index fff50ab0f..3b6d4406b 100644
--- a/lib/composer/installed.php
+++ b/lib/composer/installed.php
@@ -5,7 +5,7 @@
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
- 'reference' => 'cdde765a85ee0262181e3c493183b1fb80536e74',
+ 'reference' => '64d9eef7c926f98aa1aabe61294397be308dd885',
'name' => 'combodo/itop',
'dev' => true,
),
@@ -25,7 +25,7 @@
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
- 'reference' => 'cdde765a85ee0262181e3c493183b1fb80536e74',
+ 'reference' => '64d9eef7c926f98aa1aabe61294397be308dd885',
'dev_requirement' => false,
),
'combodo/tcpdf' => array(
diff --git a/sources/Application/UI/Base/Component/DataTable/DataTableUIBlockFactory.php b/sources/Application/UI/Base/Component/DataTable/DataTableUIBlockFactory.php
index 289e8711b..9add4be7b 100644
--- a/sources/Application/UI/Base/Component/DataTable/DataTableUIBlockFactory.php
+++ b/sources/Application/UI/Base/Component/DataTable/DataTableUIBlockFactory.php
@@ -214,7 +214,7 @@ class DataTableUIBlockFactory extends AbstractUIBlockFactory
array_key_exists('tooltip', $aAction) ? Dict::S($aAction['tooltip']) : '',
array_key_exists('name', $aAction) ? $aAction['name'] : 'undefined'
);
- $oButton->SetDataAttributes(['action-id' => $iKey]);
+ $oButton->SetDataAttributes(['action-id' => $iKey, 'tooltip-append-to' => 'body']);
$oToolbar->AddSubBlock($oButton);
}
diff --git a/sources/Application/UI/Base/Component/DataTable/tTableRowActions.php b/sources/Application/UI/Base/Component/DataTable/tTableRowActions.php
index 632d5b3c4..264763558 100644
--- a/sources/Application/UI/Base/Component/DataTable/tTableRowActions.php
+++ b/sources/Application/UI/Base/Component/DataTable/tTableRowActions.php
@@ -7,8 +7,6 @@
namespace Combodo\iTop\Application\UI\Base\Component\DataTable;
use Combodo\iTop\Application\UI\Base\Component\Dialog\DialogUIBlockFactory;
-use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
-use Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory;
/**
* Trait tTableRowActions
@@ -33,11 +31,11 @@ trait tTableRowActions
* confirmation => {
* message: string,
* message_row_data: string,
- * remember_choice_pref_key: string
+ * do_not_show_again_pref_key: string
* }
* }
*/
- protected $aRowActions;
+ protected $aRowActions = [];
/**
* Set row actions.
@@ -82,31 +80,4 @@ trait tTableRowActions
{
return DataTableUIBlockFactory::MakeActionRowToolbarTemplate($this);
}
-
- /**
- * GetRowActionsConfirmDialog.
- *
- * @return \Combodo\iTop\Application\UI\Base\Component\Html\Html
- */
- public function GetRowActionsConfirmDialog()
- {
- static::$bDialogInitialized = true;
-
- $oDialog = DialogUIBlockFactory::MakeNeutral('', '', 'table-row-action-confirmation-dialog');
-
- $oContent = UIContentBlockUIBlockFactory::MakeStandard();
- $oContent->AddCSSClass('ibo-row-action--confirmation--do-not-show-again');
- $checkBox = InputUIBlockFactory::MakeStandard('checkbox', 'do_not_show_again', false);
- $checkBox->AddCSSClass('ibo-row-action--confirmation--do-not-show-again--checkbox');
- $checkBox->SetLabel(\Dict::S('UI:UserPref:DoNotShowAgain'));
- $oContent->AddSubBlock($checkBox);
- $oDialog->AddSubBlock($oContent);
-
- return $oDialog;
- }
-
- public function GetRowActionsConfirmDialogInitializedFlag()
- {
- return static::$bDialogInitialized;
- }
}
\ No newline at end of file
diff --git a/sources/Application/UI/Base/Component/Dialog/Dialog.php b/sources/Application/UI/Base/Component/Dialog/Dialog.php
deleted file mode 100644
index 722ba2902..000000000
--- a/sources/Application/UI/Base/Component/Dialog/Dialog.php
+++ /dev/null
@@ -1,109 +0,0 @@
-sContent = $sContent;
- if (!empty($sContent)) {
- $this->AddSubBlock(new Html($sContent));
- }
- }
-
- /**
- * @return string
- */
- public function GetTitle(): string
- {
- return $this->sTitle;
- }
-
- /**
- * @param string $sTitle Title of the alert
- *
- * @return $this
- */
- public function SetTitle(string $sTitle): Dialog
- {
- $this->sTitle = $sTitle;
-
- return $this;
- }
-
- /**
- * Return the raw HTML content, should be already sanitized.
- *
- * @return string
- */
- public function GetContent(): string
- {
- return $this->sContent;
- }
-
- /**
- * Set the raw HTML content, must be already sanitized.
- *
- * @param string $sContent The raw HTML content, must be already sanitized
- *
- * @return $this
- */
- public function SetContent(string $sContent): Dialog
- {
- $this->sContent = $sContent;
-
- return $this;
- }
-
-
-
-}
\ No newline at end of file
diff --git a/sources/Application/UI/Base/Component/Dialog/DialogUIBlockFactory.php b/sources/Application/UI/Base/Component/Dialog/DialogUIBlockFactory.php
deleted file mode 100644
index 0fa444794..000000000
--- a/sources/Application/UI/Base/Component/Dialog/DialogUIBlockFactory.php
+++ /dev/null
@@ -1,54 +0,0 @@
-InitUI();
+ }
+
+ /**
+ * Initialize UI.
+ *
+ * @return void
+ */
+ private function InitUI()
+ {
+ // Create checkbox
+ $oCheckBox = InputUIBlockFactory::MakeStandard('checkbox', 'do_not_show_again', false);
+ $oCheckBox->AddCSSClass('ibo-modal-option--do-not-show-again--checkbox');
+ $oCheckBox->SetLabel(Dict::S('UI:UserPref:DoNotShowAgain'));
+ $this->AddSubBlock($oCheckBox);
+ }
+}
\ No newline at end of file
diff --git a/sources/Application/UI/Base/Component/Template/TemplateUIBlockFactory.php b/sources/Application/UI/Base/Component/Template/TemplateUIBlockFactory.php
index b62220552..8a4c10eb6 100644
--- a/sources/Application/UI/Base/Component/Template/TemplateUIBlockFactory.php
+++ b/sources/Application/UI/Base/Component/Template/TemplateUIBlockFactory.php
@@ -20,6 +20,7 @@
namespace Combodo\iTop\Application\UI\Base\Component\Template;
use Combodo\iTop\Application\UI\Base\AbstractUIBlockFactory;
+use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock;
/**
* Class TemplateUIBlockFactory
@@ -47,4 +48,17 @@ class TemplateUIBlockFactory extends AbstractUIBlockFactory
{
return new Template($sId);
}
+
+ /**
+ * Make a Template component with a block inside.
+ *
+ * @return \Combodo\iTop\Application\UI\Base\Component\Template\Template
+ */
+ public static function MakeForBlock(string $sId, UIContentBlock $oContentBlock)
+ {
+ $oBlock = TemplateUIBlockFactory::MakeStandard($sId);
+ $oBlock->AddSubBlock($oContentBlock);
+
+ return $oBlock;
+ }
}
\ No newline at end of file
diff --git a/sources/Application/UI/Links/Direct/BlockDirectLinksViewTable.php b/sources/Application/UI/Links/Direct/BlockDirectLinksViewTable.php
index aed230084..3030a4440 100644
--- a/sources/Application/UI/Links/Direct/BlockDirectLinksViewTable.php
+++ b/sources/Application/UI/Links/Direct/BlockDirectLinksViewTable.php
@@ -55,9 +55,9 @@ class BlockDirectLinksViewTable extends AbstractBlockLinksViewTable
'icon_classes' => 'fas fa-minus',
'js_row_action' => "LinkSetWorker.DetachLinkedObject('{$this->sTargetClass}', aRowData['{$this->sTargetClass}/_key_/raw'], '{$this->oAttDef->GetExtKeyToMe()}');",
'confirmation' => [
- 'message' => 'UI:Links:ActionRow:detach:confirmation',
- 'message_row_data' => "{$this->sTargetClass}/hyperlink",
- 'remember_choice_pref_key' => 'LinkSetWorker.DetachLinkedObject',
+ 'message' => 'UI:Links:ActionRow:detach:confirmation',
+ 'message_row_data' => "{$this->sTargetClass}/hyperlink",
+ 'do_not_show_again_pref_key' => 'LinkSetWorker.DetachLinkedObject',
],
);
break;
@@ -68,9 +68,9 @@ class BlockDirectLinksViewTable extends AbstractBlockLinksViewTable
'icon_classes' => 'fas fa-trash',
'js_row_action' => "LinkSetWorker.DeleteLinkedObject('{$this->oAttDef->GetLinkedClass()}', aRowData['{$this->oAttDef->GetLinkedClass()}/_key_/raw']);",
'confirmation' => [
- 'message' => 'UI:Links:ActionRow:delete:confirmation',
- 'message_row_data' => "{$this->sTargetClass}/hyperlink",
- 'remember_choice_pref_key' => 'LinkSetWorker.DeleteLinkedObject',
+ 'message' => 'UI:Links:ActionRow:delete:confirmation',
+ 'message_row_data' => "{$this->sTargetClass}/hyperlink",
+ 'do_not_show_again_pref_key' => 'LinkSetWorker.DeleteLinkedObject',
],
);
break;
diff --git a/sources/Application/UI/Links/Indirect/BlockIndirectLinksViewTable.php b/sources/Application/UI/Links/Indirect/BlockIndirectLinksViewTable.php
index db9114990..c0a93c26b 100644
--- a/sources/Application/UI/Links/Indirect/BlockIndirectLinksViewTable.php
+++ b/sources/Application/UI/Links/Indirect/BlockIndirectLinksViewTable.php
@@ -63,9 +63,9 @@ class BlockIndirectLinksViewTable extends AbstractBlockLinksViewTable
'icon_classes' => 'fas fa-minus',
'js_row_action' => "LinkSetWorker.DeleteLinkedObject('{$this->oAttDef->GetLinkedClass()}', aRowData['Link/_key_/raw']);",
'confirmation' => [
- 'message' => 'UI:Links:ActionRow:detach:confirmation',
- 'message_row_data' => "Remote/hyperlink",
- 'remember_choice_pref_key' => 'LinkSetWorker.DetachLinkedObject',
+ 'message' => 'UI:Links:ActionRow:detach:confirmation',
+ 'message_row_data' => "Remote/hyperlink",
+ 'do_not_show_again_pref_key' => 'LinkSetWorker.DetachLinkedObject',
],
);
diff --git a/sources/Application/WebPage/iTopWebPage.php b/sources/Application/WebPage/iTopWebPage.php
index 13e8cda8f..ef3494feb 100644
--- a/sources/Application/WebPage/iTopWebPage.php
+++ b/sources/Application/WebPage/iTopWebPage.php
@@ -8,7 +8,9 @@
use Combodo\iTop\Application\TwigBase\Twig\TwigHelper;
use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Breadcrumbs\Breadcrumbs;
+use Combodo\iTop\Application\UI\Base\Component\Modal\DoNotShowAgainOptionBlock;
use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
+use Combodo\iTop\Application\UI\Base\Component\Template\TemplateUIBlockFactory;
use Combodo\iTop\Application\UI\Base\iUIBlock;
use Combodo\iTop\Application\UI\Base\Layout\iUIContentBlock;
use Combodo\iTop\Application\UI\Base\Layout\NavigationMenu\NavigationMenu;
@@ -210,6 +212,9 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
$this->add_dict_entry('UI:DisconnectedDlgTitle');
$this->add_dict_entry('UI:LoginAgain');
$this->add_dict_entry('UI:StayOnThePage');
+
+ // Modals
+ $this->add_dict_entries('UI:Modal:');
}
/**
@@ -891,6 +896,9 @@ HTML;
// - Prepare content
$aData['aLayouts']['oPageContent'] = $this->GetContentLayout();
$aData['aDeferredBlocks']['oPageContent'] = $this->GetDeferredBlocks($this->GetContentLayout());
+ // - Prepare generic templates
+ $aData['aTemplates'] = array();
+ $aData['aTemplates'][] = TemplateUIBlockFactory::MakeForBlock('ibo-modal-option--do-not-show-again-template', new DoNotShowAgainOptionBlock());
// - Retrieve layouts linked files
// Note: Adding them now instead of in the template allow us to remove duplicates and lower the browser parsing time
@@ -1241,4 +1249,5 @@ EOF
return parent::SetBlockParam($sKey, $value);
}
+
}
diff --git a/templates/base/components/datatable/layout.html.twig b/templates/base/components/datatable/layout.html.twig
index bc72bca3c..c8d6d20a2 100644
--- a/templates/base/components/datatable/layout.html.twig
+++ b/templates/base/components/datatable/layout.html.twig
@@ -28,7 +28,4 @@
{% if oUIBlock.HasRowActions() %}
{{ render_block(oUIBlock.GetRowActionsTemplate()) }}
- {% if not oUIBlock.GetRowActionsConfirmDialogInitializedFlag() %}
- {{ render_block(oUIBlock.GetRowActionsConfirmDialog()) }}
- {% endif %}
{% endif %}
\ No newline at end of file
diff --git a/templates/base/components/datatable/layout.ready.js.twig b/templates/base/components/datatable/layout.ready.js.twig
index 2588bcc9d..32ffca5a2 100644
--- a/templates/base/components/datatable/layout.ready.js.twig
+++ b/templates/base/components/datatable/layout.ready.js.twig
@@ -420,6 +420,7 @@ var aOptions{{ sListIDForVarSuffix }} = {
oData: {{ oUIBlock.GetJsonAjaxData() |raw }},
oDefaultSettings: {{ oUIBlock.GetOption("oDefaultSettings")|raw }},
oLabels: {moveup: "{{ 'UI:Button:MoveUp'|dict_s }}", movedown: "{{ 'UI:Button:MoveDown'|dict_s }}"},
+ bHasRowActions: {{ oUIBlock.HasRowActions()|var_export }},
};
if ($('#datatable_dlg_{{ oUIBlock.GetId() }}').hasClass('itop-datatable'))
diff --git a/templates/base/components/datatable/row-actions/handler.js.twig b/templates/base/components/datatable/row-actions/handler.js.twig
index f1cfa1bf6..68f69b911 100644
--- a/templates/base/components/datatable/row-actions/handler.js.twig
+++ b/templates/base/components/datatable/row-actions/handler.js.twig
@@ -15,23 +15,21 @@
{% if aAction.confirmation is defined %}
- // Handle action row with confirmation
- let sTitle = '{{ 'UI:Datatables:RowActions:ConfirmationDialog'|dict_s }}';
+ // Prepare confirmation message
let sMessage = '{{ 'UI:Datatables:RowActions:ConfirmationMessage'|dict_s }}';
{% if aAction.confirmation.message is defined %}
sMessage = '{{ aAction.confirmation.message|dict_s|raw }}';
- sMessage = sMessage.replaceAll('{item}', aRowData['{{ aAction.confirmation.message_row_data }}']);
{% endif %}
- let sPrefKey = null;
- {% if aAction.confirmation.remember_choice_pref_key is defined %}
- sPrefKey = '{{ aAction.confirmation.remember_choice_pref_key }}';
- {% endif %}
- HandleActionRowConfirmation (sTitle, sMessage, sPrefKey, ActionRowFunction{{ oUIBlock.GetId() }}{{ loop.index0 }}, {
- action_id: iActionId,
- datatable: oDatatable,
- tr_element: oTrElement,
- row_data: aRowData
- });
+
+ // Handle action row with confirmation modal
+ CombodoModal.OpenConfirmationModal({
+ title: '{{ 'UI:Datatables:RowActions:ConfirmationDialog'|dict_s }}',
+ content: sMessage.replaceAll('{item}', aRowData['{{ aAction.confirmation.message_row_data }}']),
+ callback_on_confirm: ActionRowFunction{{ oUIBlock.GetId() }}{{ loop.index0 }},
+ {% if aAction.confirmation.do_not_show_again_pref_key is defined %}
+ do_not_show_again_pref_key: '{{ aAction.confirmation.do_not_show_again_pref_key }}',
+ {% endif %}
+ }, [oDatatable, oTrElement, iActionId, aRowData]);
{% else %}
diff --git a/templates/base/components/datatable/static/formtable/layout.html.twig b/templates/base/components/datatable/static/formtable/layout.html.twig
index 11a807f62..3da718895 100644
--- a/templates/base/components/datatable/static/formtable/layout.html.twig
+++ b/templates/base/components/datatable/static/formtable/layout.html.twig
@@ -21,7 +21,4 @@
{% if oUIBlock.HasRowActions() %}
{{ render_block(oUIBlock.GetRowActionsTemplate()) }}
- {% if not oUIBlock.GetRowActionsConfirmDialogInitializedFlag() %}
- {{ render_block(oUIBlock.GetRowActionsConfirmDialog()) }}
- {% endif %}
{% endif %}
\ No newline at end of file
diff --git a/templates/base/components/datatable/static/layout.html.twig b/templates/base/components/datatable/static/layout.html.twig
index 5e8d9030f..a7b9748b8 100644
--- a/templates/base/components/datatable/static/layout.html.twig
+++ b/templates/base/components/datatable/static/layout.html.twig
@@ -48,7 +48,4 @@
{% if oUIBlock.HasRowActions() %}
{{ render_block(oUIBlock.GetRowActionsTemplate()) }}
- {% if not oUIBlock.GetRowActionsConfirmDialogInitializedFlag() %}
- {{ render_block(oUIBlock.GetRowActionsConfirmDialog()) }}
- {% endif %}
{% endif %}
\ No newline at end of file
diff --git a/templates/base/components/dialog/layout.ready.js.twig b/templates/base/components/dialog/layout.ready.js.twig
index d37e9c573..e69de29bb 100644
--- a/templates/base/components/dialog/layout.ready.js.twig
+++ b/templates/base/components/dialog/layout.ready.js.twig
@@ -1,4 +0,0 @@
-$('#{{ oUIBlock.GetId() }}').alert({
- bOpenedByDefault: {{ oUIBlock.IsOpenedByDefault()|var_export }}
- {% if oUIBlock.IsSaveCollapsibleStateEnabled() %}, collapsibleStateStorageKey: '{{ oUIBlock.GetSessionCollapsibleStateStorageKey() }}'{% endif %}
-});
\ No newline at end of file
diff --git a/templates/pages/backoffice/itopwebpage/layout.html.twig b/templates/pages/backoffice/itopwebpage/layout.html.twig
index 0e838c272..9f2992368 100644
--- a/templates/pages/backoffice/itopwebpage/layout.html.twig
+++ b/templates/pages/backoffice/itopwebpage/layout.html.twig
@@ -45,6 +45,12 @@
TODO 3.1: Please wait
+
+ {# Templates #}
+ {% for oTemplate in aTemplates %}
+ {{ render_block(oTemplate, {aPage: aPage}) }}
+ {% endfor %}
+
{% endblock %}
{% block iboCapturedOutput %}