From 322fa3c8f4d131f77074d8a4f1ab0d3a18f733c8 Mon Sep 17 00:00:00 2001 From: nathan Date: Tue, 22 Mar 2022 15:49:42 -0600 Subject: [PATCH] Get nm_action dialogs working --- api/js/etemplate/Et2Dialog/Et2Dialog.ts | 41 +++++- .../etemplate/Et2Dialog/Et2DialogOverlay.ts | 11 ++ .../et2_extension_nextmatch_actions.js | 130 +++++++----------- infolog/js/app.ts | 6 +- 4 files changed, 102 insertions(+), 86 deletions(-) diff --git a/api/js/etemplate/Et2Dialog/Et2Dialog.ts b/api/js/etemplate/Et2Dialog/Et2Dialog.ts index 8f5a638536..d07a089b36 100644 --- a/api/js/etemplate/Et2Dialog/Et2Dialog.ts +++ b/api/js/etemplate/Et2Dialog/Et2Dialog.ts @@ -189,11 +189,23 @@ export class Et2Dialog extends Et2Widget(ScopedElementsMixin(SlotMixin(LionDialo // There's an issue with Et2DialogContent.style being undefined, so this has to stay false until it gets // figured out modal: Boolean, + + /** + * Title for the dialog, goes in the header + */ title: String, + + /** + * Pre-defined group of buttons, one of the BUTTONS_* + */ buttons: Number, + /** + * Instead of a message, show this template file instead + */ template: String, + // Force size on the dialog. Normally it sizes to content. width: Number, height: Number, @@ -203,6 +215,10 @@ export class Et2Dialog extends Et2Widget(ScopedElementsMixin(SlotMixin(LionDialo icon: String, value: Object, + /** + * Automatically destroy the dialog when it closes. Set to false to keep the dialog around. + */ + destroy_on_close: Boolean, } } @@ -284,6 +300,8 @@ export class Et2Dialog extends Et2Widget(ScopedElementsMixin(SlotMixin(LionDialo } // Needs to not be modal until the style thing is figured out this.modal = false; + this.dialog_type = Et2Dialog.PLAIN_MESSAGE; + this.destroy_on_close = true; this.__value = {}; this._onOpen = this._onOpen.bind(this); @@ -358,13 +376,15 @@ export class Et2Dialog extends Et2Widget(ScopedElementsMixin(SlotMixin(LionDialo this.dispatchEvent(new Event('close')); - // No real need to do this automatically, dialog could be reused without this - if(this._template_widget) + if(this.destroy_on_close) { - this._template_widget.clear(); + if(this._template_widget) + { + this._template_widget.clear(); + } + this._overlayCtrl.teardown(); + this.remove(); } - this._overlayCtrl.teardown(); - this.remove(); } _onClick(ev : MouseEvent) @@ -511,6 +531,17 @@ export class Et2Dialog extends Et2Widget(ScopedElementsMixin(SlotMixin(LionDialo return this._overlayTemplate(); } + /** + * Don't allow any children here, pass them on to the content node + * + * @param {HTMLElement} node + * @returns {any} + */ + appendChild(node : HTMLElement) + { + return this._overlayContentNode.appendChild(node); + } + /** * Defining this overlay as a templates from OverlayMixin * this is our source to give as .contentNode to OverlayController. diff --git a/api/js/etemplate/Et2Dialog/Et2DialogOverlay.ts b/api/js/etemplate/Et2Dialog/Et2DialogOverlay.ts index 0d36279a9d..fdee1ec814 100644 --- a/api/js/etemplate/Et2Dialog/Et2DialogOverlay.ts +++ b/api/js/etemplate/Et2Dialog/Et2DialogOverlay.ts @@ -75,6 +75,12 @@ export class Et2DialogOverlay extends SlotMixin(LitElement) margin-top: 0.5em; padding: 5px; } + /* Override style for legacy nextmatch action dialogs */ + ::slotted([slot="content"]) { + display: block !important; + position: relative !important; + inset: initial !important; + } ::slotted([slot="buttons"]) { flex: 1 0 auto; } @@ -219,6 +225,11 @@ export class Et2DialogOverlay extends SlotMixin(LitElement) _buttonsTemplate() { + if(!this.buttons) + { + return; + } + // Set button._parent here, otherwise button will have trouble finding our egw() return html`${repeat(this.buttons, (button : DialogButton) => button.id, (button, index) => { diff --git a/api/js/etemplate/et2_extension_nextmatch_actions.js b/api/js/etemplate/et2_extension_nextmatch_actions.js index 1083ab192e..b55a9ff725 100644 --- a/api/js/etemplate/et2_extension_nextmatch_actions.js +++ b/api/js/etemplate/et2_extension_nextmatch_actions.js @@ -428,94 +428,69 @@ export function nm_open_popup(_action, _selected) //Check if there is nextmatch on _action otherwise gets the uniqueid from _ids var uid; if (typeof _action.data.nextmatch !== 'undefined') + { uid = _action.data.nextmatch.getInstanceManager().uniqueId; - else if(typeof _selected[0] !== 'undefined') + } + else if (typeof _selected[0] !== 'undefined') + { uid = _selected[0].manager.data.nextmatch.getInstanceManager().uniqueId; + } + let action = _action; + let selected = _selected; + // Find the popup div - var popup = jQuery("#"+(uid||"") + "_"+_action.id+"_popup").first() || jQuery("[id*='" + _action.id + "_popup']").first(); - if (popup) { + var popup = document.body.querySelector("et2-dialog[id*='" + _action.id + "_popup']") || document.body.querySelector("#" + (uid || "") + "_" + _action.id + "_popup") || document.body.querySelector("[id*='" + _action.id + "_popup']"); + if (popup && popup instanceof Et2Dialog) + { + popup.open(); + } + else if (popup) + { nm_popup_action = _action; - if(_selected.length && typeof _selected[0] == 'object') + if (_selected.length && typeof _selected[0] == 'object') { _action.data.nextmatch = _selected[0]._context._widget; nm_popup_ids = _selected; } else { - egw().debug("warn", 'Not proper format for IDs, should be array of egwActionObject',_selected); + egw().debug("warn", 'Not proper format for IDs, should be array of egwActionObject', _selected); nm_popup_ids = _selected; } - var dialog = jQuery('.action_popup-content',popup); - if(dialog.length == 0) + let dialog = new Et2Dialog(); + dialog.destroy_on_close = false; + dialog.id = popup.id; + popup.setAttribute("id", "_" + popup.id); + dialog.getUpdateComplete().then(() => { - // Couldn't get the dialog, use the div less the first (header) & last (buttons) nodes - dialog = jQuery(document.createElement('div')) - .addClass('action_popup-content'); - if(popup.children().length == 1) + let title = popup.querySelector(".promptheader") + if (title) { - dialog.append(popup.children().children().slice(1,popup.children().children().length-1)); + title.slot = "heading" + dialog.appendChild(title); } - else - { - dialog.append(popup.children().slice(1,popup.children().length-1)); - } - dialog.appendTo(popup); - } - if(dialog.length == 1) - { - // Set up the buttons - var dialog_parent = dialog.parent(); - var d_buttons = []; - var action = _action; - let selected = _selected; - popup.show(); - var close_function = function() - { - dialog_parent.append(dialog); - }; - jQuery('button:visible',popup).each(function(index) { - var but = jQuery(this); - if(but.attr("id")) - { - // Find the associated widget - var widget_id = but.attr("id").replace(_action.data.nextmatch.getInstanceManager().uniqueId+'_', ''); - var button = nm_popup_action.data.nextmatch.getRoot().getWidgetById(widget_id); - } - var button_data = { - text: but.text(), - id: widget_id, - click: button && button.onclick ? function(e) { - jQuery(this).dialog("close"); - nm_popup_action = action; - nm_popup_ids = selected; - button.onclick.apply(button, e.currentTarget); - close_function(); - } : function(e) { - jQuery(this).dialog("close"); - nm_popup_action = null; - close_function(); - } - }; - if(button && button.options && button.options.image) - { - button_data.image = button.options.image; - } - d_buttons.push(button_data); - }); + popup.slot = "content"; - popup.hide(); - var _dialog = et2_dialog.show_dialog( - close_function, - '', - jQuery('.promptheader',popup).text(), - {}, - d_buttons - ); - _dialog.set_dialog_type(''); - _dialog.div.append(dialog) - .css('overflow', 'initial'); - } + // Move buttons + popup.querySelectorAll('et2-button').forEach((button) => + { + button.slot = "buttons"; + let button_click = button.onclick; + button.onclick = (e) => + { + window.nm_popup_action = button_click ? _action : null; + window.nm_popup_ids = selected; + dialog.close(); + + return button_click?.apply(button, e.currentTarget); + }; + dialog.appendChild(button); + }) + dialog.appendChild(popup); + }); + + document.body.appendChild(dialog); // Reset global variables nm_popup_action = null; @@ -534,9 +509,7 @@ window.nm_submit_popup = function(button) { if (nm_popup_action.data.nextmatch) { - // Find the associated widget - var widget_id = jQuery(button).attr("id").replace(nm_popup_action.data.nextmatch.getInstanceManager().uniqueId+'_', ''); - nm_popup_action.data.nextmatch.getRoot().getWidgetById(widget_id).clicked = true; + button.clicked = true; } // Mangle senders to get IDs where nm_action() wants them @@ -569,12 +542,13 @@ window.nm_submit_popup = function(button) */ window.nm_hide_popup = function(element, div_id) { - var prefix = element.id.substring(0,element.id.indexOf('[')); - var popup = div_id ? document.getElementById(div_id) : jQuery("#"+prefix+"_popup").get(0) || jQuery("[id*='" + prefix + "_popup']").get(0); + var prefix = element.id.substring(0, element.id.indexOf('[')); + var popup = div_id ? document.getElementById(div_id) : document.querySelector("#" + prefix + "_popup") || document.querySelector("[id*='" + prefix + "_popup']"); // Hide popup - if(popup) { - popup.style.display = 'none'; + if (popup) + { + popup.close(); } nm_popup_action = null; nm_popup_ids = null; diff --git a/infolog/js/app.ts b/infolog/js/app.ts index 807aa0844d..36ca7c4fc8 100644 --- a/infolog/js/app.ts +++ b/infolog/js/app.ts @@ -343,7 +343,7 @@ class InfologApp extends EgwApp confirm_delete(_action, _senders) { let children = false; - let child_button = jQuery('#delete_sub').get(0) || jQuery('[id*="delete_sub"]').get(0); + let child_button = document.body.querySelector('#delete_sub') || document.body.querySelector('[id*="delete_sub"]'); this._action_all = _action.parent.data.nextmatch?.getSelection().all; this._action_ids = []; if(child_button) @@ -352,13 +352,13 @@ class InfologApp extends EgwApp { this._action_ids.push(_senders[i].id.split("::").pop()); - if (jQuery(_senders[i].iface.getDOMNode()).hasClass('infolog_rowHasSubs')) + if(_senders[i].iface.getDOMNode().classList.contains("infolog_rowHasSubs")) { children = true; break; } } - child_button.style.display = children ? 'block' : 'none'; + child_button.disabled = !children; } nm_open_popup(_action, _senders); }