diff --git a/Phraseanet-production-client/dist/production.js b/Phraseanet-production-client/dist/production.js index 0614845472..476027a690 100644 --- a/Phraseanet-production-client/dist/production.js +++ b/Phraseanet-production-client/dist/production.js @@ -18905,8 +18905,8 @@ var notifyLayout = function notifyLayout(services) { var $notificationBoxContainer = (0, _jquery2.default)('#notification_box'); var $notificationTrigger = (0, _jquery2.default)('.notification_trigger'); var $notificationDialog = (0, _jquery2.default)('#notifications-dialog'); - var $notificationsContent = null; - var $notificationsNavigation = null; + var $notifications = null; + var $navigation = null; var initialize = function initialize() { /** @@ -19022,12 +19022,12 @@ var notifyLayout = function notifyLayout(services) { // create the dlg div if it does not exists // - if ($notificationDialog.length === 0) { - (0, _jquery2.default)('body').append('
'); - $notificationDialog = (0, _jquery2.default)('#notifications-dialog'); - $notificationsContent = (0, _jquery2.default)('.content', $notificationDialog); - $notificationsNavigation = (0, _jquery2.default)('.navigation', $notificationDialog); - } + // if ($notificationDialog.length === 0) { + // $('body').append('
'); + // $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") // @@ -19053,9 +19053,8 @@ var notifyLayout = function notifyLayout(services) { // $notificationDialog.addClass('loading'); _jquery2.default.ajax({ - type: 'POST', - // url: '/user/notifications/', - url: '/session/notifications/', + type: 'GET', + url: '/user/notifications/', dataType: 'json', data: { 'offset': offset, @@ -19072,7 +19071,7 @@ var notifyLayout = function notifyLayout(services) { $notificationDialog.removeClass('loading'); if (offset === 0) { - $notificationsContent.empty(); + $notifications.empty(); } var notifications = data.notifications.notifications; @@ -19084,28 +19083,49 @@ var notifyLayout = function notifyLayout(services) { // var date = notification.created_on_day; var id = 'notif_date_' + date; - var date_cont = (0, _jquery2.default)('#' + id, $notificationsContent); + var date_cont = (0, _jquery2.default)('#' + id, $notifications); + + // new day ? create the container if (date_cont.length === 0) { - $notificationsContent.append('
' + notifications[i].created_on + '
'); - date_cont = (0, _jquery2.default)('#' + id, $notificationsContent); + $notifications.append('
' + notifications[i].created_on + '
'); + date_cont = (0, _jquery2.default)('#' + id, $notifications); } - // write notif - var html = '
' + '
' + '' + '' + '
' + notification.text + ' ' + notification.time + '
' + '
' + '
'; - date_cont.append(html); + + // add pre-formatted notif + date_cont.append(notification.html); } - if (data.notifications.next_page_html) { - $notificationsNavigation.off('click', '.notification__print-action'); - $notificationsNavigation.empty().show().append(data.notifications.next_page_html); - $notificationsNavigation.on('click', '.notification__print-action', function (event) { + // handle "show more" button + // + if (data.notifications.next_offset) { + // update the "more" button + $navigation.off('click', '.notification__print-action'); + $navigation.on('click', '.notification__print-action', function (event) { event.preventDefault(); - var $el = (0, _jquery2.default)(event.currentTarget); - var offset = $el.data('offset'); - print_notifications(offset); + print_notifications(data.notifications.next_offset); }); + $navigation.show(); } else { - $notificationsNavigation.empty().hide(); + // no more ? no button + $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(); + } + */ } }); }; diff --git a/Phraseanet-production-client/dist/production.min.js b/Phraseanet-production-client/dist/production.min.js index 0614845472..476027a690 100644 --- a/Phraseanet-production-client/dist/production.min.js +++ b/Phraseanet-production-client/dist/production.min.js @@ -18905,8 +18905,8 @@ var notifyLayout = function notifyLayout(services) { var $notificationBoxContainer = (0, _jquery2.default)('#notification_box'); var $notificationTrigger = (0, _jquery2.default)('.notification_trigger'); var $notificationDialog = (0, _jquery2.default)('#notifications-dialog'); - var $notificationsContent = null; - var $notificationsNavigation = null; + var $notifications = null; + var $navigation = null; var initialize = function initialize() { /** @@ -19022,12 +19022,12 @@ var notifyLayout = function notifyLayout(services) { // create the dlg div if it does not exists // - if ($notificationDialog.length === 0) { - (0, _jquery2.default)('body').append('
'); - $notificationDialog = (0, _jquery2.default)('#notifications-dialog'); - $notificationsContent = (0, _jquery2.default)('.content', $notificationDialog); - $notificationsNavigation = (0, _jquery2.default)('.navigation', $notificationDialog); - } + // if ($notificationDialog.length === 0) { + // $('body').append('
'); + // $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") // @@ -19053,9 +19053,8 @@ var notifyLayout = function notifyLayout(services) { // $notificationDialog.addClass('loading'); _jquery2.default.ajax({ - type: 'POST', - // url: '/user/notifications/', - url: '/session/notifications/', + type: 'GET', + url: '/user/notifications/', dataType: 'json', data: { 'offset': offset, @@ -19072,7 +19071,7 @@ var notifyLayout = function notifyLayout(services) { $notificationDialog.removeClass('loading'); if (offset === 0) { - $notificationsContent.empty(); + $notifications.empty(); } var notifications = data.notifications.notifications; @@ -19084,28 +19083,49 @@ var notifyLayout = function notifyLayout(services) { // var date = notification.created_on_day; var id = 'notif_date_' + date; - var date_cont = (0, _jquery2.default)('#' + id, $notificationsContent); + var date_cont = (0, _jquery2.default)('#' + id, $notifications); + + // new day ? create the container if (date_cont.length === 0) { - $notificationsContent.append('
' + notifications[i].created_on + '
'); - date_cont = (0, _jquery2.default)('#' + id, $notificationsContent); + $notifications.append('
' + notifications[i].created_on + '
'); + date_cont = (0, _jquery2.default)('#' + id, $notifications); } - // write notif - var html = '
' + '
' + '' + '' + '
' + notification.text + ' ' + notification.time + '
' + '
' + '
'; - date_cont.append(html); + + // add pre-formatted notif + date_cont.append(notification.html); } - if (data.notifications.next_page_html) { - $notificationsNavigation.off('click', '.notification__print-action'); - $notificationsNavigation.empty().show().append(data.notifications.next_page_html); - $notificationsNavigation.on('click', '.notification__print-action', function (event) { + // handle "show more" button + // + if (data.notifications.next_offset) { + // update the "more" button + $navigation.off('click', '.notification__print-action'); + $navigation.on('click', '.notification__print-action', function (event) { event.preventDefault(); - var $el = (0, _jquery2.default)(event.currentTarget); - var offset = $el.data('offset'); - print_notifications(offset); + print_notifications(data.notifications.next_offset); }); + $navigation.show(); } else { - $notificationsNavigation.empty().hide(); + // no more ? no button + $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(); + } + */ } }); }; diff --git a/Phraseanet-production-client/src/components/notify/notifyLayout.js b/Phraseanet-production-client/src/components/notify/notifyLayout.js index ae68c04a1a..b85802760d 100644 --- a/Phraseanet-production-client/src/components/notify/notifyLayout.js +++ b/Phraseanet-production-client/src/components/notify/notifyLayout.js @@ -7,8 +7,8 @@ const notifyLayout = (services) => { const $notificationBoxContainer = $('#notification_box'); const $notificationTrigger = $('.notification_trigger'); let $notificationDialog = $('#notifications-dialog'); - let $notificationsContent = null; - let $notificationsNavigation = null; + let $notifications = $('.notifications', $notificationDialog); + let $navigation = $('.navigation', $notificationDialog); const initialize = () => { /** @@ -127,15 +127,6 @@ const notifyLayout = (services) => { $notificationDialog.dialog('close'); }; - // create the dlg div if it does not exists - // - if ($notificationDialog.length === 0) { - $('body').append('
'); - $notificationDialog = $('#notifications-dialog'); - $notificationsContent = $('.content', $notificationDialog); - $notificationsNavigation = $('.navigation', $notificationDialog); - } - // open the dlg (even if it is already opened when "load more") // $notificationDialog @@ -163,9 +154,8 @@ const notifyLayout = (services) => { // $notificationDialog.addClass('loading'); $.ajax({ - type: 'POST', - // url: '/user/notifications/', - url: '/session/notifications/', + type: 'GET', + url: '/user/notifications/', dataType: 'json', data: { 'offset': offset, @@ -182,7 +172,7 @@ const notifyLayout = (services) => { $notificationDialog.removeClass('loading'); if (offset === 0) { - $notificationsContent.empty(); + $notifications.empty(); } const notifications = data.notifications.notifications; @@ -194,37 +184,34 @@ const notifyLayout = (services) => { // const date = notification.created_on_day; const id = 'notif_date_' + date; - let date_cont = $('#' + id, $notificationsContent); + let date_cont = $('#' + id, $notifications); + + // new day ? create the container if (date_cont.length === 0) { - $notificationsContent.append('
' + notifications[i].created_on + '
'); - date_cont = $('#' + id, $notificationsContent); + $notifications.append('
' + notifications[i].created_on + '
'); + date_cont = $('#' + id, $notifications); } - // write notif - let html = '
' + - '
' + - '' + - '' + - '
' + - notification.text + ' ' + notification.time + '
' + - '
' + - '
'; - date_cont.append(html); + + // add pre-formatted notif + date_cont.append(notification.html); } - if (data.notifications.next_page_html) { - $notificationsNavigation + // handle "show more" button + // + if(data.notifications.next_offset) { + // update the "more" button + $navigation .off('click', '.notification__print-action'); - $notificationsNavigation.empty().show().append(data.notifications.next_page_html); - $notificationsNavigation + $navigation .on('click', '.notification__print-action', function (event) { event.preventDefault(); - let $el = $(event.currentTarget); - let offset = $el.data('offset'); - print_notifications(offset); + print_notifications(data.notifications.next_offset); }); + $navigation.show(); } else { - $notificationsNavigation.empty().hide(); + // no more ? no button + $navigation.hide(); } } }); diff --git a/lib/Alchemy/Phrasea/Controller/Root/SessionController.php b/lib/Alchemy/Phrasea/Controller/Root/SessionController.php index 72e621e364..f0c8d29e05 100644 --- a/lib/Alchemy/Phrasea/Controller/Root/SessionController.php +++ b/lib/Alchemy/Phrasea/Controller/Root/SessionController.php @@ -11,120 +11,15 @@ namespace Alchemy\Phrasea\Controller\Root; use Alchemy\Phrasea\Application\Helper\EntityManagerAware; use Alchemy\Phrasea\Controller\Controller; -use Alchemy\Phrasea\Model\Repositories\BasketRepository; use Alchemy\Phrasea\Model\Repositories\SessionRepository; -use Alchemy\Phrasea\Utilities\Stopwatch; -use eventsmanager_broker; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Session\Session; class SessionController extends Controller { use EntityManagerAware; - /** - * Check things to notify - * - * @param Request $request - * @return JsonResponse - */ - public function getNotifications(Request $request) - { - $stopwatch = new Stopwatch('notif'); - - if (!$request->isXmlHttpRequest()) { - $this->app->abort(400); - } - - $ret = [ - 'status' => 'unknown', - 'message' => '', - 'notifications' => false, - 'notifications_html' => false, - 'unread_basket_ids' => [] - ]; - - $authenticator = $this->getAuthenticator(); - - if (!$authenticator->isAuthenticated()) { - $ret['status'] = 'disconnected'; - - return $this->app->json($ret); - } - - try { - $this->getApplicationBox()->get_connection(); - } - catch (\Exception $e) { - return $this->app->json($ret); - } - - // module id is only used to track apps, its done in SessioManagerSubscriber (parsing url) - /* - if (1 > $moduleId = (int) $request->request->get('module')) { - $ret['message'] = 'Missing or Invalid `module` parameter'; - - return $this->app->json($ret); - } - */ - - $ret['status'] = 'ok'; - - $stopwatch->lap("start"); - - $offset = (int)$request->get('offset', 0); - $limit = (int)$request->get('limit', 10); - $what = (int)$request->get('what', eventsmanager_broker::UNREAD | eventsmanager_broker::READ); - - $notifications = $this->getEventsManager()->get_notifications($offset, $limit, $what, $stopwatch); - - $stopwatch->lap("get_notifications done"); - - $ret['notifications'] = $notifications; - $ret['notifications_html'] = $this->render('prod/notifications.html.twig', [ - 'notifications' => $notifications['notifications'] - ]); - - $stopwatch->lap("render done"); - - $baskets = $this->getBasketRepository()->findUnreadActiveByUser($authenticator->getUser()); - - $stopwatch->lap("baskets::findUnreadActiveByUser done"); - - foreach ($baskets as $basket) { - $ret['unread_basket_ids'][] = $basket->getId(); - } - - if (in_array($this->getSession()->get('phraseanet.message'), ['1', null])) { - if ($this->app['phraseanet.configuration']['main']['maintenance']) { - $ret['message'] .= $this->app->trans('The application is going down for maintenance, please logout.'); - } - - if ($this->getConf()->get(['registry', 'maintenance', 'enabled'], false)) { - $ret['message'] .= strip_tags($this->getConf()->get(['registry', 'maintenance', 'message'])); - } - } - - // return $this->app->json($ret);//, ['Server-Timing' => $stopwatch->getLapsesAsServerTimingHeader()]); - - $stopwatch->lap("fini"); - $stopwatch->stop(); - - $response = new JsonResponse($ret); - // add specific timing debug - $response->headers->set('Server-Timing', $stopwatch->getLapsesAsServerTimingHeader(), false); - $response->setCharset('UTF-8'); - - // add general timing debug - $duration = (microtime(true) - $request->server->get('REQUEST_TIME_FLOAT')) * 1000.0; - $h = '_global;' . 'dur=' . $duration; - $response->headers->set('Server-Timing', $h, false); // false : add header (don't replace) - - return $response; - } - /** * Deletes identified session * @@ -162,33 +57,6 @@ class SessionController extends Controller return $this->app->redirectPath('account_sessions'); } - /** - * @return \eventsmanager_broker - */ - private function getEventsManager() - { - return $this->app['events-manager']; - } - - /** - * @return BasketRepository - */ - private function getBasketRepository() - { - /** @var BasketRepository $ret */ - $ret = $this->getEntityManager()->getRepository('Phraseanet:Basket'); - - return $ret; - } - - /** - * @return Session - */ - private function getSession() - { - return $this->app['session']; - } - /** * @return SessionRepository */ diff --git a/lib/Alchemy/Phrasea/Controller/User/UserNotificationController.php b/lib/Alchemy/Phrasea/Controller/User/UserNotificationController.php index f7e9581208..3892f4ffe9 100644 --- a/lib/Alchemy/Phrasea/Controller/User/UserNotificationController.php +++ b/lib/Alchemy/Phrasea/Controller/User/UserNotificationController.php @@ -9,12 +9,133 @@ */ namespace Alchemy\Phrasea\Controller\User; +use Alchemy\Phrasea\Application\Helper\EntityManagerAware; use Alchemy\Phrasea\Controller\Controller; +use Alchemy\Phrasea\Model\Repositories\BasketRepository; +use Alchemy\Phrasea\Utilities\Stopwatch; +use eventsmanager_broker; +use Exception; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; class UserNotificationController extends Controller { + use EntityManagerAware; + + /** + * Check things to notify + * + * @param Request $request + * @return JsonResponse + */ + public function getNotifications(Request $request) + { + $stopwatch = new Stopwatch('notif'); + + if (!$request->isXmlHttpRequest()) { + $this->app->abort(400); + } + + $ret = [ + 'status' => 'unknown', + 'message' => '', + 'notifications' => [], + 'unread_basket_ids' => [] + ]; + + $authenticator = $this->getAuthenticator(); + + if (!$authenticator->isAuthenticated()) { + $ret['status'] = 'disconnected'; + + return $this->app->json($ret); + } + + try { + $this->getApplicationBox()->get_connection(); + } + catch (Exception $e) { + return $this->app->json($ret); + } + + $ret['status'] = 'ok'; + + $stopwatch->lap("start"); + + // get notifications from "notifications" table + // + + $offset = (int)$request->get('offset', 0); + $limit = (int)$request->get('limit', 10); + $what = (int)$request->get('what', eventsmanager_broker::UNREAD | eventsmanager_broker::READ); + + $notifications = $this->getEventsManager()->get_notifications($offset, $limit, $what, $stopwatch); + + $stopwatch->lap("get_notifications done"); + + // add html to each notif + foreach ($notifications['notifications'] as $k => $v) { + $notifications['notifications'][$k]['html'] = $this->render('prod/notification.html.twig', [ + 'notification' => $v + ] + ); + } + + $ret['notifications'] = $notifications; + + $stopwatch->lap("render done"); + + + // get unread baskets + // + + $baskets = $this->getBasketRepository()->findUnreadActiveByUser($authenticator->getUser()); + + $stopwatch->lap("baskets::findUnreadActiveByUser done"); + + foreach ($baskets as $basket) { + $ret['unread_basket_ids'][] = $basket->getId(); + } + + + // add message about maintenance + // + + if (in_array($this->getSession()->get('phraseanet.message'), ['1', null])) { + if ($this->app['phraseanet.configuration']['main']['maintenance']) { + $ret['message'] .= $this->app->trans('The application is going down for maintenance, please logout.'); + } + + if ($this->getConf()->get(['registry', 'maintenance', 'enabled'], false)) { + $ret['message'] .= strip_tags($this->getConf()->get(['registry', 'maintenance', 'message'])); + } + } + + $stopwatch->lap("end"); + $stopwatch->stop(); + + $response = new JsonResponse($ret); + + // add specific timing debug + $response->headers->set('Server-Timing', $stopwatch->getLapsesAsServerTimingHeader(), false); + $response->setCharset('UTF-8'); + + // add general timing debug + $duration = (microtime(true) - $request->server->get('REQUEST_TIME_FLOAT')) * 1000.0; + $h = '_global;' . 'dur=' . $duration; + $response->headers->set('Server-Timing', $h, false); // false : add header (don't replace) + + return $response; + } + + + + + + + + /** * Set notifications as read * @@ -61,7 +182,7 @@ class UserNotificationController extends Controller */ /** - * @return \eventsmanager_broker + * @return eventsmanager_broker */ /* remove in favor of existing /session/ route private function getEventsManager() @@ -69,4 +190,35 @@ class UserNotificationController extends Controller return $this->app['events-manager']; } */ + + + + /** + * @return eventsmanager_broker + */ + private function getEventsManager() + { + return $this->app['events-manager']; + } + + /** + * @return BasketRepository + */ + private function getBasketRepository() + { + /** @var BasketRepository $ret */ + $ret = $this->getEntityManager()->getRepository('Phraseanet:Basket'); + + return $ret; + } + + /** + * @return Session + */ + private function getSession() + { + return $this->app['session']; + } + + } diff --git a/lib/Alchemy/Phrasea/ControllerProvider/Root/Session.php b/lib/Alchemy/Phrasea/ControllerProvider/Root/Session.php index 63b7b18c1e..fdfa1a389f 100644 --- a/lib/Alchemy/Phrasea/ControllerProvider/Root/Session.php +++ b/lib/Alchemy/Phrasea/ControllerProvider/Root/Session.php @@ -41,10 +41,6 @@ class Session implements ControllerProviderInterface, ServiceProviderInterface { $controllers = $this->createCollection($app); - /** @uses SessionController::getNotifications() */ - $controllers->post('/notifications/', 'controller.session:getNotifications') - ->bind('list_notifications'); - /** @uses SessionController::deleteSession() */ // used in admin/connected_users to kill a session $controller = $controllers->post('/delete/{id}', 'controller.session:deleteSession') diff --git a/lib/Alchemy/Phrasea/ControllerProvider/User/Notifications.php b/lib/Alchemy/Phrasea/ControllerProvider/User/Notifications.php index f12f0f3bd6..e94b29a3d5 100644 --- a/lib/Alchemy/Phrasea/ControllerProvider/User/Notifications.php +++ b/lib/Alchemy/Phrasea/ControllerProvider/User/Notifications.php @@ -11,7 +11,10 @@ namespace Alchemy\Phrasea\ControllerProvider\User; +use Alchemy\Phrasea\Application as PhraseaApplication; +use Alchemy\Phrasea\Controller\User\UserNotificationController; use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait; +use Alchemy\Phrasea\Core\LazyLocator; use Silex\Application; use Silex\ControllerProviderInterface; use Silex\ServiceProviderInterface; @@ -22,12 +25,11 @@ class Notifications implements ControllerProviderInterface, ServiceProviderInter public function register(Application $app) { - /* remove in favor of existing /session/ route - * $app['controller.user.notifications'] = $app->share(function (PhraseaApplication $app) { - return (new UserNotificationController($app)); + return (new UserNotificationController($app)) + ->setEntityManagerLocator(new LazyLocator($app, 'orm.em')) + ; }); - */ } public function boot(Application $app) @@ -47,10 +49,15 @@ class Notifications implements ControllerProviderInterface, ServiceProviderInter $firewall->requireNotGuest(); }); - /* remove in favor of existing /session/ route + /** @uses UserNotificationController::getNotifications() */ + $controllers->get('/', 'controller.user.notifications:getNotifications') +// ->bind('get_notifications') + ; + + /* todo : re-implement "read" route * /** @uses UserNotificationController::listNotifications * / - $controllers->get('/', 'controller.user.notifications:listNotifications') + $controllers->get('/', 'controller.user.notifications:getNotifications') ->bind('get_notifications'); /** @uses UserNotificationController::readNotifications() * / diff --git a/lib/Alchemy/Phrasea/Core/Event/Subscriber/SessionManagerSubscriber.php b/lib/Alchemy/Phrasea/Core/Event/Subscriber/SessionManagerSubscriber.php index e14eaa1afe..15451355b0 100644 --- a/lib/Alchemy/Phrasea/Core/Event/Subscriber/SessionManagerSubscriber.php +++ b/lib/Alchemy/Phrasea/Core/Event/Subscriber/SessionManagerSubscriber.php @@ -70,27 +70,25 @@ class SessionManagerSubscriber implements EventSubscriberInterface return; } - $moduleIName= $this->getModuleName($request->getPathInfo()); + $moduleName= $this->getModuleName($request->getPathInfo()); $moduleId = $this->getModuleId($request->getPathInfo()); - if(is_null($moduleId) && $moduleIName !== "login") { + // "/" and "/login" routes do not keep session alive, nor close session, nor redirect to login + // + if(is_null($moduleName) || $moduleName == "login") { return; } + + // any other route can redirect to login if user is diconnected + // if we are already disconnected (ex. from another window), quit immediately // if (!($this->app->getAuthenticator()->isAuthenticated())) { $this->setDisconnectResponse($event); - return; } - // we must still ignore some "polling" (js) routes - // - if ($this->isJsPollingRoute($moduleId, $request)) { - return; - } - - // ANY route can disconnect the user if idle duration is over + // ANY route can disconnect the user if idle duration is passed // /** @var Session $session */ $session = $this->app['repo.sessions']->find($this->app['session']->get('session_id')); @@ -117,6 +115,12 @@ class SessionManagerSubscriber implements EventSubscriberInterface return; } + // we must still ignore some "polling" (js) routes + // + if ($this->isJsPollingRoute($request)) { + return; + } + // here the route is considered as "user activity" : update session // $entityManager = $this->app['orm.em']; @@ -135,10 +139,8 @@ class SessionManagerSubscriber implements EventSubscriberInterface { $request = $event->getRequest(); - if($this->getModuleName($request->getPathInfo()) !== 'login') { // prevent infinite redirections - $response = $request->isXmlHttpRequest() ? $this->getXmlHttpResponse() : $this->getRedirectResponse($request); - $event->setResponse($response); - } + $response = $request->isXmlHttpRequest() ? $this->getXmlHttpResponse() : $this->getRedirectResponse($request); + $event->setResponse($response); } /** @@ -193,7 +195,7 @@ class SessionManagerSubscriber implements EventSubscriberInterface } /** - * returns true is the route match a "polling" route (databox progressionbar, task manager, notifications, ...) + * returns true is the route match a "polling" route (databox progressionbar, task manager, ...) * polling routes (sent every n seconds with no user action) must not update the session * * the request should contain a "update-session=0" header, but for now we still test hardcoded routes @@ -202,7 +204,7 @@ class SessionManagerSubscriber implements EventSubscriberInterface * @param Request $request * @return bool */ - private function isJsPollingRoute($moduleId, Request $request) + private function isJsPollingRoute(Request $request) { if($request->headers->get('update-session', '1') === '0') { return true; @@ -220,11 +222,6 @@ class SessionManagerSubscriber implements EventSubscriberInterface return true; } - // admin/databox poll to update the indexation progress bar - if(preg_match('#^/.*/notifications/#', $pathInfo)) { - return true; - } - return false; } diff --git a/lib/classes/eventsmanager/broker.php b/lib/classes/eventsmanager/broker.php index fe0747dadc..0b3daef552 100644 --- a/lib/classes/eventsmanager/broker.php +++ b/lib/classes/eventsmanager/broker.php @@ -280,7 +280,7 @@ class eventsmanager_broker $bad_ids = []; // nb : we asked for a "page" of notifs (limit), but since some notifications may be ignored (bad type, bad json, ...) - // the result array may contain less than expected. + // the result array may contain less than expected (but this should not happen). foreach ($rs as $row) { $type = 'eventsmanager_' . $row['type']; if ( ! isset($this->pool_classes[$type])) { @@ -297,10 +297,6 @@ class eventsmanager_broker /** @var eventsmanager_notifyAbstract $obj */ $obj = $this->pool_classes[$type]; $datas = $obj->datas($data, $row['unread']); - // $datas = [ - // 'text' => "blabla" - // 'class' => "" | "relaod_baskets" - // ] if (count($datas) === 0) { $bad_ids[] = $row['id']; @@ -313,13 +309,12 @@ class eventsmanager_broker $notifications[] = array_merge( $datas, [ + 'id' => $row['id'], 'created_on_day' => $created_on->format('Ymd'), 'created_on' => $this->app['date-formatter']->getPrettyString($created_on), 'time' => $this->app['date-formatter']->getTime($created_on), - //, 'icon' => '' 'icon' => $this->pool_classes[$type]->icon_url(), - 'id' => $row['id'], - 'unread' => $row['unread'] + 'unread' => $row['unread'], ] ); } @@ -334,17 +329,16 @@ class eventsmanager_broker } $next_offset = $offset+$limit; - $ret = [ + + return [ 'unread_count' => $unread, 'offset' => $offset, 'limit' => $limit, // 'prev_offset' => $offset === 0 ? null : max(0, $offset-$limit), 'next_offset' => $next_offset < $total ? $next_offset : null, - 'next_page_html' => $next_offset < $total ? '' . $this->app->trans('charger d\'avantages de notifications') . '' : null, 'notifications' => $notifications ]; - return $ret; } /** diff --git a/resources/www/common/js/components/common.js b/resources/www/common/js/components/common.js index 479f5fb4a7..523cdac566 100644 --- a/resources/www/common/js/components/common.js +++ b/resources/www/common/js/components/common.js @@ -114,7 +114,7 @@ var commonModule = (function ($, p4) { }).dialog('open').css({'overflow-x': 'auto', 'overflow-y': 'hidden', 'padding': '0'}); } - function manageSession(data) + function updateNotifications(data) { if (data.status == 'disconnected' || data.status == 'session') { self.location.replace(self.location.href); @@ -122,12 +122,26 @@ var commonModule = (function ($, p4) { // add notification in bar - // fill the pseudo-dropdown with pre-formatted list of notifs (10 unread) + // fill the dropdown with pre-formatted notifs (10 unread) // - var box = $('#notification_box'); - box.empty().append(data.notifications_html); + var $box = $('#notification_box'); + var $box_notifications = $('.notifications', $box); - if (box.is(':visible')) { + $box_notifications.empty(); + if(data.notifications.notifications.length === 0) { + // no notification + $('.show_all', $box).hide(); + $('.no_notifications', $box).show(); + } + else { + $('.no_notifications', $box).hide(); + for (n in data.notifications.notifications) { + $box_notifications.append(data.notifications.notifications[n].html); + } + $('.show_all', $box).show(); + } + + if ($box.is(':visible')) { fix_notification_height(); // duplicated, better call notifyLayout.setBoxHeight(); } @@ -229,7 +243,7 @@ var commonModule = (function ($, p4) { return { showOverlay: showOverlay, hideOverlay: hideOverlay, - manageSession: manageSession + updateNotifications: updateNotifications } })(jQuery, p4); diff --git a/templates/web/common/menubar.html.twig b/templates/web/common/menubar.html.twig index 3b47bc6265..6efabfedad 100644 --- a/templates/web/common/menubar.html.twig +++ b/templates/web/common/menubar.html.twig @@ -280,9 +280,8 @@ {% if app.getAuthenticator().isAuthenticated() and module == "prod" %} - + {% include 'prod/notifications_dropdown.html.twig' %} + {% include 'prod/notifications_dialog.html.twig' %} {% endif %}