From 4b9d561bbe94f4d9bdf87fc6d966cbe2990b2bbb Mon Sep 17 00:00:00 2001 From: nathangray Date: Thu, 8 Oct 2020 11:53:17 -0600 Subject: [PATCH] CRM: Fix some list bugs - Adding an infolog did not show up - CRM.ts got disconnected if infolog list got reloaded --- addressbook/js/CRM.js | 49 ++++++++++++-- addressbook/js/CRM.ts | 54 ++++++++++++++-- api/js/etemplate/et2_extension_nextmatch.js | 60 +++++++++-------- api/js/etemplate/et2_extension_nextmatch.ts | 72 ++++++++++++--------- infolog/js/app.js | 8 +-- infolog/js/app.ts | 3 +- 6 files changed, 176 insertions(+), 70 deletions(-) diff --git a/addressbook/js/CRM.js b/addressbook/js/CRM.js index 3922e2f01f..91614ce2d5 100644 --- a/addressbook/js/CRM.js +++ b/addressbook/js/CRM.js @@ -46,6 +46,8 @@ var CRMView = /** @class */ (function (_super) { var _this = // call parent _super.call(this, 'addressbook') || this; + // List ID + _this.list_id = ""; // Reference to the list _this.nm = null; // Which addressbook contact id(s) we are showing entries for @@ -77,17 +79,19 @@ var CRMView = /** @class */ (function (_super) { CRMView.view_ready = function (et2, app_obj) { // Check to see if the template is for a CRM view if (et2.app == app_obj.appname) { - return false; + return CRMView.reconnect(app_obj); } // Make sure object is there, etemplate2 will pick it up and call our et2_ready + var crm = undefined; + // @ts-ignore if (typeof et2.app_obj.crm == "undefined" && app.classes.crm) { - et2.app_obj.crm = new app.classes.crm(); + // @ts-ignore + crm = et2.app_obj.crm = new app.classes.crm(); } - if (typeof et2.app_obj.crm == "undefined") { + if (typeof crm == "undefined") { egw.debug("error", "CRMView object is missing"); return false; } - var crm = et2.app_obj.crm; // We can set this now crm.set_view_obj(app_obj); }; @@ -103,13 +107,50 @@ var CRMView = /** @class */ (function (_super) { // call parent _super.prototype.et2_ready.call(this, et2, name); }; + /** + * Our CRM has become disconnected from its list, probably because something submitted. + * Find it, and get things working again. + * + * @param app_obj + */ + CRMView.reconnect = function (app_obj) { + var _a; + // Check + var contact_ids = app_obj.et2.getArrayMgr("content").getEntry("action_id") || ""; + debugger; + if (!contact_ids) + return; + for (var _i = 0, _b = egw_app_1.EgwApp._instances; _i < _b.length; _i++) { + var existing_app = _b[_i]; + if (existing_app instanceof CRMView && existing_app.list_id == app_obj.et2.getInstanceManager().uniqueId) { + // List was reloaded. Rebind. + existing_app.app_obj.destroy(existing_app.app_obj.appname); + if (!((_a = existing_app.nm) === null || _a === void 0 ? void 0 : _a.getParent())) { + try { + // This will probably not die cleanly, we had a reference when it was destroyed + existing_app.nm.destroy(); + } + catch (e) { } + } + return existing_app.set_view_obj(app_obj); + } + } + }; /** * Set the associated private app JS * We try and pull the needed info here */ CRMView.prototype.set_view_obj = function (app_obj) { this.app_obj = app_obj; + // Make sure object is there, etemplate2 will pick it up and call our et2_ready + app_obj.et2.getInstanceManager().app_obj.crm = this; + // Make _sure_ we get notified if the list is removed (actions, refresh) - this is not always a full + // destruction + jQuery(app_obj.et2.getDOMNode()).on('clear', function () { + this.nm = null; + }.bind(this)); // For easy reference later + this.list_id = app_obj.et2.getInstanceManager().uniqueId; this.nm = app_obj.et2.getDOMWidgetById('nm'); var contact_ids = app_obj.et2.getArrayMgr("content").getEntry("action_id") || ""; if (typeof contact_ids == "string") { diff --git a/addressbook/js/CRM.ts b/addressbook/js/CRM.ts index 45d90fb32e..3db5c1e992 100644 --- a/addressbook/js/CRM.ts +++ b/addressbook/js/CRM.ts @@ -27,6 +27,9 @@ import {et2_nextmatch} from "../../api/js/etemplate/et2_extension_nextmatch"; */ export class CRMView extends EgwApp { + // List ID + list_id: string = ""; + // Reference to the list nm: et2_nextmatch = null; @@ -80,21 +83,23 @@ export class CRMView extends EgwApp // Check to see if the template is for a CRM view if(et2.app == app_obj.appname) { - return false; + return CRMView.reconnect(app_obj); } // Make sure object is there, etemplate2 will pick it up and call our et2_ready + let crm : CRMView = undefined; + // @ts-ignore if(typeof et2.app_obj.crm == "undefined" && app.classes.crm) { - et2.app_obj.crm = new app.classes.crm(); + // @ts-ignore + crm = et2.app_obj.crm = new app.classes.crm(); } - if(typeof et2.app_obj.crm == "undefined") + if(typeof crm == "undefined") { egw.debug("error", "CRMView object is missing"); return false; } - let crm = et2.app_obj.crm; // We can set this now crm.set_view_obj(app_obj); @@ -115,6 +120,37 @@ export class CRMView extends EgwApp } + /** + * Our CRM has become disconnected from its list, probably because something submitted. + * Find it, and get things working again. + * + * @param app_obj + */ + static reconnect(app_obj : EgwApp) + { + // Check + let contact_ids = app_obj.et2.getArrayMgr("content").getEntry("action_id") || ""; + debugger; + if(!contact_ids) return; + + for (let existing_app of EgwApp._instances) + { + if(existing_app instanceof CRMView && existing_app.list_id == app_obj.et2.getInstanceManager().uniqueId) + { + // List was reloaded. Rebind. + existing_app.app_obj.destroy(existing_app.app_obj.appname); + if(!existing_app.nm?.getParent()) + { + try + { + // This will probably not die cleanly, we had a reference when it was destroyed + existing_app.nm.destroy(); + } catch (e) {} + } + return existing_app.set_view_obj(app_obj); + } + } + } /** * Set the associated private app JS * We try and pull the needed info here @@ -123,7 +159,17 @@ export class CRMView extends EgwApp { this.app_obj = app_obj; + // Make sure object is there, etemplate2 will pick it up and call our et2_ready + app_obj.et2.getInstanceManager().app_obj.crm = this + + // Make _sure_ we get notified if the list is removed (actions, refresh) - this is not always a full + // destruction + jQuery(app_obj.et2.getDOMNode()).on('clear', function() { + this.nm = null; + }.bind(this)); + // For easy reference later + this.list_id = app_obj.et2.getInstanceManager().uniqueId; this.nm = app_obj.et2.getDOMWidgetById('nm'); let contact_ids = app_obj.et2.getArrayMgr("content").getEntry("action_id") || ""; diff --git a/api/js/etemplate/et2_extension_nextmatch.js b/api/js/etemplate/et2_extension_nextmatch.js index 697160af2a..9ccb07a75f 100644 --- a/api/js/etemplate/et2_extension_nextmatch.js +++ b/api/js/etemplate/et2_extension_nextmatch.js @@ -546,6 +546,10 @@ var et2_nextmatch = /** @class */ (function (_super) { // Pre-ask for the row data, and only proceed if we actually get it // need to send nextmatch filters too, as server-side will merge old version from request otherwise this_1.egw().dataFetch(this_1.getInstanceManager().etemplate_exec_id, { refresh: _row_ids }, this_1.controller._filters, this_1.id, function (data) { + // In the event that the etemplate got removed before the data came back (Usually an action caused + // a full submit) just stop here. + if (!this.nm.getParent()) + return; if (data.total >= 1) { this.type == et2_nextmatch.ADD ? this.nm.refresh_add(this.uid, this.type) : this.nm.refresh_update(this.uid); @@ -556,7 +560,7 @@ var et2_nextmatch = /** @class */ (function (_super) { // Adjust total rows, clean grid this.nm.controller._grid.setTotalCount(this.nm.controller._grid._total - _row_ids.length); } - }, { type: _type, nm: this_1, uid: uid_1 }, [_row_ids]); + }, { type: _type, nm: this_1, uid: uid_1, prefix: this_1.controller.dataStorePrefix }, [_row_ids]); return { value: void 0 }; } switch (_type) { @@ -635,33 +639,37 @@ var et2_nextmatch = /** @class */ (function (_super) { return false; } var time = new Date().valueOf(); - var callback = function (data) { - if (data) { - if (data.class) { - data.class += " new_entry"; - } - // Don't remove if new data has not arrived - var stored = egw.dataGetUIDdata(uid); - //if(stored?.timestamp >= time) return; - // Increase displayed row count or we lose the last row when we add and the total is wrong - this.controller._grid.setTotalCount(this.controller._grid.getTotalCount() + 1); - // Insert at the top of the list, or where app said - var entry = this.controller._selectionMgr._getRegisteredRowsEntry(uid); - entry.idx = typeof index == "number" ? index : 0; - this.controller._insertDataRow(entry, true); - } - else { - debugger; - // Server didn't give us our row data - // Delete from internal references - this.controller.deleteRow(uid); - this.controller._grid.setTotalCount(this.controller._grid.getTotalCount() - 1); - } - this.egw().dataUnregisterUID(uid, callback, this); - }; - this.egw().dataRegisterUID(uid, callback, this, this.getInstanceManager().etemplate_exec_id, this.id); + this.egw().dataRegisterUID(uid, this._push_add_callback, { nm: this, uid: uid, index: index }, this.getInstanceManager().etemplate_exec_id, this.id); return true; }; + /** + * Callback for adding a new row via push + * + * Expected context: {nm: this, uid: string, index: number} + */ + et2_nextmatch.prototype._push_add_callback = function (data) { + if (data && this.nm && this.nm.getParent()) { + if (data.class) { + data.class += " new_entry"; + } + // Don't remove if new data has not arrived + var stored = egw.dataGetUIDdata(this.uid); + //if(stored?.timestamp >= time) return; + // Increase displayed row count or we lose the last row when we add and the total is wrong + this.nm.controller._grid.setTotalCount(this.nm.controller._grid.getTotalCount() + 1); + // Insert at the top of the list, or where app said + var entry = this.nm.controller._selectionMgr._getRegisteredRowsEntry(this.uid); + entry.idx = typeof this.index == "number" ? this.index : 0; + this.nm.controller._insertDataRow(entry, true); + } + else if (this.nm && this.nm.getParent()) { + // Server didn't give us our row data + // Delete from internal references + this.nm.controller.deleteRow(this.uid); + this.nm.controller._grid.setTotalCount(this.nm.controller._grid.getTotalCount() - 1); + } + this.nm.egw().dataUnregisterUID(this.uid, this.nm._push_add_callback, this); + }; /** * Is this nextmatch currently sorted by "modified" date * diff --git a/api/js/etemplate/et2_extension_nextmatch.ts b/api/js/etemplate/et2_extension_nextmatch.ts index b62b2c00e9..c1b07ffe00 100644 --- a/api/js/etemplate/et2_extension_nextmatch.ts +++ b/api/js/etemplate/et2_extension_nextmatch.ts @@ -844,6 +844,10 @@ export class et2_nextmatch extends et2_DOMWidget implements et2_IResizeable, et2 this.controller._filters, this.id, function(data) { + // In the event that the etemplate got removed before the data came back (Usually an action caused + // a full submit) just stop here. + if(!this.nm.getParent()) return; + if(data.total >= 1) { this.type == et2_nextmatch.ADD ? this.nm.refresh_add(this.uid, this.type) @@ -857,7 +861,7 @@ export class et2_nextmatch extends et2_DOMWidget implements et2_IResizeable, et2 // Adjust total rows, clean grid this.nm.controller._grid.setTotalCount(this.nm.controller._grid._total- _row_ids.length); } - }, {type: _type, nm: this, uid: uid}, [_row_ids] + }, {type: _type, nm: this, uid: uid, prefix: this.controller.dataStorePrefix}, [_row_ids] ); return; } @@ -942,39 +946,45 @@ export class et2_nextmatch extends et2_DOMWidget implements et2_IResizeable, et2 let time = new Date().valueOf(); - let callback = function(data) { - if(data) - { - if(data.class) - { - data.class += " new_entry"; - } - // Don't remove if new data has not arrived - let stored = egw.dataGetUIDdata(uid); - //if(stored?.timestamp >= time) return; - - // Increase displayed row count or we lose the last row when we add and the total is wrong - this.controller._grid.setTotalCount(this.controller._grid.getTotalCount()+1); - - // Insert at the top of the list, or where app said - var entry = this.controller._selectionMgr._getRegisteredRowsEntry(uid); - entry.idx = typeof index == "number" ? index : 0; - this.controller._insertDataRow(entry,true); - } - else - { - debugger; - // Server didn't give us our row data - // Delete from internal references - this.controller.deleteRow(uid); - this.controller._grid.setTotalCount(this.controller._grid.getTotalCount()-1); - } - this.egw().dataUnregisterUID(uid, callback, this); - }; - this.egw().dataRegisterUID(uid, callback, this, this.getInstanceManager().etemplate_exec_id, this.id); + this.egw().dataRegisterUID(uid, this._push_add_callback, {nm: this, uid: uid, index: index}, this.getInstanceManager().etemplate_exec_id, this.id); return true; } + /** + * Callback for adding a new row via push + * + * Expected context: {nm: this, uid: string, index: number} + */ + protected _push_add_callback(this: {nm: et2_nextmatch, uid: string, index: number}, data:any) + { + if(data && this.nm && this.nm.getParent()) + { + if(data.class) + { + data.class += " new_entry"; + } + // Don't remove if new data has not arrived + let stored = egw.dataGetUIDdata(this.uid); + //if(stored?.timestamp >= time) return; + + // Increase displayed row count or we lose the last row when we add and the total is wrong + this.nm.controller._grid.setTotalCount(this.nm.controller._grid.getTotalCount()+1); + + // Insert at the top of the list, or where app said + var entry = this.nm.controller._selectionMgr._getRegisteredRowsEntry(this.uid); + entry.idx = typeof this.index == "number" ? this.index : 0; + this.nm.controller._insertDataRow(entry,true); + } + else if (this.nm && this.nm.getParent()) + { + // Server didn't give us our row data + // Delete from internal references + this.nm.controller.deleteRow(this.uid); + this.nm.controller._grid.setTotalCount(this.nm.controller._grid.getTotalCount()-1); + } + this.nm.egw().dataUnregisterUID(this.uid, this.nm._push_add_callback, this); + } + /** * Is this nextmatch currently sorted by "modified" date * diff --git a/infolog/js/app.js b/infolog/js/app.js index 2db5243cf7..3900ec09d9 100644 --- a/infolog/js/app.js +++ b/infolog/js/app.js @@ -171,7 +171,6 @@ var InfologApp = /** @class */ (function (_super) { */ InfologApp.prototype.push = function (pushData) { var _this = this; - var _a; if (pushData.app !== this.appname) return; // pushData does not contain everything, just the minimum. @@ -235,14 +234,15 @@ var InfologApp = /** @class */ (function (_super) { } }; // check filters against ACL data - for (var _i = 0, _b = Object.values(filters); _i < _b.length; _i++) { - var field_filter = _b[_i]; + for (var _i = 0, _a = Object.values(filters); _i < _a.length; _i++) { + var field_filter = _a[_i]; var state_1 = _loop_1(field_filter); if (typeof state_1 === "object") return state_1.value; } // Pass actual refresh on to just nextmatch - (_a = this.et2.getDOMWidgetById('nm')) === null || _a === void 0 ? void 0 : _a.refresh(pushData.id, pushData.type); + var nm = this.et2.getDOMWidgetById('nm'); + nm.refresh(pushData.id, pushData.type); }; /** * Retrieve the current state of the application for future restoration diff --git a/infolog/js/app.ts b/infolog/js/app.ts index 5457c89dce..2f936f4f6d 100644 --- a/infolog/js/app.ts +++ b/infolog/js/app.ts @@ -262,7 +262,8 @@ class InfologApp extends EgwApp } // Pass actual refresh on to just nextmatch - (this.et2.getDOMWidgetById('nm'))?.refresh(pushData.id, pushData.type); + let nm = this.et2.getDOMWidgetById('nm'); + nm.refresh(pushData.id, pushData.type); } /**