sogo/UI/WebServerResources/js/Scheduler.services.js.map
2015-09-15 12:05:37 -04:00

1 line
64 KiB
Plaintext

{"version":3,"file":"Scheduler.services.js","sources":["Scheduler/Calendar.service.js","Scheduler/Component.service.js"],"names":["Calendar","futureCalendarData","this","init","name","id","newCalendarData","$$resource","create","angular","extend","$acl","$$Acl","$factory","$q","$timeout","$log","Settings","Resource","Component","Acl","activeUser","$Component","module","e","factory","$add","calendar","list","sibling","i","isWebCalendar","$webcalendars","isSubscription","$subscriptions","$calendars","_","find","o","localeCompare","indexOf","pluck","splice","$findAll","data","_this","forEach","push","union","$get","$subscribe","uid","path","userResource","fetch","then","calendarData","$addWebCalendar","url","d","defer","urls","webCalendarURL","reject","post","isEditable","isRemote","owner","login","debug","JSON","stringify","undefined","resolve","promise","prototype","isOwned","isSuperUser","getClassName","base","isUndefined","$rename","$save","$delete","remove","status","$deleteComponents","components","calendars","component","isDefined","c_folder","c_name","uids","$events","difference","$tasks","save","$omit","$setActivation","active","$getComponent","componentId","recurrenceId","$find","value","key","futureComponentData","pid","newComponentData","newguid","$unwrap","isNew","Preferences","Gravatar","$Preferences","$gravatar","baseURL","timeFormat","$query","search","$queryEvents","sort","asc","filterpopup","$queryTasks","$refreshTimeout","ready","settings","EventsFilterState","TasksFilterState","EventsSortingState","parseInt","TasksSortingState","show_completed","ShowCompletedTasks","$categories","defaults","SOGoCalendarCategoriesColors","SOGoTimeFormat","$selectedCount","count","filter","event","selected","length","task","$startRefreshTimeout","type","cancel","refreshViewCheck","SOGoRefreshViewCheck","f","bind","$filter","timeInterval","options","now","Date","day","getDate","month","getMonth","year","getFullYear","queryKey","capitalize","params","otherType","dirty","each","keys","$unwrapCollection","calendarId","occurrenceId","join","filterCategories","query","re","RegExp","category","saveSelectedList","componentType","$eventsBlocksForView","view","date","viewAction","startDate","endDate","beginOfWeek","setTime","getTime","addDays","setDate","setMonth","endOfWeek","$eventsBlocks","deferred","toLowerCase","sd","getDayString","ed","blocks","reduce","events","objects","eventData","componentData","object","eventsFields","start","c_startdate","hour","getHourString","flatten","block","nbr","$blocks","fields","invoke","categories","repeat","alarm","action","quantity","unit","reference","relation","classification","substring","end","addHours","dueDate","due","$isRecurrent","days","byDayMask","occurrence","frequency","byday","toString","interval","monthdays","months","until","asDate","$hasCustomRepeat","hasCustomRepeat","units","M","H","D","W","match","exec","SOGoCalendarDefaultReminder","$hasAlarm","destinationCalendar","organizer","email","$image","freebusy","updateFreeBusyCoverage","attendees","attendee","image","updateFreeBusy","b","isReadOnly","isEditableOccurrence","isInvitation","userHasRSVP","isInvitationOccurrence","enablePercentComplete","coversFreeBusy","quarter","roundedStart","roundedEnd","startQuarter","getMinutes","endQuarter","setMinutes","daysUpTo","index","hourKey","currentDay","dayKey","getHours","beginOfDay","addMinutes","sday","eday","map","addAttendee","card","c_cn","$preferredEmail","role","c_uid","hasAttendee","emails","canRemindAttendeesByEmail","addAttachUrl","attachUrl","attachUrls","deleteAttachUrl","$addDueDate","toISOString","$deleteDueDate","$addStartDate","$deleteStartDate","$reset","$shadowData","$reply","reply","delegatedTo","$futureComponentData","isError","error","formatTime","hours","minutes","formatDate","getYear","copy","startTime","endTime","dueTime","stringWithSeparator"],"mappings":"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","sourcesContent":["/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * @name Calendar\n * @constructor\n * @param {object} futureCalendarData - either an object literal or a promise\n */\n function Calendar(futureCalendarData) {\n // Data is immediately available\n this.init(futureCalendarData);\n if (this.name && !this.id) {\n // Create a new calendar on the server\n var newCalendarData = Calendar.$$resource.create('createFolder', this.name);\n angular.extend(this, newCalendarData);\n }\n if (this.id) {\n this.$acl = new Calendar.$$Acl('Calendar/' + this.id);\n }\n }\n\n /**\n * @memberof Calendar\n * @desc The factory we'll use to register with Angular\n * @returns the Calendar constructor\n */\n Calendar.$factory = ['$q', '$timeout', '$log', 'sgSettings', 'Resource', 'Component', 'Acl', function($q, $timeout, $log, Settings, Resource, Component, Acl) {\n angular.extend(Calendar, {\n $q: $q,\n $timeout: $timeout,\n $log: $log,\n $$resource: new Resource(Settings.activeUser('folderURL') + 'Calendar', Settings.activeUser()),\n $Component: Component,\n $$Acl: Acl,\n activeUser: Settings.activeUser()\n });\n\n return Calendar; // return constructor\n }];\n\n /**\n * @module SOGo.SchedulerUI\n * @desc Factory registration of Calendar in Angular module.\n */\n try {\n angular.module('SOGo.SchedulerUI');\n }\n catch(e) {\n angular.module('SOGo.SchedulerUI', ['SOGo.Common']);\n }\n angular.module('SOGo.SchedulerUI')\n .factory('Calendar', Calendar.$factory);\n\n /**\n * @memberof Calendar\n * @desc Add a new calendar to the static list of calendars\n * @param {Calendar} calendar - an Calendar object instance\n */\n Calendar.$add = function(calendar) {\n // Insert new calendar at proper index\n var list, sibling, i;\n\n if (calendar.isWebCalendar)\n list = this.$webcalendars;\n else if (calendar.isSubscription)\n list = this.$subscriptions;\n else\n list = this.$calendars;\n\n sibling = _.find(list, function(o) {\n return (o.id != 'personal' &&\n o.name.localeCompare(calendar.name) === 1);\n });\n i = sibling ? _.indexOf(_.pluck(list, 'id'), sibling.id) : 1;\n list.splice(i, 0, calendar);\n };\n\n /**\n * @memberof Calendar\n * @desc Set or get the list of calendars. Will instanciate a new Calendar object for each item.\n * @param {object[]} [data] - the metadata of the calendars\n * @returns the list of calendars\n */\n Calendar.$findAll = function(data) {\n var _this = this;\n if (data) {\n this.$calendars = [];\n this.$subscriptions = [];\n this.$webcalendars = [];\n // Instanciate Calendar objects\n angular.forEach(data, function(o, i) {\n var calendar = new Calendar(o);\n if (calendar.isWebCalendar)\n _this.$webcalendars.push(calendar);\n else if (calendar.isSubscription)\n _this.$subscriptions.push(calendar);\n else\n _this.$calendars.push(calendar);\n });\n }\n return _.union(this.$calendars, this.$subscriptions, this.$webcalendars);\n };\n\n /**\n * @memberof Calendar\n * @desc Find a calendar among local instances (personal calendars, subscriptions and Web calendars).\n * @param {string} id - the calendar ID\n * @returns an object literal of the matching Calendar instance\n */\n Calendar.$get = function(id) {\n var calendar;\n\n calendar = _.find(Calendar.$calendars, function(o) { return o.id == id; });\n if (!calendar)\n calendar = _.find(Calendar.$subscriptions, function(o) { return o.id == id; });\n if (!calendar)\n calendar = _.find(Calendar.$webcalendars, function(o) { return o.id == id; });\n\n return calendar;\n };\n\n /**\n * @memberOf Calendar\n * @desc Subscribe to another user's calendar and add it to the list of calendars.\n * @param {string} uid - user id\n * @param {string} path - path of folder for specified user\n * @returns a promise of the HTTP query result\n */\n Calendar.$subscribe = function(uid, path) {\n var _this = this;\n return Calendar.$$resource.userResource(uid).fetch(path, 'subscribe').then(function(calendarData) {\n var calendar = new Calendar(calendarData);\n if (!_.find(_this.$subscriptions, function(o) {\n return o.id == calendarData.id;\n })) {\n Calendar.$add(calendar);\n }\n return calendar;\n });\n };\n\n /**\n * @memberOf Calendar\n * @desc Subscribe to a remote Web calendar\n * @param {string} url - URL of .ics file\n * @returns a promise of the HTTP query result\n */\n Calendar.$addWebCalendar = function(url) {\n var _this = this,\n d = Calendar.$q.defer();\n\n if (_.find(_this.$webcalendars, function(o) {\n return o.urls.webCalendarURL == url;\n })) {\n // Already subscribed\n d.reject();\n }\n else {\n Calendar.$$resource.post(null, 'addWebCalendar', { url: url }).then(function(calendarData) {\n angular.extend(calendarData, {\n isWebCalendar: true,\n isEditable: true,\n isRemote: false,\n owner: Calendar.activeUser.login,\n urls: { webCalendarURL: url }\n });\n var calendar = new Calendar(calendarData);\n Calendar.$add(calendar);\n Calendar.$$resource.fetch(calendar.id, 'reload').then(function(data) {\n // TODO: show a toast of the reload status\n Calendar.$log.debug(JSON.stringify(data, undefined, 2));\n });\n d.resolve();\n }, function() {\n d.reject();\n });\n }\n\n return d.promise;\n };\n\n /**\n * @function init\n * @memberof Calendar.prototype\n * @desc Extend instance with new data and compute additional attributes.\n * @param {object} data - attributes of calendar\n */\n Calendar.prototype.init = function(data) {\n angular.extend(this, data);\n // Add 'isOwned' and 'isSubscription' attributes based on active user (TODO: add it server-side?)\n this.isOwned = Calendar.activeUser.isSuperUser || this.owner == Calendar.activeUser.login;\n this.isSubscription = !this.isRemote && this.owner != Calendar.activeUser.login;\n };\n\n /**\n * @function getClassName\n * @memberof Calendar.prototype\n * @desc Return the calendar CSS class name based on its ID.\n * @returns a string representing the foreground CSS class name\n */\n Calendar.prototype.getClassName = function(base) {\n if (angular.isUndefined(base))\n base = 'fg';\n return base + '-folder' + this.id;\n };\n\n /**\n * @function $rename\n * @memberof Calendar.prototype\n * @desc Rename the calendar and keep the list sorted\n * @param {string} name - the new name\n * @returns a promise of the HTTP operation\n */\n Calendar.prototype.$rename = function(name) {\n var i = _.indexOf(_.pluck(Calendar.$calendars, 'id'), this.id);\n this.name = name;\n Calendar.$calendars.splice(i, 1);\n Calendar.$add(this);\n return this.$save();\n };\n\n /**\n * @function $delete\n * @memberof Calendar.prototype\n * @desc Delete the calendar from the server and the static list of calendars.\n * @returns a promise of the HTTP operation\n */\n Calendar.prototype.$delete = function() {\n var _this = this,\n d = Calendar.$q.defer(),\n list,\n promise;\n\n if (this.isSubscription) {\n promise = Calendar.$$resource.fetch(this.id, 'unsubscribe');\n list = Calendar.$subscriptions;\n }\n else {\n promise = Calendar.$$resource.remove(this.id);\n if (this.isWebCalendar)\n list = Calendar.$webcalendars;\n else\n list = Calendar.$calendars;\n }\n\n promise.then(function() {\n var i = _.indexOf(_.pluck(list, 'id'), _this.id);\n list.splice(i, 1);\n d.resolve();\n }, function(data, status) {\n d.reject(data);\n });\n return d.promise;\n };\n\n /**\n * @function $deleteComponents\n * @memberof Calendar\n * @desc Delete multiple components from calendar.\n * @return a promise of the HTTP operation\n */\n Calendar.$deleteComponents = function(components) {\n\n // We create a c_folder -> event hash\n var calendars = {}, _this = this;\n\n _.forEach(components, function(component) {\n if (!angular.isDefined(calendars[component.c_folder]))\n calendars[component.c_folder] = [];\n\n calendars[component.c_folder].push(component.c_name);\n });\n\n _.forEach(calendars, function(uids, c_folder) {\n Calendar.$$resource.post(c_folder, 'batchDelete', {uids: uids});\n });\n\n // We slice both arrays - might be useful if in the future, we can delete\n // events and tasks at the same time.\n _this.$Component.$events = _.difference(_this.$Component.$events, components);\n _this.$Component.$tasks = _.difference(_this.$Component.$tasks, components);\n };\n\n /**\n * @function $save\n * @memberof Calendar.prototype\n * @desc Save the calendar properties to the server.\n * @returns a promise of the HTTP operation\n */\n Calendar.prototype.$save = function() {\n return Calendar.$$resource.save(this.id, this.$omit()).then(function(data) {\n return data;\n });\n };\n\n /**\n * @function $setActivation\n * @memberof Calendar.prototype\n * @desc Either activate or deactivate the calendar.\n * @returns a promise of the HTTP operation\n */\n Calendar.prototype.$setActivation = function() {\n return Calendar.$$resource.fetch(this.id, (this.active?'':'de') + 'activateFolder');\n };\n\n /**\n * @function $getComponent\n * @memberof Calendar.prototype\n * @desc Fetch a component attributes from the server.\n * @returns a promise of the HTTP operation\n */\n Calendar.prototype.$getComponent = function(componentId, recurrenceId) {\n return Calendar.$Component.$find(this.id, componentId, recurrenceId);\n };\n\n /**\n * @function $omit\n * @memberof Calendar.prototype\n * @desc Return a sanitized object used to send to the server.\n * @return an object literal copy of the Calendar instance\n */\n Calendar.prototype.$omit = function() {\n var calendar = {};\n angular.forEach(this, function(value, key) {\n if (key != 'constructor' &&\n key[0] != '$') {\n calendar[key] = value;\n }\n });\n return calendar;\n };\n})();\n","/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n\n(function() {\n 'use strict';\n\n /**\n * @name Component\n * @constructor\n * @param {object} futureComponentData - either an object literal or a promise\n */\n function Component(futureComponentData) {\n // Data is immediately available\n if (typeof futureComponentData.then !== 'function') {\n this.init(futureComponentData);\n if (this.pid && !this.id) {\n // Prepare for the creation of a new component;\n // Get UID from the server.\n var newComponentData = Component.$$resource.newguid(this.pid);\n this.$unwrap(newComponentData);\n this.isNew = true;\n }\n }\n else {\n // The promise will be unwrapped first\n this.$unwrap(futureComponentData);\n }\n }\n\n /**\n * @memberof Component\n * @desc The factory we'll use to register with Angular\n * @returns the Component constructor\n */\n Component.$factory = ['$q', '$timeout', '$log', 'sgSettings', 'Preferences', 'Gravatar', 'Resource', function($q, $timeout, $log, Settings, Preferences, Gravatar, Resource) {\n angular.extend(Component, {\n $q: $q,\n $timeout: $timeout,\n $log: $log,\n $Preferences: Preferences,\n $gravatar: Gravatar,\n $$resource: new Resource(Settings.baseURL(), Settings.activeUser()),\n timeFormat: \"%H:%M\",\n // Filter parameters common to events and tasks\n $query: { value: '', search: 'title_Category_Location' },\n // Filter paramaters specific to events\n $queryEvents: { sort: 'start', asc: 1, filterpopup: 'view_next7' },\n // Filter parameters specific to tasks\n $queryTasks: { sort: 'status', asc: 1, filterpopup: 'view_incomplete' },\n $refreshTimeout: null\n });\n Preferences.ready().then(function() {\n // Initialize filter parameters from user's settings\n if (Preferences.settings.Calendar.EventsFilterState)\n Component.$queryEvents.filterpopup = Preferences.settings.Calendar.EventsFilterState;\n if (Preferences.settings.Calendar.TasksFilterState)\n Component.$queryTasks.filterpopup = Preferences.settings.Calendar.TasksFilterState;\n if (Preferences.settings.Calendar.EventsSortingState) {\n Component.$queryEvents.sort = Preferences.settings.Calendar.EventsSortingState[0];\n Component.$queryEvents.asc = parseInt(Preferences.settings.Calendar.EventsSortingState[1]);\n }\n if (Preferences.settings.Calendar.TasksSortingState) {\n Component.$queryTasks.sort = Preferences.settings.Calendar.TasksSortingState[0];\n Component.$queryTasks.asc = parseInt(Preferences.settings.Calendar.TasksSortingState[1]);\n }\n Component.$queryTasks.show_completed = parseInt(Preferences.settings.ShowCompletedTasks);\n // Initialize categories from user's defaults\n Component.$categories = Preferences.defaults.SOGoCalendarCategoriesColors;\n // Initialize time format from user's defaults\n if (Preferences.defaults.SOGoTimeFormat) {\n Component.timeFormat = Preferences.defaults.SOGoTimeFormat;\n }\n });\n\n return Component; // return constructor\n }];\n\n /**\n * @module SOGo.SchedulerUI\n * @desc Factory registration of Component in Angular module.\n */\n try {\n angular.module('SOGo.SchedulerUI');\n }\n catch(e) {\n angular.module('SOGo.SchedulerUI', ['SOGo.Common']);\n }\n angular.module('SOGo.SchedulerUI')\n .factory('Component', Component.$factory);\n\n /**\n * @function $selectedCount\n * @memberof Component\n * @desc Return the number of events or tasks selected by the user.\n * @returns the number of selected events or tasks\n */\n Component.$selectedCount = function() {\n var count;\n\n count = 0;\n if (Component.$events) {\n count = (_.filter(Component.$events, function(event) { return event.selected; })).length;\n }\n if (Component.$tasks) {\n count = (_.filter(Component.$tasks, function(task) { return task.selected; })).length;\n }\n return count;\n };\n\n /**\n * @function $startRefreshTimeout\n * @memberof Component\n * @desc Starts the refresh timeout for the current selected component type, for all calendars\n */\n Component.$startRefreshTimeout = function(type) {\n var _this = this;\n\n if (Component.$refreshTimeout)\n Component.$timeout.cancel(Component.$refreshTimeout);\n\n Component.$Preferences.ready().then(function() {\n // Restart the refresh timer, if needed\n var refreshViewCheck = Component.$Preferences.defaults.SOGoRefreshViewCheck;\n if (refreshViewCheck && refreshViewCheck != 'manually') {\n var f = angular.bind(_this, Component.$filter, type);\n Component.$refreshTimeout = Component.$timeout(f, refreshViewCheck.timeInterval()*1000);\n }\n });\n };\n\n /**\n * @function $filter\n * @memberof Component\n * @desc Search for components matching some criterias\n * @param {string} type - either 'events' or 'tasks'\n * @param {object} [options] - additional options to the query\n * @returns a collection of Components instances\n */\n Component.$filter = function(type, options) {\n var _this = this,\n now = new Date(),\n day = now.getDate(),\n month = now.getMonth() + 1,\n year = now.getFullYear(),\n queryKey = '$query' + type.capitalize(),\n params = {\n day: '' + year + (month < 10?'0':'') + month + (day < 10?'0':'') + day,\n };\n\n Component.$startRefreshTimeout(type);\n\n return this.$Preferences.ready().then(function() {\n var futureComponentData,\n dirty = false,\n otherType;\n\n angular.extend(_this.$query, params);\n\n if (options) {\n _.each(_.keys(options), function(key) {\n // Query parameters common to events and tasks are compared\n dirty |= (_this.$query[key] && options[key] != Component.$query[key]);\n if (key == 'reload' && options[key])\n dirty = true;\n // Update either the common parameters or the type-specific parameters\n else if (angular.isDefined(_this.$query[key]))\n _this.$query[key] = options[key];\n else\n _this[queryKey][key] = options[key];\n });\n }\n\n // Perform query with both common and type-specific parameters\n futureComponentData = _this.$$resource.fetch(null, type + 'list',\n angular.extend(_this[queryKey], _this.$query));\n\n // Invalidate cached results of other type if $query has changed\n otherType = (type == 'tasks')? '$events' : '$tasks';\n if (dirty) {\n delete Component[otherType];\n Component.$log.debug('force reload of ' + otherType);\n }\n\n return _this.$unwrapCollection(type, futureComponentData);\n });\n };\n\n /**\n * @function $find\n * @desc Fetch a component from a specific calendar.\n * @param {string} calendarId - the calendar ID\n * @param {string} componentId - the component ID\n * @param {string} [occurrenceId] - the component ID\n * @see {@link Calendar.$getComponent}\n */\n Component.$find = function(calendarId, componentId, occurrenceId) {\n var futureComponentData, path = [calendarId, componentId];\n\n if (occurrenceId)\n path.push(occurrenceId);\n\n futureComponentData = this.$$resource.fetch(path.join('/'), 'view');\n\n return new Component(futureComponentData);\n };\n\n /**\n * @function filterCategories\n * @desc Search for categories matching some criterias\n * @param {string} search - the search string to match\n * @returns a collection of strings\n */\n Component.filterCategories = function(query) {\n var re = new RegExp(query, 'i');\n return _.filter(_.keys(Component.$categories), function(category) {\n return category.search(re) != -1;\n });\n };\n\n /**\n * @function saveSelectedList\n * @desc Save to the user's settings the currently selected list.\n * @param {string} componentType - either \"events\" or \"tasks\"\n * @returns a promise of the HTTP operation\n */\n Component.saveSelectedList = function(componentType) {\n return this.$$resource.post(null, 'saveSelectedList', { list: componentType + 'ListView' });\n };\n\n /**\n * @function $eventsBlocksForView\n * @desc Events blocks for a specific week\n * @param {string} view - Either 'day' or 'week'\n * @param {Date} type - Date of any day of the desired period\n * @returns a promise of a collection of objects describing the events blocks\n */\n Component.$eventsBlocksForView = function(view, date) {\n var viewAction, startDate, endDate, params;\n\n if (view == 'day') {\n viewAction = 'dayView';\n startDate = endDate = date;\n }\n else if (view == 'week') {\n viewAction = 'weekView';\n startDate = date.beginOfWeek();\n endDate = new Date();\n endDate.setTime(startDate.getTime());\n endDate.addDays(6);\n }\n else if (view == 'month') {\n viewAction = 'monthView';\n startDate = date;\n startDate.setDate(1);\n startDate = startDate.beginOfWeek();\n endDate = new Date();\n endDate.setTime(startDate.getTime());\n endDate.setMonth(endDate.getMonth() + 1);\n endDate.addDays(-1);\n endDate = endDate.endOfWeek();\n }\n return this.$eventsBlocks(viewAction, startDate, endDate);\n };\n\n /**\n * @function $eventsBlocks\n * @desc Events blocks for a specific view and period\n * @param {string} view - Either 'day' or 'week'\n * @param {Date} startDate - period's start date\n * @param {Date} endDate - period's end date\n * @returns a promise of a collection of objects describing the events blocks\n */\n Component.$eventsBlocks = function(view, startDate, endDate) {\n var params, futureComponentData, i,\n deferred = Component.$q.defer();\n\n params = { view: view.toLowerCase(), sd: startDate.getDayString(), ed: endDate.getDayString() };\n Component.$log.debug('eventsblocks ' + JSON.stringify(params, undefined, 2));\n futureComponentData = this.$$resource.fetch(null, 'eventsblocks', params);\n futureComponentData.then(function(data) {\n Component.$timeout(function() {\n var components = [], blocks = {};\n\n // Instantiate Component objects\n _.reduce(data.events, function(objects, eventData, i) {\n var componentData = _.object(data.eventsFields, eventData),\n start = new Date(componentData.c_startdate * 1000);\n componentData.hour = start.getHourString();\n objects.push(new Component(componentData));\n return objects;\n }, components);\n\n // Associate Component objects to blocks positions\n _.each(_.flatten(data.blocks), function(block) {\n block.component = components[block.nbr];\n });\n\n // Convert array of blocks to object with days as keys\n for (i = 0; i < data.blocks.length; i++) {\n blocks[startDate.getDayString()] = data.blocks[i];\n startDate.addDays(1);\n }\n\n Component.$log.debug('blocks ready (' + _.keys(blocks).length + ')');\n\n // Save the blocks to the object model\n Component.$blocks = blocks;\n\n deferred.resolve(blocks);\n });\n }, deferred.reject);\n\n return deferred.promise;\n };\n\n /**\n * @function $unwrapCollection\n * @desc Unwrap a promise and instanciate new Component objects using received data.\n * @param {string} type - either 'events' or 'tasks'\n * @param {promise} futureComponentData - a promise of the components' metadata\n * @returns a promise of the HTTP operation\n */\n Component.$unwrapCollection = function(type, futureComponentData) {\n var _this = this,\n components = [];\n\n return futureComponentData.then(function(data) {\n return Component.$timeout(function() {\n var fields = _.invoke(data.fields, 'toLowerCase');\n\n // Instanciate Component objects\n _.reduce(data[type], function(components, componentData, i) {\n var data = _.object(fields, componentData);\n components.push(new Component(data));\n return components;\n }, components);\n\n Component.$log.debug('list of ' + type + ' ready (' + components.length + ')');\n\n // Save the list of components to the object model\n Component['$' + type] = components;\n\n return components;\n });\n });\n };\n\n /**\n * @function init\n * @memberof Component.prototype\n * @desc Extend instance with required attributes and new data.\n * @param {object} data - attributes of component\n */\n Component.prototype.init = function(data) {\n var _this = this;\n\n this.categories = [];\n this.repeat = {};\n this.alarm = { action: 'display', quantity: 5, unit: 'MINUTES', reference: 'BEFORE', relation: 'START' };\n this.status = 'not-specified';\n angular.extend(this, data);\n\n Component.$Preferences.ready().then(function() {\n var type = (_this.type == 'appointment')? 'Events' : 'Tasks';\n\n // Set default values from user's defaults\n _this.classification = _this.classification ||\n Component.$Preferences.defaults['SOGoCalendar' + type + 'DefaultClassification'].toLowerCase();\n });\n\n if (this.startDate)\n this.start = new Date(this.startDate.substring(0,10) + ' ' + this.startDate.substring(11,16));\n else if (this.type == 'appointment') {\n this.start = new Date();\n }\n\n if (this.endDate)\n this.end = new Date(this.endDate.substring(0,10) + ' ' + this.endDate.substring(11,16));\n else if (this.type == 'appointment') {\n this.end = new Date();\n this.end.addHours(1);\n }\n\n if (this.dueDate)\n this.due = new Date(this.dueDate.substring(0,10) + ' ' + this.dueDate.substring(11,16));\n\n // Parse recurrence rule definition and initialize default values\n this.$isRecurrent = angular.isDefined(data.repeat);\n if (this.repeat.days) {\n var byDayMask = _.find(this.repeat.days, function(o) {\n return angular.isDefined(o.occurrence);\n });\n if (byDayMask)\n if (this.repeat.frequency == 'yearly')\n this.repeat.year = { byday: true };\n this.repeat.month = {\n type: 'byday',\n occurrence: byDayMask.occurrence.toString(),\n day: byDayMask.day\n };\n }\n else {\n this.repeat.days = [];\n }\n if (angular.isUndefined(this.repeat.frequency))\n this.repeat.frequency = 'never';\n if (angular.isUndefined(this.repeat.interval))\n this.repeat.interval = 1;\n if (angular.isUndefined(this.repeat.month))\n this.repeat.month = { occurrence: '1', day: 'SU', type: 'bymonthday' };\n if (angular.isUndefined(this.repeat.monthdays))\n // TODO: initialize this.repeat.monthdays with month day of start date\n this.repeat.monthdays = [];\n if (angular.isUndefined(this.repeat.months))\n // TODO: initialize this.repeat.months with month of start date\n this.repeat.months = [];\n if (angular.isUndefined(this.repeat.year))\n this.repeat.year = {};\n if (this.repeat.count)\n this.repeat.end = 'count';\n else if (this.repeat.until) {\n this.repeat.end = 'until';\n this.repeat.until = this.repeat.until.substring(0,10).asDate();\n }\n else\n this.repeat.end = 'never';\n this.$hasCustomRepeat = this.hasCustomRepeat();\n\n if (this.isNew) {\n // Set default alarm\n Component.$Preferences.ready().then(function() {\n var units = { M: 'MINUTES', H: 'HOURS', D: 'DAYS', W: 'WEEKS' };\n var match = /-PT?([0-9]+)([MHDW])/.exec(Component.$Preferences.defaults.SOGoCalendarDefaultReminder);\n if (match) {\n _this.$hasAlarm = true;\n _this.alarm.quantity = parseInt(match[1]);\n _this.alarm.unit = units[match[2]];\n }\n });\n }\n else {\n this.$hasAlarm = angular.isDefined(data.alarm);\n }\n\n // Allow the component to be moved to a different calendar\n this.destinationCalendar = this.pid;\n\n if (this.organizer && this.organizer.email) {\n this.organizer.$image = Component.$gravatar(this.organizer.email, 32);\n }\n\n // Load freebusy of attendees\n this.freebusy = this.updateFreeBusyCoverage();\n\n if (this.attendees) {\n _.each(this.attendees, function(attendee) {\n attendee.image = Component.$gravatar(attendee.email, 32);\n _this.updateFreeBusy(attendee);\n });\n }\n\n this.selected = false;\n };\n\n /**\n * @function hasCustomRepeat\n * @memberof Component.prototype\n * @desc Check if the component has a custom recurrence rule.\n * @returns true if the recurrence rule requires the full recurrence editor\n */\n Component.prototype.hasCustomRepeat = function() {\n var b = angular.isDefined(this.repeat) &&\n (this.repeat.interval > 1 ||\n this.repeat.days && this.repeat.days.length > 0 ||\n this.repeat.monthdays && this.repeat.monthdays.length > 0 ||\n this.repeat.months && this.repeat.months.length > 0);\n return b;\n };\n\n /**\n * @function isEditable\n * @memberof Component.prototype\n * @desc Check if the component is editable and not an occurrence of a recurrent component\n * @returns true or false\n */\n Component.prototype.isEditable = function() {\n return (!this.occurrenceId && !this.isReadOnly);\n };\n\n /**\n * @function isEditableOccurrence\n * @memberof Component.prototype\n * @desc Check if the component is editable and an occurrence of a recurrent component\n * @returns true or false\n */\n Component.prototype.isEditableOccurrence = function() {\n return (this.occurrenceId && !this.isReadOnly);\n };\n\n /**\n * @function isInvitation\n * @memberof Component.prototype\n * @desc Check if the component an invitation and not an occurrence of a recurrent component\n * @returns true or false\n */\n Component.prototype.isInvitation = function() {\n return (!this.occurrenceId && this.userHasRSVP);\n };\n\n /**\n * @function isInvitationOccurrence\n * @memberof Component.prototype\n * @desc Check if the component an invitation and an occurrence of a recurrent component\n * @returns true or false\n */\n Component.prototype.isInvitationOccurrence = function() {\n return (this.occurrenceId && this.userHasRSVP);\n };\n\n /**\n * @function isReadOnly\n * @memberof Component.prototype\n * @desc Check if the component is not editable and not an invitation\n * @returns true or false\n */\n Component.prototype.isReadOnly = function() {\n return (this.isReadOnly && !this.userHasRSVP);\n };\n\n /**\n * @function enablePercentComplete\n * @memberof Component.prototype\n * @desc Check if the percent completion should be enabled with respect to the\n * component's type and status.\n * @returns true if the percent completion should be displayed\n */\n Component.prototype.enablePercentComplete = function() {\n return (this.component = 'vtodo' &&\n this.status != 'not-specified' &&\n this.status != 'cancelled');\n };\n\n /**\n * @function coversFreeBusy\n * @memberof Component.prototype\n * @desc Check if a specific quarter matches the component's period\n * @returns true if the quarter covers the component's period\n */\n Component.prototype.coversFreeBusy = function(day, hour, quarter) {\n var b = (angular.isDefined(this.freebusy[day]) &&\n angular.isDefined(this.freebusy[day][hour]) &&\n this.freebusy[day][hour][quarter] == 1);\n return b;\n };\n\n /**\n * @function updateFreeBusyCoverage\n * @memberof Component.prototype\n * @desc Build a 15-minute-based representation of the component's period.\n * @returns an object literal hashed by days and hours and arrays of four 1's and 0's\n */\n Component.prototype.updateFreeBusyCoverage = function() {\n var _this = this, freebusy = {};\n\n if (this.start && this.end) {\n var roundedStart = new Date(this.start.getTime()),\n roundedEnd = new Date(this.end.getTime()),\n startQuarter = parseInt(roundedStart.getMinutes()/15 + 0.5),\n endQuarter = parseInt(roundedEnd.getMinutes()/15 + 0.5);\n roundedStart.setMinutes(15*startQuarter);\n roundedEnd.setMinutes(15*endQuarter);\n\n _.each(roundedStart.daysUpTo(roundedEnd), function(date, index) {\n var currentDay = date.getDate(),\n dayKey = date.getDayString(),\n hourKey;\n if (dayKey == _this.start.getDayString()) {\n hourKey = date.getHours().toString();\n freebusy[dayKey] = {};\n freebusy[dayKey][hourKey] = [];\n while (startQuarter > 0) {\n freebusy[dayKey][hourKey].push(0);\n startQuarter--;\n }\n }\n else {\n date = date.beginOfDay();\n freebusy[dayKey] = {};\n }\n while (date.getTime() < _this.end.getTime() &&\n date.getDate() == currentDay) {\n hourKey = date.getHours().toString();\n if (angular.isUndefined(freebusy[dayKey][hourKey]))\n freebusy[dayKey][hourKey] = [];\n freebusy[dayKey][hourKey].push(1);\n date.addMinutes(15);\n }\n });\n return freebusy;\n }\n };\n\n /**\n * @function updateFreeBusy\n * @memberof Component.prototype\n * @desc Update the freebusy information for the component's period for a specific attendee.\n * @param {Object} card - an Card object instance of the attendee\n */\n Component.prototype.updateFreeBusy = function(attendee) {\n var params, url, days;\n if (attendee.uid) {\n params =\n {\n sday: this.start.getDayString(),\n eday: this.end.getDayString()\n };\n url = ['..', '..', attendee.uid, 'freebusy.ifb'];\n days = _.map(this.start.daysUpTo(this.end), function(day) { return day.getDayString(); });\n\n if (angular.isUndefined(attendee.freebusy))\n attendee.freebusy = {};\n\n // Fetch FreeBusy information\n Component.$$resource.fetch(url.join('/'), 'ajaxRead', params).then(function(data) {\n _.each(days, function(day) {\n var hour;\n\n if (angular.isUndefined(attendee.freebusy[day]))\n attendee.freebusy[day] = {};\n\n if (angular.isUndefined(data[day]))\n data[day] = {};\n\n for (var i = 0; i <= 23; i++) {\n hour = i.toString();\n if (data[day][hour])\n attendee.freebusy[day][hour] = [\n data[day][hour][\"0\"],\n data[day][hour][\"15\"],\n data[day][hour][\"30\"],\n data[day][hour][\"45\"]\n ];\n else\n attendee.freebusy[day][hour] = [0, 0, 0, 0];\n }\n });\n });\n }\n };\n\n /**\n * @function getClassName\n * @memberof Component.prototype\n * @desc Return the component CSS class name based on its container (calendar) ID.\n * @param {string} [base] - the prefix to add to the class name (defaults to \"fg\")\n * @returns a string representing the foreground CSS class name\n */\n Component.prototype.getClassName = function(base) {\n if (angular.isUndefined(base))\n base = 'fg';\n return base + '-folder' + (this.destinationCalendar || this.c_folder);\n };\n\n /**\n * @function addAttendee\n * @memberof Component.prototype\n * @desc Add an attendee and fetch his freebusy info.\n * @param {Object} card - an Card object instance to be added to the attendees list\n */\n Component.prototype.addAttendee = function(card) {\n var attendee, url, params;\n if (card) {\n attendee = {\n name: card.c_cn,\n email: card.$preferredEmail(),\n role: 'req-participant',\n status: 'needs-action',\n uid: card.c_uid\n };\n if (!_.find(this.attendees, function(o) {\n return o.email == attendee.email;\n })) {\n attendee.image = Component.$gravatar(attendee.email, 32);\n if (this.attendees)\n this.attendees.push(attendee);\n else\n this.attendees = [attendee];\n this.updateFreeBusy(attendee);\n }\n }\n };\n\n /**\n * @function hasAttendee\n * @memberof Component.prototype\n * @desc Verify if one of the email addresses of a Card instance matches an attendee.\n * @param {Object} card - an Card object instance\n * @returns true if the Card matches an attendee\n */\n Component.prototype.hasAttendee = function(card) {\n var attendee = _.find(this.attendees, function(attendee) {\n return _.find(card.emails, function(email) {\n return email.value == attendee.email;\n });\n });\n return angular.isDefined(attendee);\n };\n\n /**\n * @function canRemindAttendeesByEmail\n * @memberof Component.prototype\n * @desc Verify if the component's reminder must be send by email and if it has at least one attendee.\n * @returns true if attendees can receive a reminder by email\n */\n Component.prototype.canRemindAttendeesByEmail = function() {\n return this.alarm.action == 'email' &&\n !this.isReadOnly &&\n this.attendees && this.attendees.length > 0;\n };\n\n /**\n * @function addAttachUrl\n * @memberof Component.prototype\n * @desc Add a new attach URL if not already defined\n * @param {string} attachUrl - the URL\n * @returns the number of values in the list of attach URLs\n */\n Component.prototype.addAttachUrl = function(attachUrl) {\n if (angular.isUndefined(this.attachUrls)) {\n this.attachUrls = [{value: attachUrl}];\n }\n else {\n for (var i = 0; i < this.attachUrls.length; i++) {\n if (this.attachUrls[i].value == attachUrl) {\n break;\n }\n }\n if (i == this.attachUrls.length)\n this.attachUrls.push({value: attachUrl});\n }\n return this.attachUrls.length - 1;\n };\n\n /**\n * @function deleteAttachUrl\n * @memberof Component.prototype\n * @desc Remove an attach URL\n * @param {number} index - the URL index in the list of attach URLs\n */\n Component.prototype.deleteAttachUrl = function(index) {\n if (index > -1 && this.attachUrls.length > index) {\n this.attachUrls.splice(index, 1);\n }\n };\n\n /**\n * @function $addDueDate\n * @memberof Component.prototype\n * @desc Add a due date\n */\n Component.prototype.$addDueDate = function() {\n this.due = new Date();\n this.dueDate = this.due.toISOString();\n };\n\n /**\n * @function $deleteDueDate\n * @memberof Component.prototype\n * @desc Delete a due date\n */\n Component.prototype.$deleteDueDate = function() {\n delete this.due;\n delete this.dueDate;\n };\n\n /**\n * @function $addStartDate\n * @memberof Component.prototype\n * @desc Add a start date\n */\n Component.prototype.$addStartDate = function() {\n this.start = new Date();\n };\n\n /**\n * @function $deleteStartDate\n * @memberof Component.prototype\n * @desc Delete a start date\n */\n Component.prototype.$deleteStartDate = function() {\n delete this.start;\n delete this.startDate;\n };\n\n /**\n * @function $reset\n * @memberof Component.prototype\n * @desc Reset the original state the component's data.\n */\n Component.prototype.$reset = function() {\n var _this = this;\n angular.forEach(this, function(value, key) {\n if (key != 'constructor' && key[0] != '$') {\n delete _this[key];\n }\n });\n this.init(this.$shadowData);\n this.$shadowData = this.$omit(true);\n };\n\n /**\n * @function reply\n * @memberof Component.prototype\n * @desc Reply to an invitation.\n * @returns a promise of the HTTP operation\n */\n Component.prototype.$reply = function() {\n var _this = this, data, path = [this.pid, this.id];\n\n if (this.occurrenceId)\n path.push(this.occurrenceId);\n\n data = {\n reply: this.reply,\n delegatedTo: this.delegatedTo,\n alarm: this.$hasAlarm? this.alarm : {}\n };\n\n return Component.$$resource.save(path.join('/'), data, { action: 'rsvpAppointment' })\n .then(function(data) {\n // Make a copy of the data for an eventual reset\n _this.$shadowData = _this.$omit(true);\n return data;\n });\n };\n\n /**\n * @function $save\n * @memberof Component.prototype\n * @desc Save the component to the server.\n */\n Component.prototype.$save = function() {\n var _this = this, options, path = [this.pid, this.id];\n\n if (this.isNew)\n options = { action: 'saveAs' + this.type.capitalize() };\n\n if (this.occurrenceId)\n path.push(this.occurrenceId);\n\n return Component.$$resource.save(path.join('/'), this.$omit(), options)\n .then(function(data) {\n // Make a copy of the data for an eventual reset\n _this.$shadowData = _this.$omit(true);\n return data;\n });\n };\n\n /**\n * @function $unwrap\n * @memberof Component.prototype\n * @desc Unwrap a promise.\n * @param {promise} futureComponentData - a promise of some of the Component's data\n */\n Component.prototype.$unwrap = function(futureComponentData) {\n var _this = this;\n\n // Expose the promise\n this.$futureComponentData = futureComponentData;\n\n // Resolve the promise\n this.$futureComponentData.then(function(data) {\n _this.init(data);\n // Make a copy of the data for an eventual reset\n _this.$shadowData = _this.$omit();\n }, function(data) {\n angular.extend(_this, data);\n _this.isError = true;\n Component.$log.error(_this.error);\n });\n };\n\n /**\n * @function $omit\n * @memberof Component.prototype\n * @desc Return a sanitized object used to send to the server.\n * @return an object literal copy of the Component instance\n */\n Component.prototype.$omit = function() {\n var component = {}, date;\n angular.forEach(this, function(value, key) {\n if (key != 'constructor' && key[0] != '$') {\n component[key] = angular.copy(value);\n }\n });\n\n // Format dates and times\n component.startDate = component.start ? formatDate(component.start) : '';\n component.startTime = component.start ? formatTime(component.start) : '';\n component.endDate = component.end ? formatDate(component.end) : '';\n component.endTime = component.end ? formatTime(component.end) : '';\n component.dueDate = component.due ? formatDate(component.due) : '';\n component.dueTime = component.due ? formatTime(component.due) : '';\n\n // Update recurrence definition depending on selections\n if (this.$hasCustomRepeat) {\n if (this.repeat.frequency == 'monthly' && this.repeat.month.type && this.repeat.month.type == 'byday' ||\n this.repeat.frequency == 'yearly' && this.repeat.year.byday) {\n // BYDAY mask for a monthly or yearly recurrence\n delete component.repeat.monthdays;\n component.repeat.days = [{ day: this.repeat.month.day, occurrence: this.repeat.month.occurrence.toString() }];\n }\n else if (this.repeat.month.type) {\n // montly recurrence by month days or yearly by month\n delete component.repeat.days;\n }\n }\n else if (this.repeat.frequency) {\n component.repeat = { frequency: this.repeat.frequency };\n }\n if (this.repeat.frequency) {\n if (this.repeat.end == 'until' && this.repeat.until)\n component.repeat.until = this.repeat.until.stringWithSeparator('-');\n else if (this.repeat.end == 'count' && this.repeat.count)\n component.repeat.count = this.repeat.count;\n else {\n delete component.repeat.until;\n delete component.repeat.count;\n }\n }\n else {\n delete component.repeat;\n }\n\n if (this.$hasAlarm) {\n if (this.alarm.action && this.alarm.action == 'email' &&\n !(this.attendees && this.attendees.length > 0)) {\n // No attendees; email reminder must be sent to organizer only\n this.alarm.attendees = 0;\n this.alarm.organizer = 1;\n }\n }\n else {\n component.alarm = {};\n }\n\n function formatTime(date) {\n var hours = date.getHours();\n if (hours < 10) hours = '0' + hours;\n\n var minutes = date.getMinutes();\n if (minutes < 10) minutes = '0' + minutes;\n return hours + ':' + minutes;\n }\n\n function formatDate(date) {\n var year = date.getYear();\n if (year < 1000) year += 1900;\n\n var month = '' + (date.getMonth() + 1);\n if (month.length == 1)\n month = '0' + month;\n\n var day = '' + date.getDate();\n if (day.length == 1)\n day = '0' + day;\n\n return year + '-' + month + '-' + day;\n }\n\n return component;\n };\n\n})();\n"]}