(js) New sgCalendarListItem component

pull/218/merge
Francis Lachapelle 2017-09-01 12:35:38 -04:00
parent 84edeb85cd
commit 02cbe23e78
3 changed files with 484 additions and 470 deletions

View File

@ -43,7 +43,7 @@
<!-- User's calendars -->
<section>
<md-subheader class="sg-md-subheader--with-secondary-icon"
md-colors="::{background: 'default-background-300'}">
md-colors="::{color: 'default-background-700', background: 'default-background-300'}">
<div layout="row" layout-align="space-between center">
<span><var:string label:value="Calendars"/></span>
<md-button class="sg-icon-button"
@ -55,99 +55,19 @@
</md-subheader>
<md-list ng-model="app.service.$calendars"
as-sortable="app.sortableCalendars" is-disabled="!app.sortableMode">
<md-list-item ng-repeat="calendar in app.service.$calendars | filter:app.filter"
as-sortable-item="as-sortable-item">
<md-switch ng-model="calendar.active"
ng-class="calendar.getClassName('md-switch')"
ng-true-value="1"
ng-false-value="0"
label:aria-label="Enable"><!-- enable --></md-switch>
<p class="sg-item-name"
ng-dblclick="app.editFolder(calendar)"
ng-show="app.editMode != calendar.id">
<span ng-bind="calendar.name"><!-- name --></span>
<md-tooltip md-delay="1000" md-autohide="true" ng-bind="calendar.name"><!-- tooltip --></md-tooltip>
<span class="sg-counter-badge" ng-show="calendar.activeTasks" ng-bind="calendar.activeTasks"><!-- active tasks count --></span>
</p>
<md-input-container class="md-flex"
ng-show="app.editMode == calendar.id">
<input class="sg-item-name" type="text"
label:aria-label="Name of the Calendar"
ng-model="calendar.name"
ng-blur="app.renameFolder(calendar)"
sg-focus-on="calendarName_{{::calendar.id}}"
sg-enter="app.renameFolder(calendar)"
sg-escape="app.revertEditing(calendar)"/>
</md-input-container>
<md-button class="md-secondary md-icon-button" md-no-ink="md-no-ink"
as-sortable-item-handle="as-sortable-item-handle">
<md-icon md-colors="::{color: 'accent-400'}">drag_handle</md-icon>
</md-button>
<md-menu class="md-secondary sg-list-sortable-hide" label:aria-label="Options">
<md-button class="md-icon-button" label:aria-label="Options"
ng-click="$mdMenu.open()"
md-menu-origin="md-menu-origin">
<md-icon>more_vert</md-icon>
</md-button>
<md-menu-content width="2">
<md-menu-item>
<md-button ng-click="app.showOnly(calendar)">
<var:string label:value="Show Only This Calendar"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button ng-click="app.showAll()">
<var:string label:value="Show All Calendars"/>
</md-button>
</md-menu-item>
<md-menu-divider><!-- divider --></md-menu-divider>
<md-menu-item>
<md-button ng-click="app.showProperties(calendar)">
<var:string label:value="Properties"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button type="button" ng-click="app.editFolder(calendar)">
<var:string label:value="Rename"/>
</md-button>
</md-menu-item>
<md-menu-item ng-show="calendar.id != 'personal'">
<md-button ng-click="app.confirmDelete(calendar)">
<var:string label:value="Delete"/>
</md-button>
</md-menu-item>
<md-menu-divider><!-- divider --></md-menu-divider>
<md-menu-item>
<md-button ng-click="app.showLinks(calendar)">
<var:string label:value="Links to this Calendar"/>
</md-button>
</md-menu-item>
<md-menu-divider><!-- divider --></md-menu-divider>
<md-menu-item>
<md-button ng-click="app.importCalendar($event, calendar)">
<var:string label:value="Import"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button ng-click="calendar.export()">
<var:string label:value="Export"/>
</md-button>
</md-menu-item>
<md-menu-divider><!-- divider --></md-menu-divider>
<md-menu-item>
<md-button ng-click="app.share(calendar)">
<var:string label:value="Sharing..."/>
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
<md-list-item
class="sg-calendar-list-item"
ng-repeat="calendar in app.service.$calendars | filter:app.filter"
as-sortable-item="as-sortable-item"
sg-calendar="calendar">
<!-- sgCalendarListItem directive -->
</md-list-item>
</md-list>
</section>
<!-- Subscriptions -->
<section>
<md-subheader class="sg-md-subheader--with-secondary-icon"
md-colors="::{background: 'default-background-300'}">
md-colors="::{color: 'default-background-700', background: 'default-background-300'}">
<div layout="row" layout-align="space-between center">
<span><var:string label:value="Subscriptions"/></span>
<md-button class="sg-icon-button"
@ -160,85 +80,22 @@
</md-subheader>
<md-list ng-model="app.service.$subscriptions"
as-sortable="app.sortableCalendars" is-disabled="!app.sortableMode">
<md-list-item ng-repeat="calendar in app.service.$subscriptions | filter:app.filter"
as-sortable-item="as-sortable-item">
<md-switch ng-model="calendar.active"
ng-class="calendar.getClassName('md-switch')"
ng-true-value="1"
ng-false-value="0"
label:aria-label="Enable"><!-- enable --></md-switch>
<p class="sg-item-name"
ng-dblclick="app.editFolder(calendar)"
ng-show="app.editMode != calendar.id">
<span ng-bind="calendar.name"><!-- name --></span>
<md-tooltip md-delay="1000" md-autohide="true" ng-bind="calendar.name"><!-- tooltip --></md-tooltip>
<span class="sg-counter-badge" ng-show="calendar.activeTasks" ng-bind="calendar.activeTasks"><!-- active tasks count --></span>
</p>
<md-input-container class="md-flex"
ng-show="app.editMode == calendar.id">
<input class="sg-item-name" type="text"
label:aria-label="Name of the Calendar"
ng-model="calendar.name"
ng-blur="app.renameFolder(calendar)"
sg-focus-on="calendarName_{{::calendar.id}}"
sg-enter="app.renameFolder(calendar)"
sg-escape="app.revertEditing(calendar)"/>
</md-input-container>
<md-button class="md-secondary md-icon-button" md-no-ink="md-no-ink"
as-sortable-item-handle="as-sortable-item-handle">
<md-icon md-colors="::{color: 'accent-400'}">drag_handle</md-icon>
</md-button>
<md-menu class="md-secondary sg-list-sortable-hide" label:aria-label="Options">
<md-button class="md-icon-button" label:aria-label="Options"
ng-click="$mdMenu.open()"
md-menu-origin="md-menu-origin">
<md-icon>more_vert</md-icon>
</md-button>
<md-menu-content width="2">
<md-menu-item>
<md-button ng-click="app.showOnly(calendar)">
<var:string label:value="Show Only This Calendar"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button ng-click="app.showAll()">
<var:string label:value="Show All Calendars"/>
</md-button>
</md-menu-item>
<md-menu-divider><!-- divider --></md-menu-divider>
<md-menu-item>
<md-button ng-click="app.showProperties(calendar)">
<var:string label:value="Properties"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button type="button" ng-click="app.editFolder(calendar)">
<var:string label:value="Rename"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button ng-click="app.confirmDelete(calendar)">
<var:string label:value="Unsubscribe Calendar"/>
</md-button>
</md-menu-item>
<md-menu-divider><!-- divider --></md-menu-divider>
<md-menu-item>
<md-button ng-click="app.showLinks(calendar)">
<var:string label:value="Links to this Calendar"/>
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
<md-list-item
class="sg-calendar-list-item"
ng-repeat="calendar in app.service.$subscriptions | filter:app.filter"
as-sortable-item="as-sortable-item"
sg-calendar="calendar">
<!-- sgCalendarListItem directive -->
</md-list-item>
</md-list>
</section>
<!-- Web Calendars -->
<section>
<md-subheader class="sg-md-subheader--with-secondary-icon"
md-colors="::{background: 'default-background-300'}">
md-colors="::{color: 'default-background-700', background: 'default-background-300'}">
<div layout="row" layout-align="space-between center">
<span><var:string label:value="Web Calendars"/></span>
<md-button class="sg-icon-button"
<md-button class="md-icon-button"
label:aria-label="Subscribe to a web calendar..."
ng-click="app.addWebCalendar()">
<md-icon>add_circle_outline</md-icon>
@ -247,67 +104,12 @@
</md-subheader>
<md-list ng-model="app.service.$webcalendars"
as-sortable="app.sortableCalendars" is-disabled="!app.sortableMode">
<md-list-item ng-repeat="calendar in app.service.$webcalendars | filter:app.filter"
as-sortable-item="as-sortable-item">
<md-switch ng-model="calendar.active"
ng-class="calendar.getClassName('md-switch')"
ng-true-value="1"
ng-false-value="0"
label:aria-label="Enable"><!-- enable --></md-switch>
<p class="sg-item-name"
ng-dblclick="app.editFolder(calendar)"
ng-show="app.editMode != calendar.id">
<span class="ng-hide" ng-show="calendar.$error">
<md-icon class="md-warn">warning</md-icon>
<md-tooltip ng-bind="calendar.$error"><!-- error as a tooltip --></md-tooltip>
</span>
<md-tooltip md-delay="1000" md-autohide="true" ng-bind="calendar.name"><!-- tooltip --></md-tooltip>
<span ng-bind="calendar.name"><!-- name --></span>
</p>
<md-input-container class="md-flex"
ng-show="app.editMode == calendar.id">
<input class="sg-item-name" type="text"
label:aria-label="Name of the Calendar"
ng-model="calendar.name"
ng-blur="app.renameFolder(calendar)"
sg-focus-on="calendarName_{{calendar.id}}"
sg-enter="app.renameFolder(calendar)"
sg-escape="app.revertEditing(calendar)"/>
</md-input-container>
<md-button class="md-secondary md-icon-button" md-no-ink="md-no-ink"
as-sortable-item-handle="as-sortable-item-handle">
<md-icon md-colors="::{color: 'accent-400'}">drag_handle</md-icon>
</md-button>
<md-menu class="md-secondary sg-list-sortable-hide" label:aria-label="Options">
<md-button class="md-icon-button" label:aria-label="Options"
ng-click="$mdMenu.open()"
md-menu-origin="md-menu-origin">
<md-icon>more_vert</md-icon>
</md-button>
<md-menu-content width="2">
<md-menu-item>
<md-button ng-click="app.showProperties(calendar)">
<var:string label:value="Properties"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button type="button" ng-click="app.editFolder(calendar)">
<var:string label:value="Rename"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button ng-click="app.confirmDelete(calendar)">
<var:string label:value="Delete"/>
</md-button>
</md-menu-item>
<md-menu-divider><!-- divider --></md-menu-divider>
<md-menu-item>
<md-button ng-click="app.showLinks(calendar)">
<var:string label:value="Links to this Calendar"/>
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
<md-list-item
class="sg-calendar-list-item"
ng-repeat="calendar in app.service.$webcalendars | filter:app.filter"
as-sortable-item="as-sortable-item"
sg-calendar="calendar">
<!-- sgCalendarListItem directive -->
</md-list-item>
</md-list>
</section>
@ -317,7 +119,7 @@
<div class="md-toolbar-tools sg-toolbar-tools--dense"
md-colors="::{backgroundColor: 'background-500'}"
ng-hide="app.sortableMode">
<md-input-container class="md-flex" md-no-float="md-no-float">
<md-input-container class="md-flex" md-no-float="true">
<md-icon>search</md-icon>
<input ng-model="app.filter.name" type="search" label:placeholder="Filter"/>
</md-input-container>
@ -712,6 +514,71 @@
</section>
</script>
<!-- template of contextual menu for a calendar -->
<script type="text/ng-template" id="UIxCalendarMenu">
<div md-whiteframe="3">
<md-menu-content width="2">
<md-menu-item>
<md-button ng-click="$menuCtrl.showOnly()">
<var:string label:value="Show Only This Calendar"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button ng-click="$menuCtrl.showAll()">
<var:string label:value="Show All Calendars"/>
</md-button>
</md-menu-item>
<md-menu-divider><!-- divider --></md-menu-divider>
<md-menu-item>
<md-button ng-click="$menuCtrl.showProperties($event)">
<var:string label:value="Properties"/>
</md-button>
</md-menu-item>
<md-menu-item>
<md-button type="button" ng-click="$menuCtrl.editFolder()">
<var:string label:value="Rename"/>
</md-button>
</md-menu-item>
<md-menu-item ng-show="$menuCtrl.calendar.id != 'personal'">
<md-button ng-click="$menuCtrl.confirmDelete($event)"
ng-switch="$menuCtrl.calendar.isSubscription">
<span ng-switch-when="true"><var:string label:value="Unsubscribe Calendar"/></span>
<span ng-switch-when="false"><var:string label:value="Delete"/></span>
</md-button>
</md-menu-item>
<md-menu-divider><!-- divider --></md-menu-divider>
<md-menu-item>
<md-button ng-click="$menuCtrl.showLinks($event)">
<var:string label:value="Links to this Calendar"/>
</md-button>
</md-menu-item>
<md-menu-divider
ng-hide="::($menuCtrl.calendar.isSubscription || $menuCtrl.calendar.isWebCalendar)">
<!-- divider -->
</md-menu-divider>
<md-menu-item ng-hide="::($menuCtrl.calendar.isSubscription || $menuCtrl.calendar.isWebCalendar)">
<md-button ng-click="$menuCtrl.importCalendar($event)">
<var:string label:value="Import"/>
</md-button>
</md-menu-item>
<md-menu-item ng-hide="::($menuCtrl.calendar.isSubscription || $menuCtrl.calendar.isWebCalendar)">
<md-button ng-click="$menuCtrl.calendar.export()">
<var:string label:value="Export"/>
</md-button>
</md-menu-item>
<md-menu-divider
ng-hide="::($menuCtrl.calendar.isSubscription || $menuCtrl.calendar.isWebCalendar)">
<!-- divider -->
</md-menu-divider>
<md-menu-item ng-hide="::($menuCtrl.calendar.isSubscription || $menuCtrl.calendar.isWebCalendar)">
<md-button ng-click="$menuCtrl.share()">
<var:string label:value="Sharing..."/>
</md-button>
</md-menu-item>
</md-menu-content>
</div>
</script>
<!-- modal inner content for acl editor -->
<script type="text/ng-template" id="UIxUserRightsEditor">
<var:component className="UIxCalUserRightsEditor" />

