2014-11-25 22:09:55 +01:00
|
|
|
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
|
|
|
|
(function() {
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @name Message
|
|
|
|
* @constructor
|
|
|
|
* @param {string} accountId - the account ID
|
|
|
|
* @param {string} mailboxPath - an array of the mailbox path components
|
|
|
|
* @param {object} futureAddressBookData - either an object literal or a promise
|
|
|
|
*/
|
|
|
|
function Message(accountId, mailboxPath, futureMessageData) {
|
|
|
|
this.accountId = accountId;
|
|
|
|
this.mailboxPath = mailboxPath;
|
|
|
|
// Data is immediately available
|
|
|
|
if (typeof futureMessageData.then !== 'function') {
|
|
|
|
//console.debug(JSON.stringify(futureMessageData, undefined, 2));
|
|
|
|
angular.extend(this, futureMessageData);
|
|
|
|
this.id = this.$absolutePath();
|
2014-12-11 15:15:33 +01:00
|
|
|
this.$formatFullAddresses();
|
2014-11-25 22:09:55 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// The promise will be unwrapped first
|
|
|
|
this.$unwrap(futureMessageData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @memberof Message
|
|
|
|
* @desc The factory we'll use to register with Angular
|
|
|
|
* @returns the Message constructor
|
|
|
|
*/
|
|
|
|
Message.$factory = ['$q', '$timeout', '$log', '$sce', 'sgSettings', 'sgResource', function($q, $timeout, $log, $sce, Settings, Resource) {
|
|
|
|
angular.extend(Message, {
|
|
|
|
$q: $q,
|
|
|
|
$timeout: $timeout,
|
|
|
|
$log: $log,
|
|
|
|
$sce: $sce,
|
|
|
|
$$resource: new Resource(Settings.baseURL, Settings.activeUser)
|
|
|
|
});
|
|
|
|
|
|
|
|
return Message; // return constructor
|
|
|
|
}];
|
|
|
|
|
|
|
|
/* Factory registration in Angular module */
|
|
|
|
angular.module('SOGo.MailerUI')
|
|
|
|
.factory('sgMessage', Message.$factory);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @function $absolutePath
|
|
|
|
* @memberof Message.prototype
|
|
|
|
* @desc Build the path of the message
|
|
|
|
* @returns a string representing the path relative to the mail module
|
|
|
|
*/
|
2014-12-11 15:15:33 +01:00
|
|
|
Message.prototype.$absolutePath = function(options) {
|
2014-11-25 22:09:55 +01:00
|
|
|
var path;
|
|
|
|
|
|
|
|
path = _.map(this.mailboxPath.split('/'), function(component) {
|
|
|
|
return 'folder' + component.asCSSIdentifier();
|
|
|
|
});
|
|
|
|
path.splice(0, 0, this.accountId); // insert account ID
|
2014-12-11 15:15:33 +01:00
|
|
|
if (options && options.asDraft && this.draftId) {
|
|
|
|
path.push(this.draftId); // add draft ID
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
path.push(this.uid); // add message UID
|
|
|
|
}
|
2014-11-25 22:09:55 +01:00
|
|
|
|
|
|
|
return path.join('/');
|
|
|
|
};
|
|
|
|
|
2014-12-11 15:15:33 +01:00
|
|
|
/**
|
|
|
|
* @function $formatFullAddresses
|
|
|
|
* @memberof Message.prototype
|
|
|
|
* @desc Preformat all sender and recipients addresses with a complete description (name <email>).
|
|
|
|
*/
|
|
|
|
Message.prototype.$formatFullAddresses = function() {
|
|
|
|
var _this = this;
|
|
|
|
|
|
|
|
// Build long representation of email addresses
|
|
|
|
_.each(['from', 'to', 'cc', 'bcc', 'reply-to'], function(type) {
|
|
|
|
_.each(_this[type], function(data, i) {
|
|
|
|
if (data.name && data.name != data.email)
|
|
|
|
data.full = data.name + ' <' + data.email + '>';
|
|
|
|
else
|
|
|
|
data.full = '<' + data.email + '>';
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2014-12-06 04:49:08 +01:00
|
|
|
/**
|
|
|
|
* @function $shortAddress
|
|
|
|
* @memberof Message.prototype
|
|
|
|
* @desc Format the first address of a specific type with a short description.
|
|
|
|
* @returns a string of the name or the email of the envelope address type
|
|
|
|
*/
|
|
|
|
Message.prototype.$shortAddress = function(type) {
|
|
|
|
var address = '';
|
|
|
|
if (this[type] && this[type].length > 0) {
|
|
|
|
address = this[type][0].name || this[type][0].email || '';
|
|
|
|
}
|
|
|
|
|
|
|
|
return address;
|
|
|
|
};
|
|
|
|
|
2014-11-25 22:09:55 +01:00
|
|
|
/**
|
|
|
|
* @function $content
|
|
|
|
* @memberof Message.prototype
|
2014-12-11 17:24:22 +01:00
|
|
|
* @desc Get the message body as accepted by SCE (Angular Strict Contextual Escaping).
|
|
|
|
* @returns the HTML representation of the body
|
2014-11-25 22:09:55 +01:00
|
|
|
*/
|
|
|
|
Message.prototype.$content = function() {
|
2014-12-11 17:24:22 +01:00
|
|
|
return Message.$sce.trustAs('html', this.content);
|
|
|
|
};
|
2014-11-25 22:09:55 +01:00
|
|
|
|
2014-12-11 17:24:22 +01:00
|
|
|
/**
|
|
|
|
* @function $update
|
|
|
|
* @memberof Message.prototype
|
|
|
|
* @desc Fetch the message body along with other metadata such as the list of attachments.
|
|
|
|
* @returns a promise of the HTTP operation
|
|
|
|
*/
|
|
|
|
Message.prototype.$update = function() {
|
|
|
|
var futureMessageData;
|
2014-11-25 22:09:55 +01:00
|
|
|
|
|
|
|
futureMessageData = Message.$$resource.fetch(this.id, 'view');
|
|
|
|
|
|
|
|
return this.$unwrap(futureMessageData);
|
|
|
|
};
|
|
|
|
|
2014-12-11 17:24:22 +01:00
|
|
|
Message.prototype.$save = function() {
|
|
|
|
var data = this.$omit();
|
|
|
|
Message.$log.debug(JSON.stringify(data, undefined, 2));
|
|
|
|
|
|
|
|
return Message.$$resource.save(this.$absolutePath({asDraft: true}), data);
|
|
|
|
};
|
|
|
|
|
|
|
|
Message.prototype.$send = function() {
|
|
|
|
var data = this.$omit(),
|
|
|
|
deferred = Message.$q.defer();
|
|
|
|
|
|
|
|
Message.$$resource.post(this.$absolutePath({asDraft: true}), 'send', data).then(function(data) {
|
|
|
|
if (data.status == 'success') {
|
|
|
|
deferred.resolve(data);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
deferred.reject(data);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return deferred.promise;
|
|
|
|
};
|
|
|
|
|
2014-11-25 22:09:55 +01:00
|
|
|
/**
|
|
|
|
* @function $unwrap
|
|
|
|
* @memberof Message.prototype
|
|
|
|
* @desc Unwrap a promise.
|
|
|
|
* @param {promise} futureMessageData - a promise of some of the Message's data
|
|
|
|
*/
|
|
|
|
Message.prototype.$unwrap = function(futureMessageData) {
|
|
|
|
var _this = this,
|
|
|
|
deferred = Message.$q.defer();
|
|
|
|
|
|
|
|
// Expose the promise
|
|
|
|
this.$futureMessageData = futureMessageData;
|
|
|
|
|
|
|
|
// Resolve the promise
|
|
|
|
this.$futureMessageData.then(function(data) {
|
|
|
|
// Calling $timeout will force Angular to refresh the view
|
|
|
|
Message.$timeout(function() {
|
|
|
|
angular.extend(_this, data);
|
|
|
|
_this.id = _this.$absolutePath();
|
2014-12-11 15:15:33 +01:00
|
|
|
_this.$formatFullAddresses();
|
|
|
|
deferred.resolve(_this);
|
2014-11-25 22:09:55 +01:00
|
|
|
});
|
|
|
|
}, function(data) {
|
|
|
|
angular.extend(_this, data);
|
|
|
|
_this.isError = true;
|
|
|
|
Message.$log.error(_this.error);
|
|
|
|
deferred.reject();
|
|
|
|
});
|
|
|
|
|
|
|
|
return deferred.promise;
|
|
|
|
};
|
|
|
|
|
2014-12-11 17:24:22 +01:00
|
|
|
/**
|
|
|
|
* @function $omit
|
|
|
|
* @memberof Message.prototype
|
|
|
|
* @desc Return a sanitized object used to send to the server.
|
|
|
|
* @return an object literal copy of the Message instance
|
|
|
|
*/
|
|
|
|
Message.prototype.$omit = function() {
|
|
|
|
var message = {};
|
|
|
|
angular.forEach(this, function(value, key) {
|
|
|
|
if (key != 'constructor' && key[0] != '$') {
|
|
|
|
message[key] = value;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Format addresses as arrays
|
|
|
|
_.each(['from', 'to', 'cc', 'bcc', 'reply-to'], function(type) {
|
|
|
|
if (message[type])
|
|
|
|
message[type] = _.invoke(message[type].split(','), 'trim');
|
|
|
|
});
|
|
|
|
|
|
|
|
//Message.$log.debug(JSON.stringify(message, undefined, 2));
|
|
|
|
return message;
|
|
|
|
};
|
|
|
|
|
2014-11-25 22:09:55 +01:00
|
|
|
})();
|