mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-01-02 20:19:27 +01:00
complete push implementation for timesheet incl. ACL check
This commit is contained in:
parent
76a5793a0a
commit
e9c4d3f07e
@ -417,6 +417,7 @@
|
|||||||
egw_script.getAttribute('data-websocket-url'),
|
egw_script.getAttribute('data-websocket-url'),
|
||||||
JSON.parse(egw_script.getAttribute('data-websocket-tokens'))
|
JSON.parse(egw_script.getAttribute('data-websocket-tokens'))
|
||||||
);
|
);
|
||||||
|
egw.set_grants(JSON.parse(egw_script.getAttribute('data-grants') || "{}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
@ -440,7 +441,7 @@
|
|||||||
// get TypeScript modules working with our loader
|
// get TypeScript modules working with our loader
|
||||||
function require(_file)
|
function require(_file)
|
||||||
{
|
{
|
||||||
return { EgwApp: window.EgwApp};
|
return window.exports;
|
||||||
}
|
}
|
||||||
var exports = {};
|
var exports = {};
|
||||||
|
|
||||||
|
@ -135,6 +135,9 @@ var EgwApp = /** @class */ (function () {
|
|||||||
/**
|
/**
|
||||||
* Handle a push notification about entry changes from the websocket
|
* Handle a push notification about entry changes from the websocket
|
||||||
*
|
*
|
||||||
|
* Get's called for data of all apps, but should only handle data of apps it displays,
|
||||||
|
* which is by default only it's own, but can be for multiple apps eg. for calendar.
|
||||||
|
*
|
||||||
* @param pushData
|
* @param pushData
|
||||||
* @param {string} pushData.app application name
|
* @param {string} pushData.app application name
|
||||||
* @param {(string|number)} pushData.id id of entry to refresh or null
|
* @param {(string|number)} pushData.id id of entry to refresh or null
|
||||||
@ -148,9 +151,40 @@ var EgwApp = /** @class */ (function () {
|
|||||||
* @param {number} pushData.account_id User that caused the notification
|
* @param {number} pushData.account_id User that caused the notification
|
||||||
*/
|
*/
|
||||||
EgwApp.prototype.push = function (pushData) {
|
EgwApp.prototype.push = function (pushData) {
|
||||||
|
// don't care about other apps data, reimplement if your app does care eg. calendar
|
||||||
|
if (pushData.app !== this.appname)
|
||||||
|
return;
|
||||||
// only handle delete by default, for simple case of uid === "$app::$id"
|
// only handle delete by default, for simple case of uid === "$app::$id"
|
||||||
if (pushData.type === 'delete') {
|
if (pushData.type === 'delete') {
|
||||||
egw.dataStoreUID(pushData.app + '::' + pushData.id, null);
|
egw.dataStoreUID(this.uid(pushData), null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Get (possible) app-specific uid
|
||||||
|
*
|
||||||
|
* @param {object} pushData see push method for individual attributes
|
||||||
|
*/
|
||||||
|
EgwApp.prototype.uid = function (pushData) {
|
||||||
|
return pushData.app + '::' + pushData.id;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Method called after apps push implementation checked visibility
|
||||||
|
*
|
||||||
|
* @param {et2_nextmatch} nm
|
||||||
|
* @param pushData see push method for individual attributes
|
||||||
|
* @todo implement better way to update nextmatch widget without disturbing the user / state
|
||||||
|
* @todo show indicator that an update has happend
|
||||||
|
* @todo rate-limit update frequency
|
||||||
|
*/
|
||||||
|
EgwApp.prototype.updateList = function (nm, pushData) {
|
||||||
|
switch (pushData.type) {
|
||||||
|
case 'add':
|
||||||
|
case 'unknown':
|
||||||
|
nm.applyFilters();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
egw.dataRefreshUID(this.uid(pushData));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
@ -1634,3 +1668,4 @@ var EgwApp = /** @class */ (function () {
|
|||||||
return EgwApp;
|
return EgwApp;
|
||||||
}());
|
}());
|
||||||
exports.EgwApp = EgwApp;
|
exports.EgwApp = EgwApp;
|
||||||
|
//# sourceMappingURL=egw_app.js.map
|
@ -15,6 +15,19 @@ import 'jqueryui';
|
|||||||
import '../jsapi/egw_global';
|
import '../jsapi/egw_global';
|
||||||
import '../etemplate/et2_types';
|
import '../etemplate/et2_types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type for push-message
|
||||||
|
*/
|
||||||
|
export interface PushData
|
||||||
|
{
|
||||||
|
type: "add"|"edit"|"update"|"delete"|"unknown";
|
||||||
|
app: string; // app-name, can include a subtype eg. "projectmanager-element"
|
||||||
|
id: string | number;
|
||||||
|
acl?: any; // app-specific acl data, eg. the owner, or array of participants
|
||||||
|
account_id: number; // user that caused the change
|
||||||
|
[propName:string]: any; // arbitrary more parameters
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common base class for application javascript
|
* Common base class for application javascript
|
||||||
* Each app should extend as needed.
|
* Each app should extend as needed.
|
||||||
@ -206,6 +219,9 @@ export abstract class EgwApp
|
|||||||
/**
|
/**
|
||||||
* Handle a push notification about entry changes from the websocket
|
* Handle a push notification about entry changes from the websocket
|
||||||
*
|
*
|
||||||
|
* Get's called for data of all apps, but should only handle data of apps it displays,
|
||||||
|
* which is by default only it's own, but can be for multiple apps eg. for calendar.
|
||||||
|
*
|
||||||
* @param pushData
|
* @param pushData
|
||||||
* @param {string} pushData.app application name
|
* @param {string} pushData.app application name
|
||||||
* @param {(string|number)} pushData.id id of entry to refresh or null
|
* @param {(string|number)} pushData.id id of entry to refresh or null
|
||||||
@ -218,12 +234,49 @@ export abstract class EgwApp
|
|||||||
* @param {object|null} pushData.acl Extra data for determining relevance. eg: owner or responsible to decide if update is necessary
|
* @param {object|null} pushData.acl Extra data for determining relevance. eg: owner or responsible to decide if update is necessary
|
||||||
* @param {number} pushData.account_id User that caused the notification
|
* @param {number} pushData.account_id User that caused the notification
|
||||||
*/
|
*/
|
||||||
push(pushData)
|
push(pushData : PushData)
|
||||||
{
|
{
|
||||||
|
// don't care about other apps data, reimplement if your app does care eg. calendar
|
||||||
|
if (pushData.app !== this.appname) return;
|
||||||
|
|
||||||
// only handle delete by default, for simple case of uid === "$app::$id"
|
// only handle delete by default, for simple case of uid === "$app::$id"
|
||||||
if (pushData.type === 'delete')
|
if (pushData.type === 'delete')
|
||||||
{
|
{
|
||||||
egw.dataStoreUID(pushData.app + '::' + pushData.id, null);
|
egw.dataStoreUID(this.uid(pushData), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get (possible) app-specific uid
|
||||||
|
*
|
||||||
|
* @param {object} pushData see push method for individual attributes
|
||||||
|
*/
|
||||||
|
uid(pushData)
|
||||||
|
{
|
||||||
|
return pushData.app + '::' + pushData.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called after apps push implementation checked visibility
|
||||||
|
*
|
||||||
|
* @param {et2_nextmatch} nm
|
||||||
|
* @param pushData see push method for individual attributes
|
||||||
|
* @todo implement better way to update nextmatch widget without disturbing the user / state
|
||||||
|
* @todo show indicator that an update has happend
|
||||||
|
* @todo rate-limit update frequency
|
||||||
|
*/
|
||||||
|
updateList(nm, pushData : PushData)
|
||||||
|
{
|
||||||
|
switch (pushData.type)
|
||||||
|
{
|
||||||
|
case 'add':
|
||||||
|
case 'unknown':
|
||||||
|
nm.applyFilters();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
egw.dataRefreshUID(this.uid(pushData));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ egw.extend('preferences', egw.MODULE_GLOBAL, function()
|
|||||||
* @access: private, use egw.preferences() or egw.set_perferences()
|
* @access: private, use egw.preferences() or egw.set_perferences()
|
||||||
*/
|
*/
|
||||||
var prefs = {};
|
var prefs = {};
|
||||||
|
var grants = {};
|
||||||
|
|
||||||
// Return the actual extension
|
// Return the actual extension
|
||||||
return {
|
return {
|
||||||
@ -171,6 +172,50 @@ egw.extend('preferences', egw.MODULE_GLOBAL, function()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setting prefs for an app or 'common'
|
||||||
|
*
|
||||||
|
* @param {object} _data
|
||||||
|
* @param {string} _app application name or undefined to set grants of all apps at once
|
||||||
|
* and therefore will be inaccessible in IE, after that window is closed
|
||||||
|
*/
|
||||||
|
set_grants: function(_data, _app)
|
||||||
|
{
|
||||||
|
if (_app)
|
||||||
|
{
|
||||||
|
grants[_app] = jQuery.extend(true, {}, _data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
grants = jQuery.extend(true, {}, _data);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query an EGroupware user preference
|
||||||
|
*
|
||||||
|
* We currently load grants from all apps in egw.js, so no need for a callback or promise.
|
||||||
|
*
|
||||||
|
* @param {string} _app app-name
|
||||||
|
* @param {function|false|undefined} _callback optional callback, if preference needs loading first
|
||||||
|
* if false given and preference is not loaded, undefined is return and no (synchronious) request is send to server
|
||||||
|
* @param {object} _context context for callback
|
||||||
|
* @return {object|undefined|false} grant object, false if not (yet) loaded and no callback or undefined
|
||||||
|
*/
|
||||||
|
grants: function( _app) //, _callback, _context)
|
||||||
|
{
|
||||||
|
/* we currently load grants from all apps in egw.js, so no need for a callback or promise
|
||||||
|
if (typeof grants[_app] == 'undefined')
|
||||||
|
{
|
||||||
|
if (_callback === false) return undefined;
|
||||||
|
var request = this.json('EGroupware\\Api\\Framework::ajax_get_preference', [_app], _callback, _context);
|
||||||
|
request.sendRequest(typeof _callback == 'function', 'GET'); // use synchronous (cachable) GET request
|
||||||
|
if (typeof grants[_app] == 'undefined') grants[_app] = {};
|
||||||
|
if (typeof _callback == 'function') return false;
|
||||||
|
}*/
|
||||||
|
return typeof grants[_app] === 'object' ? jQuery.extend({}, grants[_app]) : grants[_app];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -718,6 +718,38 @@ class Acl
|
|||||||
return $grants;
|
return $grants;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get grants for a single app
|
||||||
|
*
|
||||||
|
* We use a "get-grants" hook, in case an app need more then what Acl::get_grants returns (with default parameters!).
|
||||||
|
*
|
||||||
|
* @param string $_app app-name
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function ajax_get_grants($_app=null)
|
||||||
|
{
|
||||||
|
if (!($grants = Hooks::single('get-grants', $_app)))
|
||||||
|
{
|
||||||
|
$grants = $this->get_grants($_app);
|
||||||
|
}
|
||||||
|
return $grants;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get grants for all apps
|
||||||
|
*
|
||||||
|
* @return array with app => array of grants pairs
|
||||||
|
*/
|
||||||
|
function ajax_get_all_grants()
|
||||||
|
{
|
||||||
|
$app_grants = [];
|
||||||
|
foreach(array_keys($GLOBALS['egw_info']['user']['apps']) as $app)
|
||||||
|
{
|
||||||
|
$app_grants[$app] = $this->get_grants($app);
|
||||||
|
}
|
||||||
|
return $app_grants;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all ACL entries for an account (user or group)
|
* Deletes all ACL entries for an account (user or group)
|
||||||
*
|
*
|
||||||
|
@ -677,6 +677,7 @@ class Link extends Link\Storage
|
|||||||
*/
|
*/
|
||||||
static function unlink2($link_id,$app,&$id,$owner=0,$app2='',$id2='',$hold_for_purge=false)
|
static function unlink2($link_id,$app,&$id,$owner=0,$app2='',$id2='',$hold_for_purge=false)
|
||||||
{
|
{
|
||||||
|
error_log(__METHOD__."($link_id, '$app', $id, ...)");
|
||||||
if (self::DEBUG)
|
if (self::DEBUG)
|
||||||
{
|
{
|
||||||
echo "<p>Link::unlink('$link_id','$app',".array2string($id).",'$owner','$app2','$id2', $hold_for_purge)</p>\n";
|
echo "<p>Link::unlink('$link_id','$app',".array2string($id).",'$owner','$app2','$id2', $hold_for_purge)</p>\n";
|
||||||
@ -1479,8 +1480,9 @@ class Link extends Link\Storage
|
|||||||
* @param string $app name of app in which the updated happend
|
* @param string $app name of app in which the updated happend
|
||||||
* @param string $id id in $app of the updated entry
|
* @param string $id id in $app of the updated entry
|
||||||
* @param array $data =null updated data of changed entry, as the read-method of the BO-layer would supply it
|
* @param array $data =null updated data of changed entry, as the read-method of the BO-layer would supply it
|
||||||
|
* @param string $type ="unknown" type of update: "add", "edit", "update" or default "unknown"
|
||||||
*/
|
*/
|
||||||
static function notify_update($app,$id,$data=null)
|
static function notify_update($app,$id,$data=null,$type='unknown')
|
||||||
{
|
{
|
||||||
self::delete_cache($app,$id);
|
self::delete_cache($app,$id);
|
||||||
//error_log(__METHOD__."('$app', $id, $data)");
|
//error_log(__METHOD__."('$app', $id, $data)");
|
||||||
@ -1497,7 +1499,7 @@ class Link extends Link\Storage
|
|||||||
// in case "someone" interested in all changes (used eg. for push)
|
// in case "someone" interested in all changes (used eg. for push)
|
||||||
Hooks::process([
|
Hooks::process([
|
||||||
'location' => 'notify-all',
|
'location' => 'notify-all',
|
||||||
'type' => 'edit',
|
'type' => !empty($data[Link::OLD_LINK_TITLE]) ? 'update' : $type,
|
||||||
'app' => $app,
|
'app' => $app,
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'data' => $data,
|
'data' => $data,
|
||||||
|
@ -23,7 +23,7 @@ $replace = array(
|
|||||||
"\n});" => "\n}\n\napp.classes.$matches[1] = ".ucfirst($matches[1])."App;"
|
"\n});" => "\n}\n\napp.classes.$matches[1] = ".ucfirst($matches[1])."App;"
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
"/^\tappname:\s*'([^']+)',/m" => "\treadonly appname: '$1';",
|
"/^\tappname:\s*'([^']+)',/m" => "\treadonly appname = '$1';",
|
||||||
"/^\t([^: ,;(]+):\s*([^()]+),/m" => "\t\$1: $2;",
|
"/^\t([^: ,;(]+):\s*([^()]+),/m" => "\t\$1: $2;",
|
||||||
"/^\t([^:\n]+):\s*function\s*\(.*this._super.(apply|call)\(/msU" =>
|
"/^\t([^:\n]+):\s*function\s*\(.*this._super.(apply|call)\(/msU" =>
|
||||||
function($matches) {
|
function($matches) {
|
||||||
|
@ -640,10 +640,14 @@ class timesheet_bo extends Api\Storage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$type = !isset($old) ? 'add' :
|
||||||
|
($new['ts_status'] == self::DELETED_STATUS ? 'delete' : 'update');
|
||||||
|
|
||||||
// Check for restore of deleted contact, restore held links
|
// Check for restore of deleted contact, restore held links
|
||||||
if($old && $old['ts_status'] == self::DELETED_STATUS && $new['ts_status'] != self::DELETED_STATUS)
|
if($old && $old['ts_status'] == self::DELETED_STATUS && $new['ts_status'] != self::DELETED_STATUS)
|
||||||
{
|
{
|
||||||
Link::restore(TIMESHEET_APP, $new['ts_id']);
|
Link::restore(TIMESHEET_APP, $new['ts_id']);
|
||||||
|
$type = 'add';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!($err = parent::save()))
|
if (!($err = parent::save()))
|
||||||
@ -659,7 +663,7 @@ class timesheet_bo extends Api\Storage
|
|||||||
return implode(', ',$this->tracking->errors);
|
return implode(', ',$this->tracking->errors);
|
||||||
}
|
}
|
||||||
// notify the link-class about the update, as other apps may be subscribt to it
|
// notify the link-class about the update, as other apps may be subscribt to it
|
||||||
Link::notify_update(TIMESHEET_APP,$this->data['ts_id'],$this->data);
|
Link::notify_update(TIMESHEET_APP, $this->data['ts_id'], $this->data, $type);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $err;
|
return $err;
|
||||||
|
@ -38,7 +38,9 @@ var egw_app_1 = require("../../api/js/jsapi/egw_app");
|
|||||||
var TimesheetApp = /** @class */ (function (_super) {
|
var TimesheetApp = /** @class */ (function (_super) {
|
||||||
__extends(TimesheetApp, _super);
|
__extends(TimesheetApp, _super);
|
||||||
function TimesheetApp() {
|
function TimesheetApp() {
|
||||||
return _super !== null && _super.apply(this, arguments) || this;
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||||
|
_this.appname = 'timesheet';
|
||||||
|
return _this;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This function is called when the etemplate2 object is loaded
|
* This function is called when the etemplate2 object is loaded
|
||||||
@ -170,6 +172,46 @@ var TimesheetApp = /** @class */ (function (_super) {
|
|||||||
if (widget)
|
if (widget)
|
||||||
return widget.options.value;
|
return widget.options.value;
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* Handle a push notification about entry changes from the websocket
|
||||||
|
*
|
||||||
|
* @param pushData
|
||||||
|
* @param {string} pushData.app application name
|
||||||
|
* @param {(string|number)} pushData.id id of entry to refresh or null
|
||||||
|
* @param {string} pushData.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 {object|null} pushData.acl Extra data for determining relevance. eg: owner or responsible to decide if update is necessary
|
||||||
|
* @param {number} pushData.account_id User that caused the notification
|
||||||
|
*/
|
||||||
|
TimesheetApp.prototype.push = function (pushData) {
|
||||||
|
var _a, _b, _c;
|
||||||
|
// timesheed does NOT care about other apps data
|
||||||
|
if (pushData.app !== this.appname)
|
||||||
|
return;
|
||||||
|
if (pushData.type === 'delete') {
|
||||||
|
return _super.prototype.push.call(this, pushData);
|
||||||
|
}
|
||||||
|
// all other cases (add, edit, update) are handled identical
|
||||||
|
// check visibility
|
||||||
|
if (typeof this._grants === 'undefined') {
|
||||||
|
this._grants = egw.grants(this.appname);
|
||||||
|
}
|
||||||
|
if (typeof this._grants[pushData.acl] === 'undefined')
|
||||||
|
return;
|
||||||
|
// check if we might not see it because of an owner filter
|
||||||
|
var nm = (_a = this.et2) === null || _a === void 0 ? void 0 : _a.getWidgetById('nm');
|
||||||
|
var nm_value = (_b = nm) === null || _b === void 0 ? void 0 : _b.getValue();
|
||||||
|
if (nm && nm_value && typeof ((_c = nm_value.col_filter) === null || _c === void 0 ? void 0 : _c.ts_owner) !== 'undefined') {
|
||||||
|
if (!nm_value.col_filter.ts_owner || nm_value.col_filter.ts_owner == pushData.acl) {
|
||||||
|
this.updateList(nm, pushData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
return TimesheetApp;
|
return TimesheetApp;
|
||||||
}(egw_app_1.EgwApp));
|
}(egw_app_1.EgwApp));
|
||||||
app.classes.timesheet = TimesheetApp;
|
app.classes.timesheet = TimesheetApp;
|
||||||
|
//# sourceMappingURL=app.js.map
|
@ -26,7 +26,7 @@ import { EgwApp } from '../../api/js/jsapi/egw_app';
|
|||||||
*/
|
*/
|
||||||
class TimesheetApp extends EgwApp
|
class TimesheetApp extends EgwApp
|
||||||
{
|
{
|
||||||
readonly appname: 'timesheet';
|
readonly appname = 'timesheet';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is called when the etemplate2 object is loaded
|
* This function is called when the etemplate2 object is loaded
|
||||||
@ -191,6 +191,53 @@ class TimesheetApp extends EgwApp
|
|||||||
var widget = this.et2.getWidgetById('ts_title');
|
var widget = this.et2.getWidgetById('ts_title');
|
||||||
if(widget) return widget.options.value;
|
if(widget) return widget.options.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _grants : any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a push notification about entry changes from the websocket
|
||||||
|
*
|
||||||
|
* @param pushData
|
||||||
|
* @param {string} pushData.app application name
|
||||||
|
* @param {(string|number)} pushData.id id of entry to refresh or null
|
||||||
|
* @param {string} pushData.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 {object|null} pushData.acl Extra data for determining relevance. eg: owner or responsible to decide if update is necessary
|
||||||
|
* @param {number} pushData.account_id User that caused the notification
|
||||||
|
*/
|
||||||
|
push(pushData)
|
||||||
|
{
|
||||||
|
// timesheed does NOT care about other apps data
|
||||||
|
if (pushData.app !== this.appname) return;
|
||||||
|
|
||||||
|
if (pushData.type === 'delete')
|
||||||
|
{
|
||||||
|
return super.push(pushData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// all other cases (add, edit, update) are handled identical
|
||||||
|
// check visibility
|
||||||
|
if (typeof this._grants === 'undefined')
|
||||||
|
{
|
||||||
|
this._grants = egw.grants(this.appname);
|
||||||
|
}
|
||||||
|
if (typeof this._grants[pushData.acl] === 'undefined') return;
|
||||||
|
|
||||||
|
// check if we might not see it because of an owner filter
|
||||||
|
let nm = this.et2?.getWidgetById('nm');
|
||||||
|
let nm_value = nm?.getValue();
|
||||||
|
if (nm && nm_value && typeof nm_value.col_filter?.ts_owner !== 'undefined')
|
||||||
|
{
|
||||||
|
if (!nm_value.col_filter.ts_owner || nm_value.col_filter.ts_owner == pushData.acl)
|
||||||
|
{
|
||||||
|
this.updateList(nm, pushData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app.classes.timesheet = TimesheetApp;
|
app.classes.timesheet = TimesheetApp;
|
||||||
|
Loading…
Reference in New Issue
Block a user