View File

@ -6,26 +6,15 @@
/**
* @ngInject
*/
CalendarsController.$inject = ['$rootScope', '$scope', '$window', '$mdDialog', '$log', '$mdToast', 'FileUploader', 'sgFocus', 'Dialog', 'sgSettings', 'Preferences', 'Calendar', 'User', 'stateCalendars'];
function CalendarsController($rootScope, $scope, $window, $mdDialog, $log, $mdToast, FileUploader, focus, Dialog, Settings, Preferences, Calendar, User, stateCalendars) {
CalendarsController.$inject = ['$rootScope', '$scope', '$window', '$mdDialog', '$log', '$mdToast', 'Dialog', 'sgSettings', 'Preferences', 'Calendar'];
function CalendarsController($rootScope, $scope, $window, $mdDialog, $log, $mdToast, Dialog, Settings, Preferences, Calendar) {
var vm = this;
vm.activeUser = Settings.activeUser;
vm.service = Calendar;
vm.newCalendar = newCalendar;
vm.addWebCalendar = addWebCalendar;
vm.confirmDelete = confirmDelete;
vm.editFolder = editFolder;
vm.revertEditing = revertEditing;
vm.renameFolder = renameFolder;
vm.share = share;
vm.importCalendar = importCalendar;
vm.showOnly = showOnly;
vm.showAll = showAll;
vm.showLinks = showLinks;
vm.showProperties = showProperties;
vm.subscribeToFolder = subscribeToFolder;
// vm.today = today;
vm.filter = { name: '' };
vm.sortableMode = false;
@ -164,234 +153,6 @@
}
}
function confirmDelete(folder) {
if (folder.isSubscription) {
// Unsubscribe without confirmation
folder.$delete()
.catch(function(data, status) {
Dialog.alert(l('An error occured while deleting the calendar "%{0}".', folder.name),
l(data.error));
});
}
else {
Dialog.confirm(l('Warning'), l('Are you sure you want to delete the calendar "%{0}"?', folder.name),
{ ok: l('Delete') })
.then(function() {
folder.$delete()
.catch(function(data, status) {
Dialog.alert(l('An error occured while deleting the calendar "%{0}".', folder.name),
l(data.error));
});
});
}
}
function importCalendar($event, folder) {
$mdDialog.show({
parent: angular.element(document.body),
targetEvent: $event,
clickOutsideToClose: true,
escapeToClose: true,
templateUrl: 'UIxCalendarImportDialog',
controller: CalendarImportDialogController,
controllerAs: '$CalendarImportDialogController',
locals: {
folder: folder
}
});
/**
* @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;
}
}
}
function showOnly(calendar) {
_.forEach(Calendar.$findAll(), function(o) {
if (calendar.id == o.id)
o.active = 1;
else
o.active = 0;
});
}
function showAll() {
_.forEach(Calendar.$findAll(), function(o) { o.active = 1; });
}
function showLinks(calendar) {
$mdDialog.show({
parent: angular.element(document.body),
clickOutsideToClose: true,
escapeToClose: true,
templateUrl: calendar.id + '/links',
controller: LinksDialogController,
controllerAs: 'links',
locals: {
calendar: calendar
}
});
/**
* @ngInject
*/
LinksDialogController.$inject = ['$mdDialog', 'calendar'];
function LinksDialogController($mdDialog, calendar) {
var vm = this;
vm.calendar = calendar;
vm.close = close;
function close() {
$mdDialog.hide();
}
}
}
function showProperties(calendar) {
var color = calendar.color;
$mdDialog.show({
templateUrl: calendar.id + '/properties',
controller: PropertiesDialogController,
controllerAs: 'properties',
clickOutsideToClose: true,
escapeToClose: true,
locals: {
srcCalendar: calendar
}
}).catch(function() {
// Restore original color when cancelling or closing the dialog
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;
});
function saveProperties() {
vm.calendar.$save();
// Refresh list instance
srcCalendar.init(vm.calendar.$omit());
$mdDialog.hide();
}
function close() {
$mdDialog.cancel();
}
}
}
function editFolder(folder) {
vm.calendarName = folder.name;
vm.editMode = folder.id;
focus('calendarName_' + folder.id);
}
function revertEditing(folder) {
folder.$reset();
vm.editMode = false;
}
function renameFolder(folder) {
folder.$rename()
.then(function(data) {
vm.editMode = false;
});
}
function share(calendar) {
calendar.$acl.$users().then(function() {
$mdDialog.show({
templateUrl: calendar.id + '/UIxAclEditor', // UI/Templates/UIxAclEditor.wox
controller: 'AclController', // from the ng module SOGo.Common
controllerAs: 'acl',
clickOutsideToClose: true,
escapeToClose: true,
locals: {
usersWithACL: calendar.$acl.users,
User: User,
folder: calendar
}
});
});
}
// Callback of sgSubscribe directive
function subscribeToFolder(calendarData) {
@ -405,14 +166,6 @@
});
}
// function today() {
// var fragments = $window.location.hash.split('/'),
// state = fragments[1],
// view = fragments[2],
// now = new Date(),
// path = ['#', state, view, now.getDayString()];
// $window.location = path.join('/');
// }
}
angular

View File

@ -0,0 +1,394 @@
/* -*- 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
*/
sgCalendarListItemController.$inject = ['$scope', '$element', '$mdToast', '$mdPanel', '$mdMedia', '$mdSidenav', 'sgConstant', 'Dialog', 'Calendar'];
function sgCalendarListItemController($scope, $element, $mdToast, $mdPanel, $mdMedia, $mdSidenav, sgConstant, Dialog, Calendar) {
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;
});
function saveProperties() {
vm.calendar.$save();
// Refresh list instance
srcCalendar.init(vm.calendar.$omit());
$mdDialog.hide();
}
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);
})();