2015-05-06 04:06:13 +02:00
|
|
|
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
|
|
|
|
(function() {
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @ngInject
|
|
|
|
*/
|
2016-09-27 21:19:24 +02:00
|
|
|
CalendarListController.$inject = ['$rootScope', '$scope', '$timeout', '$state', '$mdDialog', 'sgHotkeys', 'sgFocus', 'Dialog', 'Preferences', 'Calendar', 'Component'];
|
|
|
|
function CalendarListController($rootScope, $scope, $timeout, $state, $mdDialog, sgHotkeys, focus, Dialog, Preferences, Calendar, Component) {
|
|
|
|
var vm = this, hotkeys = [];
|
2015-05-06 04:06:13 +02:00
|
|
|
|
|
|
|
vm.component = Component;
|
2015-07-08 20:46:07 +02:00
|
|
|
vm.componentType = 'events';
|
|
|
|
vm.selectedList = 0;
|
2015-05-06 04:06:13 +02:00
|
|
|
vm.selectComponentType = selectComponentType;
|
2015-08-12 22:11:38 +02:00
|
|
|
vm.unselectComponents = unselectComponents;
|
|
|
|
vm.selectAll = selectAll;
|
2016-09-27 21:19:24 +02:00
|
|
|
vm.searchMode = searchMode;
|
2015-09-09 21:18:00 +02:00
|
|
|
vm.toggleComponentSelection = toggleComponentSelection;
|
2015-08-12 22:11:38 +02:00
|
|
|
vm.confirmDeleteSelectedComponents = confirmDeleteSelectedComponents;
|
2015-07-21 14:26:50 +02:00
|
|
|
vm.openEvent = openEvent;
|
|
|
|
vm.openTask = openTask;
|
2015-05-06 04:06:13 +02:00
|
|
|
vm.newComponent = newComponent;
|
2016-03-08 19:20:34 +01:00
|
|
|
vm.filterpopup = filterpopup;
|
2015-07-08 20:46:07 +02:00
|
|
|
vm.filter = filter;
|
2015-07-09 22:35:19 +02:00
|
|
|
vm.filteredBy = filteredBy;
|
|
|
|
vm.sort = sort;
|
|
|
|
vm.sortedBy = sortedBy;
|
2015-11-06 21:12:24 +01:00
|
|
|
vm.reload = reload;
|
2015-07-08 20:46:07 +02:00
|
|
|
vm.cancelSearch = cancelSearch;
|
2016-03-08 19:20:34 +01:00
|
|
|
vm.mode = { search: false, multiple: 0 };
|
2015-07-08 20:46:07 +02:00
|
|
|
|
2016-09-27 21:19:24 +02:00
|
|
|
|
|
|
|
_registerHotkeys(hotkeys);
|
|
|
|
|
2015-07-08 20:46:07 +02:00
|
|
|
// Select list based on user's settings
|
|
|
|
Preferences.ready().then(function() {
|
|
|
|
var type = 'events';
|
|
|
|
if (Preferences.settings.Calendar.SelectedList == 'tasksListView') {
|
|
|
|
vm.selectedList = 1;
|
|
|
|
type = 'tasks';
|
|
|
|
}
|
2016-10-12 17:01:59 +02:00
|
|
|
selectComponentType(type, { reload: true }); // fetch events/tasks lists
|
2015-07-08 20:46:07 +02:00
|
|
|
});
|
2015-05-06 04:06:13 +02:00
|
|
|
|
2015-07-30 17:55:02 +02:00
|
|
|
// Refresh current list when the list of calendars is modified
|
2015-11-06 21:12:24 +01:00
|
|
|
$rootScope.$on('calendars:list', function() {
|
2015-07-30 17:55:02 +02:00
|
|
|
Component.$filter(vm.componentType, { reload: true });
|
|
|
|
});
|
|
|
|
|
2015-11-09 18:15:16 +01:00
|
|
|
// Update the component being dragged
|
2015-11-06 21:12:24 +01:00
|
|
|
$rootScope.$on('calendar:dragend', updateComponentFromGhost);
|
|
|
|
|
2016-09-27 21:19:24 +02:00
|
|
|
$scope.$on('$destroy', function() {
|
|
|
|
// Deregister hotkeys
|
|
|
|
_.forEach(hotkeys, function(key) {
|
|
|
|
sgHotkeys.deregisterHotkey(key);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
function _registerHotkeys(keys) {
|
|
|
|
keys.push(sgHotkeys.createHotkey({
|
|
|
|
key: l('hotkey_search'),
|
|
|
|
description: l('Search'),
|
|
|
|
callback: searchMode
|
|
|
|
}));
|
|
|
|
keys.push(sgHotkeys.createHotkey({
|
|
|
|
key: l('hotkey_create_event'),
|
|
|
|
description: l('Create a new event'),
|
|
|
|
callback: newComponent,
|
|
|
|
args: 'appointment'
|
|
|
|
}));
|
|
|
|
keys.push(sgHotkeys.createHotkey({
|
|
|
|
key: l('hotkey_create_task'),
|
|
|
|
description: l('Create a new task'),
|
|
|
|
callback: newComponent,
|
|
|
|
args: 'task'
|
|
|
|
}));
|
|
|
|
|
|
|
|
// Register the hotkeys
|
|
|
|
_.forEach(keys, function(key) {
|
|
|
|
sgHotkeys.registerHotkey(key);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-05-06 04:06:13 +02:00
|
|
|
// Switch between components tabs
|
|
|
|
function selectComponentType(type, options) {
|
|
|
|
if (options && options.reload || vm.componentType != type) {
|
2015-07-01 21:17:55 +02:00
|
|
|
if (angular.isUndefined(Component['$' + type]))
|
|
|
|
Component.$filter(type);
|
2015-08-12 22:11:38 +02:00
|
|
|
vm.unselectComponents();
|
2015-05-06 04:06:13 +02:00
|
|
|
vm.componentType = type;
|
2015-08-07 20:13:27 +02:00
|
|
|
Component.saveSelectedList(type);
|
2015-05-06 04:06:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-12 22:11:38 +02:00
|
|
|
function unselectComponents() {
|
2016-03-08 19:20:34 +01:00
|
|
|
_.forEach(Component['$' + vm.componentType], function(component) {
|
|
|
|
component.selected = false;
|
|
|
|
});
|
|
|
|
vm.mode.multiple = 0;
|
2015-08-12 22:11:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function selectAll() {
|
2016-03-03 19:38:54 +01:00
|
|
|
_.forEach(Component['$' + vm.componentType], function(component) {
|
2015-08-12 22:11:38 +02:00
|
|
|
component.selected = true;
|
|
|
|
});
|
2016-03-08 19:20:34 +01:00
|
|
|
vm.mode.multiple = Component['$' + vm.componentType].length;
|
2015-08-12 22:11:38 +02:00
|
|
|
}
|
|
|
|
|
2015-09-09 21:18:00 +02:00
|
|
|
function toggleComponentSelection($event, component) {
|
|
|
|
component.selected = !component.selected;
|
2016-03-08 19:20:34 +01:00
|
|
|
vm.mode.multiple += component.selected? 1 : -1;
|
2015-09-09 21:18:00 +02:00
|
|
|
$event.preventDefault();
|
|
|
|
$event.stopPropagation();
|
|
|
|
}
|
|
|
|
|
2016-09-27 21:19:24 +02:00
|
|
|
function searchMode() {
|
|
|
|
vm.mode.search = true;
|
|
|
|
focus('search');
|
|
|
|
}
|
|
|
|
|
2015-08-12 22:11:38 +02:00
|
|
|
function confirmDeleteSelectedComponents() {
|
|
|
|
Dialog.confirm(l('Warning'),
|
2016-02-10 16:52:46 +01:00
|
|
|
l('Are you sure you want to delete the selected components?'),
|
|
|
|
{ ok: l('Delete') })
|
2015-08-12 22:11:38 +02:00
|
|
|
.then(function() {
|
|
|
|
// User confirmed the deletion
|
2016-02-11 15:33:58 +01:00
|
|
|
var components = _.filter(Component['$' + vm.componentType], function(component) {
|
|
|
|
return component.selected;
|
|
|
|
});
|
|
|
|
Calendar.$deleteComponents(components).then(function() {
|
2016-07-20 17:07:57 +02:00
|
|
|
vm.mode.multiple = 0;
|
2016-02-11 15:33:58 +01:00
|
|
|
$rootScope.$emit('calendars:list');
|
|
|
|
});
|
2015-08-12 22:11:38 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-07-21 14:26:50 +02:00
|
|
|
function openEvent($event, event) {
|
2015-11-26 18:04:52 +01:00
|
|
|
openComponent($event, event, 'appointment');
|
2015-07-21 14:26:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function openTask($event, task) {
|
2015-11-26 18:04:52 +01:00
|
|
|
openComponent($event, task, 'task');
|
2015-07-21 14:26:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function openComponent($event, component, type) {
|
2015-11-26 18:04:52 +01:00
|
|
|
if (component.viewable) {
|
|
|
|
// UI/Templates/SchedulerUI/UIxAppointmentViewTemplate.wox or
|
|
|
|
// UI/Templates/SchedulerUI/UIxTaskViewTemplate.wox
|
|
|
|
var templateUrl = 'UIx' + type.capitalize() + 'ViewTemplate';
|
|
|
|
$mdDialog.show({
|
|
|
|
parent: angular.element(document.body),
|
|
|
|
targetEvent: $event,
|
|
|
|
clickOutsideToClose: true,
|
|
|
|
escapeToClose: true,
|
|
|
|
templateUrl: templateUrl,
|
|
|
|
controller: 'ComponentController',
|
|
|
|
controllerAs: 'editor',
|
|
|
|
locals: {
|
|
|
|
stateComponent: component
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2015-07-21 14:26:50 +02:00
|
|
|
}
|
|
|
|
|
2016-06-10 22:50:21 +02:00
|
|
|
function newComponent($event, type, baseComponent) {
|
|
|
|
var component;
|
2015-05-06 04:06:13 +02:00
|
|
|
|
2015-11-09 18:15:16 +01:00
|
|
|
if (baseComponent) {
|
2015-11-06 21:12:24 +01:00
|
|
|
component = baseComponent;
|
2015-11-09 18:15:16 +01:00
|
|
|
}
|
|
|
|
else {
|
2015-12-14 21:04:31 +01:00
|
|
|
component = new Component({ pid: Calendar.$defaultCalendar(), type: type });
|
2015-11-09 18:15:16 +01:00
|
|
|
}
|
2015-05-06 04:06:13 +02:00
|
|
|
|
2015-07-21 14:26:50 +02:00
|
|
|
// UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox or
|
|
|
|
// UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox
|
|
|
|
var templateUrl = 'UIx' + type.capitalize() + 'EditorTemplate';
|
2015-11-06 21:12:24 +01:00
|
|
|
return $mdDialog.show({
|
2015-07-21 14:26:50 +02:00
|
|
|
parent: angular.element(document.body),
|
|
|
|
targetEvent: $event,
|
|
|
|
clickOutsideToClose: true,
|
|
|
|
escapeToClose: true,
|
|
|
|
templateUrl: templateUrl,
|
|
|
|
controller: 'ComponentEditorController',
|
|
|
|
controllerAs: 'editor',
|
|
|
|
locals: {
|
|
|
|
stateComponent: component
|
|
|
|
}
|
|
|
|
});
|
2015-05-06 04:06:13 +02:00
|
|
|
}
|
|
|
|
|
2015-11-06 21:12:24 +01:00
|
|
|
// Adjust component or create new component through drag'n'drop
|
|
|
|
function updateComponentFromGhost($event) {
|
2015-12-16 04:55:02 +01:00
|
|
|
var component, pointerHandler, coordinates, delta, params, calendarNumber, activeCalendars;
|
2015-11-06 21:12:24 +01:00
|
|
|
|
|
|
|
component = Component.$ghost.component;
|
|
|
|
pointerHandler = Component.$ghost.pointerHandler;
|
|
|
|
|
|
|
|
if (component.isNew) {
|
|
|
|
coordinates = pointerHandler.currentEventCoordinates;
|
2016-02-03 20:37:53 +01:00
|
|
|
component.summary = '';
|
2015-11-20 21:36:24 +01:00
|
|
|
if (component.isAllDay)
|
|
|
|
coordinates.duration -= 96;
|
2015-11-06 21:12:24 +01:00
|
|
|
component.setDelta(coordinates.duration * 15);
|
2016-06-10 22:50:21 +02:00
|
|
|
newComponent(null, 'appointment', component).finally(function() {
|
2015-11-06 21:12:24 +01:00
|
|
|
$timeout(function() {
|
2016-02-15 21:58:58 +01:00
|
|
|
Component.$resetGhost();
|
2015-11-06 21:12:24 +01:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
delta = pointerHandler.currentEventCoordinates.getDelta(pointerHandler.originalEventCoordinates);
|
|
|
|
params = {
|
|
|
|
days: delta.dayNumber,
|
|
|
|
start: delta.start * 15,
|
|
|
|
duration: delta.duration * 15
|
|
|
|
};
|
2015-12-16 04:55:02 +01:00
|
|
|
if (pointerHandler.originalCalendar && delta.dayNumber !== 0) {
|
|
|
|
// The day number actually represents the destination calendar among the active calendars
|
|
|
|
calendarNumber = pointerHandler.currentEventCoordinates.dayNumber;
|
|
|
|
activeCalendars = _.filter(Calendar.$findAll(), { active: 1 });
|
|
|
|
params.destination = activeCalendars[calendarNumber].id;
|
|
|
|
params.days = 0;
|
|
|
|
}
|
2015-11-06 21:12:24 +01:00
|
|
|
if (component.isException || !component.occurrenceId)
|
|
|
|
// Component is an exception to a recurrence or is not recurrent;
|
|
|
|
// Immediately perform the adjustments
|
|
|
|
component.$adjust(params).then(function() {
|
|
|
|
$rootScope.$emit('calendars:list');
|
2016-02-15 21:58:58 +01:00
|
|
|
}, function(response) {
|
|
|
|
onComponentAdjustError(response, component, params);
|
|
|
|
}).finally(function() {
|
2015-11-06 21:12:24 +01:00
|
|
|
$timeout(function() {
|
2016-02-15 21:58:58 +01:00
|
|
|
Component.$resetGhost();
|
2015-11-06 21:12:24 +01:00
|
|
|
});
|
|
|
|
});
|
|
|
|
else if (component.occurrenceId) {
|
|
|
|
$mdDialog.show({
|
|
|
|
clickOutsideToClose: true,
|
|
|
|
escapeToClose: true,
|
|
|
|
locals: {
|
|
|
|
component: component,
|
|
|
|
params: params
|
|
|
|
},
|
|
|
|
template: [
|
2016-02-15 21:58:58 +01:00
|
|
|
'<md-dialog flex="50" sm-flex="80" xs-flex="90">',
|
2015-11-06 21:12:24 +01:00
|
|
|
' <md-dialog-content class="md-dialog-content">',
|
|
|
|
' <p>' + l('editRepeatingItem') + '</p>',
|
|
|
|
' </md-dialog-content>',
|
2015-11-27 17:58:14 +01:00
|
|
|
' <md-dialog-actions>',
|
2015-11-06 21:12:24 +01:00
|
|
|
' <md-button ng-click="updateThisOccurrence()">' + l('button_thisOccurrenceOnly') + '</md-button>',
|
|
|
|
' <md-button ng-click="updateAllOccurrences()">' + l('button_allOccurrences') + '</md-button>',
|
2015-11-27 17:58:14 +01:00
|
|
|
' </md-dialog-actions>',
|
2015-11-06 21:12:24 +01:00
|
|
|
'</md-dialog>'
|
|
|
|
].join(''),
|
|
|
|
controller: RecurrentComponentDialogController
|
|
|
|
}).then(function() {
|
|
|
|
$rootScope.$emit('calendars:list');
|
|
|
|
}).finally(function() {
|
|
|
|
$timeout(function() {
|
2016-02-15 21:58:58 +01:00
|
|
|
Component.$resetGhost();
|
2015-11-06 21:12:24 +01:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @ngInject
|
|
|
|
*/
|
|
|
|
RecurrentComponentDialogController.$inject = ['$scope', '$mdDialog', 'component', 'params'];
|
|
|
|
function RecurrentComponentDialogController($scope, $mdDialog, component, params) {
|
|
|
|
$scope.updateThisOccurrence = function() {
|
2016-02-15 21:58:58 +01:00
|
|
|
component.$adjust(params).then($mdDialog.hide, function(response) {
|
|
|
|
$mdDialog.cancel().then(function() {
|
|
|
|
onComponentAdjustError(response, component, params);
|
|
|
|
});
|
|
|
|
});
|
2015-11-06 21:12:24 +01:00
|
|
|
};
|
|
|
|
$scope.updateAllOccurrences = function() {
|
|
|
|
delete component.occurrenceId;
|
2016-02-15 21:58:58 +01:00
|
|
|
component.$adjust(params).then($mdDialog.hide, function(response) {
|
|
|
|
$mdDialog.cancel().then(function() {
|
|
|
|
onComponentAdjustError(response, component, params);
|
|
|
|
});
|
|
|
|
});
|
2015-11-06 21:12:24 +01:00
|
|
|
};
|
|
|
|
}
|
2016-02-15 21:58:58 +01:00
|
|
|
|
|
|
|
function onComponentAdjustError(response, component, params) {
|
|
|
|
if (response.status == 403 &&
|
|
|
|
response.data && response.data.message && angular.isObject(response.data.message)) {
|
|
|
|
$mdDialog.show({
|
|
|
|
parent: angular.element(document.body),
|
|
|
|
clickOutsideToClose: false,
|
|
|
|
escapeToClose: false,
|
|
|
|
templateUrl: 'UIxAttendeeConflictDialog',
|
|
|
|
controller: AttendeeConflictDialogController,
|
|
|
|
controllerAs: '$AttendeeConflictDialogController',
|
|
|
|
locals: {
|
|
|
|
component: component,
|
|
|
|
params: params,
|
|
|
|
conflictError: response.data.message
|
|
|
|
}
|
|
|
|
}).then(function() {
|
|
|
|
$rootScope.$emit('calendars:list');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @ngInject
|
|
|
|
*/
|
|
|
|
AttendeeConflictDialogController.$inject = ['$scope', '$mdDialog', 'component', 'params', 'conflictError'];
|
|
|
|
function AttendeeConflictDialogController($scope, $mdDialog, component, params, conflictError) {
|
|
|
|
var vm = this;
|
|
|
|
|
|
|
|
vm.conflictError = conflictError;
|
|
|
|
vm.cancel = $mdDialog.cancel;
|
|
|
|
vm.save = save;
|
|
|
|
|
|
|
|
function save() {
|
|
|
|
component.$adjust(angular.extend({ ignoreConflicts: true }, params)).then($mdDialog.hide);
|
|
|
|
}
|
|
|
|
}
|
2015-11-06 21:12:24 +01:00
|
|
|
}
|
|
|
|
|
2016-03-08 19:20:34 +01:00
|
|
|
function filterpopup() {
|
|
|
|
return Component['$query' + vm.componentType.capitalize()].filterpopup;
|
|
|
|
}
|
|
|
|
|
2015-07-08 20:46:07 +02:00
|
|
|
function filter(filterpopup) {
|
2015-07-16 22:29:00 +02:00
|
|
|
Component.$filter(vm.componentType, { filterpopup: filterpopup });
|
2015-07-09 22:35:19 +02:00
|
|
|
}
|
2015-07-08 20:46:07 +02:00
|
|
|
|
2015-07-09 22:35:19 +02:00
|
|
|
function filteredBy(filterpopup) {
|
|
|
|
return Component['$query' + vm.componentType.capitalize()].filterpopup == filterpopup;
|
|
|
|
}
|
|
|
|
|
|
|
|
function sort(field) {
|
|
|
|
Component.$filter(vm.componentType, { sort: field });
|
|
|
|
}
|
|
|
|
|
|
|
|
function sortedBy(field) {
|
|
|
|
return Component['$query' + vm.componentType.capitalize()].sort == field;
|
2015-07-08 20:46:07 +02:00
|
|
|
}
|
|
|
|
|
2015-11-06 21:12:24 +01:00
|
|
|
function reload() {
|
2016-05-13 21:50:24 +02:00
|
|
|
Calendar.reloadWebCalendars().finally(function() {
|
|
|
|
$rootScope.$emit('calendars:list');
|
|
|
|
});
|
2015-11-06 21:12:24 +01:00
|
|
|
}
|
|
|
|
|
2015-07-08 20:46:07 +02:00
|
|
|
function cancelSearch() {
|
|
|
|
vm.mode.search = false;
|
2015-07-09 22:35:19 +02:00
|
|
|
Component.$filter(vm.componentType, { value: '' });
|
2015-07-08 20:46:07 +02:00
|
|
|
}
|
2015-05-06 04:06:13 +02:00
|
|
|
}
|
2016-09-27 21:19:24 +02:00
|
|
|
|
2015-05-06 04:06:13 +02:00
|
|
|
angular
|
2015-07-29 17:47:01 +02:00
|
|
|
.module('SOGo.SchedulerUI')
|
2015-05-06 04:06:13 +02:00
|
|
|
.controller('CalendarListController', CalendarListController);
|
|
|
|
})();
|