mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-26 08:39:07 +01:00
* Notifications: fixed deleting and grouping of popup notifications by app-name and -id and show full total independent of max. 100 shown entries
This commit is contained in:
parent
4d31227b43
commit
4b683b38ea
@ -2287,7 +2287,7 @@ class Db
|
||||
|
||||
if ($this->Debug) echo "<p>sql='$sql'</p>";
|
||||
|
||||
if ($line === false && $file === false) // call by union, to return the sql rather then run the query
|
||||
if ($line === false && $file === false) // call by union, to return the sql rather than run the query
|
||||
{
|
||||
return $sql;
|
||||
}
|
||||
|
@ -596,7 +596,7 @@ abstract class Tracking
|
||||
|
||||
if (!$this->notify_current_user && $this->user) // do we have a current user and should we notify the current user about his own changes
|
||||
{
|
||||
//error_log("do_notificaton() adding user=$this->user to email_sent, to not notify him");
|
||||
//error_log("do_notification() adding user=$this->user to email_sent, to not notify him");
|
||||
$email_sent[] = $GLOBALS['egw']->accounts->id2name($this->user,'account_email');
|
||||
}
|
||||
$skip_notify = $this->get_config('skip_notify',$data,$old);
|
||||
@ -722,8 +722,8 @@ abstract class Tracking
|
||||
*
|
||||
* Called by track() or externally for sending async notifications
|
||||
*
|
||||
* Method changes $GLOBALS['egw_info']['user'], so everything called by it, eg. get_(subject|body|links|attachements),
|
||||
* must NOT store something from user enviroment! By the end of the method, everything get changed back.
|
||||
* Method changes $GLOBALS['egw_info']['user'], so everything called by it, e.g. get_(subject|body|links|attachments),
|
||||
* must NOT store something from user environment! By the end of the method, everything get changed back.
|
||||
*
|
||||
* @param array $data current entry
|
||||
* @param array $old = null old/last state of the entry or null for a new entry
|
||||
@ -807,7 +807,7 @@ abstract class Tracking
|
||||
$attachments = $this->get_attachments($data,$old,$receiver);
|
||||
}
|
||||
|
||||
// restore user enviroment BEFORE calling notification class or returning
|
||||
// restore user environment BEFORE calling notification class or returning
|
||||
$GLOBALS['egw_info']['user'] = $save_user;
|
||||
// need to call preferences constructor and read_repository, to set user timezone again
|
||||
$GLOBALS['egw']->preferences->__construct($GLOBALS['egw_info']['user']['account_id']);
|
||||
@ -843,12 +843,12 @@ abstract class Tracking
|
||||
$notification->set_reply_to($reply_to);
|
||||
$notification->set_subject($subject);
|
||||
$notification->set_links(array($link));
|
||||
$notification->set_popupdata($link?$link['app']:null, $link);
|
||||
$notification->set_popupdata($link['app']??null, $link, $link['id']??null);
|
||||
if ($attachments && is_array($attachments))
|
||||
{
|
||||
$notification->set_attachments($attachments);
|
||||
}
|
||||
// run immediatly during async service, as sending mail with Horde fails, if PHP is already in shutdown
|
||||
// run immediately during async service, as sending mail with Horde fails, if PHP is already in shutdown
|
||||
// (json requests take care of that by calling Egw::__desctruct() explicit before it's regular triggered)
|
||||
$run = isset($GLOBALS['egw_info']['flags']['async-service']) ? 'call_user_func_array' : Api\Egw::class.'::on_shutdown';
|
||||
$run(static function($notification, $sender, $receiver, $subject)
|
||||
@ -1088,7 +1088,7 @@ abstract class Tracking
|
||||
* @param array $data
|
||||
* @param array $old
|
||||
* @param boolean $integrate_link to have links embedded inside the body
|
||||
* @param int|string $receiver nummeric account_id or email address
|
||||
* @param int|string $receiver numeric account_id or email address
|
||||
* @return string
|
||||
*/
|
||||
public function get_body($html_email,$data,$old,$integrate_link = true,$receiver=null)
|
||||
|
@ -1236,9 +1236,9 @@ class calendar_boupdate extends calendar_bo
|
||||
// popup notifiactions: set subject, different message (without separator) and (always) links
|
||||
$notification->set_popupsubject($subject);
|
||||
|
||||
if ($method =='REQUEST')
|
||||
if ($method == 'REQUEST')
|
||||
{
|
||||
// Add ACCEPT|REHECT|TENTATIVE actions
|
||||
// Add ACCEPT|REJECT|TENTATIVE actions
|
||||
$notification->set_popupdata('calendar', array(
|
||||
'event_id' => $event['id'],
|
||||
'user_id' => $userid,
|
||||
|
@ -593,7 +593,7 @@ class notifications {
|
||||
}
|
||||
break; // stop running through chain
|
||||
}
|
||||
// backend sucseeded
|
||||
// backend succeeded
|
||||
$user_notified = true;
|
||||
if($action == 'stop' || $action == 'fail') { break; } // stop running through chain
|
||||
}
|
||||
@ -827,13 +827,15 @@ class notifications {
|
||||
* Set popup data
|
||||
*
|
||||
* @param string $_appname
|
||||
* @param array $_data
|
||||
* @param ?array $_data
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function set_popupdata($_appname, $_data)
|
||||
public function set_popupdata(string $_appname, ?array $_data, ?int $_id=null)
|
||||
{
|
||||
$this->popup_data = array(
|
||||
'appname' => $_appname,
|
||||
'id' => $_id ?: $_data['id'] ?? null,
|
||||
'data' => $_data
|
||||
);
|
||||
|
||||
|
@ -129,13 +129,14 @@ class notifications_ajax
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove given notification id(s) from the table
|
||||
* Remove given notification id(s) and app_ids from the table
|
||||
*
|
||||
* @param int[]|array[] $notifymessages one or multiple notify_id(s) or objects incl. id attribute
|
||||
* @param array[] $app_ids app-name int[] pairs
|
||||
*/
|
||||
public function delete_message(array $notifymessages)
|
||||
public function delete_message(array $notifymessages, array $app_ids=[])
|
||||
{
|
||||
$this->update($notifymessages, null); // null = delete
|
||||
$this->update($notifymessages, null, $app_ids ?? []); // null = delete
|
||||
|
||||
// if we delete all messages (we either delete one or all!), we return the next chunk of messages directly
|
||||
if (count($notifymessages) > 1)
|
||||
@ -165,11 +166,12 @@ class notifications_ajax
|
||||
*
|
||||
* @param array $notifymessages
|
||||
* @param string|null $status use null to delete
|
||||
* @param array[] $app_ids app-name int[] pairs
|
||||
* @return array
|
||||
*/
|
||||
protected function update(array $notifymessages, $status='SEEN')
|
||||
protected function update(array $notifymessages, $status='SEEN', array $app_ids=[])
|
||||
{
|
||||
$notify_ids = $app_ids = [];
|
||||
$notify_ids = [];
|
||||
foreach ($notifymessages as $data)
|
||||
{
|
||||
if (is_array($data) && !empty($data['id']))
|
||||
@ -187,14 +189,13 @@ class notifications_ajax
|
||||
}
|
||||
$cut_off = $this->db->quote(Api\DateTime::to(self::CUT_OFF_DATE, Api\DateTime::DATABASE));
|
||||
try {
|
||||
// MariaDB code using JSON_EXTRACT()
|
||||
foreach($app_ids as $app => $ids)
|
||||
{
|
||||
$where = [
|
||||
'account_id' => $this->recipient->account_id,
|
||||
'notify_type' => self::_type,
|
||||
"JSON_EXTRACT(notify_data, '$.appname') = ".$this->db->quote($app),
|
||||
"JSON_EXTRACT(notify_data, '$.data.id') IN (".implode(',', array_map([$this->db, 'quote'], array_unique($ids))).')',
|
||||
'notify_app' => $app,
|
||||
'notify_app_id' => array_unique($ids),
|
||||
'notify_created > '.$cut_off,
|
||||
];
|
||||
if (isset($status))
|
||||
@ -207,21 +208,8 @@ class notifications_ajax
|
||||
}
|
||||
}
|
||||
}
|
||||
// other DBs
|
||||
catch (Api\Db\Exception $e) {
|
||||
foreach($this->db->select(self::_notification_table, 'notify_id,notify_data', [
|
||||
'account_id' => $this->recipient->account_id,
|
||||
'notify_type' => self::_type,
|
||||
'notify_created > '.$cut_off,
|
||||
"notify_data <> '[]'", // does not return NULL or '[]' rows
|
||||
], __LINE__, __FILE__, false,'', self::_appname) as $row)
|
||||
{
|
||||
if (($data = json_decode($row['notify_data'], true)) &&
|
||||
isset($data['data']['id']) && in_array($data['data']['id'], $app_ids[$data['appname']] ?? []))
|
||||
{
|
||||
$notify_ids[] = $row['notify_id'];
|
||||
}
|
||||
}
|
||||
// ignore, if DB is not yet updated with notify_app(_id) columns
|
||||
}
|
||||
$where = [
|
||||
'notify_id' => array_unique($notify_ids),
|
||||
|
@ -18,7 +18,7 @@ use EGroupware\Api;
|
||||
* @abstract egwpopup is a two stage notification. In the first stage
|
||||
* notification is written into self::_notification_table.
|
||||
* In the second stage a request from the client reads
|
||||
* out the table to look if there is a notificaton for this
|
||||
* out the table to look if there is a notification for this
|
||||
* client. The second stage is done in class.notifications_ajax.inc.php
|
||||
*/
|
||||
class notifications_popup implements notifications_iface
|
||||
@ -128,6 +128,8 @@ class notifications_popup implements notifications_iface
|
||||
'notify_type' => self::_type,
|
||||
'notify_data' => $_data && is_array($_data) ? json_encode($_data) : NULL,
|
||||
'notify_created' => new Api\DateTime(),
|
||||
'notify_app' => $_data['appname'],
|
||||
'notify_app_id' => $_data['id'],
|
||||
), false,__LINE__,__FILE__,self::_appname);
|
||||
if ($result === false) throw new Exception("Can't save notification into SQL table");
|
||||
$push = new Api\Json\Push($this->recipient->account_id);
|
||||
@ -154,10 +156,20 @@ class notifications_popup implements notifications_iface
|
||||
|
||||
$result = [];
|
||||
if (($total = $db->select(self::_notification_table, 'COUNT(*)', [
|
||||
'account_id' => $_account_id,
|
||||
'notify_type' => self::_type,
|
||||
'notify_created > '.($cut_off=$db->quote(Api\DateTime::to(notifications_ajax::CUT_OFF_DATE, Api\DateTime::DATABASE))),
|
||||
], __LINE__, __FILE__, false, '', self::_appname)->fetchColumn()))
|
||||
'account_id' => $_account_id,
|
||||
'notify_type' => self::_type,
|
||||
'notify_created > '.($cut_off=$db->quote(Api\DateTime::to(notifications_ajax::CUT_OFF_DATE, Api\DateTime::DATABASE))),
|
||||
'notify_app_id IS NULL',
|
||||
], __LINE__, __FILE__, false, '', self::_appname)->fetchColumn()+
|
||||
$db->select(
|
||||
'('.$db->select(self::_notification_table, 'notify_app,notify_app_id', [
|
||||
'account_id' => $_account_id,
|
||||
'notify_type' => self::_type,
|
||||
'notify_created > '.($cut_off=$db->quote(Api\DateTime::to(notifications_ajax::CUT_OFF_DATE, Api\DateTime::DATABASE))),
|
||||
'notify_app_id IS NOT NULL',
|
||||
], false, false, false, 'GROUP BY notify_app,notify_app_id', self::_appname).') AS app_ids',
|
||||
'COUNT(*)', false, __LINE__, __FILE__, false, '', self::_appname)->fetchColumn()
|
||||
))
|
||||
{
|
||||
$n = 0;
|
||||
$chunk_size = 150;
|
||||
@ -188,26 +200,22 @@ class notifications_popup implements notifications_iface
|
||||
'current' => new Api\DateTime('now'),
|
||||
'actions' => is_array($actions) ? $actions : NULL,
|
||||
'extra_data' => $data['data'] ?? [],
|
||||
'app' => $notification['notify_app'] ?? $data['data']['app'] ?? null,
|
||||
'app_id' => $notification['notify_app_id'] ?? $data['data']['id'] ?? null,
|
||||
];
|
||||
// aggregate by app:id reporting only the newest entry
|
||||
if (!empty($data['extra_data']['id']))
|
||||
if (!empty($data['app_id']))
|
||||
{
|
||||
if (!isset($result[$id = $data['extra_data']['app'] . ':' . $data['extra_data']['id']]))
|
||||
if (!isset($result[$id = $data['app'] . ':' . $data['app_id']]))
|
||||
{
|
||||
$result[$id] = $data;
|
||||
}
|
||||
else
|
||||
{
|
||||
$total--;
|
||||
/* in case we want to show all
|
||||
$result['id']['others'][] = $data;
|
||||
*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$result[] = $data;
|
||||
}
|
||||
if (count($result) >= min($num_rows, $total)) break;
|
||||
}
|
||||
$n += $chunk_size;
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
* @subpackage ajaxpoup
|
||||
* @link http://www.egroupware.org
|
||||
* @author Cornelius Weiss <nelius@cwtech.de>, Christian Binder <christian@jaytraxx.de>, Ralf Becker <rb@egroupware.org>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@ -570,7 +569,17 @@
|
||||
|
||||
notifications.prototype.delete_all = function () {
|
||||
if (!notifymessages || Object.entries(notifymessages).length == 0) return false;
|
||||
egw.request("notifications.notifications_ajax.delete_message", [Object.keys(notifymessages)]);
|
||||
const app_ids = {};
|
||||
for(const id in notifymessages)
|
||||
{
|
||||
const notification = notifymessages[id];
|
||||
if (notification.data?.id && notification.data.app)
|
||||
{
|
||||
if (typeof app_ids[notification.data.app] === "undefined") app_ids[notification.data.app] = [];
|
||||
app_ids[notification.data.app].push(notification.data.id);
|
||||
}
|
||||
}
|
||||
egw.request("notifications.notifications_ajax.delete_message", [Object.keys(notifymessages), app_ids]);
|
||||
notifymessages = {};
|
||||
_currentRawData = []; // otherwise response from delete_message/get_notifications might not get parsed
|
||||
this.total = 0;
|
||||
@ -585,11 +594,14 @@
|
||||
*/
|
||||
notifications.prototype.button_delete = function(_node, _event) {
|
||||
_event.stopPropagation();
|
||||
var egwpopup_message = _node[0];
|
||||
var id = egwpopup_message[0].id.replace(/egwpopup_message_/ig,'');
|
||||
egw.request("notifications.notifications_ajax.delete_message", [[id]]);
|
||||
var nextNode = egwpopup_message.next();
|
||||
var keepLoadingPrompt = false;
|
||||
const egwpopup_message = _node[0];
|
||||
const id = egwpopup_message[0].id.replace(/egwpopup_message_/ig,'');
|
||||
const notification = notifymessages[id];
|
||||
const app_ids = {};
|
||||
if (notification.data?.id) app_ids[notification.data.app] = [notification.data.id];
|
||||
egw.request("notifications.notifications_ajax.delete_message", [[id], app_ids]);
|
||||
const nextNode = egwpopup_message.next();
|
||||
let keepLoadingPrompt = false;
|
||||
delete (notifymessages[id]);
|
||||
this.total -= 1;
|
||||
this.counterUpdate();
|
||||
@ -935,7 +947,8 @@
|
||||
// toggle notifications bar
|
||||
jQuery('.button_right_toggle', '#egwpopup').click(function(){window.app.notifications.toggle();});
|
||||
$egwpopup_fw.click(function(){window.app.notifications.toggle();});
|
||||
jQuery(".egwpopup_deleteall", '#egwpopup').click(function(){
|
||||
jQuery(".egwpopup_deleteall", '#egwpopup').click(function(_ev){
|
||||
_ev.stopPropagation();
|
||||
et2_dialog.show_dialog( function(_button){
|
||||
if (_button == 2) window.app.notifications.delete_all();
|
||||
},
|
||||
|
@ -14,7 +14,7 @@ if (!defined('NOTIFICATION_APP'))
|
||||
}
|
||||
|
||||
$setup_info[NOTIFICATION_APP]['name'] = NOTIFICATION_APP;
|
||||
$setup_info[NOTIFICATION_APP]['version'] = '23.1';
|
||||
$setup_info[NOTIFICATION_APP]['version'] = '23.1.001';
|
||||
$setup_info[NOTIFICATION_APP]['app_order'] = 1;
|
||||
$setup_info[NOTIFICATION_APP]['tables'] = array('egw_notificationpopup');
|
||||
$setup_info[NOTIFICATION_APP]['enable'] = 2;
|
||||
@ -39,4 +39,4 @@ $setup_info[NOTIFICATION_APP]['hooks']['config'] = 'notifications.notifications.
|
||||
$setup_info[NOTIFICATION_APP]['depends'][] = array(
|
||||
'appname' => 'api',
|
||||
'versions' => Array('23.1')
|
||||
);
|
||||
);
|
||||
|
@ -18,11 +18,13 @@ $phpgw_baseline = array(
|
||||
'notify_created' => array('type' => 'timestamp','meta' => 'timestamp','default' => 'current_timestamp','comment' => 'creation time of notification'),
|
||||
'notify_type' => array('type' => 'ascii','precision' => '32','comment' => 'notification type'),
|
||||
'notify_status' => array('type' => 'varchar','precision' => '32','comment' => 'notification status'),
|
||||
'notify_data' => array('type' => 'varchar','precision' => '4096','comment' => 'notification data')
|
||||
'notify_data' => array('type' => 'varchar','precision' => '4096','comment' => 'notification data'),
|
||||
'notify_app' => array('type' => 'ascii','precision' => '16','comment' => 'appname'),
|
||||
'notify_app_id' => array('type' => 'ascii','precision' => '64','comment' => 'application id')
|
||||
),
|
||||
'pk' => array('notify_id'),
|
||||
'fk' => array(),
|
||||
'ix' => array('account_id','notify_created'),
|
||||
'ix' => array('notify_created',array('account_id','notify_type'),array('notify_app','notify_app_id')),
|
||||
'uc' => array()
|
||||
)
|
||||
);
|
||||
);
|
@ -9,6 +9,8 @@
|
||||
* @subpackage setup
|
||||
*/
|
||||
|
||||
use EGroupware\Api;
|
||||
|
||||
function notifications_upgrade0_5()
|
||||
{
|
||||
$GLOBALS['egw_setup']->oProc->AlterColumn('egw_notificationpopup','account_id',array(
|
||||
@ -201,4 +203,60 @@ function notifications_upgrade21_1()
|
||||
));
|
||||
|
||||
return $GLOBALS['setup_info']['notifications']['currentver'] = '23.1';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add explicit columns for app-name and -id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function notifications_upgrade23_1()
|
||||
{
|
||||
$GLOBALS['egw_setup']->oProc->AddColumn('egw_notificationpopup','notify_app',array(
|
||||
'type' => 'ascii',
|
||||
'precision' => '16',
|
||||
'comment' => 'appname'
|
||||
));
|
||||
|
||||
$GLOBALS['egw_setup']->oProc->AddColumn('egw_notificationpopup','notify_app_id',array(
|
||||
'type' => 'ascii',
|
||||
'precision' => '64',
|
||||
'comment' => 'application id'
|
||||
));
|
||||
|
||||
/** @var Api\Db $db */
|
||||
$db = $GLOBALS['egw_setup']->db;
|
||||
try {
|
||||
$db->update('egw_notificationpopup',array(
|
||||
"notify_app=JSON_VALUE(notify_data,'$.data.app')",
|
||||
"notify_app_id=JSON_VALUE(notify_data,'$.data.id')",
|
||||
), 'notify_data IS NOT NULL', __LINE__, __FILE__, 'notifications');
|
||||
}
|
||||
catch (Api\Db\Exception\InvalidSql $e) {
|
||||
$start = 0;
|
||||
$chunk_size = 1000;
|
||||
do
|
||||
{
|
||||
foreach($rs=$db->select('egw_notificationpopup','notify_id,notify_data','notify_data IS NOT NULL',
|
||||
__LINE__, __FILE__, $start, '', 'notifications', $chunk_size) as $row)
|
||||
{
|
||||
$data = json_decode($row['notify_data']);
|
||||
if ($data && !empty($data['data']['id']))
|
||||
{
|
||||
$db->update('egw_notficationpopup', [
|
||||
'notify_app' => $data['data']['app'],
|
||||
'notify_id' => $data['data']['id'],
|
||||
], ['notify_id' => $row['notify_id']], __LINE__, __FILE__, 'notifications');
|
||||
}
|
||||
++$start;
|
||||
}
|
||||
}
|
||||
while ($start && !($start % $chunk_size));
|
||||
}
|
||||
|
||||
$GLOBALS['egw_setup']->oProc->CreateIndex('egw_notificationpopup', array('notify_app','notify_app_id'), false);
|
||||
$GLOBALS['egw_setup']->oProc->CreateIndex('egw_notificationpopup', array('account_id','notify_type'), false);
|
||||
$GLOBALS['egw_setup']->oProc->DropIndex('egw_notificationpopup', array('account_id'));
|
||||
|
||||
return $GLOBALS['setup_info']['notifications']['currentver'] = '23.1.001';
|
||||
}
|
Loading…
Reference in New Issue
Block a user