Initial JavaScript models for calendar module

pull/91/head
Francis Lachapelle 2015-03-30 13:52:26 -04:00
parent d72f83ee95
commit 8b6a3d0e3f
2 changed files with 407 additions and 0 deletions

View File

@ -0,0 +1,191 @@
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
(function() {
'use strict';
/**
* @name Calendar
* @constructor
* @param {object} futureCalendarData - either an object literal or a promise
*/
function Calendar(futureCalendarData) {
// Data is immediately available
angular.extend(this, futureCalendarData);
if (this.name && !this.id) {
// Create a new calendar on the server
var newCalendarData = Calendar.$$resource.create('createFolder', this.name);
angular.extend(this, newCalendarData);
}
if (this.id) {
this.$acl = new Calendar.$$Acl('Calendar/' + this.id);
}
}
/**
* @memberof Calendar
* @desc The factory we'll use to register with Angular
* @returns the Calendar constructor
*/
Calendar.$factory = ['$q', '$timeout', '$log', 'sgSettings', 'sgResource', 'sgCard', 'sgAcl', function($q, $timeout, $log, Settings, Resource, Card, Acl) {
angular.extend(Calendar, {
$q: $q,
$timeout: $timeout,
$log: $log,
$$resource: new Resource(Settings.activeUser.folderURL + 'Calendar', Settings.activeUser),
$Card: Card,
$$Acl: Acl,
activeUser: Settings.activeUser
});
return Calendar; // return constructor
}];
/* Factory registration in Angular module */
angular.module('SOGo.SchedulerUI')
.factory('sgCalendar', Calendar.$factory);
/**
* @memberof Calendar
* @desc Add a new calendar to the static list of calendars
* @param {Calendar} calendar - an Calendar object instance
*/
Calendar.$add = function(calendar) {
// Insert new calendar at proper index
var sibling, i;
calendar.isOwned = this.activeUser.isSuperUser || calendar.owner == this.activeUser.login;
calendar.isSubscription = calendar.owner != this.activeUser.login;
sibling = _.find(this.$calendars, function(o) {
return (o.isRemote
|| (!calendar.isSubscription && o.isSubscription)
|| (o.id != 'personal'
&& o.isSubscription === calendar.isSubscription
&& o.name.localeCompare(calendar.name) === 1));
});
i = sibling ? _.indexOf(_.pluck(this.$calendars, 'id'), sibling.id) : 1;
this.$calendars.splice(i, 0, calendar);
};
/**
* @memberof Calendar
* @desc Set or get the list of calendars. Will instanciate a new Calendar object for each item.
* @param {object[]} [data] - the metadata of the calendars
* @returns the list of calendars
*/
Calendar.$findAll = function(data) {
var _this = this;
if (data) {
this.$calendars = data;
// Instanciate Calendar objects
angular.forEach(this.$calendars, function(o, i) {
_this.$calendars[i] = new Calendar(o);
// Add 'isOwned' and 'isSubscription' attributes based on active user (TODO: add it server-side?)
// _this.$calendars[i].isSubscription = _this.$calendars[i].owner != _this.activeUser.login;
// _this.$calendars[i].isOwned = _this.activeUser.isSuperUser
// || _this.$calendars[i].owner == _this.activeUser.login;
});
}
return this.$calendars;
};
/**
* @memberOf Calendar
* @desc Subscribe to another user's calendar and add it to the list of calendars.
* @param {string} uid - user id
* @param {string} path - path of folder for specified user
* @returns a promise of the HTTP query result
*/
Calendar.$subscribe = function(uid, path) {
var _this = this;
return Calendar.$$resource.userResource(uid).fetch(path, 'subscribe').then(function(calendarData) {
var calendar = new Calendar(calendarData);
if (!_.find(_this.$calendars, function(o) {
return o.id == calendarData.id;
})) {
Calendar.$add(calendar);
}
return calendar;
});
};
/**
* @function $rename
* @memberof Calendar.prototype
* @desc Rename the calendar and keep the list sorted
* @param {string} name - the new name
* @returns a promise of the HTTP operation
*/
Calendar.prototype.$rename = function(name) {
var i = _.indexOf(_.pluck(Calendar.$calendars, 'id'), this.id);
this.name = name;
Calendar.$calendars.splice(i, 1);
Calendar.$add(this);
return this.$save();
};
/**
* @function $delete
* @memberof Calendar.prototype
* @desc Delete the calendar from the server and the static list of calendars.
* @returns a promise of the HTTP operation
*/
Calendar.prototype.$delete = function() {
var _this = this,
d = Calendar.$q.defer(),
promise;
if (this.isSubscription)
promise = Calendar.$$resource.fetch(this.id, 'unsubscribe');
else
promise = Calendar.$$resource.remove(this.id);
promise.then(function() {
var i = _.indexOf(_.pluck(Calendar.$calendars, 'id'), _this.id);
Calendar.$calendars.splice(i, 1);
d.resolve(true);
}, function(data, status) {
d.reject(data);
});
return d.promise;
};
/**
* @function $save
* @memberof Calendar.prototype
* @desc Save the calendar properties to the server.
* @returns a promise of the HTTP operation
*/
Calendar.prototype.$save = function() {
return Calendar.$$resource.save(this.id, this.$omit()).then(function(data) {
return data;
});
};
/**
* @function $setActivation
* @memberof Calendar.prototype
* @desc Either activate or deactivate the calendar.
* @returns a promise of the HTTP operation
*/
Calendar.prototype.$setActivation = function() {
return Calendar.$$resource.fetch(this.id, (this.active?'':'de') + 'activateFolder');
};
/**
* @function $omit
* @memberof Calendar.prototype
* @desc Return a sanitized object used to send to the server.
* @return an object literal copy of the Calendar instance
*/
Calendar.prototype.$omit = function() {
var calendar = {};
angular.forEach(this, function(value, key) {
if (key != 'constructor' &&
key[0] != '$') {
calendar[key] = value;
}
});
return calendar;
};
})();

