sogo/UI/WebServerResources/js/Scheduler.js.map
2016-01-26 09:17:16 -05:00

1 line
128 KiB
Plaintext

{"version":3,"sources":["Scheduler/Scheduler.app.js","Scheduler/CalendarController.js","Scheduler/CalendarListController.js","Scheduler/CalendarsController.js","Scheduler/ComponentController.js","Scheduler/sgCalendarDay.directive.js","Scheduler/sgCalendarDayBlock.directive.js","Scheduler/sgCalendarDayTable.directive.js","Scheduler/sgCalendarGhost.directive.js","Scheduler/sgCalendarMonthDay.directive.js","Scheduler/sgCalendarMonthEvent.directive.js","Scheduler/sgCalendarScrollView.directive.js","Scheduler/sgCalendarTable.directive.js","Scheduler/sgCategoryStylesheet.directive.js","Scheduler/sgDraggableCalendarBlock.directive.js","Scheduler/sgDroppableBlock.directive.js"],"names":["configure","$stateProvider","$urlRouterProvider","state","url","views","calendars","templateUrl","controller","controllerAs","resolve","stateCalendars","calendarView","$stateParams","view","day","stateEventsBlocks","when","now","Date","getDayString","otherwise","Calendar","$calendars","$findAll","window","calendarsData","Component","$eventsBlocksForView","asDate","then","_","forEach","id","calendar","name","calendarName","runBlock","$rootScope","$log","$location","$state","Preferences","$on","event","toState","toParams","fromState","fromParams","error","go","current","previous","rejection","length","ready","exec","settings","View","replace","angular","module","config","run","$inject","CalendarController","$scope","updateView","data","vm","changeDate","$event","date","element","currentTarget","attr","changeView","deregisterCalendarsList","this","CalendarListController","$timeout","$mdDialog","Dialog","selectComponentType","type","options","reload","componentType","isUndefined","$filter","unselectComponents","saveSelectedList","each","component","selected","selectAll","toggleComponentSelection","preventDefault","stopPropagation","confirmDeleteSelectedComponents","confirm","l","components","filter","$deleteComponents","status","openEvent","openComponent","openTask","task","viewable","capitalize","show","parent","document","body","targetEvent","clickOutsideToClose","escapeToClose","locals","stateComponent","newComponent","baseComponent","pid","$defaultCalendar","updateComponentFromGhost","RecurrentComponentDialogController","params","updateThisOccurrence","$adjust","hide","cancel","updateAllOccurrences","occurrenceId","pointerHandler","coordinates","delta","calendarNumber","activeCalendars","$ghost","isNew","currentEventCoordinates","isAllDay","duration","setDelta","getDelta","originalEventCoordinates","days","dayNumber","start","originalCalendar","active","destination","isException","$emit","template","join","filterpopup","filteredBy","sort","field","sortedBy","cancelSearch","mode","search","value","selectedList","SelectedList","CalendarsController","$window","$mdToast","FileUploader","focus","Settings","User","newCalendar","ev","prompt","isEditable","isRemote","owner","UserLogin","$id","$add","addWebCalendar","inputType","$addWebCalendar","confirmDelete","folder","isSubscription","$delete","alert","importCalendar","CalendarImportDialogController","scope","filterByExtension","item","isTextFile","indexOf","test","position","hideDelay","uploader","ApplicationBaseURL","autoUpload","queueLimit","filters","fn","onSuccessItem","response","headers","msg","imported","simple","content","onErrorItem","close","exportCalendar","location","href","showLinks","LinksDialogController","showProperties","PropertiesDialogController","srcCalendar","saveProperties","$save","init","$omit","$watch","color","editFolder","editMode","revertEditing","$reset","renameFolder","$rename","share","$acl","$users","usersWithACL","users","subscribeToFolder","calendarData","debug","$subscribe","today","fragments","hash","split","path","activeUser","service","categories","map","defaults","SOGoCalendarCategories","asCSSIdentifier","SOGoCalendarCategoriesColors","union","o","pick","$subscriptions","$webcalendars","newList","oldList","ids","pluck","i","isEqual","$get","$setActivation","ComponentController","AddressBook","Alarm","cardFilter","$query","$filterAll","$cards","edit","editAllOccurrences","$getComponent","$futureComponentData","reply","c","$reply","getAlarms","replyAllOccurrences","delegatedTo","$hasAlarm","alarm","deleteOccurrence","remove","deleteAllOccurrences","toggleRawSource","$$resource","post","ComponentRawSourceDialogController","organizer","ComponentEditorController","Card","addAttachUrl","toggleRecurrenceEditor","showRecurrenceEditor","$hasCustomRepeat","toggleAttendeesEditor","showAttendeesEditor","addAttendee","card","isString","isValidEmail","emails","searchText","save","form","$valid","getDays","end","daysUpTo","stringWithSeparator","getHours","hours","push","toString","addStartDate","$addStartDate","oldStartDate","getTime","addDueDate","$addDueDate","oldDueDate","due","updateStartTime","addMinutes","getMinutes","adjustStartTime","valueOf","oldEndDate","updateFreeBusy","updateEndTime","adjustEndTime","minutesTo","updateDueTime","adjustDueTime","attendeesEditor","isDefined","attendees","sgCalendarDay","restrict","dayString","sgCalendarDayController","index","findIndex","directive","sgCalendarDayBlock","CalendarSettings","link","iElement","attrs","pc","left","right","block","siblings","css","addClass","clickBlock","sgCalendarDayTable","blocks","sgCalendarGhost","ctrls","initGhost","calendarDayCtrl","originalCalendarNumber","hideGhost","forEachRight","domElement","classList","removeClass","updateGhost","showGhost","isRelative","originalDay","currentDay","wasOtherBlock","durationLeft","maxDuration","enableTransition","$view","scrollViewCtrl","EventDragDayLength","startHour","getStartTime","parseInt","quarterHeight","topOffset","endHour","getEndTime","quartersToHM","quarters","minutes","mins","Math","floor","deregisterDragStart","deregisterDrag","deregisterDragEnd","require","sgCalendarMonthDay","sgCalendarMonthEvent","sgCalendarScrollView","$document","$q","$mdGesture","sgCalendarScrollViewController","initView","getQuarterHeight","scrollStep","maxX","getMaxColumns","scrollView","on","updateCoordinates","time","hourCell","quartersOffset","SOGoDayStartTime","getElementById","scrollTop","offsetTop","hour0","hour23","height","getDayDimensions","viewLeft","width","leftOffset","nodes","domRect","tileHeader","getElementsByClassName","getBoundingClientRect","clientHeight","offset","top","max","dayDimensions","extend","x","y","dayHeight","dayWidth","daysOffset","onDragStart","updateFromPointerHandler","onDragEnd","off","pointerCoordinates","scrollY","minY","getContainerBasedCoordinates","lastScroll","deregisterDragStop","sgCalendarTable","blocksType","sgCategoryStylesheet","ngModel","sgDraggableCalendarBlock","initGrips","blockIndex","isFirstBlock","isLastBlock","dragGrip","leftGrip","rightGrip","topGrip","bottomGrip","matchesProperty","c_isallday","parentNode","tagName","append","clone","onDragDetect","dragMode","target","className","SOGoEventDragPointerHandler","initFromEvent","one","onDrag","dragStart","eventType","isHourCell","isMonthly","startDate","newData","hasClass","parseDate","$mdDateLocaleProvider","b","dragging","prepareWithEventType","initFromBlock","initFromCalendar","starthour","updateFromEvent","pointer","dragHasStarted","SOGoCoordinates","SOGoEventDragEventCoordinates","setEventType","editable","prototype","otherCoordinates","getDistance","sqrt","sum","_quartersToHM","originalCoordinates","currentCoordinates","originalViewCoordinates","currentViewCoordinates","getEventViewCoordinates","pageX","pageY","newEventCoordinates","setTimeFromQuarters","updateEventCoordinates","distance","newDuration","deltaQuarters","deltaDays","ceil","JSON","stringify","container","clientWidth","methods","multiday","getEventMultiDayViewCoordinates","multiday-allday","getEventMultiDayAllDayViewCoordinates","monthly","getEventMonthlyViewCoordinates","unknown","method","pxCoordinates","EventDragHorizontalOffset","maxY","minX","daysTopOffset","daysY","setHours","sgDroppableBlock","onDrop","deregister"],"mappings":"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","file":"Scheduler.js","sourcesContent":["/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* JavaScript for SOGo.SchedulerUI module */\n\n(function() {\n 'use strict';\n\n angular.module('SOGo.SchedulerUI', ['ui.router', 'angularFileUpload', 'SOGo.Common', 'SOGo.PreferencesUI', 'SOGo.ContactsUI', 'SOGo.MailerUI'])\n .config(configure)\n .run(runBlock);\n\n /**\n * @ngInject\n */\n configure.$inject = ['$stateProvider', '$urlRouterProvider'];\n function configure($stateProvider, $urlRouterProvider) {\n $stateProvider\n .state('calendars', {\n url: '/calendar',\n views: {\n calendars: {\n templateUrl: 'UIxCalMainView', // UI/Templates/SchedulerUI/UIxCalMainView.wox\n controller: 'CalendarsController',\n controllerAs: 'app'\n }\n },\n resolve: {\n stateCalendars: stateCalendars\n }\n })\n .state('calendars.view', {\n url: '/{view:(?:day|week|month|multicolumnday)}/:day',\n //sticky: true,\n //deepStateRedirect: true,\n views: {\n calendarView: {\n templateUrl: function($stateParams) {\n // UI/Templates/SchedulerUI/UIxCalDayView.wox or\n // UI/Templates/SchedulerUI/UIxCalWeekView.wox or\n // UI/Templates/SchedulerUI/UIxCalMonthView.wox or\n // UI/Templates/SchedulerUI/UIxCalMulticolumnDayView.wox\n return $stateParams.view + 'view?day=' + $stateParams.day;\n },\n controller: 'CalendarController',\n controllerAs: 'calendar'\n }\n },\n resolve: {\n stateEventsBlocks: stateEventsBlocks\n }\n });\n\n $urlRouterProvider.when('/calendar/day', function() {\n // If no date is specified, show today\n var now = new Date();\n return '/calendar/day/' + now.getDayString();\n });\n $urlRouterProvider.when('/calendar/multicolumnday', function() {\n // If no date is specified, show today\n var now = new Date();\n return '/calendar/multicolumnday/' + now.getDayString();\n });\n $urlRouterProvider.when('/calendar/week', function() {\n // If no date is specified, show today's week\n var now = new Date();\n return '/calendar/week/' + now.getDayString();\n });\n $urlRouterProvider.when('/calendar/month', function() {\n // If no date is specified, show today's month\n var now = new Date();\n return '/calendar/month/' + now.getDayString();\n });\n\n // If none of the above states are matched, use this as the fallback.\n // runBlock will also act as a fallback by looking at user's settings\n $urlRouterProvider.otherwise('/calendar');\n }\n\n /**\n * @ngInject\n */\n stateCalendars.$inject = ['Calendar'];\n function stateCalendars(Calendar) {\n return Calendar.$calendars || Calendar.$findAll(window.calendarsData);\n }\n\n /**\n * @ngInject\n */\n stateEventsBlocks.$inject = ['$stateParams', 'Component', 'Calendar'];\n function stateEventsBlocks($stateParams, Component, Calendar) {\n // See CalendarController.js\n return Component.$eventsBlocksForView($stateParams.view, $stateParams.day.asDate())\n .then(function(views) {\n _.forEach(views, function(view) {\n if (view.id) {\n // Note: this can't be done in Component service since it would make Component dependent on\n // the Calendar service and create a circular dependency\n view.calendar = new Calendar({ id: view.id, name: view.calendarName });\n }\n });\n return views;\n });\n }\n\n /**\n * @ngInject\n */\n runBlock.$inject = ['$rootScope', '$log', '$location', '$state', 'Preferences'];\n function runBlock($rootScope, $log, $location, $state, Preferences) {\n $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {\n $log.error(error);\n $state.go('calendar');\n });\n $rootScope.$on('$routeChangeError', function(event, current, previous, rejection) {\n $log.error(event, current, previous, rejection);\n });\n if ($location.url().length === 0) {\n // Restore user's last view\n Preferences.ready().then(function() {\n var url = '/calendar/',\n view = /(.+)view/.exec(Preferences.settings.Calendar.View);\n if (view)\n url += view[1];\n else\n url += 'week';\n $location.replace().url(url);\n });\n }\n }\n\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * @ngInject\n */\n CalendarController.$inject = ['$scope', '$rootScope', '$state', '$stateParams', 'Calendar', 'Component', 'stateEventsBlocks'];\n function CalendarController($scope, $rootScope, $state, $stateParams, Calendar, Component, stateEventsBlocks) {\n var vm = this, deregisterCalendarsList;\n\n vm.views = stateEventsBlocks;\n vm.changeDate = changeDate;\n vm.changeView = changeView;\n\n // Refresh current view when the list of calendars is modified\n deregisterCalendarsList = $rootScope.$on('calendars:list', updateView);\n\n $scope.$on('$destroy', deregisterCalendarsList);\n\n function updateView() {\n // See stateEventsBlocks in Scheduler.app.js\n Component.$eventsBlocksForView($stateParams.view, $stateParams.day.asDate()).then(function(data) {\n vm.views = data;\n _.forEach(vm.views, function(view) {\n if (view.id) {\n // Note: this can't be done in Component service since it would make Component dependent on\n // the Calendar service and create a circular dependency\n view.calendar = new Calendar({ id: view.id, name: view.calendarName });\n }\n });\n });\n }\n\n // Change calendar's date\n function changeDate($event) {\n var date = angular.element($event.currentTarget).attr('date');\n $state.go('calendars.view', { day: date });\n }\n\n // Change calendar's view\n function changeView(view) {\n $state.go('calendars.view', { view: view });\n }\n}\n\n angular\n .module('SOGo.SchedulerUI') \n .controller('CalendarController', CalendarController);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * @ngInject\n */\n CalendarListController.$inject = ['$rootScope', '$timeout', '$state', '$mdDialog', 'Dialog', 'Preferences', 'Calendar', 'Component'];\n function CalendarListController($rootScope, $timeout, $state, $mdDialog, Dialog, Preferences, Calendar, Component) {\n var vm = this;\n\n vm.component = Component;\n vm.componentType = 'events';\n vm.selectedList = 0;\n vm.selectComponentType = selectComponentType;\n vm.unselectComponents = unselectComponents;\n vm.selectAll = selectAll;\n vm.toggleComponentSelection = toggleComponentSelection;\n vm.confirmDeleteSelectedComponents = confirmDeleteSelectedComponents;\n vm.openEvent = openEvent;\n vm.openTask = openTask;\n vm.newComponent = newComponent;\n vm.filter = filter;\n vm.filteredBy = filteredBy;\n vm.sort = sort;\n vm.sortedBy = sortedBy;\n vm.reload = reload;\n vm.cancelSearch = cancelSearch;\n vm.mode = { search: false };\n\n // Select list based on user's settings\n Preferences.ready().then(function() {\n var type = 'events';\n if (Preferences.settings.Calendar.SelectedList == 'tasksListView') {\n vm.selectedList = 1;\n type = 'tasks';\n }\n selectComponentType(type, { reload: true });\n });\n\n // Refresh current list when the list of calendars is modified\n $rootScope.$on('calendars:list', function() {\n Component.$filter(vm.componentType, { reload: true });\n });\n\n // Update the component being dragged\n $rootScope.$on('calendar:dragend', updateComponentFromGhost);\n\n // Switch between components tabs\n function selectComponentType(type, options) {\n if (options && options.reload || vm.componentType != type) {\n if (angular.isUndefined(Component['$' + type]))\n Component.$filter(type);\n vm.unselectComponents();\n vm.componentType = type;\n Component.saveSelectedList(type);\n }\n }\n\n function unselectComponents() {\n _.each(Component['$' + vm.componentType], function(component) { component.selected = false; });\n }\n\n function selectAll() {\n _.each(Component['$' + vm.componentType], function(component) {\n component.selected = true;\n });\n }\n\n function toggleComponentSelection($event, component) {\n component.selected = !component.selected;\n $event.preventDefault();\n $event.stopPropagation();\n }\n\n function confirmDeleteSelectedComponents() {\n Dialog.confirm(l('Warning'),\n l('Are you sure you want to delete the selected components?'))\n .then(function() {\n // User confirmed the deletion\n var components = _.filter(Component['$' + vm.componentType], function(component) { return component.selected; });\n Calendar.$deleteComponents(components);\n }, function(data, status) {\n // Delete failed\n });\n }\n\n function openEvent($event, event) {\n openComponent($event, event, 'appointment');\n }\n\n function openTask($event, task) {\n openComponent($event, task, 'task');\n }\n\n function openComponent($event, component, type) {\n if (component.viewable) {\n // UI/Templates/SchedulerUI/UIxAppointmentViewTemplate.wox or\n // UI/Templates/SchedulerUI/UIxTaskViewTemplate.wox\n var templateUrl = 'UIx' + type.capitalize() + 'ViewTemplate';\n $mdDialog.show({\n parent: angular.element(document.body),\n targetEvent: $event,\n clickOutsideToClose: true,\n escapeToClose: true,\n templateUrl: templateUrl,\n controller: 'ComponentController',\n controllerAs: 'editor',\n locals: {\n stateComponent: component\n }\n });\n }\n }\n\n function newComponent($event, baseComponent) {\n var type = 'appointment', component;\n\n if (baseComponent) {\n component = baseComponent;\n type = baseComponent.type;\n }\n else {\n if (vm.componentType == 'tasks')\n type = 'task';\n component = new Component({ pid: Calendar.$defaultCalendar(), type: type });\n }\n\n // UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox or\n // UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox\n var templateUrl = 'UIx' + type.capitalize() + 'EditorTemplate';\n return $mdDialog.show({\n parent: angular.element(document.body),\n targetEvent: $event,\n clickOutsideToClose: true,\n escapeToClose: true,\n templateUrl: templateUrl,\n controller: 'ComponentEditorController',\n controllerAs: 'editor',\n locals: {\n stateComponent: component\n }\n });\n }\n\n // Adjust component or create new component through drag'n'drop\n function updateComponentFromGhost($event) {\n var component, pointerHandler, coordinates, delta, params, calendarNumber, activeCalendars;\n\n component = Component.$ghost.component;\n pointerHandler = Component.$ghost.pointerHandler;\n\n if (component.isNew) {\n coordinates = pointerHandler.currentEventCoordinates;\n if (component.isAllDay)\n coordinates.duration -= 96;\n component.setDelta(coordinates.duration * 15);\n newComponent(null, component).finally(function() {\n $timeout(function() {\n Component.$ghost.pointerHandler = null;\n Component.$ghost.component = null;\n });\n });\n }\n else {\n delta = pointerHandler.currentEventCoordinates.getDelta(pointerHandler.originalEventCoordinates);\n params = {\n days: delta.dayNumber,\n start: delta.start * 15,\n duration: delta.duration * 15\n };\n if (pointerHandler.originalCalendar && delta.dayNumber !== 0) {\n // The day number actually represents the destination calendar among the active calendars\n calendarNumber = pointerHandler.currentEventCoordinates.dayNumber;\n activeCalendars = _.filter(Calendar.$findAll(), { active: 1 });\n params.destination = activeCalendars[calendarNumber].id;\n params.days = 0;\n }\n if (component.isException || !component.occurrenceId)\n // Component is an exception to a recurrence or is not recurrent;\n // Immediately perform the adjustments\n component.$adjust(params).then(function() {\n $rootScope.$emit('calendars:list');\n $timeout(function() {\n Component.$ghost = {};\n });\n });\n else if (component.occurrenceId) {\n $mdDialog.show({\n clickOutsideToClose: true,\n escapeToClose: true,\n locals: {\n component: component,\n params: params\n },\n template: [\n '<md-dialog flex=\"50\" md-flex=\"80\" sm-flex=\"90\">',\n ' <md-dialog-content class=\"md-dialog-content\">',\n ' <p>' + l('editRepeatingItem') + '</p>',\n ' </md-dialog-content>',\n ' <md-dialog-actions>',\n ' <md-button ng-click=\"updateThisOccurrence()\">' + l('button_thisOccurrenceOnly') + '</md-button>',\n ' <md-button ng-click=\"updateAllOccurrences()\">' + l('button_allOccurrences') + '</md-button>',\n ' </md-dialog-actions>',\n '</md-dialog>'\n ].join(''),\n controller: RecurrentComponentDialogController\n }).then(function() {\n $rootScope.$emit('calendars:list');\n }).finally(function() {\n $timeout(function() {\n Component.$ghost = {};\n });\n });\n }\n }\n\n /**\n * @ngInject\n */\n RecurrentComponentDialogController.$inject = ['$scope', '$mdDialog', 'component', 'params'];\n function RecurrentComponentDialogController($scope, $mdDialog, component, params) {\n $scope.updateThisOccurrence = function() {\n component.$adjust(params).then($mdDialog.hide, $mdDialog.cancel);\n };\n $scope.updateAllOccurrences = function() {\n delete component.occurrenceId;\n component.$adjust(params).then($mdDialog.hide, $mdDialog.cancel);\n };\n }\n }\n\n function filter(filterpopup) {\n Component.$filter(vm.componentType, { filterpopup: filterpopup });\n }\n\n function filteredBy(filterpopup) {\n return Component['$query' + vm.componentType.capitalize()].filterpopup == filterpopup;\n }\n\n function sort(field) {\n Component.$filter(vm.componentType, { sort: field });\n }\n\n function sortedBy(field) {\n return Component['$query' + vm.componentType.capitalize()].sort == field;\n }\n\n function reload() {\n $rootScope.$emit('calendars:list');\n }\n\n function cancelSearch() {\n vm.mode.search = false;\n Component.$filter(vm.componentType, { value: '' });\n }\n }\n \n angular\n .module('SOGo.SchedulerUI')\n .controller('CalendarListController', CalendarListController);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * @ngInject\n */\n CalendarsController.$inject = ['$rootScope', '$scope', '$window', '$mdDialog', '$log', '$mdToast', 'FileUploader', 'sgFocus', 'Dialog', 'sgSettings', 'Preferences', 'Calendar', 'User', 'stateCalendars'];\n function CalendarsController($rootScope, $scope, $window, $mdDialog, $log, $mdToast, FileUploader, focus, Dialog, Settings, Preferences, Calendar, User, stateCalendars) {\n var vm = this;\n\n vm.activeUser = Settings.activeUser;\n vm.service = Calendar;\n vm.newCalendar = newCalendar;\n vm.addWebCalendar = addWebCalendar;\n vm.confirmDelete = confirmDelete;\n vm.editFolder = editFolder;\n vm.revertEditing = revertEditing;\n vm.renameFolder = renameFolder;\n vm.share = share;\n vm.importCalendar = importCalendar;\n vm.exportCalendar = exportCalendar;\n vm.showLinks = showLinks;\n vm.showProperties = showProperties;\n vm.subscribeToFolder = subscribeToFolder;\n vm.today = today;\n\n Preferences.ready().then(function() {\n vm.categories = _.map(Preferences.defaults.SOGoCalendarCategories, function(name) {\n return { id: name.asCSSIdentifier(),\n name: name,\n color: Preferences.defaults.SOGoCalendarCategoriesColors[name]\n };\n });\n });\n\n // Dispatch the event named 'calendars:list' when a calendar is activated or deactivated or\n // when the color of a calendar is changed\n $scope.$watch(\n function() {\n return _.union(\n _.map(Calendar.$calendars, function(o) { return _.pick(o, ['id', 'active', 'color']); }),\n _.map(Calendar.$subscriptions, function(o) { return _.pick(o, ['id', 'active', 'color']); }),\n _.map(Calendar.$webcalendars, function(o) { return _.pick(o, ['id', 'active', 'color']); })\n );\n },\n function(newList, oldList) {\n // Identify which calendar has changed\n var ids = _.pluck(_.filter(newList, function(o, i) { return !_.isEqual(o, oldList[i]); }), 'id');\n if (ids.length > 0) {\n $log.debug(ids.join(', ') + ' changed');\n _.each(ids, function(id) {\n var calendar = Calendar.$get(id);\n calendar.$setActivation().then(function() {\n $rootScope.$emit('calendars:list');\n });\n });\n }\n },\n true // compare for object equality\n );\n\n function newCalendar(ev) {\n Dialog.prompt(l('New calendar'), l('Name of the Calendar'))\n .then(function(name) {\n var calendar = new Calendar(\n {\n name: name,\n isEditable: true,\n isRemote: false,\n owner: UserLogin\n }\n );\n calendar.$id().then(function() {\n Calendar.$add(calendar);\n });\n });\n }\n\n function addWebCalendar() {\n Dialog.prompt(l('Subscribe to a web calendar...'), l('URL of the Calendar'), {inputType: 'url'})\n .then(function(url) {\n Calendar.$addWebCalendar(url);\n });\n }\n\n function confirmDelete(folder) {\n if (folder.isSubscription) {\n // Unsubscribe without confirmation\n folder.$delete()\n .then(function() {\n $rootScope.$emit('calendars:list');\n }, function(data, status) {\n Dialog.alert(l('An error occured while deleting the calendar \"%{0}\".', folder.name),\n l(data.error));\n });\n }\n else {\n Dialog.confirm(l('Warning'), l('Are you sure you want to delete the calendar <em>%{0}</em>?', folder.name))\n .then(function() {\n folder.$delete()\n .then(function() {\n $rootScope.$emit('calendars:list');\n }, function(data, status) {\n Dialog.alert(l('An error occured while deleting the calendar \"%{0}\".', folder.name),\n l(data.error));\n });\n });\n }\n }\n\n function importCalendar($event, folder) {\n $mdDialog.show({\n parent: angular.element(document.body),\n targetEvent: $event,\n clickOutsideToClose: true,\n escapeToClose: true,\n templateUrl: 'UIxCalendarImportDialog',\n controller: CalendarImportDialogController,\n controllerAs: '$CalendarImportDialogController',\n locals: {\n folder: folder\n }\n });\n\n /**\n * @ngInject\n */\n CalendarImportDialogController.$inject = ['scope', '$mdDialog', 'folder'];\n function CalendarImportDialogController(scope, $mdDialog, folder) {\n var vm = this;\n\n vm.uploader = new FileUploader({\n url: ApplicationBaseURL + [folder.id, 'import'].join('/'),\n autoUpload: true,\n queueLimit: 1,\n filters: [{ name: filterByExtension, fn: filterByExtension }],\n onSuccessItem: function(item, response, status, headers) {\n var msg;\n\n $mdDialog.hide();\n\n if (response.imported === 0)\n msg = l('No event was imported.');\n else {\n msg = l('A total of %{0} events were imported in the calendar.', response.imported);\n $rootScope.$emit('calendars:list');\n }\n\n $mdToast.show(\n $mdToast.simple()\n .content(msg)\n .position('top right')\n .hideDelay(3000));\n },\n onErrorItem: function(item, response, status, headers) {\n $mdToast.show({\n template: [\n '<md-toast>',\n ' <div class=\"md-toast-content\">',\n ' <md-icon class=\"md-warn md-hue-1\">error_outline</md-icon>',\n ' <span>' + l('An error occurred while importing calendar.') + '</span>',\n ' </div>',\n '</md-toast>'\n ].join(''),\n position: 'top right',\n hideDelay: 3000\n });\n }\n });\n\n vm.close = function() {\n $mdDialog.hide();\n };\n\n function filterByExtension(item) {\n var isTextFile = item.type.indexOf('text') === 0 ||\n /\\.(ics)$/.test(item.name);\n\n if (!isTextFile)\n $mdToast.show({\n template: [\n '<md-toast>',\n ' <div class=\"md-toast-content\">',\n ' <md-icon class=\"md-warn md-hue-1\">error_outline</md-icon>',\n ' <span>' + l('Select an iCalendar file (.ics).') + '</span>',\n ' </div>',\n '</md-toast>'\n ].join(''),\n position: 'top right',\n hideDelay: 3000\n });\n\n return isTextFile;\n }\n }\n }\n\n function exportCalendar(calendar) {\n window.location.href = ApplicationBaseURL + '/' + calendar.id + '.ics' + '/export';\n }\n\n function showLinks(calendar) {\n $mdDialog.show({\n parent: angular.element(document.body),\n clickOutsideToClose: true,\n escapeToClose: true,\n templateUrl: calendar.id + '/links',\n controller: LinksDialogController,\n controllerAs: 'links',\n locals: {\n calendar: calendar\n }\n });\n \n /**\n * @ngInject\n */\n LinksDialogController.$inject = ['$mdDialog', 'calendar'];\n function LinksDialogController($mdDialog, calendar) {\n var vm = this;\n vm.calendar = calendar;\n vm.close = close;\n\n function close() {\n $mdDialog.hide();\n }\n }\n }\n\n function showProperties(calendar) {\n var color = calendar.color;\n $mdDialog.show({\n templateUrl: calendar.id + '/properties',\n controller: PropertiesDialogController,\n controllerAs: 'properties',\n clickOutsideToClose: true,\n escapeToClose: true,\n locals: {\n srcCalendar: calendar\n }\n }).catch(function() {\n // Restore original color when cancelling or closing the dialog\n calendar.color = color;\n });\n \n /**\n * @ngInject\n */\n PropertiesDialogController.$inject = ['$scope', '$mdDialog', 'srcCalendar'];\n function PropertiesDialogController($scope, $mdDialog, srcCalendar) {\n var vm = this;\n\n vm.calendar = new Calendar(srcCalendar.$omit());\n vm.saveProperties = saveProperties;\n vm.close = close;\n\n $scope.$watch('properties.calendar.color', function() {\n srcCalendar.color = vm.calendar.color;\n });\n\n function saveProperties() {\n vm.calendar.$save();\n // Refresh list instance\n srcCalendar.init(vm.calendar.$omit());\n $mdDialog.hide();\n }\n\n function close() {\n $mdDialog.cancel();\n }\n }\n }\n\n function editFolder(folder) {\n vm.calendarName = folder.name;\n vm.editMode = folder.id;\n focus('calendarName_' + folder.id);\n }\n\n function revertEditing(folder) {\n folder.$reset();\n vm.editMode = false;\n }\n\n function renameFolder(folder) {\n folder.$rename()\n .then(function(data) {\n vm.editMode = false;\n }, function(data, status) {\n Dialog.alert(l('Warning'), data);\n });\n }\n\n function share(calendar) {\n calendar.$acl.$users().then(function() {\n $mdDialog.show({\n templateUrl: calendar.id + '/UIxAclEditor', // UI/Templates/UIxAclEditor.wox\n controller: 'AclController', // from the ng module SOGo.Common\n controllerAs: 'acl',\n clickOutsideToClose: true,\n escapeToClose: true,\n locals: {\n usersWithACL: calendar.$acl.users,\n User: User,\n folder: calendar\n }\n });\n });\n }\n\n // Callback of sgSubscribe directive\n function subscribeToFolder(calendarData) {\n $log.debug('subscribeToFolder ' + calendarData.owner + calendarData.name);\n Calendar.$subscribe(calendarData.owner, calendarData.name).then(function(data) {\n $mdToast.show(\n $mdToast.simple()\n .content(l('Successfully subscribed to calendar'))\n .position('top right')\n .hideDelay(3000));\n });\n }\n\n function today() {\n var fragments = $window.location.hash.split('/'),\n state = fragments[1],\n view = fragments[2],\n now = new Date(),\n path = ['#', state, view, now.getDayString()];\n $window.location = path.join('/');\n }\n }\n\n angular\n .module('SOGo.SchedulerUI')\n .controller('CalendarsController', CalendarsController);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * @ngInject\n */\n ComponentController.$inject = ['$rootScope', '$mdDialog', 'Calendar', 'AddressBook', 'Alarm', 'stateComponent'];\n function ComponentController($rootScope, $mdDialog, Calendar, AddressBook, Alarm, stateComponent) {\n var vm = this, component;\n\n vm.component = stateComponent;\n vm.close = close;\n vm.cardFilter = cardFilter;\n vm.edit = edit;\n vm.editAllOccurrences = editAllOccurrences;\n vm.reply = reply;\n vm.replyAllOccurrences = replyAllOccurrences;\n vm.deleteOccurrence = deleteOccurrence;\n vm.deleteAllOccurrences = deleteAllOccurrences;\n vm.toggleRawSource = toggleRawSource;\n\n // Load all attributes of component\n if (angular.isUndefined(vm.component.$futureComponentData)) {\n component = Calendar.$get(vm.component.pid).$getComponent(vm.component.id, vm.component.occurrenceId);\n component.$futureComponentData.then(function() {\n vm.component = component;\n vm.organizer = [vm.component.organizer];\n });\n }\n\n function close() {\n $mdDialog.hide();\n }\n\n // Autocomplete cards for attendees\n function cardFilter($query) {\n AddressBook.$filterAll($query);\n return AddressBook.$cards;\n }\n\n function edit() {\n var type = (vm.component.component == 'vevent')? 'Appointment':'Task';\n $mdDialog.hide().then(function() {\n // UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox or\n // UI/Templates/SchedulerUI/UIxTaskEditorTemplate.wox\n var templateUrl = 'UIx' + type + 'EditorTemplate';\n $mdDialog.show({\n parent: angular.element(document.body),\n clickOutsideToClose: true,\n escapeToClose: true,\n templateUrl: templateUrl,\n controller: 'ComponentEditorController',\n controllerAs: 'editor',\n locals: {\n stateComponent: vm.component\n }\n });\n });\n }\n\n function editAllOccurrences() {\n component = Calendar.$get(vm.component.pid).$getComponent(vm.component.id);\n component.$futureComponentData.then(function() {\n vm.component = component;\n edit();\n });\n }\n\n function reply(component) {\n var c = component || vm.component;\n\n c.$reply().then(function() {\n $rootScope.$emit('calendars:list');\n $mdDialog.hide();\n Alarm.getAlarms();\n });\n }\n\n function replyAllOccurrences() {\n // Retrieve master event\n component = Calendar.$get(vm.component.pid).$getComponent(vm.component.id);\n component.$futureComponentData.then(function() {\n // Propagate the participant status and alarm to the master event\n component.reply = vm.component.reply;\n component.delegatedTo = vm.component.delegatedTo;\n component.$hasAlarm = vm.component.$hasAlarm;\n component.alarm = vm.component.alarm;\n // Send reply to the server\n reply(component);\n });\n }\n\n function deleteOccurrence() {\n vm.component.remove(true).then(function() {\n $rootScope.$emit('calendars:list');\n $mdDialog.hide();\n });\n }\n\n function deleteAllOccurrences() {\n vm.component.remove().then(function() {\n $rootScope.$emit('calendars:list');\n $mdDialog.hide();\n });\n }\n\n function toggleRawSource($event) {\n Calendar.$$resource.post(vm.component.pid + '/' + vm.component.id, \"raw\").then(function(data) {\n $mdDialog.hide();\n $mdDialog.show({\n parent: angular.element(document.body),\n targetEvent: $event,\n clickOutsideToClose: true,\n escapeToClose: true,\n template: [\n '<md-dialog flex=\"80\" flex-xs=\"100\" aria-label=\"' + l('View Raw Source') + '\">',\n ' <md-dialog-content class=\"md-dialog-content\">',\n ' <pre>',\n data,\n ' </pre>',\n ' </md-dialog-content>',\n ' <md-dialog-actions>',\n ' <md-button ng-click=\"close()\">' + l('Close') + '</md-button>',\n ' </md-dialog-actions>',\n '</md-dialog>'\n ].join(''),\n controller: ComponentRawSourceDialogController\n });\n\n /**\n * @ngInject\n */\n ComponentRawSourceDialogController.$inject = ['scope', '$mdDialog'];\n function ComponentRawSourceDialogController(scope, $mdDialog) {\n scope.close = function() {\n $mdDialog.hide();\n };\n }\n });\n }\n }\n\n /**\n * @ngInject\n */\n ComponentEditorController.$inject = ['$rootScope', '$scope', '$log', '$timeout', '$mdDialog', 'User', 'Calendar', 'Component', 'AddressBook', 'Card', 'Alarm', 'stateComponent'];\n function ComponentEditorController($rootScope, $scope, $log, $timeout, $mdDialog, User, Calendar, Component, AddressBook, Card, Alarm, stateComponent) {\n var vm = this, component, oldStartDate, oldEndDate, oldDueDate;\n\n vm.service = Calendar;\n vm.component = stateComponent;\n vm.categories = {};\n vm.showRecurrenceEditor = vm.component.$hasCustomRepeat;\n vm.toggleRecurrenceEditor = toggleRecurrenceEditor;\n vm.showAttendeesEditor = angular.isDefined(vm.component.attendees);\n vm.toggleAttendeesEditor = toggleAttendeesEditor;\n //vm.searchText = null;\n vm.cardFilter = cardFilter;\n vm.addAttendee = addAttendee;\n vm.addAttachUrl = addAttachUrl;\n vm.cancel = cancel;\n vm.save = save;\n vm.attendeesEditor = {\n days: getDays(),\n hours: getHours()\n };\n vm.addStartDate = addStartDate;\n vm.addDueDate = addDueDate;\n\n // Synchronize start and end dates\n vm.updateStartTime = updateStartTime;\n vm.adjustStartTime = adjustStartTime;\n vm.updateEndTime = updateEndTime;\n vm.adjustEndTime = adjustEndTime;\n vm.updateDueTime = updateDueTime;\n vm.adjustDueTime = adjustDueTime;\n\n if (vm.component.start)\n oldStartDate = new Date(vm.component.start.getTime());\n if (vm.component.end)\n oldEndDate = new Date(vm.component.end.getTime());\n if (vm.component.due)\n oldDueDate = new Date(vm.component.due.getTime());\n\n function addAttachUrl() {\n var i = vm.component.addAttachUrl('');\n focus('attachUrl_' + i);\n }\n\n function toggleRecurrenceEditor() {\n vm.showRecurrenceEditor = !vm.showRecurrenceEditor;\n vm.component.$hasCustomRepeat = vm.showRecurrenceEditor;\n }\n\n function toggleAttendeesEditor() {\n vm.showAttendeesEditor = !vm.showAttendeesEditor;\n }\n\n // Autocomplete cards for attendees\n function cardFilter($query) {\n AddressBook.$filterAll($query);\n return AddressBook.$cards;\n }\n\n function addAttendee(card) {\n if (angular.isString(card)) {\n // User pressed \"Enter\" in search field, adding a non-matching card\n if (card.isValidEmail()) {\n vm.component.addAttendee(new Card({ emails: [{ value: card }] }));\n vm.searchText = '';\n }\n }\n else {\n vm.component.addAttendee(card);\n }\n }\n\n function save(form) {\n if (form.$valid) {\n vm.component.$save()\n .then(function(data) {\n $rootScope.$emit('calendars:list');\n $mdDialog.hide();\n Alarm.getAlarms();\n }, function(data, status) {\n $log.debug('failed');\n });\n }\n }\n\n function cancel() {\n vm.component.$reset();\n if (vm.component.isNew) {\n // Cancelling the creation of a component\n vm.component = null;\n }\n $mdDialog.cancel();\n }\n\n function getDays() {\n var days = [];\n\n if (vm.component.start && vm.component.end)\n days = vm.component.start.daysUpTo(vm.component.end);\n\n return _.map(days, function(date) {\n return { stringWithSeparator: date.stringWithSeparator(),\n getDayString: date.getDayString() };\n });\n }\n\n function getHours() {\n var hours = [];\n for (var i = 0; i <= 23; i++) {\n //hours.push(Component.timeFormat.formatTime(i, 0));\n hours.push(i.toString());\n }\n return hours;\n }\n\n function addStartDate() {\n vm.component.$addStartDate();\n oldStartDate = new Date(vm.component.start.getTime());\n }\n\n function addDueDate() {\n vm.component.$addDueDate();\n oldDueDate = new Date(vm.component.due.getTime());\n }\n\n function updateStartTime() {\n // When using the datepicker, the time is reset to 00:00; restore it\n vm.component.start.addMinutes(oldStartDate.getHours() * 60 + oldStartDate.getMinutes());\n adjustStartTime();\n }\n\n function adjustStartTime() {\n // Preserve the delta between the start and end dates\n var delta;\n delta = oldStartDate.valueOf() - vm.component.start.valueOf();\n if (delta !== 0) {\n oldStartDate = new Date(vm.component.start.getTime());\n if (vm.component.type === 'appointment') {\n vm.component.end = new Date(vm.component.start.getTime());\n vm.component.end.addMinutes(vm.component.delta);\n oldEndDate = new Date(vm.component.end.getTime());\n }\n updateFreeBusy();\n }\n }\n\n function updateEndTime() {\n // When using the datepicker, the time is reset to 00:00; restore it\n vm.component.end.addMinutes(oldEndDate.getHours() * 60 + oldEndDate.getMinutes());\n adjustEndTime();\n }\n\n function adjustEndTime() {\n // The end date must be after the start date\n var delta = oldEndDate.valueOf() - vm.component.end.valueOf();\n if (delta !== 0) {\n delta = vm.component.start.minutesTo(vm.component.end);\n if (delta < 0)\n vm.component.end = new Date(oldEndDate.getTime());\n else {\n vm.component.delta = delta;\n oldEndDate = new Date(vm.component.end.getTime());\n }\n updateFreeBusy();\n }\n }\n\n function updateDueTime() {\n // When using the datepicker, the time is reset to 00:00; restore it\n vm.component.due.addMinutes(oldDueDate.getHours() * 60 + oldDueDate.getMinutes());\n adjustDueTime();\n }\n\n function adjustDueTime() {\n oldDueDate = new Date(vm.component.due.getTime());\n }\n\n function updateFreeBusy() {\n vm.attendeesEditor.days = getDays();\n vm.component.updateFreeBusy();\n }\n }\n\n angular\n .module('SOGo.SchedulerUI')\n .controller('ComponentController', ComponentController)\n .controller('ComponentEditorController', ComponentEditorController);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n /* jshint validthis: true */\n 'use strict';\n\n /*\n * sgCalendarDay - An element that represents a day in the calendar's view\n * @memberof SOGo.SchedulerUI\n * @restrict element\n * @param {string} sgDay - the day of the events to display (YYYYMMDD)\n * @param {string} sgDayString - the day in ISO8601 format (YYYY-MM-DDTHH:MM+-HH:MM)\n * @param {number} sgDayNumber - the day index within the calendar's view\n *\n * @example:\n\n <sg-calendar-day\n sg-day-string=\"2015-11-01T00:00-05:00\"\n sg-day-number=\"0\"\n sg-day=\"20151101\">\n ..\n </sg-calendar-day-table>\n */\n function sgCalendarDay() {\n return {\n restrict: 'E',\n scope: {\n day: '@sgDay',\n dayNumber: '@sgDayNumber',\n dayString: '@sgDayString',\n calendar: '@sgCalendar'\n },\n controller: sgCalendarDayController\n };\n }\n\n /**\n * @ngInject\n */\n sgCalendarDayController.$inject = ['$scope', 'Calendar'];\n function sgCalendarDayController($scope, Calendar) {\n // Expose some scope variables to the controller\n // See the sgCalendarDayTable directive\n this.day = $scope.day;\n this.dayNumber = $scope.dayNumber;\n this.dayString = $scope.dayString;\n this.calendarData = function() {\n var pid, index, activeCalendars;\n if ($scope.calendar) {\n // A calendar is associated to the day; identify its index among active calendars\n pid = $scope.calendar;\n activeCalendars = _.filter(Calendar.$findAll(), { active: 1 });\n index = _.findIndex(activeCalendars, function(calendar) {\n return calendar.id == pid;\n });\n return { pid: pid, index: index };\n }\n\n return null;\n };\n }\n\n angular\n .module('SOGo.SchedulerUI')\n .directive('sgCalendarDay', sgCalendarDay);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /*\n * sgCalendarDayBlock - An event block to be displayed in a week\n * @memberof SOGo.SchedulerUI\n * @restrict element\n * @param {object} sgBlock - the event block definition\n * @param {function} sgClick - the function to call when clicking on a block.\n * Two variables are available: clickEvent (the event that triggered the mouse click),\n * and clickComponent (a Component object)\n *\n * @example:\n\n <sg-calendar-day-block\n ng-repeat=\"block in blocks[day]\"\n sg-block=\"block\"\n sg-click=\"open(clickEvent, clickComponent)\" />\n */\n sgCalendarDayBlock.$inject = ['CalendarSettings'];\n function sgCalendarDayBlock(CalendarSettings) {\n return {\n restrict: 'E',\n scope: {\n block: '=sgBlock',\n clickBlock: '&sgClick'\n },\n replace: true,\n template: [\n '<div class=\"sg-event\"',\n // Add a class while dragging\n ' ng-class=\"{\\'sg-event--dragging\\': block.dragging}\">',\n ' <div class=\"eventInside\"',\n ' ng-click=\"clickBlock({clickEvent: $event, clickComponent: block.component})\">',\n // Categories color stripes\n ' <div class=\"sg-category\" ng-repeat=\"category in block.component.categories\"',\n ' ng-class=\"\\'bg-category\\' + category\"',\n ' ng-style=\"{ right: ($index * 3) + \\'px\\' }\"></div>',\n ' <div class=\"text\">{{ block.component.summary }}',\n ' <span class=\"icons\">',\n // Component is reccurent\n ' <md-icon ng-if=\"block.component.occurrenceId\" class=\"material-icons icon-repeat\"></md-icon>',\n // Component has an alarm\n ' <md-icon ng-if=\"block.component.c_nextalarm\" class=\"material-icons icon-alarm\"></md-icon>',\n // Component is confidential\n ' <md-icon ng-if=\"block.component.c_classification == 1\" class=\"material-icons icon-visibility-off\"></md-icon>',\n // Component is private\n ' <md-icon ng-if=\"block.component.c_classification == 2\" class=\"material-icons icon-vpn-key\"></md-icon>',\n ' </span>',\n // Location\n ' <div class=\"secondary\" ng-if=\"block.component.c_location\">',\n ' <md-icon>place</md-icon> {{block.component.c_location}}',\n ' </div>',\n ' </div>',\n ' </div>',\n ' <div class=\"ghostStartHour\" ng-if=\"block.startHour\">{{ block.startHour }}</div>',\n ' <div class=\"ghostEndHour\" ng-if=\"block.endHour\">{{ block.endHour }}</div>',\n '</div>'\n ].join(''),\n link: link\n };\n\n function link(scope, iElement, attrs) {\n var pc, left, right;\n\n // Compute overlapping (2%)\n pc = 100 / scope.block.siblings;\n left = scope.block.position * pc;\n right = 100 - (scope.block.position + 1) * pc;\n if (pc < 100) {\n if (left > 0)\n left -= 2;\n if (right > 0)\n right -= 2;\n }\n\n // Add some padding (2%)\n if (left === 0)\n left = 2;\n if (right === 0)\n right = 2;\n\n // Set position\n iElement.css('left', left + '%');\n iElement.css('right', right + '%');\n iElement.addClass('starts' + scope.block.start);\n iElement.addClass('lasts' + scope.block.length);\n\n // Set background color\n if (scope.block.component)\n iElement.addClass('bg-folder' + scope.block.component.pid);\n }\n }\n\n angular\n .module('SOGo.SchedulerUI')\n .directive('sgCalendarDayBlock', sgCalendarDayBlock);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /*\n * sgCalendarDayTable - Build list of blocks for a specific day\n * @memberof SOGo.SchedulerUI\n * @restrict element\n * @param {object} sgBlocks - the events blocks definitions for the current view\n * @param {string} sgDay - the day of the events to display\n * @param {function} sgClick - the function to call when clicking on a block.\n * Two variables are available: event (the event that triggered the mouse click),\n * and component (a Component object)\n *\n * @example:\n\n <sg-calendar-day-table\n sg-blocks=\"calendar.blocks\"\n sg-day=\"20150330\"\n sg-click=\"open({ event: clickEvent, component: clickComponent })\"/>\n */\n function sgCalendarDayTable() {\n return {\n restrict: 'E',\n scope: {\n blocks: '=sgBlocks',\n day: '@sgDay',\n clickBlock: '&sgClick'\n },\n template: [\n '<sg-calendar-day-block',\n ' class=\"sg-draggable-calendar-block\"',\n ' ng-repeat=\"block in blocks[day]\"',\n ' sg-block=\"block\"',\n ' sg-click=\"clickBlock({event: clickEvent, component: clickComponent})\"/>'\n ].join('')\n };\n }\n\n angular\n .module('SOGo.SchedulerUI')\n .directive('sgCalendarDayTable', sgCalendarDayTable);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /*\n * sgCalendarBlock - Applied to an event ghost block to be displayed while dragging an event block. Each day of the\n * calendar's view must have a ghost block.\n * @memberof SOGo.SchedulerUI\n * @restrict attribute\n *\n * @example:\n\n <sg-calendar-day-block\n sg-calendar-ghost\n sg-block=\"list.component.$ghost\">/\n */\n sgCalendarGhost.$inject = ['$rootScope', '$timeout', 'CalendarSettings', 'Calendar', 'Component'];\n function sgCalendarGhost($rootScope, $timeout, CalendarSettings, Calendar, Component) {\n return {\n restrict: 'A',\n require: ['^sgCalendarDay', '^sgCalendarScrollView'],\n link: link\n };\n\n function link(scope, iElement, attrs, ctrls) {\n var domElement, calendarDayCtrl, scrollViewCtrl, calendarNumber, originalCalendarNumber;\n\n domElement = iElement[0];\n calendarDayCtrl = ctrls[0];\n scrollViewCtrl = ctrls[1];\n calendarNumber = -1;\n\n iElement.addClass('sg-event--ghost md-whiteframe-3dp ng-hide');\n\n // Listen on drag gestures\n var deregisterDragStart = $rootScope.$on('calendar:dragstart', initGhost);\n var deregisterDrag = $rootScope.$on('calendar:drag', updateGhost);\n var deregisterDragEnd = $rootScope.$on('calendar:dragend', hideGhost);\n\n // Deregister listeners on destroy\n scope.$on('$destroy', function() {\n deregisterDragStart();\n deregisterDrag();\n deregisterDragEnd();\n });\n\n function initGhost() {\n var pid, calendarData;\n\n // Expose ghost block to the scope\n scope.block = Component.$ghost;\n\n calendarData = calendarDayCtrl.calendarData();\n if (calendarData) {\n // A calendar is associated to the day; this is a special multicolumn day view\n calendarNumber = calendarData.index;\n pid = calendarData.pid;\n originalCalendarNumber = scope.block.pointerHandler.originalCalendar.index;\n }\n\n if (!pid)\n pid = scope.block.component.pid;\n\n // Set background color\n iElement.addClass('bg-folder' + pid);\n }\n\n function hideGhost() {\n // Remove background color\n _.forEachRight(domElement.classList, function(c) {\n if (/^bg-folder/.test(c))\n iElement.removeClass(c);\n });\n // Hide ghost\n iElement.addClass('ng-hide');\n }\n\n function updateGhost() {\n // From SOGoEventDragGhostController._updateGhosts\n var showGhost, isRelative, originalDay, currentDay, wasOtherBlock,\n start, duration, durationLeft, maxDuration, enableTransition;\n\n showGhost = false;\n enableTransition = function() {\n iElement.removeClass('sg-event--notransition');\n };\n\n if (Calendar.$view && Calendar.$view.type == scrollViewCtrl.type) {\n // The view of the dragging block is the scrolling view of this ghost block\n\n isRelative = scrollViewCtrl.type === 'multiday-allday';\n originalDay = scope.block.pointerHandler.originalEventCoordinates.dayNumber;\n currentDay = scope.block.pointerHandler.currentEventCoordinates.dayNumber;\n start = scope.block.pointerHandler.currentEventCoordinates.start;\n durationLeft = scope.block.pointerHandler.currentEventCoordinates.duration;\n maxDuration = CalendarSettings.EventDragDayLength - start;\n\n if (angular.isUndefined(durationLeft))\n return;\n\n duration = durationLeft;\n if (duration > maxDuration)\n duration = maxDuration;\n\n if (currentDay > -1 && // pointer is inside viewport\n ((calendarNumber < 0 && // day is not associated to a calendar\n currentDay == calendarDayCtrl.dayNumber) || // pointer is inside ghost's day\n currentDay == calendarNumber && // pointer is inside ghost's calendar\n (originalCalendarNumber == calendarNumber || // still inside original calendar\n !scope.block.component.isException) // not an exception, event can be moved to a\n // different calendar\n )) {\n // This ghost block (day) is the first of the dragging event\n showGhost = true;\n if (!isRelative) {\n // Show start hour and set the vertical position\n scope.block.startHour = getStartTime(start);\n wasOtherBlock = parseInt(iElement.css('top')) === 0;\n if (wasOtherBlock)\n iElement.addClass('sg-event--notransition');\n // Set the height\n if (Calendar.$view.quarterHeight) {\n iElement.css('top', (start * Calendar.$view.quarterHeight) + 'px');\n iElement.css('height', (duration * Calendar.$view.quarterHeight) + 'px');\n }\n else\n iElement.css('top', Calendar.$view.topOffset + 'px');\n if (wasOtherBlock)\n $timeout(enableTransition);\n }\n iElement.removeClass('fg-folder' + scope.block.component.pid);\n iElement.removeClass('sg-event--ghost--last');\n iElement.addClass('sg-event--ghost--first');\n }\n\n durationLeft -= duration;\n currentDay++;\n\n // Search a subsequent block that matches the current ghost's day\n while (!showGhost && durationLeft && currentDay <= calendarDayCtrl.dayNumber) {\n duration = durationLeft;\n if (duration > CalendarSettings.EventDragDayLength)\n duration = CalendarSettings.EventDragDayLength;\n if (currentDay > -1 && currentDay == calendarDayCtrl.dayNumber) {\n // The dragging event overlaps this current ghost's day\n showGhost = true;\n if (!isRelative) {\n wasOtherBlock = parseInt(iElement.css('top')) !== 0;\n if (wasOtherBlock)\n iElement.addClass('sg-event--notransition');\n iElement.css('top', Calendar.$view.topOffset + 'px');\n // Set the height\n if (Calendar.$view.quarterHeight)\n iElement.css('height', (duration * Calendar.$view.quarterHeight) + 'px');\n if (wasOtherBlock)\n $timeout(enableTransition);\n }\n iElement.removeClass('sg-event--ghost--first');\n iElement.removeClass('sg-event--ghost--last');\n // Trick for all-day events: set the foreground color to the background color so the event's title\n // is not visible but the div size remains identical.\n iElement.addClass('fg-folder' + scope.block.component.pid);\n }\n durationLeft -= duration;\n currentDay++;\n start = 0;\n }\n if (!durationLeft) {\n // Reached last ghost block\n if (isRelative) {\n iElement.addClass('sg-event--ghost--last');\n }\n else {\n // Set the end date\n scope.block.endHour = getEndTime(start, duration);\n }\n }\n }\n\n if (showGhost)\n iElement.removeClass('ng-hide');\n else\n iElement.addClass('ng-hide');\n }\n\n function quartersToHM(quarters) {\n var minutes, hours, mins;\n\n minutes = quarters * 15;\n hours = Math.floor(minutes / 60);\n if (hours < 10)\n hours = \"0\" + hours;\n mins = minutes % 60;\n if (mins < 10)\n mins = \"0\" + mins;\n\n return \"\" + hours + \":\" + mins;\n }\n\n function getStartTime(start) {\n return quartersToHM(start);\n }\n\n function getEndTime(start, duration) {\n var end = (start + duration) % CalendarSettings.EventDragDayLength;\n return quartersToHM(end);\n }\n }\n }\n\n angular\n .module('SOGo.SchedulerUI')\n .directive('sgCalendarGhost', sgCalendarGhost);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /*\n * sgCalendarMonthDay - Build list of blocks for a specific day in a month\n * @memberof SOGo.Common\n * @restrict element\n * @param {object} sgBlocks - the events blocks definitions for the current view\n * @param {string} sgDay - the day of the events to display\n * @ngInject\n * @example:\n\n <sg-calendar-monh-day\n sg-blocks=\"calendar.blocks\"\n sg-day=\"20150408\"\n sg-click=\"open({ event: clickEvent, component: clickComponent })\"/>\n */\n function sgCalendarMonthDay() {\n return {\n restrict: 'E',\n scope: {\n blocks: '=sgBlocks',\n day: '@sgDay',\n clickBlock: '&sgClick'\n },\n template: [\n '<sg-calendar-month-event',\n ' class=\"sg-draggable-calendar-block\"',\n ' ng-repeat=\"block in blocks[day]\"',\n ' sg-block=\"block\"',\n ' sg-click=\"clickBlock({event: clickEvent, component: clickComponent})\"/>'\n ].join('')\n };\n }\n\n angular\n .module('SOGo.SchedulerUI')\n .directive('sgCalendarMonthDay', sgCalendarMonthDay);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /*\n * sgCalendarMonthEvent - An event block to be displayed in a month\n * @memberof SOGo.Common\n * @restrict element\n * @param {object} sgBlock - the event block definition\n * @ngInject\n * @example:\n\n <sg-calendar-month-event\n ng-repeat=\"block in blocks[day]\"\n sg-block=\"block\"/>\n */\n function sgCalendarMonthEvent() {\n return {\n restrict: 'E',\n scope: {\n block: '=sgBlock',\n clickBlock: '&sgClick'\n },\n replace: true,\n template: [\n '<div class=\"sg-event\"',\n // Add a class while dragging\n ' ng-class=\"{\\'sg-event--dragging\\': block.dragging}\"',\n ' ng-click=\"clickBlock({clickEvent: $event, clickComponent: block.component})\">',\n ' <span class=\"secondary\" ng-if=\"!block.component.c_isallday\">{{ block.starthour }}</span>',\n ' {{ block.component.summary }}',\n ' <span class=\"icons\">',\n // Component is reccurent\n ' <md-icon ng-if=\"block.component.occurrenceId\" class=\"material-icons icon-repeat\"></md-icon>',\n // Component has an alarm\n ' <md-icon ng-if=\"block.component.c_nextalarm\" class=\"material-icons icon-alarm\"></md-icon>',\n // Component is confidential\n ' <md-icon ng-if=\"block.component.c_classification == 1\" class=\"material-icons icon-visibility-off\"></md-icon>',\n // Component is private\n ' <md-icon ng-if=\"block.component.c_classification == 2\" class=\"material-icons icon-vpn-key\"></md-icon>',\n ' </span>',\n '</div>'\n ].join(''),\n link: link\n };\n\n function link(scope, iElement, attrs) {\n if (scope.block.component)\n iElement.addClass('bg-folder' + scope.block.component.pid);\n }\n }\n\n angular\n .module('SOGo.SchedulerUI')\n .directive('sgCalendarMonthEvent', sgCalendarMonthEvent);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n /* jshint validthis: true */\n 'use strict';\n\n /*\n * sgCalendarScrollView - scrollable view that contains draggable elements\n * @memberof SOGo.SchedulerUI\n * @restrict attribute\n * @param {string} sgCalendarScrollView - the view type (multiday, multiday-allday, or monthly)\n *\n * @example:\n\n <md-content sg-calendar-scroll-view=\"multiday\">\n ..\n </md-content>\n */\n sgCalendarScrollView.$inject = ['$rootScope', '$window', '$document', '$q', '$timeout', '$mdGesture', 'Calendar', 'Component', 'Preferences'];\n function sgCalendarScrollView($rootScope, $window, $document, $q, $timeout, $mdGesture, Calendar, Component, Preferences) {\n return {\n restrict: 'A',\n scope: {\n type: '@sgCalendarScrollView'\n },\n controller: sgCalendarScrollViewController,\n link: function(scope, element, attrs, controller) {\n var view, scrollView, type, lastScroll, deregisterDragStart, deregisterDragStop;\n\n scrollView = element[0];\n type = scope.type; // multiday, multiday-allday, monthly, unknown?\n lastScroll = 0;\n\n // Listen to dragstart and dragend events\n deregisterDragStart = $rootScope.$on('calendar:dragstart', onDragStart);\n deregisterDragStop = $rootScope.$on('calendar:dragend', onDragEnd);\n\n // Update the \"view\" object literal once the Angular template has been transformed\n $timeout(initView);\n\n // Deregister listeners when destroying the view\n scope.$on('$destroy', function() {\n deregisterDragStart();\n deregisterDragStop();\n element.off('mouseover', updateFromPointerHandler);\n angular.element($window).off('resize', updateCoordinates);\n });\n\n function initView() {\n var quarterHeight;\n\n // Quarter height doesn't change if window is resize; compute it only once\n quarterHeight = getQuarterHeight();\n\n view = {\n type: type,\n quarterHeight: quarterHeight,\n scrollStep: 6 * quarterHeight,\n maxX: getMaxColumns(),\n\n // Expose a reference of the view element\n element: scrollView\n };\n\n // Compute coordinates of view element; recompute it on window resize\n angular.element($window).on('resize', updateCoordinates);\n updateCoordinates();\n\n if (type != 'monthly')\n // Scroll to the day start hour defined in the user's defaults\n Preferences.ready().then(function() {\n var time, hourCell, quartersOffset;\n if (Preferences.defaults.SOGoDayStartTime) {\n time = Preferences.defaults.SOGoDayStartTime.split(':');\n hourCell = document.getElementById('hour' + parseInt(time[0]));\n quartersOffset = parseInt(time[1]) * quarterHeight;\n scrollView.scrollTop = hourCell.offsetTop + quartersOffset;\n }\n });\n }\n\n function getQuarterHeight() {\n var hour0, hour23, height = null;\n\n hour0 = document.getElementById('hour0');\n hour23 = document.getElementById('hour23');\n if (hour0 && hour23)\n height = ((hour23.offsetTop - hour0.offsetTop) / (23 * 4));\n\n return height;\n }\n\n function getDayDimensions(viewLeft) {\n var width, height, leftOffset, topOffset, nodes, domRect, tileHeader;\n\n height = width = leftOffset = topOffset = 0;\n nodes = scrollView.getElementsByClassName('day0');\n\n if (nodes.length > 0) {\n domRect = nodes[0].getBoundingClientRect();\n height = domRect.height;\n width = domRect.width;\n leftOffset = domRect.left - viewLeft;\n tileHeader = nodes[0].getElementsByClassName('sg-calendar-tile-header');\n if (tileHeader.length > 0)\n topOffset = tileHeader[0].clientHeight;\n }\n\n return { height: height, width: width, offset: { left: leftOffset, top: topOffset } };\n }\n\n function getMaxColumns() {\n var max = 0;\n\n //if (type == 'multiday') {\n max = scrollView.getElementsByClassName('day').length - 1;\n //}\n\n return max;\n }\n\n // View has been resized;\n // Compute the view's origins (x, y), a day's dimensions and left margin.\n function updateCoordinates() {\n var domRect, dayDimensions;\n\n domRect = scrollView.getBoundingClientRect();\n dayDimensions = getDayDimensions(domRect.left);\n\n angular.extend(view, {\n coordinates: {\n x: domRect.left,\n y: domRect.top\n },\n dayHeight: dayDimensions.height,\n dayWidth: dayDimensions.width,\n daysOffset: dayDimensions.offset.left,\n topOffset: dayDimensions.offset.top\n });\n }\n\n function onDragStart() {\n element.on('mouseover', updateFromPointerHandler);\n updateFromPointerHandler();\n }\n\n function onDragEnd() {\n element.off('mouseover', updateFromPointerHandler);\n Calendar.$view = null;\n }\n\n // From SOGoScrollController.updateFromPointerHandler\n function updateFromPointerHandler() {\n var scrollStep, pointerHandler, pointerCoordinates, now, scrollY, minY, delta;\n\n scrollStep = view.scrollStep;\n pointerHandler = Component.$ghost.pointerHandler;\n if (pointerHandler) {\n pointerCoordinates = pointerHandler.getContainerBasedCoordinates(view);\n\n if (pointerCoordinates) {\n // Pointer is inside view; Adjust scrollbar if necessary\n Calendar.$view = view;\n now = new Date().getTime();\n if (!lastScroll || now > lastScroll + 100) {\n lastScroll = now;\n scrollY = pointerCoordinates.y - scrollStep;\n if (scrollY < 0) {\n minY = -scrollView.scrollTop;\n if (scrollY < minY)\n scrollY = minY;\n scrollView.scrollTop += scrollY;\n }\n else {\n scrollY = pointerCoordinates.y + scrollStep;\n delta = scrollY - scrollView.clientHeight;\n if (delta > 0) {\n scrollView.scrollTop += delta;\n }\n }\n }\n }\n }\n }\n }\n };\n }\n\n sgCalendarScrollViewController.$inject = ['$scope'];\n function sgCalendarScrollViewController($scope) {\n // Expose the view type to the controller\n // See sgCalendarDayBlockGhost\n this.type = $scope.type;\n }\n\n angular\n .module('SOGo.SchedulerUI')\n .directive('sgCalendarScrollView', sgCalendarScrollView);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /*\n * sgCalendarDayTable - Build list of blocks for a specific day\n * @memberof SOGo.Common\n * @restrict element\n * @param {object} sgBlocks - the events blocks definitions for the current view\n * @param {string} sgDay - the day of the events to display\n * @param {function} sgClick - the function to call when clicking on a block.\n * Two variables are available: event (the event that triggered the mouse click),\n * and component (a Component object)\n *\n * @example:\n\n <sg-calendar-day-table\n sg-blocks=\"calendar.blocks\"\n sg-day=\"20150330\"\n sg-click=\"open({ event: clickEvent, component: clickComponent })\"/>\n */\n function sgCalendarTable() {\n return {\n restrict: 'E',\n scope: {\n calendars: '=sgCalendars',\n calendar: '@sgCalendar',\n blocksType: '@sgBlocksType',\n day: '@sgDay',\n clickBlock: '&sgClick'\n },\n template: [\n '<sg-calendar-day-table',\n ' sg-blocks=\"calendars[calendar][blocksType]\"',\n ' sg-day=\"day\"',\n ' sg-click=\"clickBlock({event: clickEvent, component: clickComponent})\"/>'\n ].join('')\n };\n }\n\n angular\n .module('SOGo.SchedulerUI')\n .directive('sgCalendarTable', sgCalendarTable);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n /* jshint validthis: true */\n 'use strict';\n\n /*\n * sgCategoryStylesheet - Add CSS stylesheet for a category's color\n * @memberof SOGo.SchedulerUI\n * @restrict attribute\n * @param {object} ngModel - the object literal describing the category\n * @example:\n\n <sg-category-stylesheet\n ng-repeat=\"category in categories\"\n ng-model=\"category\" />\n */\n function sgCategoryStylesheet() {\n return {\n restrict: 'E',\n require: 'ngModel',\n scope: {\n ngModel: '='\n },\n replace: true,\n template: [\n '<style type=\"text/css\">',\n /* Background color */\n ' .bg-category{{ ngModel.id }} {',\n ' background-color: {{ ngModel.color }} !important;',\n ' }',\n /* Border color */\n ' .bdr-category{{ ngModel.id }} {',\n ' border-color: {{ ngModel.color }} !important;',\n ' }',\n '</style>'\n ].join('')\n };\n }\n\n angular\n .module('SOGo.SchedulerUI')\n .directive('sgCategoryStylesheet', sgCategoryStylesheet);\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /*\n * sgDraggableCalendarBlock - Make an element draggable\n * @memberof SOGo.SchedulerUI\n * @restrict class or attribute\n *\n * @example:\n\n <div class=\"sg-draggable-calendar-block\"/>\n */\n sgDraggableCalendarBlock.$inject = ['$rootScope', '$timeout', '$log', 'Preferences', 'Calendar', 'CalendarSettings', 'Component'];\n function sgDraggableCalendarBlock($rootScope, $timeout, $log, Preferences, Calendar, CalendarSettings, Component) {\n return {\n restrict: 'CA',\n require: '^sgCalendarDay',\n link: link\n };\n\n function link(scope, element, attrs, calendarDayCtrl) {\n if (scope.block) {\n if (scope.block.component.editable) {\n // Add dragging grips to existing event block\n initGrips();\n }\n else {\n element.removeClass('sg-draggable-calendar-block');\n return;\n }\n }\n\n // Start dragging on mousedown\n element.on('mousedown', onDragDetect);\n\n // Deregister listeners when removing the element from the DOM\n scope.$on('$destroy', function() {\n element.off('mousedown', onDragDetect);\n element.off('mousemove', onDrag);\n });\n\n function initGrips() {\n var component, dayNumber, blockIndex, isFirstBlock, isLastBlock,\n dragGrip, leftGrip, rightGrip, topGrip, bottomGrip;\n\n component = scope.block.component;\n dayNumber = scope.block.dayNumber;\n blockIndex = _.findIndex(component.blocks, _.matchesProperty('dayNumber', dayNumber));\n isFirstBlock = (blockIndex === 0);\n isLastBlock = (blockIndex === component.blocks.length - 1);\n\n dragGrip = angular.element('<div class=\"dragGrip\"></div>');\n dragGrip.addClass('bdr-folder' + component.pid);\n\n if (component.c_isallday ||\n element[0].parentNode.tagName === 'SG-CALENDAR-MONTH-DAY') {\n if (isFirstBlock) {\n leftGrip = angular.element('<div class=\"dragGrip-left\"></div>').append(dragGrip);\n element.append(leftGrip);\n }\n if (isLastBlock) {\n rightGrip = angular.element('<div class=\"dragGrip-right\"></div>').append(dragGrip.clone());\n element.append(rightGrip);\n }\n }\n else {\n if (isFirstBlock) {\n topGrip = angular.element('<div class=\"dragGrip-top\"></div>').append(dragGrip);\n element.append(topGrip);\n }\n if (isLastBlock) {\n bottomGrip = angular.element('<div class=\"dragGrip-bottom\"></div>').append(dragGrip.clone());\n element.append(bottomGrip);\n }\n }\n }\n\n function onDragDetect(ev) {\n var block, dragMode, eventType, startDate, newData, newComponent, pointerHandler;\n\n ev.stopPropagation();\n\n dragMode = 'move-event';\n \n if (scope.block && scope.block.component) {\n // Move or resize existing component\n if (ev.target.className == 'dragGrip-top' ||\n ev.target.className == 'dragGrip-left')\n dragMode = 'change-start';\n else if (ev.target.className == 'dragGrip-bottom' ||\n ev.target.className == 'dragGrip-right' )\n dragMode = 'change-end';\n }\n else {\n // Create new component from dragging\n dragMode = 'change-end';\n }\n\n // Initialize pointer handler\n pointerHandler = new SOGoEventDragPointerHandler(dragMode);\n pointerHandler.initFromEvent(ev);\n\n // Update Component.$ghost\n Component.$ghost.pointerHandler = pointerHandler;\n\n // Stop dragging on the next \"mouseup\"\n angular.element(document).one('mouseup', onDragEnd);\n\n // Listen to mousemove and start dragging when mouse has moved from at least 3 pixels\n angular.element(document).on('mousemove', onDrag);\n }\n\n function dragStart(ev) {\n var block, dragMode, eventType, isHourCell, isMonthly, startDate, newData, newComponent, pointerHandler, calendarData;\n\n isHourCell = element.hasClass('clickableHourCell');\n isMonthly = (element[0].parentNode.tagName == 'SG-CALENDAR-MONTH-DAY') ||\n element.hasClass('clickableDayCell');\n\n calendarData = calendarDayCtrl.calendarData();\n\n if (scope.block && scope.block.component) {\n // Move or resize existing component\n block = scope.block;\n }\n else {\n // Create new component from dragging\n startDate = calendarDayCtrl.dayString.parseDate(Preferences.$mdDateLocaleProvider, '%Y-%m-%e');\n newData = {\n type: 'appointment',\n pid: calendarData? calendarData.pid : Calendar.$defaultCalendar(),\n //summary: l('New Event'),\n startDate: startDate,\n isAllDay: isHourCell? 0 : 1\n };\n newComponent = new Component(newData);\n block = {\n component: newComponent,\n dayNumber: calendarDayCtrl.dayNumber,\n length: 0\n };\n block.component.blocks = [block];\n }\n\n // Determine event type\n eventType = 'multiday';\n if (isMonthly)\n eventType = 'monthly';\n else if (block.component.c_isallday)\n eventType = 'multiday-allday';\n\n // Mark all blocks as being dragged\n _.forEach(block.component.blocks, function(b) {\n b.dragging = true;\n });\n\n // Update pointer handler\n pointerHandler = Component.$ghost.pointerHandler;\n pointerHandler.prepareWithEventType(eventType);\n pointerHandler.initFromBlock(block);\n if (calendarData)\n // When the day is associated to a calendar, the day number becomes the calendar index\n // among the active calendars\n pointerHandler.initFromCalendar(calendarData);\n\n // Update Component.$ghost\n Component.$ghost.starthour = block.starthour;\n Component.$ghost.component = block.component;\n\n $log.debug('emit calendar:dragstart ' + eventType + ' ' + dragMode);\n $rootScope.$emit('calendar:dragstart');\n }\n\n function onDrag(ev) {\n var pointerHandler = Component.$ghost.pointerHandler;\n\n // Update\n // - currentCoordinates\n // - currentViewCoordinates\n // - currentEventCoordinates\n $timeout(function() {\n pointerHandler.updateFromEvent(ev);\n });\n }\n\n function onDragEnd(ev) {\n var block, pointer;\n\n block = scope.block;\n pointer = Component.$ghost.pointerHandler;\n\n // Deregister mouse events\n angular.element(document).off('mousemove', onDrag);\n\n if (pointer.dragHasStarted) {\n $rootScope.$emit('calendar:dragend');\n pointer.dragHasStarted = false;\n }\n\n // Unmark all blocks as being dragged\n if (block && block.component)\n _.forEach(block.component.blocks, function(b) {\n b.dragging = false;\n });\n }\n\n /**\n * SOGoCoordinates\n */\n function SOGoCoordinates() {\n }\n\n SOGoCoordinates.prototype = {\n x: -1,\n y: -1,\n\n getDelta: function SC_getDelta(otherCoordinates) {\n var delta = new SOGoCoordinates();\n delta.x = this.x - otherCoordinates.x;\n delta.y = this.y - otherCoordinates.y;\n\n return delta;\n },\n\n getDistance: function SC_getDistance(otherCoordinates) {\n var delta = this.getDelta(otherCoordinates);\n\n return Math.sqrt(delta.x * delta.x + delta.y * delta.y);\n },\n\n clone: function SC_clone() {\n var coordinates = new SOGoCoordinates();\n coordinates.x = this.x;\n coordinates.y = this.y;\n\n return coordinates;\n }\n };\n\n /**\n * SOGoEventDragEventCoordinates\n */\n function SOGoEventDragEventCoordinates(eventType) {\n this.setEventType(eventType);\n }\n\n SOGoEventDragEventCoordinates.prototype = {\n dayNumber: -1,\n start: -1,\n duration: -1,\n\n eventType: null,\n\n setEventType: function(eventType) {\n this.eventType = eventType;\n },\n\n initFromBlock: function(block) {\n if (this.eventType === 'monthly') {\n this.start = 0;\n this.duration = block.component.blocks.length * 96;\n }\n else {\n // Get the start (first quarter) from the event's first block\n // Compute overall length\n this.start = block.component.blocks[0].start;\n this.duration = _.sum(block.component.blocks, function(b) {\n return b.length;\n });\n }\n\n // Get the dayNumber from the event's first block\n this.dayNumber = block.component.blocks[0].dayNumber;\n },\n\n initFromCalendar: function(calendarNumber) {\n this.dayNumber = calendarNumber;\n },\n\n getDelta: function(otherCoordinates) {\n var delta = new SOGoEventDragEventCoordinates();\n delta.dayNumber = (this.dayNumber - otherCoordinates.dayNumber);\n delta.start = (this.start - otherCoordinates.start);\n delta.duration = (this.duration - otherCoordinates.duration);\n\n return delta;\n },\n\n _quartersToHM: function(quarters) {\n var minutes = quarters * 15;\n var hours = Math.floor(minutes / 60);\n if (hours < 10)\n hours = \"0\" + hours;\n var mins = minutes % 60;\n if (mins < 10)\n mins = \"0\" + mins;\n\n return \"\" + hours + \":\" + mins;\n },\n\n getStartTime: function() {\n return this._quartersToHM(this.start);\n },\n\n getEndTime: function() {\n var end = (this.start + this.duration) % CalendarSettings.EventDragDayLength;\n return this._quartersToHM(end);\n },\n\n clone: function() {\n var coordinates = new SOGoEventDragEventCoordinates();\n coordinates.dayNumber = this.dayNumber;\n coordinates.start = this.start;\n coordinates.duration = this.duration;\n\n return coordinates;\n }\n };\n\n /**\n * SOGoEventDragPointerHandler\n */\n function SOGoEventDragPointerHandler(dragMode) {\n this.dragMode = dragMode;\n }\n\n SOGoEventDragPointerHandler.prototype = {\n // Pointer absolute xy coordinates within page\n originalCoordinates: null,\n currentCoordinates: null,\n\n // Pointer relative xy coordinates within view (row-column)\n originalViewCoordinates: null,\n currentViewCoordinates: null,\n\n // Event start-duration coordinates\n originalEventCoordinates: null,\n currentEventCoordinates: null,\n\n originalCalendar: null,\n\n dragHasStarted: false,\n\n // Function to return the day and quarter coordinates of the pointer cursor\n // within the day view\n getEventViewCoordinates: null,\n\n initFromBlock: function SEDPH_initFromBlock(block) {\n this.currentEventCoordinates = new SOGoEventDragEventCoordinates(this.eventType);\n this.originalEventCoordinates = new SOGoEventDragEventCoordinates(this.eventType);\n this.originalEventCoordinates.initFromBlock(block);\n },\n\n initFromEvent: function SEDPH_initFromEvent(event) {\n this.currentCoordinates = new SOGoCoordinates();\n this.updateFromEvent(event);\n this.originalCoordinates = this.currentCoordinates.clone();\n },\n\n initFromCalendar: function SEDPH_initFromCalendar(calendarData) {\n this.originalCalendar = calendarData;\n this.currentEventCoordinates.initFromCalendar(calendarData.index);\n this.originalEventCoordinates.initFromCalendar(calendarData.index);\n },\n\n // Method continuously called while dragging\n updateFromEvent: function SEDPH_updateFromEvent(event) {\n // Event here is a DOM event, not a calendar event!\n this.currentCoordinates.x = event.pageX;\n this.currentCoordinates.y = event.pageY;\n\n // From SOGoEventDragGhostController.updateFromPointerHandler\n if (this.dragHasStarted && Calendar.$view) {\n var newEventCoordinates = this.getEventViewCoordinates(Calendar.$view);\n if (!this.originalViewCoordinates) {\n this.originalViewCoordinates = this.getEventViewCoordinates(Calendar.$view, this.originalCoordinates);\n if (Component.$ghost.component.isNew) {\n this.setTimeFromQuarters(Component.$ghost.component.start, this.originalViewCoordinates.y);\n $log.debug('new event start date ' + Component.$ghost.component.start);\n }\n }\n if (!this.currentViewCoordinates ||\n !newEventCoordinates ||\n newEventCoordinates.x != this.currentViewCoordinates.x ||\n newEventCoordinates.y != this.currentViewCoordinates.y) {\n this.currentViewCoordinates = newEventCoordinates;\n if (this.originalViewCoordinates) {\n if (!newEventCoordinates) {\n this.currentViewCoordinates = this.originalViewCoordinates.clone();\n }\n this.updateEventCoordinates();\n }\n }\n }\n else if (this.originalCoordinates &&\n this.currentCoordinates &&\n !this.dragHasStarted) {\n var distance = this.getDistance();\n if (distance > 3) {\n this.dragHasStarted = true;\n dragStart(event);\n }\n }\n },\n\n // SOGoEventDragGhostController._updateCoordinates\n // Extend this.currentCoordinates with start, dayNumber and duration\n updateEventCoordinates: function SEDGC__updateCoordinates() {\n var newDuration;\n\n // Compute delta wrt to position of mouse at dragstart on the day/quarter grid\n var delta = this.currentViewCoordinates.getDelta(this.originalViewCoordinates);\n var deltaQuarters = delta.x * CalendarSettings.EventDragDayLength + delta.y;\n $log.debug('quarters delta ' + deltaQuarters);\n\n if (angular.isUndefined(this.originalEventCoordinates.start)) {\n this.originalEventCoordinates.dayNumber = this.originalViewCoordinates.x;\n this.originalEventCoordinates.start = this.originalViewCoordinates.y;\n }\n // if (currentView == \"multicolumndayview\")\n // this._updateMulticolumnViewDayNumber_SEDGC();\n // else\n this.currentEventCoordinates.dayNumber = this.originalEventCoordinates.dayNumber;\n\n if (this.dragMode == \"move-event\") {\n this.currentEventCoordinates.start = this.originalEventCoordinates.start + deltaQuarters;\n this.currentEventCoordinates.duration = this.originalEventCoordinates.duration;\n }\n else {\n if (this.dragMode == \"change-start\") {\n newDuration = this.originalEventCoordinates.duration - deltaQuarters;\n if (newDuration > 0) {\n this.currentEventCoordinates.start = this.originalEventCoordinates.start + deltaQuarters;\n this.currentEventCoordinates.duration = newDuration;\n }\n else if (newDuration < 0) {\n this.currentEventCoordinates.start = (this.originalEventCoordinates.start + this.originalEventCoordinates.duration);\n this.currentEventCoordinates.duration = -newDuration;\n }\n }\n else if (this.dragMode == \"change-end\") {\n newDuration = this.originalEventCoordinates.duration + deltaQuarters;\n if (newDuration > 0) {\n this.currentEventCoordinates.start = this.originalEventCoordinates.start;\n this.currentEventCoordinates.duration = newDuration;\n }\n else if (newDuration < 0) {\n this.currentEventCoordinates.start = this.originalEventCoordinates.start + newDuration;\n this.currentEventCoordinates.duration = -newDuration;\n }\n }\n }\n\n var deltaDays;\n if (this.currentEventCoordinates.start < 0) {\n deltaDays = Math.ceil(-this.currentEventCoordinates.start / CalendarSettings.EventDragDayLength);\n this.currentEventCoordinates.start += deltaDays * CalendarSettings.EventDragDayLength;\n this.currentEventCoordinates.dayNumber -= deltaDays;\n }\n else if (this.currentEventCoordinates.start >= CalendarSettings.EventDragDayLength) {\n deltaDays = Math.floor(this.currentEventCoordinates.start / CalendarSettings.EventDragDayLength);\n this.currentEventCoordinates.start -= deltaDays * CalendarSettings.EventDragDayLength;\n\n // This dayNumber needs to be updated with the calendar number.\n // if (currentView == \"multicolumndayview\")\n // this._updateMulticolumnViewDayNumber_SEDGC();\n this.currentEventCoordinates.dayNumber += deltaDays;\n }\n $log.debug('event coordinates ' + JSON.stringify(this.currentEventCoordinates));\n $rootScope.$emit('calendar:drag');\n },\n\n // SOGoEventDragPointerHandler.getContainerBasedCoordinates\n getContainerBasedCoordinates: function SEDPH_getCBC(view, pointerCoordinates) {\n var currentCoordinates = pointerCoordinates || this.currentCoordinates;\n var coordinates = currentCoordinates.getDelta(view.coordinates);\n var container = view.element;\n\n if (coordinates.x < view.daysOffset || coordinates.x > container.clientWidth ||\n coordinates.y < 0 || coordinates.y > container.clientHeight)\n coordinates = null;\n\n return coordinates;\n },\n\n prepareWithEventType: function SEDPH_prepareWithEventType(eventType) {\n var methods = { \"multiday\": this.getEventMultiDayViewCoordinates,\n \"multiday-allday\": this.getEventMultiDayAllDayViewCoordinates,\n \"monthly\": this.getEventMonthlyViewCoordinates,\n \"unknown\": null };\n var method = methods[eventType];\n this.eventType = eventType;\n this.getEventViewCoordinates = method;\n },\n\n getEventMultiDayViewCoordinates: function SEDPH_gEMultiDayViewC(view, pointerCoordinates) {\n /* x = day; y = quarter */\n var coordinates = this.getEventMultiDayAllDayViewCoordinates(view, pointerCoordinates); // get the x coordinate\n if (coordinates) {\n var quarterHeight = view.quarterHeight;\n var pxCoordinates = this.getContainerBasedCoordinates(view, pointerCoordinates);\n pxCoordinates.y += view.element.scrollTop;\n\n coordinates.y = Math.floor((pxCoordinates.y - CalendarSettings.EventDragHorizontalOffset) / quarterHeight);\n var maxY = CalendarSettings.EventDragDayLength - 1;\n if (coordinates.y < 0)\n coordinates.y = 0;\n else if (coordinates.y > maxY)\n coordinates.y = maxY;\n }\n\n return coordinates;\n },\n getEventMultiDayAllDayViewCoordinates: function SEDPH_gEMultiDayADVC(view, pointerCoordinates) {\n /* x = day; y = quarter */\n var coordinates;\n\n var pxCoordinates = this.getContainerBasedCoordinates(view, pointerCoordinates);\n if (pxCoordinates) {\n coordinates = new SOGoCoordinates();\n\n var dayWidth = view.dayWidth;\n var daysOffset = view.daysOffset;\n\n coordinates.x = Math.floor((pxCoordinates.x - daysOffset) / dayWidth);\n var minX = 0;\n var maxX = Calendar.$view.maxX;\n if (this.dragMode != 'move-event') {\n var calendarData = calendarDayCtrl.calendarData();\n if (calendarData)\n // Resizing an event can't span a different day when in multicolumn view\n minX = maxX = calendarData.index;\n }\n if (coordinates.x < minX)\n coordinates.x = minX;\n else if (coordinates.x > maxX)\n coordinates.x = maxX;\n coordinates.y = 0;\n }\n else {\n coordinates = null;\n }\n\n return coordinates;\n },\n getEventMonthlyViewCoordinates: function SEDPH_gEMonthlyViewC(view, pointerCoordinates) {\n /* x = day; y = quarter */\n var coordinates;\n\n var pxCoordinates = this.getContainerBasedCoordinates(view, pointerCoordinates);\n if (pxCoordinates) {\n coordinates = new SOGoCoordinates();\n\n var daysTopOffset = 0;\n var dayWidth = view.dayWidth;\n var daysOffset = view.daysOffset;\n var dayHeight = view.dayHeight;\n var daysY = Math.floor((pxCoordinates.y - daysTopOffset) / dayHeight);\n if (daysY < 0)\n daysY = 0;\n\n coordinates.x = Math.floor((pxCoordinates.x - daysOffset) / dayWidth);\n if (coordinates.x < 0)\n coordinates.x = 0;\n else if (coordinates.x > 6)\n coordinates.x = 6;\n coordinates.x += 7 * daysY;\n coordinates.y = 0;\n }\n else {\n coordinates = null;\n }\n\n return coordinates;\n },\n\n getDistance: function SEDPH_getDistance() {\n return this.currentCoordinates.getDistance(this.originalCoordinates);\n },\n\n setTimeFromQuarters: function SEDPH_setTimeFromQuarters(date, quarters) {\n var hours, minutes;\n hours = Math.floor(quarters / 4);\n minutes = (quarters % 4) * 15;\n date.setHours(hours, minutes);\n }\n };\n }\n }\n\n angular\n .module('SOGo.SchedulerUI')\n .directive('sgDraggableCalendarBlock', sgDraggableCalendarBlock);\n})();\n\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /*\n * sgCalendarDayTable - Build list of blocks for a specific day\n * @memberof SOGo.Common\n * @restrict element\n * @param {object} sgBlocks - the events blocks definitions for the current view\n * @param {string} sgDay - the day of the events to display\n * @param {function} sgClick - the function to call when clicking on a block.\n * Two variables are available: event (the event that triggered the mouse click),\n * and component (a Component object)\n *\n * @example:\n\n http://www.html5rocks.com/en/tutorials/dnd/basics/\n https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_and_drop\n\n <sg-calendar-day-table\n sg-blocks=\"calendar.blocks\"\n sg-day=\"20150330\"\n sg-click=\"open({ event: clickEvent, component: clickComponent })\"/>\n */\n sgDroppableBlock.$inject = ['$rootScope', '$timeout', '$mdGesture', 'Calendar', 'CalendarSettings', 'Component'];\n function sgDroppableBlock($rootScope, $timeout, $mdGesture, Calendar, CalendarSettings, Component) {\n return {\n restrict: 'CA',\n scope: {\n onDrop: '&sgOnDrop'\n },\n link: function (scope, element, attrs, controller) {\n var deregister = $rootScope.$on('calendar:dragend', scope.onDrop);\n scope.$on('$destroy', deregister);\n }\n };\n }\n \n angular\n .module('SOGo.SchedulerUI')\n .directive('sgDroppableBlock', sgDroppableBlock);\n})();\n\n"]}