PHRAS-3442_optimize-list-notifications_4.1-bis

WIP
mark notif as read
fix test
This commit is contained in:
jygaulier
2021-06-17 17:13:35 +02:00
parent f8cfd08f4f
commit 47c0e4b1cc
10 changed files with 160 additions and 143 deletions

View File

@@ -18905,8 +18905,8 @@ var notifyLayout = function notifyLayout(services) {
var $notificationBoxContainer = (0, _jquery2.default)('#notification_box'); var $notificationBoxContainer = (0, _jquery2.default)('#notification_box');
var $notificationTrigger = (0, _jquery2.default)('.notification_trigger'); var $notificationTrigger = (0, _jquery2.default)('.notification_trigger');
var $notificationDialog = (0, _jquery2.default)('#notifications-dialog'); var $notificationDialog = (0, _jquery2.default)('#notifications-dialog');
var $notifications = null; var $notifications = (0, _jquery2.default)('.notifications', $notificationDialog);
var $navigation = null; var $navigation = (0, _jquery2.default)('.navigation', $notificationDialog);
var initialize = function initialize() { var initialize = function initialize() {
/** /**
@@ -19020,15 +19020,6 @@ var notifyLayout = function notifyLayout(services) {
$notificationDialog.dialog('close'); $notificationDialog.dialog('close');
}; };
// create the dlg div if it does not exists
//
// if ($notificationDialog.length === 0) {
// $('body').append('<div id="notifications-dialog"><div class="content"></div><div class="navigation"></div></div>');
// $notificationDialog = $('#notifications-dialog');
$notifications = (0, _jquery2.default)('.notifications', $notificationDialog);
$navigation = (0, _jquery2.default)('.navigation', $notificationDialog);
// }
// open the dlg (even if it is already opened when "load more") // open the dlg (even if it is already opened when "load more")
// //
$notificationDialog.dialog({ $notificationDialog.dialog({
@@ -19076,7 +19067,8 @@ var notifyLayout = function notifyLayout(services) {
var notifications = data.notifications.notifications; var notifications = data.notifications.notifications;
var i = 0; var i = 0;
for (i in notifications) {
var _loop = function _loop() {
var notification = notifications[i]; var notification = notifications[i];
// group notifs by day // group notifs by day
@@ -19093,6 +19085,13 @@ var notifyLayout = function notifyLayout(services) {
// add pre-formatted notif // add pre-formatted notif
date_cont.append(notification.html); date_cont.append(notification.html);
(0, _jquery2.default)('.notification_' + notification.id + '_unread', $notifications).tooltip().click(function () {
mark_read(notification.id);
});
};
for (i in notifications) {
_loop();
} }
// handle "show more" button // handle "show more" button
@@ -19109,51 +19108,35 @@ var notifyLayout = function notifyLayout(services) {
// no more ? no button // no more ? no button
$navigation.hide(); $navigation.hide();
} }
/*
if (data.notifications.next_page_html) {
$navigation
.off('click', '.notification__print-action');
$navigation.empty().show().append(data.notifications.next_page_html);
$navigation
.on('click', '.notification__print-action', function (event) {
event.preventDefault();
let $el = $(event.currentTarget);
let offset = $el.data('offset');
print_notifications(offset);
});
}
else {
$navigation.empty().hide();
}
*/
} }
}); });
}; };
/* remove in favor of existing /session/ route
const read_notifications = () => { var mark_read = function mark_read(notification_id) {
var notifications = []; _jquery2.default.ajax({
$('#notification_box .unread').each(function () { type: 'PATCH',
notifications.push($(this).attr('id').split('_').pop()); url: '/user/notifications/' + notification_id + '/',
});
$.ajax({
type: 'POST',
url: '/user/notifications/read/',
data: { data: {
notifications: notifications.join('_') 'read': 1
}, },
success: function (data) { success: function success(data) {
$('.notification_trigger .counter').css('visibility', 'hidden').empty(); (0, _jquery2.default)('.notification_' + notification_id + '_unread', $notifications).hide();
(0, _jquery2.default)('.notification_' + notification_id + '_read', $notifications).show();
} }
}); });
}; };
/*
const clear_notifications = () => { const clear_notifications = () => {
var unread = $('#notification_box .unread'); var unread = $('#notification_box .unread');
if (unread.length === 0) { if (unread.length === 0) {
return; return;
} }
unread.removeClass('unread'); unread.removeClass('unread');
$('.notification_trigger .counter').css('visibility', 'hidden').empty(); $('.notification_trigger .counter').css('visibility', 'hidden').empty();
}; };
*/ */
return { return {

View File

@@ -18905,8 +18905,8 @@ var notifyLayout = function notifyLayout(services) {
var $notificationBoxContainer = (0, _jquery2.default)('#notification_box'); var $notificationBoxContainer = (0, _jquery2.default)('#notification_box');
var $notificationTrigger = (0, _jquery2.default)('.notification_trigger'); var $notificationTrigger = (0, _jquery2.default)('.notification_trigger');
var $notificationDialog = (0, _jquery2.default)('#notifications-dialog'); var $notificationDialog = (0, _jquery2.default)('#notifications-dialog');
var $notifications = null; var $notifications = (0, _jquery2.default)('.notifications', $notificationDialog);
var $navigation = null; var $navigation = (0, _jquery2.default)('.navigation', $notificationDialog);
var initialize = function initialize() { var initialize = function initialize() {
/** /**
@@ -19020,15 +19020,6 @@ var notifyLayout = function notifyLayout(services) {
$notificationDialog.dialog('close'); $notificationDialog.dialog('close');
}; };
// create the dlg div if it does not exists
//
// if ($notificationDialog.length === 0) {
// $('body').append('<div id="notifications-dialog"><div class="content"></div><div class="navigation"></div></div>');
// $notificationDialog = $('#notifications-dialog');
$notifications = (0, _jquery2.default)('.notifications', $notificationDialog);
$navigation = (0, _jquery2.default)('.navigation', $notificationDialog);
// }
// open the dlg (even if it is already opened when "load more") // open the dlg (even if it is already opened when "load more")
// //
$notificationDialog.dialog({ $notificationDialog.dialog({
@@ -19076,7 +19067,8 @@ var notifyLayout = function notifyLayout(services) {
var notifications = data.notifications.notifications; var notifications = data.notifications.notifications;
var i = 0; var i = 0;
for (i in notifications) {
var _loop = function _loop() {
var notification = notifications[i]; var notification = notifications[i];
// group notifs by day // group notifs by day
@@ -19093,6 +19085,13 @@ var notifyLayout = function notifyLayout(services) {
// add pre-formatted notif // add pre-formatted notif
date_cont.append(notification.html); date_cont.append(notification.html);
(0, _jquery2.default)('.notification_' + notification.id + '_unread', $notifications).tooltip().click(function () {
mark_read(notification.id);
});
};
for (i in notifications) {
_loop();
} }
// handle "show more" button // handle "show more" button
@@ -19109,51 +19108,35 @@ var notifyLayout = function notifyLayout(services) {
// no more ? no button // no more ? no button
$navigation.hide(); $navigation.hide();
} }
/*
if (data.notifications.next_page_html) {
$navigation
.off('click', '.notification__print-action');
$navigation.empty().show().append(data.notifications.next_page_html);
$navigation
.on('click', '.notification__print-action', function (event) {
event.preventDefault();
let $el = $(event.currentTarget);
let offset = $el.data('offset');
print_notifications(offset);
});
}
else {
$navigation.empty().hide();
}
*/
} }
}); });
}; };
/* remove in favor of existing /session/ route
const read_notifications = () => { var mark_read = function mark_read(notification_id) {
var notifications = []; _jquery2.default.ajax({
$('#notification_box .unread').each(function () { type: 'PATCH',
notifications.push($(this).attr('id').split('_').pop()); url: '/user/notifications/' + notification_id + '/',
});
$.ajax({
type: 'POST',
url: '/user/notifications/read/',
data: { data: {
notifications: notifications.join('_') 'read': 1
}, },
success: function (data) { success: function success(data) {
$('.notification_trigger .counter').css('visibility', 'hidden').empty(); (0, _jquery2.default)('.notification_' + notification_id + '_unread', $notifications).hide();
(0, _jquery2.default)('.notification_' + notification_id + '_read', $notifications).show();
} }
}); });
}; };
/*
const clear_notifications = () => { const clear_notifications = () => {
var unread = $('#notification_box .unread'); var unread = $('#notification_box .unread');
if (unread.length === 0) { if (unread.length === 0) {
return; return;
} }
unread.removeClass('unread'); unread.removeClass('unread');
$('.notification_trigger .counter').css('visibility', 'hidden').empty(); $('.notification_trigger .counter').css('visibility', 'hidden').empty();
}; };
*/ */
return { return {

View File

@@ -194,6 +194,10 @@ const notifyLayout = (services) => {
// add pre-formatted notif // add pre-formatted notif
date_cont.append(notification.html); date_cont.append(notification.html);
$('.notification_' + notification.id + '_unread', $notifications).tooltip().click(
function () {
mark_read(notification.id);
});
} }
// handle "show more" button // handle "show more" button
@@ -216,26 +220,21 @@ const notifyLayout = (services) => {
} }
}); });
}; };
/* remove in favor of existing /session/ route
const read_notifications = () => {
var notifications = [];
$('#notification_box .unread').each(function () {
notifications.push($(this).attr('id').split('_').pop());
});
const mark_read = (notification_id) => {
$.ajax({ $.ajax({
type: 'POST', type: 'PATCH',
url: '/user/notifications/read/', url: '/user/notifications/' + notification_id + '/',
data: { data: {
notifications: notifications.join('_') 'read': 1
}, },
success: function (data) { success: function (data) {
$('.notification_trigger .counter').css('visibility', 'hidden').empty(); $('.notification_' + notification_id + '_unread', $notifications).hide();
$('.notification_' + notification_id + '_read', $notifications).show();
} }
}); });
}; };
/*
const clear_notifications = () => { const clear_notifications = () => {
var unread = $('#notification_box .unread'); var unread = $('#notification_box .unread');

View File

@@ -130,37 +130,35 @@ class UserNotificationController extends Controller
} }
/** /**
* Set notifications as read * patch a notification
* for now the only usefull thing is to mark it as "read"
* *
* @param Request $request * @param Request $request
* @return JsonResponse * @return JsonResponse
*/ */
/* remove in favor of existing /session/ route public function patchNotification(Request $request, $notification_id)
public function readNotifications(Request $request)
{ {
if (!$request->isXmlHttpRequest()) { if (!$request->isXmlHttpRequest()) {
$this->app->abort(400); $this->app->abort(400);
} }
if($request->get('read', '0') === '1') {
// mark as read
try { try {
$this->getEventsManager()->read( $this->getEventsManager()->read(
explode('_', (string) $request->request->get('notifications')), [$notification_id],
$this->getAuthenticatedUser()->getId() $this->getAuthenticatedUser()->getId()
); );
return $this->app->json(['success' => true, 'message' => '']); return $this->app->json(['success' => true, 'message' => '']);
} catch (\Exception $e) { }
catch (\Exception $e) {
return $this->app->json(['success' => false, 'message' => $e->getMessage()]); return $this->app->json(['success' => false, 'message' => $e->getMessage()]);
} }
} }
*/ }
/** /**
* Get all notifications * Get all notifications

View File

@@ -54,8 +54,11 @@ class Notifications implements ControllerProviderInterface, ServiceProviderInter
// ->bind('get_notifications') // ->bind('get_notifications')
; ;
/* todo : re-implement "read" route $controllers->patch('/{notification_id}/', 'controller.user.notifications:patchNotification')
* ->assert('notification_id', '\d+')
->bind('set_notifications_readed');
/*
/** @uses UserNotificationController::listNotifications * / /** @uses UserNotificationController::listNotifications * /
$controllers->get('/', 'controller.user.notifications:getNotifications') $controllers->get('/', 'controller.user.notifications:getNotifications')
->bind('get_notifications'); ->bind('get_notifications');

View File

@@ -233,8 +233,16 @@ class eventsmanager_broker
// delete old already read notifs (nb: we do this for everybody - not only the current user -) // delete old already read notifs (nb: we do this for everybody - not only the current user -)
// todo: for now we use "created_on" since there is no timestamp set when reading. // todo: for now we use "created_on" since there is no timestamp set when reading.
// //
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// do restore : for testing we do not yet delete
$sql = "DELETE FROM `notifications` WHERE `unread`=0 AND TIMESTAMPDIFF(HOUR, `created_on`, NOW()) > 10"; $sql = "DELETE FROM `notifications` WHERE `unread`=0 AND TIMESTAMPDIFF(HOUR, `created_on`, NOW()) > 10";
$this->app->getApplicationBox()->get_connection()->exec($sql); // $this->app->getApplicationBox()->get_connection()->exec($sql);
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// get count of unread notifications (to be displayed on navbar) // get count of unread notifications (to be displayed on navbar)
// //

View File

@@ -135,8 +135,16 @@ var commonModule = (function ($, p4) {
} }
else { else {
$('.no_notifications', $box).hide(); $('.no_notifications', $box).hide();
for (n in data.notifications.notifications) { for (var n in data.notifications.notifications) {
$box_notifications.append(data.notifications.notifications[n].html); var notification = data.notifications.notifications[n];
$box_notifications.append(notification.html);
$('.notification_' + notification.id + '_read', $box_notifications).click(
function (event) {
console.log("++++++++++ clicked("+notification.id+")")
});
} }
$('.show_all', $box).show(); $('.show_all', $box).show();
} }

View File

@@ -64,7 +64,7 @@
{#<script type="text/javascript" src="{{ path('minifier', { 'f' : '/assets/requirejs/require.js,/scripts/apps/admin/require.config.js,/scripts/apps/admin/main/main.js' }) }}"></script>#} {#<script type="text/javascript" src="{{ path('minifier', { 'f' : '/assets/requirejs/require.js,/scripts/apps/admin/require.config.js,/scripts/apps/admin/main/main.js' }) }}"></script>#}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div id="admin-app" data-usr="{{ app.getAuthenticatedUser().getId() }}" data-notif-url="{{ path('list_notifications') }}"> <div id="admin-app" data-usr="{{ app.getAuthenticatedUser().getId() }}">
<div id="left" class="PNB left-view" style="width:250px;right:auto;" data-tree-url="{{ path("admin_display_tree") }}" data-websocket="{{ "ws://" ~ app["conf"].get(["main" ,"websocket-server", "host"]) ~ ":" ~ app["conf"].get(["main" ,"websocket-server", "port"]) ~ "/websockets" }}"> <div id="left" class="PNB left-view" style="width:250px;right:auto;" data-tree-url="{{ path("admin_display_tree") }}" data-websocket="{{ "ws://" ~ app["conf"].get(["main" ,"websocket-server", "host"]) ~ ":" ~ app["conf"].get(["main" ,"websocket-server", "port"]) ~ "/websockets" }}">
<div class="PNB10" style="right:0; top:0px;"> <div class="PNB10" style="right:0; top:0px;">
<div id="FNDR"> <div id="FNDR">

View File

@@ -1,4 +1,4 @@
<div style="position:relative;" id="notification_{{notification['id']}}" class="notification {% if notification['unread'] == '1' %}unread{% endif %}"> <div style="position:relative;" class="notification {% if notification['unread'] == '1' %}unread{% endif %}">
<table style="width:100%;" cellspacing="0" cellpadding="0" border="0"> <table style="width:100%;" cellspacing="0" cellpadding="0" border="0">
<tr style="border-top: 1px grey solid"> <tr style="border-top: 1px grey solid">
<td style="width:25px; vertical-align: top;"> <td style="width:25px; vertical-align: top;">
@@ -10,6 +10,10 @@
<span class="time">{{notification['created_on']}}</span> <span class="time">{{notification['created_on']}}</span>
</p> </p>
</td> </td>
<td style="width:25px; vertical-align: bottom;">
<span class="notification_{{notification['id']}}_read" title="{{ 'notification::read:tooltip' | trans }}" style="display: {{ notification['unread'] == '1' ? 'none' : 'inherit' }}">&#9989;</span>
<span class="notification_{{notification['id']}}_unread" title="{{ 'notification::unread:tooltip' | trans }}" style="cursor: pointer; display: {{ notification['unread'] == '1' ? 'inherit' : 'none' }}">&#x1F441;</span>
</td>
</tr> </tr>
</table> </table>
</div> </div>

View File

@@ -2,8 +2,8 @@
namespace Alchemy\Tests\Phrasea\Core\Event\Subscriber; namespace Alchemy\Tests\Phrasea\Core\Event\Subscriber;
use Alchemy\Phrasea\Core\Event\Subscriber\SessionManagerSubscriber;
use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Core\Event\Subscriber\SessionManagerSubscriber;
use Alchemy\Phrasea\Model\Entities\Session; use Alchemy\Phrasea\Model\Entities\Session;
use Symfony\Component\HttpKernel\Client; use Symfony\Component\HttpKernel\Client;
@@ -235,10 +235,6 @@ class SessionManagerSubscriberTest extends \PhraseanetAuthenticatedWebTestCase
$app['orm.em'] = $this->getMockBuilder('Doctrine\ORM\EntityManager')->disableOriginalConstructor()->getMock(); $app['orm.em'] = $this->getMockBuilder('Doctrine\ORM\EntityManager')->disableOriginalConstructor()->getMock();
$app['orm.em']->expects($this->never())->method('flush'); $app['orm.em']->expects($this->never())->method('flush');
$app->get('/login', function () {
return '';
})->bind("homepage");
$app->get($route, function () { $app->get($route, function () {
return ''; return '';
}); });
@@ -254,8 +250,43 @@ class SessionManagerSubscriberTest extends \PhraseanetAuthenticatedWebTestCase
public function forbiddenRouteProvider() public function forbiddenRouteProvider()
{ {
return [ return [
['/admin/databox/17/informations/documents/'], ['/'],
['/login/'],
];
}
/**
* @dataProvider notUserActivityRouteProvider
*/
public function testNotUserActivityRoutes($route)
{
$app = new Application(Application::ENV_TEST);
$app['dispatcher']->addSubscriber(new SessionManagerSubscriber($app));
$app['authentication'] = $this->getMockBuilder('Alchemy\Phrasea\Authentication\Authenticator')->disableOriginalConstructor()->getMock();
$app['authentication']->expects($this->once())->method('isAuthenticated');
$app['orm.em'] = $this->getMockBuilder('Doctrine\ORM\EntityManager')->disableOriginalConstructor()->getMock();
$app['orm.em']->expects($this->never())->method('flush');
$app->get($route, function () {
return '';
});
$client = new Client($app);
$client->request('GET', $route, [], [], [
'HTTP_CONTENT-TYPE' => 'application/json',
'HTTP_ACCEPT' => 'application/json',
'HTTP_X-Requested-With' => 'XMLHttpRequest',
]);
}
public function notUserActivityRouteProvider()
{
return [
['/session/'],
['/user/'],
['/admin/task-manager/tasks/'], ['/admin/task-manager/tasks/'],
['/admin/databox/17/informations/documents/']
]; ];
} }
} }