View File

@ -0,0 +1,216 @@
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
(function() {
'use strict';
/**
* @name Component
* @constructor
* @param {object} futureComponentData - either an object literal or a promise
*/
function Component(futureComponentData) {
// Data is immediately available
if (typeof futureComponentData.then !== 'function') {
angular.extend(this, futureComponentData);
}
else {
// The promise will be unwrapped first
this.$unwrap(futureComponentData);
}
}
/**
* @memberof Component
* @desc The factory we'll use to register with Angular
* @returns the Component constructor
*/
Component.$factory = ['$q', '$timeout', '$log', 'sgSettings', 'sgResource', function($q, $timeout, $log, Settings, Resource) {
angular.extend(Component, {
$q: $q,
$timeout: $timeout,
$log: $log,
$$resource: new Resource(Settings.baseURL, Settings.activeUser)
});
return Component; // return constructor
}];
/**
* @module SOGo.SchedulerUI
* @desc Factory registration of Component in Angular module.
*/
angular.module('SOGo.SchedulerUI')
/* Factory registration in Angular module */
.factory('sgComponent', Component.$factory);
/**
* @function $filter
* @memberof Component.prototype
* @desc Search for components matching some criterias
* @param {string} type - Either 'events' or 'tasks'
* @param {object} [options] - additional options to the query
* @returns a collection of Components instances
*/
Component.$filter = function(type, options) {
var _this = this,
now = new Date(),
day = now.getDate(),
month = now.getMonth() + 1,
year = now.getFullYear(),
defaultParams = {
search: 'title_Category_Location',
day: '' + year + (month < 10?'0':'') + month + (day < 10?'0':'') + day,
filterpopup: 'view_thismonth'
};
if (angular.isUndefined(this.$filterOptions))
this.$filterOptions = defaultParams;
if (options)
angular.extend(this.$filterOptions, options);
var futureComponentData = this.$$resource.fetch(null, type + 'list', this.$filterOptions);
return this.$unwrapCollection(type, futureComponentData);
};
/**
* @function $eventsBlocksForWeek
* @memberof Component.prototype
* @desc Events blocks for a specific week
* @param {Date} type - Date of any day of the week
* @returns a promise of a collection of Components instances
*/
Component.$eventsBlocksForWeek = function(date) {
var startDate, endDate, params, i,
deferred = Component.$q.defer();
startDate = date.beginOfWeek();
endDate = new Date();
endDate.setTime(startDate.getTime());
endDate.addDays(6);
params = { view: 'weekView', sd: startDate.getDayString(), ed: endDate.getDayString() };
Component.$log.debug('eventsblocks ' + JSON.stringify(params, undefined, 2));
var futureComponentData = this.$$resource.fetch(null, 'eventsblocks', params);
futureComponentData.then(function(data) {
Component.$timeout(function() {
var components = [], blocks = {};
// Instantiate Component objects
_.reduce(data.events, function(objects, eventData, i) {
var componentData = _.object(data.eventsFields, eventData),
start = new Date(componentData.c_startdate * 1000);
componentData.hour = start.getHourString();
objects.push(new Component(componentData));
return objects;
}, components);
// Associate Component objects to blocks positions
_.each(_.flatten(data.blocks), function(block) {
block.component = components[block.nbr];
});
// Convert array of blocks to object with days as keys
for (i = 0; i < 7; i++) {
blocks[startDate.getDayString()] = data.blocks[i];
startDate.addDays(1);
}
Component.$log.debug('blocks ready (' + _.keys(blocks).length + ')');
// Save the blocks to the object model
Component.$blocks = blocks;
deferred.resolve(blocks);
});
}, deferred.reject);
return deferred.promise;
};
/**
* @function $unwrap
* @memberof Comonent.prototype
* @desc Unwrap a promise and instanciate new Component objects using received data.
* @param {promise} futureComponentData - a promise of the components' metadata
* @returns a promise of the HTTP operation
*/
Component.$unwrapCollection = function(type, futureComponentData) {
var _this = this,
deferred = Component.$q.defer(),
components = [];
futureComponentData.then(function(data) {
Component.$timeout(function() {
var fields = _.invoke(data.fields, 'toLowerCase');
// Instanciate Component objects
_.reduce(data[type], function(components, componentData, i) {
var data = _.object(fields, componentData);
components.push(new Component(data));
return components;
}, components);
Component.$log.debug('list of ' + type + ' ready (' + components.length + ')');
// Save the list of components to the object model
Component['$' + type] = components;
deferred.resolve(components);
});
}, function(data) {
deferred.reject();
});
return deferred.promise;
};
/**
* @function $unwrap
* @memberof Component.prototype
* @desc Unwrap a promise.
* @param {promise} futureComponentData - a promise of some of the Component's data
*/
Component.prototype.$unwrap = function(futureComponentData) {
var _this = this,
deferred = Component.$q.defer();
// Expose the promise
this.$futureComponentData = futureComponentData;
// Resolve the promise
this.$futureComponentData.then(function(data) {
// Calling $timeout will force Angular to refresh the view
Component.$timeout(function() {
angular.extend(_this, data);
deferred.resolve(_this);
});
}, function(data) {
angular.extend(_this, data);
_this.isError = true;
Component.$log.error(_this.error);
deferred.reject();
});
return deferred.promise;
};
/**
* @function $omit
* @memberof Component.prototype
* @desc Return a sanitized object used to send to the server.
* @return an object literal copy of the Component instance
*/
Component.prototype.$omit = function() {
var component = {};
angular.forEach(this, function(value, key) {
if (key != 'constructor' && key[0] != '$') {
component[key] = value;
}
});
return component;
};
})();