2017-09-01 18:35:38 +02:00
|
|
|
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* sgCalendarListItem - A directive that defines the content of a md-list-item for a calendar.
|
|
|
|
* @memberof SOGo.SchedulerUI
|
|
|
|
*/
|
|
|
|
function sgCalendarListItem() {
|
|
|
|
return {
|
|
|
|
restrict: 'C',
|
|
|
|
scope: {},
|
|
|
|
bindToController: {
|
|
|
|
calendar: '=sgCalendar'
|
|
|
|
},
|
|
|
|
template: [
|
|
|
|
'<md-switch ng-model="$ctrl.calendar.active"',
|
|
|
|
' ng-class="$ctrl.calendar.getClassName(\'md-switch\')"',
|
|
|
|
' ng-true-value="1"',
|
|
|
|
' ng-false-value="0"',
|
|
|
|
' aria-label="' + l('Enable') + '"></md-switch>',
|
|
|
|
'<p class="sg-item-name"',
|
|
|
|
' ng-dblclick="$ctrl.editFolder($event)">',
|
|
|
|
' <span ng-bind="$ctrl.calendar.name"></span>',
|
|
|
|
' <md-tooltip md-delay="1000"',
|
|
|
|
' md-autohide="true"',
|
|
|
|
' ng-bind="$ctrl.calendar.name"></md-tooltip>',
|
|
|
|
' <span class="sg-counter-badge ng-hide"',
|
|
|
|
' ng-show="calendar.activeTasks"',
|
|
|
|
' ng-bind="calendar.activeTasks"></span>',
|
|
|
|
'</p>',
|
|
|
|
'<md-input-container class="md-flex ng-hide">',
|
|
|
|
' <input class="sg-item-name" type="text"',
|
|
|
|
' aria-label="' + l('Name of the Calendar') + '"',
|
|
|
|
' ng-blur="$ctrl.saveFolder($event)"',
|
|
|
|
' sg-enter="$ctrl.saveFolder($event)"',
|
|
|
|
' sg-escape="$ctrl.revertEditing()" />',
|
|
|
|
'</md-input-container>',
|
|
|
|
'<md-button class="md-secondary md-icon-button" ',
|
|
|
|
' as-sortable-item-handle="as-sortable-item-handle">',
|
|
|
|
' <md-icon md-colors="::{color: \'accent-400\'}">drag_handle</md-icon>',
|
|
|
|
'</md-button>',
|
|
|
|
'<md-icon class="md-menu sg-list-sortable-hide"',
|
|
|
|
' ng-click="$ctrl.showMenu($event)"',
|
|
|
|
' aria-label="' + l("Options") + '">more_vert</md-icon>'
|
|
|
|
].join(''),
|
|
|
|
controller: 'sgCalendarListItemController',
|
|
|
|
controllerAs: '$ctrl'
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @ngInject
|
|
|
|
*/
|
2017-10-16 16:31:06 +02:00
|
|
|
sgCalendarListItemController.$inject = ['$rootScope', '$scope', '$element', '$mdToast', '$mdPanel', '$mdMedia', '$mdSidenav', 'sgConstant', 'Dialog', 'Calendar'];
|
|
|
|
function sgCalendarListItemController($rootScope, $scope, $element, $mdToast, $mdPanel, $mdMedia, $mdSidenav, sgConstant, Dialog, Calendar) {
|
2017-09-01 18:35:38 +02:00
|
|
|
var $ctrl = this;
|
|
|
|
|
|
|
|
|
|
|
|
this.$onInit = function() {
|
|
|
|
this.editMode = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.$postLink = function() {
|
|
|
|
this.clickableElement = $element.find('p')[0];
|
|
|
|
this.nameElements = this.clickableElement.getElementsByClassName('sg-calendar-name');
|
|
|
|
this.inputContainer = $element.find('md-input-container')[0];
|
|
|
|
this.inputElement = $element.find('input')[0];
|
|
|
|
this.moreOptionsButton = _.last($element.find('md-icon'));
|
|
|
|
this.updateCalendarName();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.updateCalendarName = function() {
|
|
|
|
_.forEach(this.nameElements, function(e) {
|
|
|
|
e.innerHTML = $ctrl.calendar.name;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.editFolder = function($event) {
|
|
|
|
this.editMode = true;
|
|
|
|
this.inputElement.value = this.calendar.name;
|
|
|
|
this.clickableElement.classList.add('ng-hide');
|
|
|
|
this.inputContainer.classList.remove('ng-hide');
|
|
|
|
this.inputElement.focus();
|
|
|
|
this.inputElement.select();
|
|
|
|
if ($event) {
|
|
|
|
$event.stopPropagation();
|
|
|
|
$event.preventDefault();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.saveFolder = function($event) {
|
|
|
|
if (this.inputElement.disabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this.calendar.name = this.inputElement.value;
|
|
|
|
this.inputElement.disabled = true;
|
|
|
|
this.calendar.$rename()
|
|
|
|
.then(function(data) {
|
|
|
|
$ctrl.editMode = false;
|
|
|
|
$ctrl.inputContainer.classList.add('ng-hide');
|
|
|
|
$ctrl.clickableElement.classList.remove('ng-hide');
|
|
|
|
$ctrl.updateCalendarName();
|
|
|
|
})
|
|
|
|
.finally(function() {
|
|
|
|
$ctrl.inputElement.disabled = false;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.revertEditing = function() {
|
|
|
|
this.editMode = false;
|
|
|
|
this.clickableElement.classList.remove('ng-hide');
|
|
|
|
this.inputContainer.classList.add('ng-hide');
|
|
|
|
this.inputElement.value = this.calendar.name;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.confirmDelete = function() {
|
|
|
|
if (this.calendar.isSubscription) {
|
|
|
|
// Unsubscribe without confirmation
|
|
|
|
this.calendar.$delete()
|
|
|
|
.catch(function(data, status) {
|
|
|
|
Dialog.alert(l('An error occured while deleting the calendar "%{0}".', $ctrl.calendar.name),
|
|
|
|
l(data.error));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Dialog.confirm(l('Warning'), l('Are you sure you want to delete the calendar "%{0}"?', this.calendar.name),
|
|
|
|
{ ok: l('Delete') })
|
|
|
|
.then(function() {
|
|
|
|
$ctrl.calendar.$delete()
|
|
|
|
.catch(function(data, status) {
|
|
|
|
Dialog.alert(l('An error occured while deleting the calendar "%{0}".', $ctrl.calendar.name),
|
|
|
|
l(data.error));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.showMenu = function($event) {
|
|
|
|
var panelPosition = $mdPanel.newPanelPosition()
|
|
|
|
.relativeTo(this.moreOptionsButton)
|
|
|
|
.addPanelPosition(
|
|
|
|
$mdPanel.xPosition.ALIGN_START,
|
|
|
|
$mdPanel.yPosition.ALIGN_TOPS
|
|
|
|
);
|
|
|
|
|
|
|
|
var panelAnimation = $mdPanel.newPanelAnimation()
|
|
|
|
.openFrom(this.moreOptionsButton)
|
|
|
|
.duration(100)
|
|
|
|
.withAnimation($mdPanel.animation.FADE);
|
|
|
|
|
|
|
|
var config = {
|
|
|
|
attachTo: angular.element(document.body),
|
|
|
|
locals: {
|
|
|
|
itemCtrl: this,
|
|
|
|
calendar: this.calendar,
|
|
|
|
editFolder: angular.bind(this, this.editFolder),
|
|
|
|
confirmDelete: angular.bind(this, this.confirmDelete)
|
|
|
|
},
|
|
|
|
bindToController: true,
|
|
|
|
controller: MenuController,
|
|
|
|
controllerAs: '$menuCtrl',
|
|
|
|
position: panelPosition,
|
|
|
|
animation: panelAnimation,
|
|
|
|
targetEvent: $event,
|
|
|
|
templateUrl: 'UIxCalendarMenu',
|
|
|
|
trapFocus: true,
|
|
|
|
clickOutsideToClose: true,
|
|
|
|
escapeToClose: true,
|
|
|
|
focusOnOpen: true
|
|
|
|
};
|
|
|
|
|
|
|
|
$mdPanel.open(config)
|
|
|
|
.then(function(panelRef) {
|
|
|
|
// Automatically close panel when clicking inside of it
|
|
|
|
panelRef.panelEl.one('click', function() {
|
|
|
|
panelRef.close();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
MenuController.$inject = ['mdPanelRef', '$mdDialog', 'FileUploader', 'User'];
|
|
|
|
function MenuController(mdPanelRef, $mdDialog, FileUploader, User) {
|
|
|
|
var $menuCtrl = this;
|
|
|
|
|
|
|
|
this.showOnly = function() {
|
|
|
|
_.forEach(Calendar.$findAll(), function(o) {
|
|
|
|
if ($menuCtrl.calendar.id == o.id)
|
|
|
|
o.active = 1;
|
|
|
|
else
|
|
|
|
o.active = 0;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
this.showAll = function() {
|
|
|
|
_.forEach(Calendar.$findAll(), function(o) { o.active = 1; });
|
|
|
|
};
|
|
|
|
|
|
|
|
this.showProperties = function() {
|
|
|
|
var color = this.calendar.color;
|
|
|
|
$mdDialog.show({
|
|
|
|
templateUrl: this.calendar.id + '/properties',
|
|
|
|
controller: PropertiesDialogController,
|
|
|
|
controllerAs: 'properties',
|
|
|
|
clickOutsideToClose: true,
|
|
|
|
escapeToClose: true,
|
|
|
|
locals: {
|
|
|
|
srcCalendar: this.calendar
|
|
|
|
}
|
|
|
|
}).catch(function() {
|
|
|
|
// Restore original color when cancelling or closing the dialog
|
|
|
|
$menuCtrl.calendar.color = color;
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @ngInject
|
|
|
|
*/
|
|
|
|
PropertiesDialogController.$inject = ['$scope', '$mdDialog', 'srcCalendar'];
|
|
|
|
function PropertiesDialogController($scope, $mdDialog, srcCalendar) {
|
|
|
|
var vm = this;
|
|
|
|
|
|
|
|
vm.calendar = new Calendar(srcCalendar.$omit());
|
|
|
|
vm.saveProperties = saveProperties;
|
|
|
|
vm.close = close;
|
|
|
|
|
|
|
|
$scope.$watch(function() { return vm.calendar.color; }, function() {
|
|
|
|
srcCalendar.color = vm.calendar.color;
|
|
|
|
});
|
|
|
|
|
2017-09-18 20:22:29 +02:00
|
|
|
function saveProperties(form) {
|
|
|
|
if (form.$valid) {
|
|
|
|
vm.calendar.$save();
|
|
|
|
// Refresh list instance
|
|
|
|
srcCalendar.init(vm.calendar.$omit());
|
|
|
|
$mdDialog.hide();
|
|
|
|
}
|
2017-09-01 18:35:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function close() {
|
|
|
|
$mdDialog.cancel();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
this.showLinks = function() {
|
|
|
|
$mdDialog.show({
|
|
|
|
parent: angular.element(document.body),
|
|
|
|
clickOutsideToClose: true,
|
|
|
|
escapeToClose: true,
|
|
|
|
templateUrl: this.calendar.id + '/links',
|
|
|
|
controller: LinksDialogController,
|
|
|
|
controllerAs: 'links',
|
|
|
|
locals: {
|
|
|
|
calendar: this.calendar
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @ngInject
|
|
|
|
*/
|
|
|
|
LinksDialogController.$inject = ['$mdDialog', 'calendar'];
|
|
|
|
function LinksDialogController($mdDialog, calendar) {
|
|
|
|
var vm = this;
|
|
|
|
vm.calendar = calendar;
|
|
|
|
vm.close = close;
|
|
|
|
|
|
|
|
function close() {
|
|
|
|
$mdDialog.hide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
this.importCalendar = function() {
|
|
|
|
$mdDialog.show({
|
|
|
|
parent: angular.element(document.body),
|
|
|
|
targetEvent: $event,
|
|
|
|
clickOutsideToClose: true,
|
|
|
|
escapeToClose: true,
|
|
|
|
templateUrl: 'UIxCalendarImportDialog',
|
|
|
|
controller: CalendarImportDialogController,
|
|
|
|
controllerAs: '$CalendarImportDialogController',
|
|
|
|
locals: {
|
|
|
|
folder: this.calendar
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @ngInject
|
|
|
|
*/
|
|
|
|
CalendarImportDialogController.$inject = ['scope', '$mdDialog', 'folder'];
|
|
|
|
function CalendarImportDialogController(scope, $mdDialog, folder) {
|
|
|
|
var vm = this;
|
|
|
|
|
|
|
|
vm.uploader = new FileUploader({
|
|
|
|
url: ApplicationBaseURL + [folder.id, 'import'].join('/'),
|
|
|
|
autoUpload: true,
|
|
|
|
queueLimit: 1,
|
|
|
|
filters: [{ name: filterByExtension, fn: filterByExtension }],
|
|
|
|
onSuccessItem: function(item, response, status, headers) {
|
|
|
|
var msg;
|
|
|
|
|
|
|
|
$mdDialog.hide();
|
|
|
|
|
|
|
|
if (response.imported === 0)
|
|
|
|
msg = l('No event was imported.');
|
|
|
|
else {
|
|
|
|
msg = l('A total of %{0} events were imported in the calendar.', response.imported);
|
|
|
|
$rootScope.$emit('calendars:list');
|
|
|
|
}
|
|
|
|
|
|
|
|
$mdToast.show(
|
|
|
|
$mdToast.simple()
|
|
|
|
.content(msg)
|
|
|
|
.position('top right')
|
|
|
|
.hideDelay(3000));
|
|
|
|
},
|
|
|
|
onErrorItem: function(item, response, status, headers) {
|
|
|
|
$mdToast.show({
|
|
|
|
template: [
|
|
|
|
'<md-toast>',
|
|
|
|
' <div class="md-toast-content">',
|
|
|
|
' <md-icon class="md-warn md-hue-1">error_outline</md-icon>',
|
|
|
|
' <span>' + l('An error occurred while importing calendar.') + '</span>',
|
|
|
|
' </div>',
|
|
|
|
'</md-toast>'
|
|
|
|
].join(''),
|
|
|
|
position: 'top right',
|
|
|
|
hideDelay: 3000
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
vm.close = function() {
|
|
|
|
$mdDialog.hide();
|
|
|
|
};
|
|
|
|
|
|
|
|
function filterByExtension(item) {
|
|
|
|
var isTextFile = item.type.indexOf('text') === 0 ||
|
|
|
|
/\.(ics)$/.test(item.name);
|
|
|
|
|
|
|
|
if (!isTextFile)
|
|
|
|
$mdToast.show({
|
|
|
|
template: [
|
|
|
|
'<md-toast>',
|
|
|
|
' <div class="md-toast-content">',
|
|
|
|
' <md-icon class="md-warn md-hue-1">error_outline</md-icon>',
|
|
|
|
' <span>' + l('Select an iCalendar file (.ics).') + '</span>',
|
|
|
|
' </div>',
|
|
|
|
'</md-toast>'
|
|
|
|
].join(''),
|
|
|
|
position: 'top right',
|
|
|
|
hideDelay: 3000
|
|
|
|
});
|
|
|
|
|
|
|
|
return isTextFile;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
this.share = function() {
|
|
|
|
// Fetch list of ACL users
|
|
|
|
this.calendar.$acl.$users().then(function() {
|
|
|
|
// Show ACL editor
|
|
|
|
$mdDialog.show({
|
|
|
|
templateUrl: $menuCtrl.calendar.id + '/UIxAclEditor', // UI/Templates/UIxAclEditor.wox
|
|
|
|
controller: 'AclController', // from the ng module SOGo.Common
|
|
|
|
controllerAs: 'acl',
|
|
|
|
clickOutsideToClose: true,
|
|
|
|
escapeToClose: true,
|
|
|
|
locals: {
|
|
|
|
usersWithACL: $menuCtrl.calendar.$acl.users,
|
|
|
|
User: User,
|
|
|
|
folder: $menuCtrl.calendar
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
} // MenuController
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
angular
|
|
|
|
.module('SOGo.SchedulerUI')
|
|
|
|
.controller('sgCalendarListItemController', sgCalendarListItemController)
|
|
|
|
.directive('sgCalendarListItem', sgCalendarListItem);
|
|
|
|
})();
|