From 6e0936bd98a0fe3201705344185d130e742b53c9 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 23 Jan 2020 11:26:44 +0100 Subject: [PATCH] first take on pushing app-changes to all clients --- api/js/jsapi/egw_app.js | 13 ++++++--- api/js/jsapi/egw_app.ts | 16 +++++++----- api/src/Link.php | 26 +++++++++++++++--- timesheet/inc/class.timesheet_hooks.inc.php | 3 ++- timesheet/js/app.js | 26 ++++++++++++++++++ timesheet/js/app.ts | 29 +++++++++++++++++++++ 6 files changed, 99 insertions(+), 14 deletions(-) diff --git a/api/js/jsapi/egw_app.js b/api/js/jsapi/egw_app.js index 08a036a7fd..e0c1c5dac3 100644 --- a/api/js/jsapi/egw_app.js +++ b/api/js/jsapi/egw_app.js @@ -138,18 +138,22 @@ var EgwApp = /** @class */ (function () { * It can use the extra _data parameter to determine if the client has read access to * the entry - if an update of the list is necessary. * - * @param {string} _type either 'update', 'edit', 'delete', 'add' or null + * @param _type either 'update', 'edit', 'delete', 'add' or null * - update: request just modified data from given rows. Sorting is not considered, * so if the sort field is changed, the row will not be moved. * - edit: rows changed, but sorting may be affected. Requires full reload. * - delete: just delete the given rows clientside (no server interaction neccessary) * - add: requires full reload for proper sorting - * @param {string} _app application name - * @param {(string|number)} _id id of entry to refresh or null - * @param {mixed} _data eg. owner or responsible to decide if update is necessary + * @param _app application name incl. sub-type eg. "projectmanager-element" + * @param _id id of entry to refresh or null + * @param _data eg. owner or responsible to decide if update is necessary * @returns {undefined} */ EgwApp.prototype.push = function (_type, _app, _id, _data) { + // only handle delete by default, for simple case of uid === "$app::$id" + if (_type === 'delete') { + egw.dataDeleteUID(_app + '::' + _id); + } }; /** * Open an entry. @@ -1632,3 +1636,4 @@ var EgwApp = /** @class */ (function () { return EgwApp; }()); exports.EgwApp = EgwApp; +//# sourceMappingURL=egw_app.js.map \ No newline at end of file diff --git a/api/js/jsapi/egw_app.ts b/api/js/jsapi/egw_app.ts index 428b2691be..1bac01d2c5 100644 --- a/api/js/jsapi/egw_app.ts +++ b/api/js/jsapi/egw_app.ts @@ -209,20 +209,24 @@ export abstract class EgwApp * It can use the extra _data parameter to determine if the client has read access to * the entry - if an update of the list is necessary. * - * @param {string} _type either 'update', 'edit', 'delete', 'add' or null + * @param _type either 'update', 'edit', 'delete', 'add' or null * - update: request just modified data from given rows. Sorting is not considered, * so if the sort field is changed, the row will not be moved. * - edit: rows changed, but sorting may be affected. Requires full reload. * - delete: just delete the given rows clientside (no server interaction neccessary) * - add: requires full reload for proper sorting - * @param {string} _app application name - * @param {(string|number)} _id id of entry to refresh or null - * @param {mixed} _data eg. owner or responsible to decide if update is necessary + * @param _app application name incl. sub-type eg. "projectmanager-element" + * @param _id id of entry to refresh or null + * @param _data eg. owner or responsible to decide if update is necessary * @returns {undefined} */ - push(_type, _app, _id, _data) + push(_type : string, _app : string, _id : string|number, _data? : any) { - + // only handle delete by default, for simple case of uid === "$app::$id" + if (_type === 'delete') + { + egw.dataDeleteUID(_app+'::'+_id); + } } /** diff --git a/api/src/Link.php b/api/src/Link.php index d441db8d97..ae28ebde5f 100644 --- a/api/src/Link.php +++ b/api/src/Link.php @@ -58,7 +58,7 @@ namespace EGroupware\Api; * 'add_app' => 'link_app', // name of get parameter to add links to other app * 'add_id' => 'link_id', // --------------------- " ------------------- id * 'add_popup' => '400x300', // size of popup (XxY), if add is in popup - * 'notify' => 'app.class.method', // method to be called if an other applications liks or unlinks with app: notify(array $data) + * 'notify' => 'app.class.method', // method to be called if an other applications links or unlinks with app: notify(array $data) * 'file_access' => 'app.class.method', // method to be called to check file access rights of a given user, see links_stream_wrapper class * // boolean file_access(string $id,int $check,string $rel_path=null,int $user=null) * 'file_access_user' => false, // true if file_access method supports 4th parameter $user, if app is NOT supporting it @@ -91,6 +91,9 @@ namespace EGroupware\Api; * ), * 'fetch' => 'app.class.method', // method to return entry data for a given id. the method called should support id, and expected mime-type * // basically you should return something like array(id, title, mimetype, body, linked-files) + * + * 'push_data' => "key" | ["key1", ...] // keys of ACL relevant and privacy save data needed for push of changes to client + * * 'additional' => array( // allow one app to register sub-types, * 'app-sub' => array( // different from 'types' approach above * // every value defined above @@ -590,9 +593,9 @@ class Link extends Link\Storage if (is_array($link)) $app_ids[$link['app']][] = $link['id']; } } - foreach($app_ids as $app => $a_ids) + foreach($app_ids as $a_app => $a_ids) { - self::titles($app,array_unique($a_ids)); + self::titles($a_app,array_unique($a_ids)); } } return $links; @@ -694,6 +697,14 @@ class Link extends Link\Storage { if (!$link_id && !$app2 && !$id2 && $app2 != '!'.self::VFS_APPNAME) { + // in case "someone" interested in all changes (used eg. for push) + Hooks::process([ + 'location' => 'notify-all', + 'type' => 'delete', + 'app' => $app, + 'id' => $id, + ], null, true); + self::delete_attached($app,$id); // deleting all attachments self::delete_cache($app,$id); } @@ -1482,6 +1493,15 @@ class Link extends Link\Storage // Update client side with new title Json\Response::get()->apply('egw.link_title_callback',array(array($app => array($id => self::title($app, $id))))); } + + // in case "someone" interested in all changes (used eg. for push) + Hooks::process([ + 'location' => 'notify-all', + 'type' => 'edit', + 'app' => $app, + 'id' => $id, + 'data' => $data, + ], null, true); } /** diff --git a/timesheet/inc/class.timesheet_hooks.inc.php b/timesheet/inc/class.timesheet_hooks.inc.php index d3d795b69c..b83d6add86 100644 --- a/timesheet/inc/class.timesheet_hooks.inc.php +++ b/timesheet/inc/class.timesheet_hooks.inc.php @@ -67,7 +67,8 @@ class timesheet_hooks 'file_access'=> TIMESHEET_APP.'.timesheet_bo.file_access', 'file_access_user' => true, // file_access supports 4th parameter $user 'notify' => TIMESHEET_APP.'.timesheet_bo.notify', - 'merge' => true, + 'merge' => true, + 'push_data' => 'ts_owner', ); } diff --git a/timesheet/js/app.js b/timesheet/js/app.js index 63bf2661ce..57eac75487 100644 --- a/timesheet/js/app.js +++ b/timesheet/js/app.js @@ -170,6 +170,32 @@ var TimesheetApp = /** @class */ (function (_super) { if (widget) return widget.options.value; }; + /** + * Push method receives push notification about updates to entries from the application + * + * It can use the extra _data parameter to determine if the client has read access to + * the entry - if an update of the list is necessary. + * + * @param _type either 'update', 'edit', 'delete', 'add' or null + * - update: request just modified data from given rows. Sorting is not considered, + * so if the sort field is changed, the row will not be moved. + * - edit: rows changed, but sorting may be affected. Requires full reload. + * - delete: just delete the given rows clientside (no server interaction neccessary) + * - add: requires full reload for proper sorting + * @param _app application name incl. sub-type eg. "projectmanager-element" + * @param _id id of entry to refresh or null + * @param _data eg. owner or responsible to decide if update is necessary + * @returns {undefined} + */ + TimesheetApp.prototype.push = function (_type, _app, _id, _data) { + console.log('app.timesheet.push', arguments); + switch (_type) { + case 'delete': + _super.prototype.push.apply(this, arguments); + break; + } + }; return TimesheetApp; }(egw_app_1.EgwApp)); app.classes.timesheet = TimesheetApp; +//# sourceMappingURL=app.js.map \ No newline at end of file diff --git a/timesheet/js/app.ts b/timesheet/js/app.ts index 17da1918c0..3e9c0b50ed 100644 --- a/timesheet/js/app.ts +++ b/timesheet/js/app.ts @@ -191,6 +191,35 @@ class TimesheetApp extends EgwApp var widget = this.et2.getWidgetById('ts_title'); if(widget) return widget.options.value; } + + /** + * Push method receives push notification about updates to entries from the application + * + * It can use the extra _data parameter to determine if the client has read access to + * the entry - if an update of the list is necessary. + * + * @param _type either 'update', 'edit', 'delete', 'add' or null + * - update: request just modified data from given rows. Sorting is not considered, + * so if the sort field is changed, the row will not be moved. + * - edit: rows changed, but sorting may be affected. Requires full reload. + * - delete: just delete the given rows clientside (no server interaction neccessary) + * - add: requires full reload for proper sorting + * @param _app application name incl. sub-type eg. "projectmanager-element" + * @param _id id of entry to refresh or null + * @param _data eg. owner or responsible to decide if update is necessary + * @returns {undefined} + */ + push(_type : string, _app : string, _id : string|number, _data? : any) + { + console.log('app.timesheet.push', arguments); + + switch (_type) + { + case 'delete': + super.push.apply(this, arguments); + break; + } + } } app.classes.timesheet = TimesheetApp;