feat(web): support desktop notifications, add global inbox polling
Fixes #1234, fixes #3382, fixes #4295pull/287/head
parent
7efcb58b6e
commit
8205acc5d5
|
@ -323,6 +323,7 @@
|
|||
"refreshview_every_20_minutes" = "Every 20 minutes";
|
||||
"refreshview_every_30_minutes" = "Every 30 minutes";
|
||||
"refreshview_once_per_hour" = "Once per hour";
|
||||
"Enable Desktop Notifications" = "Enable Desktop Notifications";
|
||||
|
||||
/* Return receipts */
|
||||
"When I receive a request for a return receipt" = "When I receive a request for a return receipt";
|
||||
|
|
|
@ -115,7 +115,7 @@
|
|||
</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
<md-button class="sg-icon-button" label:aria-label="Get Mail" ng-click="mailbox.selectedFolder.$filter()" >
|
||||
<md-button class="sg-icon-button" label:aria-label="Get Mail" ng-click="mailbox.refresh()" >
|
||||
<md-icon>refresh</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
|
|
|
@ -200,6 +200,17 @@
|
|||
</md-select>
|
||||
</md-input-container>
|
||||
|
||||
<div layout="row" layout-align="start start" ng-if="app.preferences.supportsNotifications()">
|
||||
<md-checkbox flex="20"
|
||||
ng-model="app.preferences.defaults.SOGoDesktopNotifications"
|
||||
ng-true-value="1"
|
||||
ng-false-value="0"
|
||||
ng-change="app.onDesktopNotificationsChange()"
|
||||
label:aria-label="Enable Desktop Notifications">
|
||||
<var:string label:value="Enable Desktop Notifications"/>
|
||||
</md-checkbox>
|
||||
</div>
|
||||
|
||||
<var:if condition="externalAvatarsEnabled">
|
||||
<div layout="row" layout-align="start start">
|
||||
<md-checkbox flex="20"
|
||||
|
|
|
@ -1,153 +0,0 @@
|
|||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @name Alarm
|
||||
* @constructor
|
||||
*/
|
||||
function Alarm() {
|
||||
this.currentAlarm = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name getAlarms
|
||||
* @desc Fetch the list of alarms from the server and use the last one
|
||||
*/
|
||||
Alarm.getAlarms = function() {
|
||||
var _this = this;
|
||||
var now = new Date();
|
||||
var browserTime = Math.floor(now.getTime()/1000);
|
||||
|
||||
this.$$resource.fetch('', 'alarmslist?browserTime=' + browserTime).then(function(data) {
|
||||
|
||||
var alarms = data.alarms.sort(function reverseSortByAlarmTime(a, b) {
|
||||
var x = parseInt(a[2]);
|
||||
var y = parseInt(b[2]);
|
||||
return (y - x);
|
||||
});
|
||||
|
||||
if (alarms.length > 0) {
|
||||
var next = alarms.pop();
|
||||
var now = new Date();
|
||||
var utc = Math.floor(now.getTime()/1000);
|
||||
var url = next[0] + '/' + next[1];
|
||||
var alarmTime = parseInt(next[2]);
|
||||
var delay = alarmTime;
|
||||
if (alarmTime > 0) delay -= utc;
|
||||
var d = new Date(alarmTime*1000);
|
||||
//console.log ("now = " + now.toUTCString());
|
||||
//console.log ("next event " + url + " in " + delay + " seconds (on " + d.toUTCString() + ")");
|
||||
|
||||
var f = angular.bind(_this, Alarm.showAlarm, url);
|
||||
|
||||
if (_this.currentAlarm)
|
||||
_this.$timeout.cancel(_this.currentAlarm);
|
||||
|
||||
_this.currentAlarm = _this.$timeout(f, delay*1000);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @name showAlarm
|
||||
* @desc Show the latest alarm using a toast
|
||||
* @param url The URL of the calendar component for snoozing
|
||||
*/
|
||||
Alarm.showAlarm = function(url) {
|
||||
var _this = this;
|
||||
|
||||
this.$$resource.fetch(url, '?resetAlarm=yes').then(function(data) {
|
||||
_this.$toast.show({
|
||||
position: 'top right',
|
||||
hideDelay: 0,
|
||||
template: [
|
||||
'<md-toast>',
|
||||
' <div class="md-toast-content">',
|
||||
' <div layout="column" layout="start end">',
|
||||
' <p class="sg-padded--top">{{ summary }}</p>',
|
||||
' <div layout="row" layout-align="start center">',
|
||||
' <md-input-container>',
|
||||
' <label style="color: white">{{ "Snooze for " | loc }}</label>',
|
||||
' <md-select ng-model="reminder">',
|
||||
' <md-option value="5">',
|
||||
l('5 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value="10">',
|
||||
l('10 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value="15">',
|
||||
l('15 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value="30">',
|
||||
l('30 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value="45">',
|
||||
l('45 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value="60">',
|
||||
l('1 hour'),
|
||||
' </md-option>',
|
||||
' <md-option value="1440">',
|
||||
l('1 day'),
|
||||
' </md-option>',
|
||||
' </md-select>',
|
||||
' </md-input-container>',
|
||||
' <md-button ng-click="snooze()">',
|
||||
l('Snooze'),
|
||||
' </md-button>',
|
||||
' <md-button ng-click="close()">',
|
||||
l('Close'),
|
||||
' </md-button>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
'</md-toast>'
|
||||
].join(''),
|
||||
locals: {
|
||||
url: url
|
||||
},
|
||||
controller: AlarmController
|
||||
});
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
AlarmController.$inject = ['scope', '$mdToast', 'url'];
|
||||
function AlarmController(scope, $mdToast, url) {
|
||||
scope.summary = data.summary;
|
||||
scope.reminder = '10';
|
||||
scope.close = function() {
|
||||
$mdToast.hide();
|
||||
};
|
||||
scope.snooze = function() {
|
||||
_this.$$resource.fetch(url, 'view?snoozeAlarm=' + scope.reminder);
|
||||
$mdToast.hide();
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @memberof Alarm
|
||||
* @desc The factory we'll register as Alarm in the Angular module SOGo.Common
|
||||
* @ngInject
|
||||
*/
|
||||
AlarmService.$inject = ['$timeout', 'sgSettings', 'Resource', '$mdToast'];
|
||||
function AlarmService($timeout, Settings, Resource, $mdToast) {
|
||||
angular.extend(Alarm, {
|
||||
$timeout: $timeout,
|
||||
$$resource: new Resource(Settings.activeUser('folderURL') + 'Calendar', Settings.activeUser()),
|
||||
$toast: $mdToast
|
||||
});
|
||||
|
||||
return Alarm; // return constructor
|
||||
}
|
||||
|
||||
/* Factory registration in Angular module */
|
||||
angular
|
||||
.module('SOGo.Common')
|
||||
.factory('Alarm', AlarmService);
|
||||
|
||||
})();
|
|
@ -7,8 +7,8 @@
|
|||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
navController.$inject = ['$rootScope', '$scope', '$timeout', '$interval', '$http', '$window', '$mdSidenav', '$mdToast', '$mdMedia', '$log', 'sgConstant', 'sgSettings', 'Resource', 'Alarm'];
|
||||
function navController($rootScope, $scope, $timeout, $interval, $http, $window, $mdSidenav, $mdToast, $mdMedia, $log, sgConstant, sgSettings, Resource, Alarm) {
|
||||
navController.$inject = ['$rootScope', '$scope', '$timeout', '$interval', '$http', '$window', '$mdSidenav', '$mdToast', '$mdMedia', '$log', 'sgConstant', 'sgSettings', 'Resource', 'Preferences'];
|
||||
function navController($rootScope, $scope, $timeout, $interval, $http, $window, $mdSidenav, $mdToast, $mdMedia, $log, sgConstant, sgSettings, Resource, Preferences) {
|
||||
var resource = new Resource(sgSettings.baseURL(), sgSettings.activeUser());
|
||||
|
||||
this.$onInit = function() {
|
||||
|
@ -52,7 +52,12 @@
|
|||
|
||||
if (sgSettings.activeUser('path').calendar) {
|
||||
// Fetch Calendar alarms
|
||||
Alarm.getAlarms();
|
||||
Preferences.getAlarms();
|
||||
}
|
||||
|
||||
if (sgSettings.activeUser('path').mail) {
|
||||
// Poll inbox for new messages
|
||||
Preferences.pollInbox();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -475,7 +475,7 @@ Date.prototype.getDayString = function() {
|
|||
return newString;
|
||||
};
|
||||
|
||||
// MMHH
|
||||
// HH00
|
||||
Date.prototype.getHourString = function() {
|
||||
var newString = this.getHours() + '00';
|
||||
if (newString.length == 3)
|
||||
|
|
|
@ -151,6 +151,11 @@
|
|||
return Mailbox.$query.asc;
|
||||
};
|
||||
|
||||
this.refresh = function () {
|
||||
Preferences.pollInbox();
|
||||
this.selectedFolder.$filter();
|
||||
};
|
||||
|
||||
this.searchMode = function($event) {
|
||||
vm.mode.search = true;
|
||||
focus('search');
|
||||
|
|
|
@ -10,6 +10,12 @@
|
|||
function Preferences() {
|
||||
var _this = this, defaultsElement, settingsElement, data;
|
||||
|
||||
this.nextAlarm = null;
|
||||
this.nextInboxPoll = null;
|
||||
this.currentToast = Preferences.$q.when(true); // Show only one toast at a time (see https://github.com/angular/material/issues/2799)
|
||||
this.lastUid = null;
|
||||
this.notifications = {};
|
||||
|
||||
this.defaults = {};
|
||||
this.settings = {Mail: {}};
|
||||
|
||||
|
@ -197,13 +203,16 @@
|
|||
* @desc The factory we'll use to register with Angular
|
||||
* @returns the Preferences constructor
|
||||
*/
|
||||
Preferences.$factory = ['$document', '$q', '$timeout', '$log', '$mdDateLocale', 'sgSettings', 'Gravatar', 'Resource', 'User', function($document, $q, $timeout, $log, $mdDateLocaleProvider, Settings, Gravatar, Resource, User) {
|
||||
Preferences.$factory = ['$window', '$document', '$q', '$timeout', '$log', '$state', '$mdDateLocale', '$mdToast', 'sgSettings', 'Gravatar', 'Resource', 'User', function($window, $document, $q, $timeout, $log, $state, $mdDateLocaleProvider, $mdToast, Settings, Gravatar, Resource, User) {
|
||||
angular.extend(Preferences, {
|
||||
$window: $window,
|
||||
$document: $document,
|
||||
$q: $q,
|
||||
$timeout: $timeout,
|
||||
$log: $log,
|
||||
$state: $state,
|
||||
$mdDateLocaleProvider: $mdDateLocaleProvider,
|
||||
$toast: $mdToast,
|
||||
$gravatar: Gravatar,
|
||||
$$resource: new Resource(Settings.activeUser('folderURL'), Settings.activeUser()),
|
||||
$resourcesURL: Settings.resourcesURL(),
|
||||
|
@ -283,6 +292,346 @@
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @function supportsNotifications
|
||||
* @memberof Preferences.prototype
|
||||
* @desc Check if the browser supports the Notifications API
|
||||
* @returns true if the browser is compatible
|
||||
* @see {@link https://notifications.spec.whatwg.org/|Notifications API}
|
||||
*/
|
||||
Preferences.prototype.supportsNotifications = function () {
|
||||
if (typeof Notification === 'undefined') {
|
||||
Preferences.$log.warn("Notifications are not available for your browser.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function authorizeNotifications
|
||||
* @memberof Preferences.prototype
|
||||
* @desc Request authorization to send notifications
|
||||
*/
|
||||
Preferences.prototype.authorizeNotifications = function () {
|
||||
if (this.supportsNotifications()) {
|
||||
Notification.requestPermission(function (permission) {
|
||||
return permission;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @function createNotification
|
||||
* @memberof Preferences.prototype
|
||||
* @desc Display a HTML5 notification
|
||||
* @param {string} id - a unique identifier
|
||||
* @param {string} title
|
||||
* @param {object} config - parameters of the notification (body, icon, onClick)
|
||||
*/
|
||||
Preferences.prototype.createNotification = function (id, title, config) {
|
||||
var _this = this,
|
||||
params = _.pick(config, ['body', 'icon']);
|
||||
if (this.supportsNotifications ()) {
|
||||
params.tag = id;
|
||||
params.lang = '';
|
||||
params.dir = 'auto';
|
||||
this.notifications[id] = new Notification(title, params);
|
||||
this.notifications[id].onclick = function () {
|
||||
config.onClick();
|
||||
_this.notifications[id].close();
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @function viewInboxMessage
|
||||
* @memberof Preferences.prototype
|
||||
* @desc Go to the specified message of the main account's inbox
|
||||
* @param {string} uid - the message UID
|
||||
*/
|
||||
Preferences.prototype.viewInboxMessage = function(uid) {
|
||||
if (Preferences.$state.get('mail.account')) {
|
||||
// Currently in Mail module -- view message
|
||||
Preferences.$state.go('mail.account.mailbox.message', { accountId: 0, mailboxId: 'INBOX', messageId: uid });
|
||||
}
|
||||
else {
|
||||
// On a different module -- reload page
|
||||
Preferences.$window.location = Preferences.$$resource.path('Mail', 'view#!/Mail/0/INBOX/' + uid);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @function pollInbox
|
||||
* @memberof Preferences.prototype
|
||||
* @desc Poll server for new messages in main account's inbox, display notifications or toasts
|
||||
*/
|
||||
Preferences.prototype.pollInbox = function() {
|
||||
var _this = this, params;
|
||||
|
||||
params = {
|
||||
sortingAttributes: {
|
||||
sort: 'arrival',
|
||||
asc: 0,
|
||||
noHeaders: 0,
|
||||
dry: 1
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
searchBy: 'flags',
|
||||
searchInput: 'unseen'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
if (this.nextInboxPoll)
|
||||
Preferences.$timeout.cancel(this.nextInboxPoll);
|
||||
|
||||
Preferences.$$resource.post('Mail', '0/folderINBOX/view', params).then(function(data) {
|
||||
var uids = data.uids;
|
||||
var uidHeaderIndex = data.headers[0].indexOf('uid');
|
||||
var fromHeaderIndex = data.headers[0].indexOf('From');
|
||||
var subjectHeaderIndex = data.headers[0].indexOf('Subject');
|
||||
if (data.threaded) {
|
||||
data.uids.splice(0, 1);
|
||||
uids = _.map(data.uids, 0);
|
||||
}
|
||||
if (_this.lastUid) {
|
||||
_.find(uids, function (uid, index) {
|
||||
var headers, id, href, toast;
|
||||
if (uid > _this.lastUid) {
|
||||
// New unseen message
|
||||
Preferences.$log.debug('Show notification for message ' + uid);
|
||||
headers = _.find(data.headers, function(h) {
|
||||
return h[uidHeaderIndex] == uid;
|
||||
});
|
||||
if (_this.defaults.SOGoDesktopNotifications) {
|
||||
id = 'mail-inbox-' + uid;
|
||||
href = Preferences.$state.href('mail.account.mailbox.message', { accountId: 0, mailboxId: 'INBOX', messageId: uid });
|
||||
_this.createNotification(id, headers[subjectHeaderIndex], {
|
||||
body: headers[fromHeaderIndex][0].name || headers[fromHeaderIndex][0].email,
|
||||
icon: '/SOGo.woa/WebServerResources/img/email-256px.png',
|
||||
onClick: function () {
|
||||
_this.viewInboxMessage(uid);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
toast = {
|
||||
template: [
|
||||
'<md-toast role="alert">',
|
||||
' <div class="md-toast-content">',
|
||||
' <div layout="row" layout-align="start center" flex>',
|
||||
' <md-icon class="md-primary md-hue-1">email</md-icon>',
|
||||
' <div class="sg-padded--left">',
|
||||
headers[subjectHeaderIndex],
|
||||
' <div class="sg-hint">',
|
||||
headers[fromHeaderIndex][0].name || headers[fromHeaderIndex][0].email,
|
||||
' </div>',
|
||||
' </div>',
|
||||
' <div flex></div>',
|
||||
' <md-button ng-click="close()">',
|
||||
l('View'),
|
||||
' </md-button>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
'</md-toast>'
|
||||
].join(''),
|
||||
position: 'top right',
|
||||
hideDelay: 5000,
|
||||
controller: toastController
|
||||
};
|
||||
_this.currentToast = _this.currentToast.then(function () {
|
||||
return Preferences.$toast.show(toast)
|
||||
.then(function(response) {
|
||||
if (response === 'ok') {
|
||||
_this.viewInboxMessage(uid);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
return false; // Continue to next unseen message
|
||||
}
|
||||
else {
|
||||
return true; // No more new messages
|
||||
}
|
||||
});
|
||||
if (uids[0] > _this.lastUid) {
|
||||
_this.lastUid = uids[0];
|
||||
}
|
||||
} else {
|
||||
_this.lastUid = uids[0];
|
||||
}
|
||||
}).finally(function () {
|
||||
var refreshViewCheck = _this.defaults.SOGoRefreshViewCheck;
|
||||
if (refreshViewCheck && refreshViewCheck != 'manually')
|
||||
_this.nextInboxPoll = Preferences.$timeout(angular.bind(_this, _this.pollInbox), refreshViewCheck.timeInterval()*1000);
|
||||
});
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
toastController.$inject = ['scope', '$mdToast'];
|
||||
function toastController (scope, $mdToast) {
|
||||
scope.close = function() {
|
||||
$mdToast.hide('ok');
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @function getAlarms
|
||||
* @memberof Preferences.prototype
|
||||
* @desc Fetch the list of alarms from the server and schedule the last one
|
||||
*/
|
||||
Preferences.prototype.getAlarms = function() {
|
||||
var _this = this;
|
||||
var now = new Date();
|
||||
var browserTime = Math.floor(now.getTime()/1000);
|
||||
|
||||
Preferences.$$resource.fetch('Calendar', 'alarmslist?browserTime=' + browserTime).then(function(data) {
|
||||
var alarms = data.alarms.sort(function reverseSortByAlarmTime(a, b) {
|
||||
var x = parseInt(a[2]);
|
||||
var y = parseInt(b[2]);
|
||||
return (y - x);
|
||||
});
|
||||
if (alarms.length > 0) {
|
||||
var next = alarms.pop();
|
||||
var now = new Date();
|
||||
var utc = Math.floor(now.getTime()/1000);
|
||||
var url = next[0] + '/' + next[1];
|
||||
var alarmTime = parseInt(next[2]);
|
||||
var delay = alarmTime;
|
||||
if (alarmTime > 0) delay -= utc;
|
||||
var d = new Date(alarmTime*1000);
|
||||
//console.log ("now = " + now.toUTCString());
|
||||
//console.log ("next event " + url + " in " + delay + " seconds (on " + d.toUTCString() + ")");
|
||||
|
||||
var f = angular.bind(_this, _this.showAlarm, url);
|
||||
|
||||
if (_this.nextAlarm)
|
||||
Preferences.$timeout.cancel(_this.nextAlarm);
|
||||
|
||||
_this.nextAlarm = Preferences.$timeout(f, delay*1000);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @function showAlarm
|
||||
* @memberof Preferences.prototype
|
||||
* @desc Show the latest alarm using a notification and a toast
|
||||
* @param url The URL of the calendar component for snoozing
|
||||
*/
|
||||
Preferences.prototype.showAlarm = function(url) {
|
||||
var _this = this;
|
||||
|
||||
Preferences.$$resource.fetch('Calendar/' + url, '?resetAlarm=yes').then(function(data) {
|
||||
var today = new Date().beginOfDay(),
|
||||
day = data.startDate.split(/T/)[0].asDate(),
|
||||
period = [],
|
||||
id;
|
||||
if (day.getTime() != today.getTime() || data.localizedStartDate != data.localizedEndDate) {
|
||||
period.push(data.localizedStartDate);
|
||||
}
|
||||
if (!data.isAllDay) {
|
||||
period.push(data.localizedStartTime);
|
||||
period.push('-');
|
||||
}
|
||||
if (data.localizedStartDate != data.localizedEndDate) {
|
||||
period.push(data.localizedEndDate);
|
||||
}
|
||||
if (!data.isAllDay) {
|
||||
period.push(data.localizedEndTime);
|
||||
}
|
||||
if (_this.defaults.SOGoDesktopNotifications) {
|
||||
id = 'calendar-' + data.id;
|
||||
_this.createNotification(id, data.summary, {
|
||||
body: period.join(' '),
|
||||
icon: '/SOGo.woa/WebServerResources/img/event-256px.png',
|
||||
onClick: function () {
|
||||
if (Preferences.$state.get('calendars.view')) {
|
||||
// Currently in Calendar module -- go to event's day
|
||||
Preferences.$state.go('calendars.view', { view: 'day', day: day.getDayString()});
|
||||
}
|
||||
else {
|
||||
// On a different module -- reload page
|
||||
Preferences.$window.location = Preferences.$$resource.path('Calendar', 'view#!/calendar/day/' + day.getDayString());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
_this.currentToast = _this.currentToast.then(function () {
|
||||
return Preferences.$toast.show({
|
||||
position: 'top right',
|
||||
hideDelay: 0,
|
||||
template: [
|
||||
'<md-toast>',
|
||||
' <div class="md-toast-content">',
|
||||
' <div layout="column" layout="start end">',
|
||||
' <p class="sg-padded--top">{{ summary }}</p>',
|
||||
' <div layout="row" layout-align="start center">',
|
||||
' <md-input-container>',
|
||||
' <label style="color: white">{{ "Snooze for " | loc }}</label>',
|
||||
' <md-select ng-model="reminder">',
|
||||
' <md-option value="5">',
|
||||
l('5 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value="10">',
|
||||
l('10 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value="15">',
|
||||
l('15 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value="30">',
|
||||
l('30 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value="45">',
|
||||
l('45 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value="60">',
|
||||
l('1 hour'),
|
||||
' </md-option>',
|
||||
' <md-option value="1440">',
|
||||
l('1 day'),
|
||||
' </md-option>',
|
||||
' </md-select>',
|
||||
' </md-input-container>',
|
||||
' <md-button ng-click="snooze()">',
|
||||
l('Snooze'),
|
||||
' </md-button>',
|
||||
' <md-button ng-click="close()">',
|
||||
l('Close'),
|
||||
' </md-button>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
'</md-toast>'
|
||||
].join(''),
|
||||
locals: {
|
||||
url: url
|
||||
},
|
||||
controller: AlarmController
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
AlarmController.$inject = ['scope', 'url'];
|
||||
function AlarmController(scope, url) {
|
||||
scope.summary = data.summary;
|
||||
scope.reminder = '10';
|
||||
scope.close = function() {
|
||||
Preferences.$toast.hide();
|
||||
};
|
||||
scope.snooze = function() {
|
||||
Preferences.$$resource.fetch(url, 'view?snoozeAlarm=' + scope.reminder);
|
||||
Preferences.$toast.hide();
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @function $save
|
||||
* @memberof Preferences.prototype
|
||||
|
|
|
@ -55,6 +55,11 @@
|
|||
});
|
||||
};
|
||||
|
||||
this.onDesktopNotificationsChange = function() {
|
||||
if (this.preferences.defaults.SOGoDesktopNotifications)
|
||||
this.preferences.authorizeNotifications();
|
||||
};
|
||||
|
||||
this.resetContactsCategories = function(form) {
|
||||
this.preferences.defaults.SOGoContactsCategories = $window.defaultContactsCategories;
|
||||
form.$setDirty();
|
||||
|
@ -466,7 +471,9 @@
|
|||
if (this.passwords.newPasswordConfirmation && this.passwords.newPasswordConfirmation.length &&
|
||||
this.passwords.newPassword != this.passwords.newPasswordConfirmation) {
|
||||
form.newPasswordConfirmation.$setValidity('newPasswordMismatch', false);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
form.newPasswordConfirmation.$setValidity('newPasswordMismatch', true);
|
||||
}
|
||||
if (this.passwords.newPassword && this.passwords.newPassword.length > 0 &&
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
CalendarListController.$inject = ['$rootScope', '$scope', '$q', '$timeout', '$state', '$mdDialog', 'sgHotkeys', 'sgFocus', 'Dialog', 'Preferences', 'CalendarSettings', 'Calendar', 'Component', 'Alarm'];
|
||||
function CalendarListController($rootScope, $scope, $q, $timeout, $state, $mdDialog, sgHotkeys, focus, Dialog, Preferences, CalendarSettings, Calendar, Component, Alarm) {
|
||||
CalendarListController.$inject = ['$rootScope', '$scope', '$q', '$timeout', '$state', '$mdDialog', 'sgHotkeys', 'sgFocus', 'Dialog', 'Preferences', 'CalendarSettings', 'Calendar', 'Component'];
|
||||
function CalendarListController($rootScope, $scope, $q, $timeout, $state, $mdDialog, sgHotkeys, focus, Dialog, Preferences, CalendarSettings, Calendar, Component) {
|
||||
var vm = this, hotkeys = [], type, sortLabels;
|
||||
|
||||
sortLabels = {
|
||||
|
@ -263,7 +263,7 @@
|
|||
// Immediately perform the adjustments
|
||||
component.$adjust(params).then(function() {
|
||||
$rootScope.$emit('calendars:list');
|
||||
Alarm.getAlarms();
|
||||
Preferences.getAlarms();
|
||||
}, function(response) {
|
||||
onComponentAdjustError(response, component, params);
|
||||
}).finally(function() {
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
ComponentController.$inject = ['$rootScope', '$scope', '$q', '$mdDialog', 'Calendar', 'Component', 'AddressBook', 'Alarm', 'Account', 'stateComponent'];
|
||||
function ComponentController($rootScope, $scope, $q, $mdDialog, Calendar, Component, AddressBook, Alarm, Account, stateComponent) {
|
||||
ComponentController.$inject = ['$rootScope', '$scope', '$q', '$mdDialog', 'Preferences', 'Calendar', 'Component', 'AddressBook', 'Account', 'stateComponent'];
|
||||
function ComponentController($rootScope, $scope, $q, $mdDialog, Preferences, Calendar, Component, AddressBook, Account, stateComponent) {
|
||||
var vm = this, component;
|
||||
|
||||
this.$onInit = function () {
|
||||
|
@ -119,7 +119,7 @@
|
|||
|
||||
c.$reply().then(function() {
|
||||
$rootScope.$emit('calendars:list');
|
||||
Alarm.getAlarms();
|
||||
Preferences.getAlarms();
|
||||
$mdDialog.hide();
|
||||
});
|
||||
};
|
||||
|
@ -205,8 +205,8 @@
|
|||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
ComponentEditorController.$inject = ['$rootScope', '$scope', '$log', '$timeout', '$window', '$element', '$mdDialog', '$mdToast', 'sgFocus', 'User', 'CalendarSettings', 'Calendar', 'Component', 'Attendees', 'AddressBook', 'Card', 'Alarm', 'Preferences', 'stateComponent'];
|
||||
function ComponentEditorController($rootScope, $scope, $log, $timeout, $window, $element, $mdDialog, $mdToast, focus, User, CalendarSettings, Calendar, Component, Attendees, AddressBook, Card, Alarm, Preferences, stateComponent) {
|
||||
ComponentEditorController.$inject = ['$rootScope', '$scope', '$log', '$timeout', '$window', '$element', '$mdDialog', '$mdToast', 'sgFocus', 'User', 'CalendarSettings', 'Calendar', 'Component', 'Attendees', 'AddressBook', 'Card', 'Preferences', 'stateComponent'];
|
||||
function ComponentEditorController($rootScope, $scope, $log, $timeout, $window, $element, $mdDialog, $mdToast, focus, User, CalendarSettings, Calendar, Component, Attendees, AddressBook, Card, Preferences, stateComponent) {
|
||||
var vm = this, component, oldStartDate, oldEndDate, oldDueDate, dayStartTime, dayEndTime;
|
||||
|
||||
this.$onInit = function () {
|
||||
|
@ -470,7 +470,7 @@
|
|||
this.component.$save(options)
|
||||
.then(function(data) {
|
||||
$rootScope.$emit('calendars:list');
|
||||
Alarm.getAlarms();
|
||||
Preferences.getAlarms();
|
||||
$mdDialog.hide();
|
||||
}, function(response) {
|
||||
if (response.status == CalendarSettings.ConflictHTTPErrorCode &&
|
||||
|
|
Loading…
Reference in New Issue