diff --git a/api/js/etemplate/et2_extension_nextmatch.js b/api/js/etemplate/et2_extension_nextmatch.js index 2cdd69c95d..967e6a7ebf 100644 --- a/api/js/etemplate/et2_extension_nextmatch.js +++ b/api/js/etemplate/et2_extension_nextmatch.js @@ -501,9 +501,8 @@ var et2_nextmatch = /** @class */ (function (_super) { var uid = _row_ids[i].toString().indexOf(this.controller.dataStorePrefix) == 0 ? _row_ids[i] : this.controller.dataStorePrefix + "::" + _row_ids[i]; switch (_type) { case "update": - if (!this.egw().dataRefreshUID(uid)) { - // Could not update just that row - this.applyFilters(); + if (!this.refresh_update(uid)) { + // Could not update just the row, full refresh has been requested break id_loop; } break; @@ -524,18 +523,49 @@ var et2_nextmatch = /** @class */ (function (_super) { // Trigger an event so app code can act on it jQuery(this).triggerHandler("refresh", [this, _row_ids, _type]); }; + /** + * An entry has been updated. Request new data, and ask app about where the row + * goes now. + * + * @param uid + */ + et2_nextmatch.prototype.refresh_update = function (uid) { + if (!this.egw().dataRefreshUID(uid)) { + // Could not update just that row + this.applyFilters(); + return false; + } + // Row data update has been sent, let's move it where app wants it + var entry = this.controller._selectionMgr._getRegisteredRowsEntry(uid); + // Need to delete first as there's a good chance indexes will change in an unknown way + // and we can't always find it by UID after due to duplication + this.controller._grid.deleteRow(entry.idx); + // Pretend it's a new row, let app tell us where it goes and we'll mark it as new + if (!this.refresh_add(uid, "update")) { + // App did not want the row, or doesn't know where it goes but we've already removed it... + // Put it back before anyone notices. New data coming from server anyway. + var callback_1 = function (data) { + data.class += "new_entry"; + this.egw().dataUnregisterUID(uid, callback_1, this); + }; + this.egw().dataRegisterUID(uid, callback_1, this, this.getInstanceManager().etemplate_exec_id, this.id); + this.controller._insertDataRow(entry, true); + } + return true; + }; /** * An entry has been added. Put it in the list. * * @param uid * @return boolean false: not added, true: added */ - et2_nextmatch.prototype.refresh_add = function (uid) { + et2_nextmatch.prototype.refresh_add = function (uid, type) { + if (type === void 0) { type = "add"; } var index = 0; var appname = this._get_appname(); - if (appname && this.egw().window.app[appname] && typeof this.egw().window.app[appname].nm_refresh_add == "function") { + if (appname && this.egw().window.app[appname] && typeof this.egw().window.app[appname].nm_refresh_index == "function") { var sort = Object.values(this.controller._indexMap).map(function (e) { return ({ index: e.idx, uid: e.uid }); }); - index = this.egw().window.app[appname].nm_refresh_add(this, uid, sort); + index = this.egw().window.app[appname].nm_refresh_index(this, uid, sort, type); } // App cancelled the add if (index === false) { diff --git a/api/js/etemplate/et2_extension_nextmatch.ts b/api/js/etemplate/et2_extension_nextmatch.ts index db7c211603..8c20171083 100644 --- a/api/js/etemplate/et2_extension_nextmatch.ts +++ b/api/js/etemplate/et2_extension_nextmatch.ts @@ -766,10 +766,9 @@ export class et2_nextmatch extends et2_DOMWidget implements et2_IResizeable, et2 switch(_type) { case "update": - if(!this.egw().dataRefreshUID(uid)) + if(!this.refresh_update(uid)) { - // Could not update just that row - this.applyFilters(); + // Could not update just the row, full refresh has been requested break id_loop; } break; @@ -790,20 +789,58 @@ export class et2_nextmatch extends et2_DOMWidget implements et2_IResizeable, et2 jQuery(this).triggerHandler("refresh",[this,_row_ids,_type]); } + /** + * An entry has been updated. Request new data, and ask app about where the row + * goes now. + * + * @param uid + */ + protected refresh_update(uid: string) + { + if(!this.egw().dataRefreshUID(uid)) + { + // Could not update just that row + this.applyFilters(); + return false; + } + + // Row data update has been sent, let's move it where app wants it + let entry = this.controller._selectionMgr._getRegisteredRowsEntry(uid); + + // Need to delete first as there's a good chance indexes will change in an unknown way + // and we can't always find it by UID after due to duplication + this.controller._grid.deleteRow(entry.idx); + + // Pretend it's a new row, let app tell us where it goes and we'll mark it as new + if(!this.refresh_add(uid, "update")) + { + // App did not want the row, or doesn't know where it goes but we've already removed it... + // Put it back before anyone notices. New data coming from server anyway. + let callback = function(data) { + data.class += "new_entry"; + this.egw().dataUnregisterUID(uid, callback, this); + }; + this.egw().dataRegisterUID(uid, callback, this, this.getInstanceManager().etemplate_exec_id, this.id); + this.controller._insertDataRow(entry,true); + } + + return true; + } + /** * An entry has been added. Put it in the list. * * @param uid * @return boolean false: not added, true: added */ - protected refresh_add(uid:string) + protected refresh_add(uid:string, type = "add") { let index = 0; let appname = this._get_appname(); - if(appname && this.egw().window.app[appname] && typeof this.egw().window.app[appname].nm_refresh_add == "function") + if(appname && this.egw().window.app[appname] && typeof this.egw().window.app[appname].nm_refresh_index == "function") { let sort = Object.values(this.controller._indexMap).map(e => ({index:e.idx, uid:e.uid})); - index = this.egw().window.app[appname].nm_refresh_add(this, uid, sort) + index = this.egw().window.app[appname].nm_refresh_index(this, uid, sort, type) } // App cancelled the add diff --git a/api/js/jsapi/egw_app.js b/api/js/jsapi/egw_app.js index f0a54884a4..cc04b098f4 100644 --- a/api/js/jsapi/egw_app.js +++ b/api/js/jsapi/egw_app.js @@ -178,15 +178,22 @@ var EgwApp = /** @class */ (function () { }; /** * Callback from nextmatch so application can have some control over - * where new rows (added via push) are added. This is only called when - * the type is "add". + * where new rows (added via push) are added. This is called when + * the type is "add" or "update". + * + * Returning false for a new row will cause nm to do a full reload of all data. + * For an update the row will be updated in place. * * @param nm Nextmatch the entry is going to be added to * @param uid - * @param current_order + * @param current_order List of ids in order + * @param update_type add or update + * + * @return number | boolean Row index (0 at the top) or false to not insert the row */ - EgwApp.prototype.nm_refresh_add = function (nm, uid, current_order) { + EgwApp.prototype.nm_refresh_index = function (nm, uid, current_order, update_type) { var _a; + return false; // Do we have a modified field so we can check nm sort order? if (this.modification_field_name) { var value = nm.getValue(); diff --git a/api/js/jsapi/egw_app.ts b/api/js/jsapi/egw_app.ts index efc5c58d6b..9c5550435f 100644 --- a/api/js/jsapi/egw_app.ts +++ b/api/js/jsapi/egw_app.ts @@ -281,15 +281,22 @@ export abstract class EgwApp /** * Callback from nextmatch so application can have some control over - * where new rows (added via push) are added. This is only called when - * the type is "add". + * where new rows (added via push) are added. This is called when + * the type is "add" or "update". + * + * Returning false for a new row will cause nm to do a full reload of all data. + * For an update the row will be updated in place. * * @param nm Nextmatch the entry is going to be added to * @param uid - * @param current_order + * @param current_order List of ids in order + * @param update_type add or update + * + * @return number | boolean Row index (0 at the top) or false to not insert the row */ - nm_refresh_add(nm: et2_nextmatch, uid: string, current_order: string[]) : number|boolean + nm_refresh_index(nm: et2_nextmatch, uid: string, current_order: string[], update_type: string) : number|boolean { + return false; // Do we have a modified field so we can check nm sort order? if(this.modification_field_name) {