Expose user's settings and defaults inline

This improves performance by removing two AJAX calls and a lot of
JavaScript promises.
This commit is contained in:
Francis Lachapelle
2017-06-01 13:46:57 -04:00
parent 1fa056bb25
commit 89bfa0c536
22 changed files with 441 additions and 484 deletions
@@ -102,11 +102,9 @@
else
list.splice(sibling, 0, calendar);
this.$Preferences.ready().then(function() {
if (Calendar.$Preferences.settings.Calendar.FoldersOrder)
// Save list order
Calendar.saveFoldersOrder(_.flatMap(Calendar.$findAll(), 'id'));
});
if (Calendar.$Preferences.settings.Calendar.FoldersOrder)
// Save list order
Calendar.saveFoldersOrder(_.flatMap(Calendar.$findAll(), 'id'));
// Refresh list of calendars to fetch links associated to new calendar
Calendar.$reloadAll();
};
@@ -23,23 +23,23 @@
vm.changeView = changeView;
_registerHotkeys(hotkeys);
this.$onInit = function() {
_registerHotkeys(hotkeys);
Preferences.ready().then(function() {
_formatDate(vm.selectedDate);
});
// Refresh current view when the list of calendars is modified
deregisterCalendarsList = $rootScope.$on('calendars:list', updateView);
// Refresh current view when the list of calendars is modified
deregisterCalendarsList = $rootScope.$on('calendars:list', updateView);
$scope.$on('$destroy', function() {
// Destroy event listener when the controller is being deactivated
deregisterCalendarsList();
// Deregister hotkeys
_.forEach(hotkeys, function(key) {
sgHotkeys.deregisterHotkey(key);
$scope.$on('$destroy', function() {
// Destroy event listener when the controller is being deactivated
deregisterCalendarsList();
// Deregister hotkeys
_.forEach(hotkeys, function(key) {
sgHotkeys.deregisterHotkey(key);
});
});
});
};
function _registerHotkeys(keys) {
@@ -8,7 +8,7 @@
*/
CalendarListController.$inject = ['$rootScope', '$scope', '$timeout', '$state', '$mdDialog', 'sgHotkeys', 'sgFocus', 'Dialog', 'Preferences', 'CalendarSettings', 'Calendar', 'Component', 'Alarm'];
function CalendarListController($rootScope, $scope, $timeout, $state, $mdDialog, sgHotkeys, focus, Dialog, Preferences, CalendarSettings, Calendar, Component, Alarm) {
var vm = this, hotkeys = [];
var vm = this, hotkeys = [], type;
vm.component = Component;
vm.componentType = 'events';
@@ -32,32 +32,32 @@
vm.mode = { search: false, multiple: 0 };
_registerHotkeys(hotkeys);
this.$onInit = function() {
_registerHotkeys(hotkeys);
// Select list based on user's settings
Preferences.ready().then(function() {
var type = 'events';
// Select list based on user's settings
type = 'events';
if (Preferences.settings.Calendar.SelectedList == 'tasksListView') {
vm.selectedList = 1;
type = 'tasks';
}
selectComponentType(type, { reload: true }); // fetch events/tasks lists
});
// Refresh current list when the list of calendars is modified
$rootScope.$on('calendars:list', function() {
Component.$filter(vm.componentType, { reload: true });
});
// Update the component being dragged
$rootScope.$on('calendar:dragend', updateComponentFromGhost);
$scope.$on('$destroy', function() {
// Deregister hotkeys
_.forEach(hotkeys, function(key) {
sgHotkeys.deregisterHotkey(key);
// Refresh current list when the list of calendars is modified
$rootScope.$on('calendars:list', function() {
Component.$filter(vm.componentType, { reload: true });
});
});
// Update the component being dragged
$rootScope.$on('calendar:dragend', updateComponentFromGhost);
$scope.$on('$destroy', function() {
// Deregister hotkeys
_.forEach(hotkeys, function(key) {
sgHotkeys.deregisterHotkey(key);
});
});
};
function _registerHotkeys(keys) {
@@ -38,47 +38,47 @@
accept: _sortableAccept
};
Preferences.ready().then(function() {
this.$onInit = function() {
vm.categories = _.map(Preferences.defaults.SOGoCalendarCategories, function(name) {
return { id: name.asCSSIdentifier(),
name: name,
color: Preferences.defaults.SOGoCalendarCategoriesColors[name]
};
});
});
// Dispatch the event named 'calendars:list' when a calendar is activated or deactivated or
// when the color of a calendar is changed
$scope.$watch(
function() {
return _.union(
_.map(Calendar.$calendars, function(o) { return _.pick(o, ['id', 'active', 'color']); }),
_.map(Calendar.$subscriptions, function(o) { return _.pick(o, ['id', 'active', 'color']); }),
_.map(Calendar.$webcalendars, function(o) { return _.pick(o, ['id', 'active', 'color']); })
);
},
function(newList, oldList) {
var commonList, ids, promise;
// Dispatch the event named 'calendars:list' when a calendar is activated or deactivated or
// when the color of a calendar is changed
$scope.$watch(
function() {
return _.union(
_.map(Calendar.$calendars, function(o) { return _.pick(o, ['id', 'active', 'color']); }),
_.map(Calendar.$subscriptions, function(o) { return _.pick(o, ['id', 'active', 'color']); }),
_.map(Calendar.$webcalendars, function(o) { return _.pick(o, ['id', 'active', 'color']); })
);
},
function(newList, oldList) {
var commonList, ids, promise;
// Identify which calendar has changed
commonList = _.intersectionBy(newList, oldList, 'id');
ids = _.map(_.filter(commonList, function(o) {
var oldObject = _.find(oldList, { id: o.id });
return !_.isEqual(o, oldObject);
}), 'id');
promise = Calendar.$q.when();
// Identify which calendar has changed
commonList = _.intersectionBy(newList, oldList, 'id');
ids = _.map(_.filter(commonList, function(o) {
var oldObject = _.find(oldList, { id: o.id });
return !_.isEqual(o, oldObject);
}), 'id');
promise = Calendar.$q.when();
if (ids.length > 0) {
$log.debug(ids.join(', ') + ' changed');
promise = Calendar.saveFoldersActivation(ids);
}
if (ids.length > 0 || commonList.length != newList.length || commonList.length != oldList.length)
promise.then(function() {
$rootScope.$emit('calendars:list');
});
},
true // compare for object equality
);
if (ids.length > 0) {
$log.debug(ids.join(', ') + ' changed');
promise = Calendar.saveFoldersActivation(ids);
}
if (ids.length > 0 || commonList.length != newList.length || commonList.length != oldList.length)
promise.then(function() {
$rootScope.$emit('calendars:list');
});
},
true // compare for object equality
);
};
/**
* Only allow to sort items within the same list.
@@ -52,28 +52,26 @@
$refreshTimeout: null,
$ghost: {}
});
Preferences.ready().then(function() {
// Initialize filter parameters from user's settings
if (Preferences.settings.Calendar.EventsFilterState)
Component.$queryEvents.filterpopup = Preferences.settings.Calendar.EventsFilterState;
if (Preferences.settings.Calendar.TasksFilterState)
Component.$queryTasks.filterpopup = Preferences.settings.Calendar.TasksFilterState;
if (Preferences.settings.Calendar.EventsSortingState) {
Component.$queryEvents.sort = Preferences.settings.Calendar.EventsSortingState[0];
Component.$queryEvents.asc = parseInt(Preferences.settings.Calendar.EventsSortingState[1]);
}
if (Preferences.settings.Calendar.TasksSortingState) {
Component.$queryTasks.sort = Preferences.settings.Calendar.TasksSortingState[0];
Component.$queryTasks.asc = parseInt(Preferences.settings.Calendar.TasksSortingState[1]);
}
Component.$queryTasks.show_completed = parseInt(Preferences.settings.ShowCompletedTasks);
// Initialize categories from user's defaults
Component.$categories = Preferences.defaults.SOGoCalendarCategoriesColors;
// Initialize time format from user's defaults
if (Preferences.defaults.SOGoTimeFormat) {
Component.timeFormat = Preferences.defaults.SOGoTimeFormat;
}
});
// Initialize filter parameters from user's settings
if (Preferences.settings.Calendar.EventsFilterState)
Component.$queryEvents.filterpopup = Preferences.settings.Calendar.EventsFilterState;
if (Preferences.settings.Calendar.TasksFilterState)
Component.$queryTasks.filterpopup = Preferences.settings.Calendar.TasksFilterState;
if (Preferences.settings.Calendar.EventsSortingState) {
Component.$queryEvents.sort = Preferences.settings.Calendar.EventsSortingState[0];
Component.$queryEvents.asc = parseInt(Preferences.settings.Calendar.EventsSortingState[1]);
}
if (Preferences.settings.Calendar.TasksSortingState) {
Component.$queryTasks.sort = Preferences.settings.Calendar.TasksSortingState[0];
Component.$queryTasks.asc = parseInt(Preferences.settings.Calendar.TasksSortingState[1]);
}
Component.$queryTasks.show_completed = parseInt(Preferences.settings.ShowCompletedTasks);
// Initialize categories from user's defaults
Component.$categories = Preferences.defaults.SOGoCalendarCategoriesColors;
// Initialize time format from user's defaults
if (Preferences.defaults.SOGoTimeFormat) {
Component.timeFormat = Preferences.defaults.SOGoTimeFormat;
}
return Component; // return constructor
}];
@@ -124,19 +122,15 @@
* current view.
*/
Component.$startRefreshTimeout = function(type) {
var _this = this;
if (Component.$refreshTimeout)
Component.$timeout.cancel(Component.$refreshTimeout);
Component.$Preferences.ready().then(function() {
// Restart the refresh timer, if needed
var refreshViewCheck = Component.$Preferences.defaults.SOGoRefreshViewCheck;
if (refreshViewCheck && refreshViewCheck != 'manually') {
var f = angular.bind(Component.$rootScope, Component.$rootScope.$emit, 'calendars:list');
Component.$refreshTimeout = Component.$timeout(f, refreshViewCheck.timeInterval()*1000);
}
});
// Restart the refresh timer, if needed
var refreshViewCheck = Component.$Preferences.defaults.SOGoRefreshViewCheck;
if (refreshViewCheck && refreshViewCheck != 'manually') {
var f = angular.bind(Component.$rootScope, Component.$rootScope.$emit, 'calendars:list');
Component.$refreshTimeout = Component.$timeout(f, refreshViewCheck.timeInterval()*1000);
}
};
/**
@@ -166,44 +160,41 @@
queryKey = '$query' + type.capitalize(),
params = {
day: '' + year + (month < 10?'0':'') + month + (day < 10?'0':'') + day,
};
},
futureComponentData,
dirty = false,
otherType;
Component.$startRefreshTimeout(type);
return this.$Preferences.ready().then(function() {
var futureComponentData,
dirty = false,
otherType;
angular.extend(this.$query, params);
angular.extend(_this.$query, params);
if (options) {
_.forEach(_.keys(options), function(key) {
// Query parameters common to events and tasks are compared
dirty |= (_this.$query[key] && options[key] != Component.$query[key]);
if (key == 'reload' && options[key])
dirty = true;
// Update either the common parameters or the type-specific parameters
else if (angular.isDefined(_this.$query[key]))
_this.$query[key] = options[key];
else
_this[queryKey][key] = options[key];
});
}
if (options) {
_.forEach(_.keys(options), function(key) {
// Query parameters common to events and tasks are compared
dirty |= (_this.$query[key] && options[key] != Component.$query[key]);
if (key == 'reload' && options[key])
dirty = true;
// Update either the common parameters or the type-specific parameters
else if (angular.isDefined(_this.$query[key]))
_this.$query[key] = options[key];
else
_this[queryKey][key] = options[key];
});
}
// Perform query with both common and type-specific parameters
futureComponentData = this.$$resource.fetch(null, type + 'list',
angular.extend(this[queryKey], this.$query));
// Perform query with both common and type-specific parameters
futureComponentData = _this.$$resource.fetch(null, type + 'list',
angular.extend(_this[queryKey], _this.$query));
// Invalidate cached results of other type if $query has changed
if (dirty) {
otherType = (type == 'tasks')? '$events' : '$tasks';
delete Component[otherType];
Component.$log.debug('force reload of ' + otherType);
}
// Invalidate cached results of other type if $query has changed
if (dirty) {
otherType = (type == 'tasks')? '$events' : '$tasks';
delete Component[otherType];
Component.$log.debug('force reload of ' + otherType);
}
return _this.$unwrapCollection(type, futureComponentData);
});
return this.$unwrapCollection(type, futureComponentData);
};
/**
@@ -256,40 +247,36 @@
* @returns a promise of a collection of objects describing the events blocks
*/
Component.$eventsBlocksForView = function(view, date) {
var _this = this;
var firstDayOfWeek, viewAction, startDate, endDate, params;
return Component.$Preferences.ready().then(function(data) {
var firstDayOfWeek, viewAction, startDate, endDate, params;
firstDayOfWeek = Component.$Preferences.defaults.SOGoFirstDayOfWeek;
if (view == 'day') {
viewAction = 'dayView';
startDate = endDate = date;
}
else if (view == 'multicolumnday') {
viewAction = 'multicolumndayView';
startDate = endDate = date;
}
else if (view == 'week') {
viewAction = 'weekView';
startDate = date.beginOfWeek(firstDayOfWeek);
endDate = new Date();
endDate.setTime(startDate.getTime());
endDate.addDays(6);
}
else if (view == 'month') {
viewAction = 'monthView';
startDate = date;
startDate.setDate(1);
startDate = startDate.beginOfWeek(firstDayOfWeek);
endDate = new Date();
endDate.setTime(date.getTime());
endDate.setMonth(endDate.getMonth() + 1);
endDate.addDays(-1);
endDate = endDate.endOfWeek(firstDayOfWeek);
}
return _this.$eventsBlocks(viewAction, startDate, endDate);
});
firstDayOfWeek = Component.$Preferences.defaults.SOGoFirstDayOfWeek;
if (view == 'day') {
viewAction = 'dayView';
startDate = endDate = date;
}
else if (view == 'multicolumnday') {
viewAction = 'multicolumndayView';
startDate = endDate = date;
}
else if (view == 'week') {
viewAction = 'weekView';
startDate = date.beginOfWeek(firstDayOfWeek);
endDate = new Date();
endDate.setTime(startDate.getTime());
endDate.addDays(6);
}
else if (view == 'month') {
viewAction = 'monthView';
startDate = date;
startDate.setDate(1);
startDate = startDate.beginOfWeek(firstDayOfWeek);
endDate = new Date();
endDate.setTime(date.getTime());
endDate.setMonth(endDate.getMonth() + 1);
endDate.addDays(-1);
endDate = endDate.endOfWeek(firstDayOfWeek);
}
return this.$eventsBlocks(viewAction, startDate, endDate);
};
/**
@@ -533,12 +520,10 @@
if (this.c_category) {
// c_category is only defined in list mode (when calling $filter)
Component.$Preferences.ready().then(function() {
// Filter out categories for which there's no associated color
_this.categories = _.invokeMap(_.filter(_this.c_category, function(name) {
return Component.$Preferences.defaults.SOGoCalendarCategoriesColors[name];
}), 'asCSSIdentifier');
});
// Filter out categories for which there's no associated color
this.categories = _.invokeMap(_.filter(this.c_category, function(name) {
return Component.$Preferences.defaults.SOGoCalendarCategoriesColors[name];
}), 'asCSSIdentifier');
}
// Parse recurrence rule definition and initialize default values
@@ -591,24 +576,22 @@
if (this.isNew) {
// Set default values
Component.$Preferences.ready().then(function() {
var type = (_this.type == 'appointment')? 'Events' : 'Tasks';
var type = (this.type == 'appointment')? 'Events' : 'Tasks';
// Set default classification
_this.classification = Component.$Preferences.defaults['SOGoCalendar' + type + 'DefaultClassification'].toLowerCase();
// Set default classification
this.classification = Component.$Preferences.defaults['SOGoCalendar' + type + 'DefaultClassification'].toLowerCase();
// Set default alarm
var units = { M: 'MINUTES', H: 'HOURS', D: 'DAYS', W: 'WEEKS' };
var match = /-PT?([0-9]+)([MHDW])/.exec(Component.$Preferences.defaults.SOGoCalendarDefaultReminder);
if (match) {
_this.$hasAlarm = true;
_this.alarm.quantity = parseInt(match[1]);
_this.alarm.unit = units[match[2]];
}
// Set default alarm
var units = { M: 'MINUTES', H: 'HOURS', D: 'DAYS', W: 'WEEKS' };
var match = /-PT?([0-9]+)([MHDW])/.exec(Component.$Preferences.defaults.SOGoCalendarDefaultReminder);
if (match) {
this.$hasAlarm = true;
this.alarm.quantity = parseInt(match[1]);
this.alarm.unit = units[match[2]];
}
// Set notitifications
_this.sendAppointmentNotifications = Component.$Preferences.defaults.SOGoAppointmentSendEMailNotifications;
});
// Set notitifications
this.sendAppointmentNotifications = Component.$Preferences.defaults.SOGoAppointmentSendEMailNotifications;
}
else if (angular.isUndefined(data.$hasAlarm)) {
this.$hasAlarm = angular.isDefined(data.alarm);
@@ -116,26 +116,24 @@
});
if ($location.url().length === 0) {
// Restore user's last view
Preferences.ready().then(function() {
var url = '/calendar/',
view = /(.+)view/.exec(Preferences.settings.Calendar.View);
if (view)
url += view[1];
else
url += 'week';
// Append today's date or next enabled weekday
var now = new Date();
if (Preferences.defaults.SOGoCalendarWeekdays) {
var weekDays = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];
var weekDay = weekDays[now.getDay()];
while (Preferences.defaults.SOGoCalendarWeekdays.indexOf(weekDay) < 0) {
now.addDays(1);
weekDay = weekDays[now.getDay()];
}
var url = '/calendar/',
view = /(.+)view/.exec(Preferences.settings.Calendar.View);
if (view)
url += view[1];
else
url += 'week';
// Append today's date or next enabled weekday
var now = new Date();
if (Preferences.defaults.SOGoCalendarWeekdays) {
var weekDays = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];
var weekDay = weekDays[now.getDay()];
while (Preferences.defaults.SOGoCalendarWeekdays.indexOf(weekDay) < 0) {
now.addDays(1);
weekDay = weekDays[now.getDay()];
}
url += '/' + now.getDayString();
$location.replace().url(url);
});
}
url += '/' + now.getDayString();
$location.replace().url(url);
}
}
@@ -48,17 +48,16 @@
function initView() {
view = new sgScrollView(element, type);
if (type != 'monthly')
if (type != 'monthly') {
// Scroll to the day start hour defined in the user's defaults
Preferences.ready().then(function() {
var time, hourCell, quartersOffset;
if (Preferences.defaults.SOGoDayStartTime) {
time = Preferences.defaults.SOGoDayStartTime.split(':');
hourCell = document.getElementById('hour' + parseInt(time[0]));
quartersOffset = parseInt(time[1]) * view.quarterHeight;
view.element.scrollTop = hourCell.offsetTop + quartersOffset;
}
});
var time, hourCell, quartersOffset;
if (Preferences.defaults.SOGoDayStartTime) {
time = Preferences.defaults.SOGoDayStartTime.split(':');
hourCell = document.getElementById('hour' + parseInt(time[0]));
quartersOffset = parseInt(time[1]) * view.quarterHeight;
view.element.scrollTop = hourCell.offsetTop + quartersOffset;
}
}
// Expose quarter height to the controller
// See sgNowLine directive