popup notifications 1
This commit is contained in:
@@ -28,7 +28,7 @@ use \Espo\Core\Exceptions\Error,
|
||||
|
||||
class Activities extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
public static $defaultAction = 'index';
|
||||
public static $defaultAction = 'index';
|
||||
|
||||
public function actionListCalendarEvents($params, $data, $request)
|
||||
{
|
||||
@@ -48,6 +48,13 @@ class Activities extends \Espo\Core\Controllers\Base
|
||||
return $service->getEvents($this->getUser()->id, $from, $to);
|
||||
}
|
||||
|
||||
public function actionPopupNotifications()
|
||||
{
|
||||
$userId = $this->getUser()->id;
|
||||
|
||||
return $this->getService('Activities')->getPopupNotifications($userId);
|
||||
}
|
||||
|
||||
public function actionList($params, $data, $request)
|
||||
{
|
||||
$name = $params['name'];
|
||||
@@ -68,7 +75,7 @@ class Activities extends \Espo\Core\Controllers\Base
|
||||
$scope = null;
|
||||
if (!empty($where) && !empty($where['scope']) && $where['scope'] !== 'false') {
|
||||
$scope = $where['scope'];
|
||||
}
|
||||
}
|
||||
|
||||
$service = $this->getService('Activities');
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"event": {
|
||||
"url": "Activities/action/popupNotifications",
|
||||
"interval": 5,
|
||||
"view": "Crm:Meeting.PopupNotification"
|
||||
}
|
||||
}
|
||||
@@ -430,11 +430,23 @@ class Activities extends \Espo\Core\Services\Base
|
||||
";
|
||||
|
||||
|
||||
$sth = $pdo->prepare($sql);
|
||||
$sth->execute();
|
||||
$sth = $pdo->prepare($sql);
|
||||
$sth->execute();
|
||||
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
public function getPopupNotifications($userId)
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'id' => '43276532423',
|
||||
'entityType' => 'Call',
|
||||
'dateStart' => '2014-12-05 14:10',
|
||||
'name' => 'Test Call'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{{#if closeButton}}
|
||||
<a href="javascript:" class="pull-right close" data-action="close" aria-hidden="true">×</a>
|
||||
{{/if}}
|
||||
<h4>{{header}}</h4>
|
||||
|
||||
|
||||
<div class="cell form-group">
|
||||
<div class="field">
|
||||
{{notificationData.name}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="cell cell-dateStart form-group">
|
||||
<div class="field field-dateStart">
|
||||
{{{dateStart}}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('Crm:Views.Meeting.PopupNotification', 'Views.PopupNotification', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
type: 'event',
|
||||
|
||||
style: 'warning',
|
||||
|
||||
template: 'crm:meeting.popup-notification',
|
||||
|
||||
closeButton: true,
|
||||
|
||||
setup: function () {
|
||||
|
||||
},
|
||||
|
||||
data: function () {
|
||||
return _.extend({
|
||||
header: this.translate(this.notificationData.entityType, 'scopeNames')
|
||||
}, Dep.prototype.data.call(this));
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('Views.Notifications.Badge', 'View', function (Dep) {
|
||||
|
||||
@@ -28,6 +28,8 @@ Espo.define('Views.Notifications.Badge', 'View', function (Dep) {
|
||||
updateFrequency: 10,
|
||||
|
||||
timeout: null,
|
||||
|
||||
popupNotificationsData: null,
|
||||
|
||||
events: {
|
||||
'click a[data-action="showNotifications"]': function (e) {
|
||||
@@ -40,13 +42,48 @@ Espo.define('Views.Notifications.Badge', 'View', function (Dep) {
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
for (var name in this.popoupTimeouts) {
|
||||
clearTimeout(this.popoupTimeouts[name]);
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.lastId = 0;
|
||||
this.shownNotificationIds = [];
|
||||
this.closedNotificationIds = [];
|
||||
this.popoupTimeouts = {};
|
||||
|
||||
delete localStorage['closePopupNotificationId'];
|
||||
|
||||
window.addEventListener('storage', function (e) {
|
||||
if (e.key == 'closePopupNotificationId') {
|
||||
var id = localStorage.getItem('closePopupNotificationId');
|
||||
if (id) {
|
||||
var key = 'popup-' + id;
|
||||
if (this.hasView(key)) {
|
||||
this.markPopupRemoved(id);
|
||||
this.clearView(key);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}.bind(this), false);
|
||||
},
|
||||
|
||||
afterRender: function () {
|
||||
this.$badge = this.$el.find('.notifications-button');
|
||||
this.$icon = this.$el.find('.notifications-button .icon');
|
||||
this.$icon = this.$el.find('.notifications-button .icon');
|
||||
|
||||
this.checkUpdates();
|
||||
|
||||
this.$popupContainer = $('#popup-notifications-container');
|
||||
if (!$(this.$popupContainer).size()) {
|
||||
this.$popupContainer = $('<div>').attr('id', 'popup-notifications-container').addClass('hidden').appendTo('body');
|
||||
}
|
||||
|
||||
var popupNotificationsData = this.popupNotificationsData = this.getMetadata().get('app.popupNotifications') || {};
|
||||
for (var name in popupNotificationsData) {
|
||||
this.checkPopupNotifications(name);
|
||||
}
|
||||
},
|
||||
|
||||
showNotRead: function (count) {
|
||||
@@ -59,7 +96,7 @@ Espo.define('Views.Notifications.Badge', 'View', function (Dep) {
|
||||
this.$badge.attr('title', '');
|
||||
},
|
||||
|
||||
checkUpdates: function () {
|
||||
checkUpdates: function () {
|
||||
$.ajax('Notification/action/notReadCount').done(function (count) {
|
||||
if (count) {
|
||||
this.showNotRead(count);
|
||||
@@ -70,7 +107,65 @@ Espo.define('Views.Notifications.Badge', 'View', function (Dep) {
|
||||
|
||||
this.timeout = setTimeout(function () {
|
||||
this.checkUpdates();
|
||||
}.bind(this), this.updateFrequency * 1000)
|
||||
}.bind(this), this.updateFrequency * 1000);
|
||||
},
|
||||
|
||||
checkPopupNotifications: function (name) {
|
||||
var data = this.popupNotificationsData[name] || {};
|
||||
var url = data.url;
|
||||
var interval = data.interval;
|
||||
|
||||
if (!url || !interval) return;
|
||||
|
||||
$.ajax(url).done(function (list) {
|
||||
list.forEach(function (d) {
|
||||
this.showPopupNotification(name, d);
|
||||
}, this);
|
||||
}.bind(this));
|
||||
|
||||
this.popoupTimeouts[name] = setTimeout(function () {
|
||||
this.checkPopupNotifications(name);
|
||||
}.bind(this), interval * 1000);
|
||||
},
|
||||
|
||||
showPopupNotification: function (name, data) {
|
||||
var view = this.popupNotificationsData[name].view;
|
||||
if (!view) return;
|
||||
|
||||
var id = data.id || null;
|
||||
|
||||
if (id) {
|
||||
id = name + '_' + id;
|
||||
if (~this.shownNotificationIds.indexOf(id)) return;
|
||||
if (~this.closedNotificationIds.indexOf(id)) return;
|
||||
} else {
|
||||
id = this.lastId++;
|
||||
}
|
||||
|
||||
this.shownNotificationIds.push(id);
|
||||
|
||||
this.createView('popup-' + id, view, {
|
||||
notificationData: data,
|
||||
id: id
|
||||
}, function (view) {
|
||||
view.render();
|
||||
this.$popupContainer.removeClass('hidden');
|
||||
this.listenTo(view, 'remove', function () {
|
||||
this.markPopupRemoved(id);
|
||||
localStorage.setItem('closePopupNotificationId', id);
|
||||
}, this);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
markPopupRemoved: function (id) {
|
||||
var index = this.shownNotificationIds.indexOf(id);
|
||||
if (index > -1) {
|
||||
this.shownNotificationIds.splice(index, 1);
|
||||
}
|
||||
if (this.shownNotificationIds.length == 0) {
|
||||
this.$popupContainer.addClass('hidden');
|
||||
}
|
||||
this.closedNotificationIds.push(id);
|
||||
},
|
||||
|
||||
showNotifications: function () {
|
||||
@@ -82,12 +177,12 @@ Espo.define('Views.Notifications.Badge', 'View', function (Dep) {
|
||||
'z-index': 1001,
|
||||
'right': 0,
|
||||
'left': 'auto'
|
||||
});
|
||||
});
|
||||
|
||||
$container.appendTo(this.$el.find('.notifications-panel-container'));
|
||||
|
||||
this.createView('panel', 'Notifications.Panel', {
|
||||
el: '#notifications-panel',
|
||||
el: '#notifications-panel',
|
||||
}, function (view) {
|
||||
view.render();
|
||||
this.listenTo(view, 'all-read', function () {
|
||||
@@ -96,24 +191,24 @@ Espo.define('Views.Notifications.Badge', 'View', function (Dep) {
|
||||
}, this);
|
||||
}.bind(this));
|
||||
|
||||
$document = $(document);
|
||||
$document.on('mouseup.notification', function (e) {
|
||||
if (!$container.is(e.target) && $container.has(e.target).length === 0) {
|
||||
$document = $(document);
|
||||
$document.on('mouseup.notification', function (e) {
|
||||
if (!$container.is(e.target) && $container.has(e.target).length === 0) {
|
||||
this.closeNotifications();
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
closeNotifications: function () {
|
||||
$container = $('#notifications-panel');
|
||||
|
||||
$('#notifications-panel').remove();
|
||||
$('#notifications-panel').remove();
|
||||
$document = $(document);
|
||||
if (this.hasView('panel')) {
|
||||
this.getView('panel').remove();
|
||||
};
|
||||
$document.off('mouseup.notification');
|
||||
$container.remove();
|
||||
$document.off('mouseup.notification');
|
||||
$container.remove();
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('Views.PopupNotification', 'View', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
type: 'default',
|
||||
|
||||
style: 'default',
|
||||
|
||||
closeButton: true,
|
||||
|
||||
init: function () {
|
||||
Dep.prototype.init.call(this);
|
||||
|
||||
var id = this.options.id;
|
||||
var containerSelector = this.containerSelector = '#' + id;
|
||||
|
||||
this.on('render', function () {
|
||||
$(containerSelector).remove();
|
||||
|
||||
var className = 'popup-notification-' + Espo.Utils.toDom(this.type);
|
||||
|
||||
$('<div>').attr('id', id)
|
||||
.addClass('popup-notification')
|
||||
.addClass(className)
|
||||
.addClass('popup-notification-' + this.style)
|
||||
.appendTo('#popup-notifications-container');
|
||||
|
||||
this.setElement(containerSelector);
|
||||
}, this);
|
||||
|
||||
this.on('after:render', function () {
|
||||
this.$el.find('[data-action="close"]').on('click', function () {
|
||||
this.cancel();
|
||||
}.bind(this));
|
||||
}, this);
|
||||
|
||||
this.once('remove', function () {
|
||||
$(containerSelector).remove();
|
||||
});
|
||||
|
||||
this.notificationData = this.options.notificationData;
|
||||
},
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
closeButton: this.closeButton,
|
||||
notificationData: this.notificationData
|
||||
};
|
||||
},
|
||||
|
||||
onCancel: function () {
|
||||
},
|
||||
|
||||
cancel: function () {
|
||||
this.onCancel();
|
||||
this.trigger('cancel');
|
||||
this.remove();
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -677,3 +677,77 @@ img.avatar.avatar-link {
|
||||
.complext-text a {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#popup-notifications-container {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
position: fixed;
|
||||
height: auto;
|
||||
z-index: 1000;
|
||||
|
||||
float: right;
|
||||
}
|
||||
|
||||
.popup-notification {
|
||||
width: 400px;
|
||||
padding: 14px;
|
||||
background-color: @panel-bg;
|
||||
border: 1px solid @main-gray;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.popup-notification a.close{
|
||||
margin-top: -8px;
|
||||
margin-right: -3px;
|
||||
}
|
||||
|
||||
.popup-notification-default {
|
||||
border-color: @gray-light;
|
||||
}
|
||||
|
||||
.popup-notification-danger {
|
||||
border-color: @brand-danger;
|
||||
}
|
||||
|
||||
.popup-notification-warning {
|
||||
border-color: @brand-warning;
|
||||
}
|
||||
|
||||
.popup-notification-primary {
|
||||
border-color: @brand-primary;
|
||||
}
|
||||
|
||||
.popup-notification-success {
|
||||
border-color: @brand-success;
|
||||
}
|
||||
|
||||
.popup-notification-info {
|
||||
border-color: @brand-info;
|
||||
}
|
||||
|
||||
.popup-notification h4 {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.popup-notification-default h4 {
|
||||
color: @gray-light;
|
||||
}
|
||||
|
||||
.popup-notification-danger h4 {
|
||||
color: @brand-danger;
|
||||
}
|
||||
|
||||
.popup-notification-warning h4 {
|
||||
color: @brand-warning;
|
||||
}
|
||||
|
||||
.popup-notification-primary h4 {
|
||||
color: @brand-primary;
|
||||
}
|
||||
|
||||
.popup-notification-success h4 {
|
||||
color: @brand-success;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user