summaryrefslogtreecommitdiff
path: root/web-ui/app/js/services
diff options
context:
space:
mode:
authorOla Bini <ola.bini@gmail.com>2014-07-31 19:29:33 -0300
committerOla Bini <ola.bini@gmail.com>2014-07-31 19:29:33 -0300
commit04cf441c5ae18400c6b4865b0b37a71718dc9d46 (patch)
treedd0b0d049ec00389e2d4561b226c46eb1682b997 /web-ui/app/js/services
parent639a663a4c37020003586438fdcd7ac529a00f10 (diff)
Add web-ui based on previous code
Diffstat (limited to 'web-ui/app/js/services')
-rw-r--r--web-ui/app/js/services/delete_service.js43
-rw-r--r--web-ui/app/js/services/mail_service.js254
-rw-r--r--web-ui/app/js/services/model/mail.js147
3 files changed, 444 insertions, 0 deletions
diff --git a/web-ui/app/js/services/delete_service.js b/web-ui/app/js/services/delete_service.js
new file mode 100644
index 00000000..7c6e8cc4
--- /dev/null
+++ b/web-ui/app/js/services/delete_service.js
@@ -0,0 +1,43 @@
+/*global _ */
+
+define(['flight/lib/component', 'page/events', 'views/i18n'], function (defineComponent, events, i18n) {
+ 'use strict';
+
+ return defineComponent(function() {
+
+ this.successDeleteMessageFor = function(mail) {
+ return mail.isInTrash() ?
+ i18n('Your message was permanently deleted!') :
+ i18n('Your message was moved to trash!');
+ };
+
+ this.successDeleteManyMessageFor = function(mail) {
+ return mail.isInTrash() ?
+ i18n('Your messages were permanently deleted!') :
+ i18n('Your messages were moved to trash!');
+ };
+
+ this.deleteEmail = function (event, data) {
+ this.trigger(document, events.mail.delete, {
+ mail: data.mail,
+ successMessage: this.successDeleteMessageFor(data.mail)
+ });
+ };
+
+ this.deleteManyEmails = function (event, data) {
+ var emails = _.values(data.checkedMails),
+ firstEmail = emails[_.first(_.keys(emails))];
+
+ this.trigger(document, events.mail.deleteMany, {
+ mails: emails,
+ successMessage: this.successDeleteManyMessageFor(firstEmail)
+ });
+ };
+
+ this.after('initialize', function () {
+ this.on(document, events.ui.mail.delete, this.deleteEmail);
+ this.on(document, events.ui.mail.deleteMany, this.deleteManyEmails);
+ });
+
+ });
+});
diff --git a/web-ui/app/js/services/mail_service.js b/web-ui/app/js/services/mail_service.js
new file mode 100644
index 00000000..86642f37
--- /dev/null
+++ b/web-ui/app/js/services/mail_service.js
@@ -0,0 +1,254 @@
+/*global _ */
+/*global Smail */
+
+define(
+ [
+ 'flight/lib/component',
+ 'views/i18n',
+ 'services/model/mail',
+ 'page/events'
+ ], function (defineComponent, i18n, Mail, events) {
+
+ 'use strict';
+
+ return defineComponent(mailService);
+
+ function mailService() {
+ var that;
+
+ this.defaultAttrs({
+ mailsResource: '/mails',
+ singleMailResource: '/mail',
+ currentTag: '',
+ lastQuery: '',
+ currentPage: 0,
+ numPages: 0,
+ w: 25
+ });
+
+ this.errorMessage = function(msg) {
+ return function() {
+ that.trigger(document, events.ui.userAlerts.displayMessage, { message: msg });
+ };
+ };
+
+ this.updateTags = function(ev, data) {
+ var that = this;
+ var ident = data.ident;
+ $.ajax('/mail/' + ident + '/tags', {
+ type: 'POST',
+ contentType: 'application/json; charset=utf-8',
+ data: JSON.stringify({newtags: data.tags})
+ }).done(function(data) {
+ that.refreshResults();
+ $(document).trigger(events.mail.tags.updated, { ident: ident, tags: data });
+ })
+ .fail(this.errorMessage(i18n('Could not update mail tags')));
+ };
+
+ this.readMail = function(ev, data) {
+ var mailIdents;
+ if (data.checkedMails) {
+ mailIdents = _.map(data.checkedMails, function(mail) {
+ return mail.ident;
+ });
+ $.ajax( '/mails/read', {
+ type: 'POST',
+ data: {idents: JSON.stringify(mailIdents)}
+ }).done(this.triggerMailsRead(data.checkedMails));
+ } else {
+ $.ajax('/mail/' + data.ident + '/read', {type: 'POST'});
+ }
+ };
+
+ this.unreadMail = function(ev, data) {
+ var mailIdents;
+ if (data.checkedMails) {
+ mailIdents = _.map(data.checkedMails, function(mail) {
+ return mail.ident;
+ });
+ $.ajax( '/mails/unread', {
+ type: 'POST',
+ data: {idents: JSON.stringify(mailIdents)}
+ }).done(this.triggerMailsRead(data.checkedMails));
+ } else {
+ $.ajax('/mail/' + data.ident + '/read', {type: 'POST'});
+ }
+ };
+
+ this.triggerMailsRead = function(mails) {
+ return _.bind(function() {
+ this.refreshResults();
+ this.trigger(document, events.ui.mail.unchecked, { mails: mails });
+ this.trigger(document, events.ui.mails.hasMailsChecked, false);
+ }, this);
+ };
+
+ this.triggerDeleted = function(dataToDelete) {
+ return _.bind(function() {
+ var mails = dataToDelete.mails || [dataToDelete.mail];
+
+ this.refreshResults();
+ this.trigger(document, events.ui.userAlerts.displayMessage, { message: dataToDelete.successMessage});
+ this.trigger(document, events.ui.mail.unchecked, { mails: mails });
+ this.trigger(document, events.ui.mails.hasMailsChecked, false);
+ this.trigger(document, events.mail.deleted, { mails: mails });
+ }, this);
+ };
+
+ this.deleteMail = function(ev, data) {
+ $.ajax('/mail/' + data.mail.ident,
+ {type: 'DELETE'})
+ .done(this.triggerDeleted(data))
+ .fail(this.errorMessage(i18n('Could not delete email')));
+ };
+
+ this.deleteManyMails = function(ev, data) {
+ var dataToDelete = data;
+ var mailIdents = _.map(data.mails, function(mail) {
+ return mail.ident;
+ });
+
+ $.ajax('/mails', {
+ type: 'DELETE',
+ data: {idents: JSON.stringify(mailIdents)}
+ }).done(this.triggerDeleted(dataToDelete))
+ .fail(this.errorMessage(i18n('Could not delete emails')));
+ };
+
+ function compileQuery(data) {
+ var query = 'tag:"' + that.attr.currentTag + '"';
+
+ if (data.tag === 'all') {
+ query = 'in:all';
+ }
+ return query;
+ }
+
+ this.fetchByTag = function(ev, data) {
+ this.attr.currentTag = data.tag;
+ this.updateCurrentPageNumber(0);
+
+ this.fetchMail(compileQuery(data), this.attr.currentTag, false, data);
+ };
+
+ this.refreshResults = function(ev, data) {
+ var query = this.attr.lastQuery;
+ this.fetchMail(query, this.attr.currentTag, true);
+ };
+
+ this.newSearch = function(ev, data) {
+ var query = data.query;
+ this.attr.currentTag = 'all';
+ this.fetchMail(query, 'all');
+ };
+
+ this.mailFromJSON = function(mail) {
+ return Mail.create(mail);
+ };
+
+ this.parseMails = function(data) {
+ data.mails = _.map(data.mails, this.mailFromJSON, this);
+
+ return data;
+ };
+
+ function escaped(s) {
+ return encodeURI(s);
+ }
+
+ this.excludeTrashedEmailsForDraftsAndSent = function(query) {
+ if (query === 'tag:"drafts"' || query === 'tag:"sent"') {
+ return query + ' -in:"trash"';
+ } else {
+ return query;
+ }
+ };
+
+ this.fetchMail = function(query, tag, fromRefresh, eventData) {
+ var p = this.attr.currentPage;
+ var w = this.attr.w;
+ var url = this.attr.mailsResource + '?q='+ escaped(this.excludeTrashedEmailsForDraftsAndSent(query)) + '&p=' + p + '&w=' + w;
+ this.attr.lastQuery = this.excludeTrashedEmailsForDraftsAndSent(query);
+ $.ajax(url, { dataType: 'json' })
+ .done(function(data) {
+ this.attr.numPages = Math.ceil(data.stats.total / this.attr.w);
+ var eventToTrigger = fromRefresh ? events.mails.availableForRefresh : events.mails.available;
+ this.trigger(document, eventToTrigger, _.merge(_.merge({tag: tag }, eventData), this.parseMails(data)));
+ }.bind(this))
+ .fail(function() {
+ this.trigger(document, events.ui.userAlerts.displayMessage, { message: i18n('Could not fetch messages') });
+ }.bind(this));
+ };
+
+ function createSingleMailUrl(mailsResource, ident){
+ return mailsResource + '/' + ident;
+ }
+
+ this.fetchSingle = function(event, data) {
+ var fetchUrl = createSingleMailUrl(this.attr.singleMailResource, data.mail);
+
+ $.ajax(fetchUrl, { dataType: 'json' })
+ .done(function(mail) {
+ if (_.isNull(mail)) {
+ this.trigger(data.caller, events.mail.notFound);
+ return;
+ }
+
+ this.trigger(data.caller, events.mail.here, { mail: this.mailFromJSON(mail) });
+ }.bind(this));
+ };
+
+ this.previousPage = function() {
+ if(this.attr.currentPage > 0) {
+ this.updateCurrentPageNumber(this.attr.currentPage - 1);
+ this.refreshResults();
+ }
+ };
+
+ this.nextPage = function() {
+ if(this.attr.currentPage < (this.attr.numPages - 1)) {
+ this.updateCurrentPageNumber(this.attr.currentPage + 1);
+ this.refreshResults();
+ }
+ };
+
+ this.updateCurrentPageNumber = function(newCurrentPage) {
+ this.attr.currentPage = newCurrentPage;
+ this.trigger(document, events.ui.page.changed, {
+ currentPage: this.attr.currentPage,
+ numPages: this.attr.numPages
+ });
+ };
+
+ this.wantDraftReplyForMail = function(ev, data) {
+ $.ajax('/draft_reply_for/' + data.ident, { dataType: 'json' })
+ .done(function(mail) {
+ if (_.isNull(mail)) {
+ this.trigger(document, events.mail.draftReply.notFound);
+ return;
+ }
+ this.trigger(document, events.mail.draftReply.here, { mail: this.mailFromJSON(mail) });
+ }.bind(this));
+ };
+
+ this.after('initialize', function () {
+ that = this;
+
+ this.on(events.mail.want, this.fetchSingle);
+ this.on(document, events.mail.read, this.readMail);
+ this.on(document, events.mail.unread, this.unreadMail);
+ this.on(document, events.mail.tags.update, this.updateTags);
+ this.on(document, events.mail.delete, this.deleteMail);
+ this.on(document, events.mail.deleteMany, this.deleteManyMails);
+ this.on(document, events.search.perform, this.newSearch);
+ this.on(events.mail.draftReply.want, this.wantDraftReplyForMail);
+
+ this.on(events.ui.mails.fetchByTag, this.fetchByTag);
+ this.on(events.ui.mails.refresh, this.refreshResults);
+ this.on(events.ui.page.previous, this.previousPage);
+ this.on(events.ui.page.next, this.nextPage);
+ });
+ }
+ }
+);
diff --git a/web-ui/app/js/services/model/mail.js b/web-ui/app/js/services/model/mail.js
new file mode 100644
index 00000000..6f99465e
--- /dev/null
+++ b/web-ui/app/js/services/model/mail.js
@@ -0,0 +1,147 @@
+/*global _ */
+'use strict';
+
+define(['helpers/contenttype'],
+ function (contentType) {
+
+ var asMail = (function () {
+
+ function isSentMail() {
+ return _.contains(this.tags, 'sent');
+ }
+
+ function isDraftMail() {
+ return _.contains(this.tags, 'drafts');
+ }
+
+ function normalize(recipients) {
+ return _.chain([recipients])
+ .flatten()
+ .filter(function (r) {
+ return !_.isUndefined(r) && !_.isEmpty(r);
+ })
+ .value();
+ }
+
+ function isInTrash() {
+ return _.contains(this.tags, 'trash');
+ }
+
+ function setDraftReplyFor(ident) {
+ this.draft_reply_for = ident;
+ }
+
+ function recipients(){
+ return {
+ to: normalize(this.header.to),
+ cc: normalize(this.header.cc)
+ };
+ }
+
+ function replyToAddress() {
+ var recipients;
+
+ if (this.isSentMail()) {
+ recipients = this.recipients();
+ } else {
+ recipients = {
+ to: normalize(this.header.reply_to || this.header.from),
+ cc: []
+ };
+ }
+
+ return recipients;
+ }
+
+ function replyToAllAddress() {
+ return {
+ to: normalize([this.header.reply_to, this.header.from, this.header.to]),
+ cc: normalize(this.header.cc)
+ };
+ }
+
+ function getHeadersFromMailPart (rawBody) {
+ var lines, headerLines, endOfHeaders, headers;
+
+ lines = rawBody.split('\n');
+ endOfHeaders = _.indexOf(lines, '');
+ headerLines = lines.slice(0, endOfHeaders);
+
+ headers = _.map(headerLines, function (headerLine) {
+ return headerLine.split(': ');
+ });
+
+ return _.object(headers);
+ }
+
+ function getBodyFromMailPart (rawBody) {
+ var lines, endOfHeaders;
+
+ lines = rawBody.split('\n');
+ endOfHeaders = _.indexOf(lines, '');
+
+ return lines.slice(endOfHeaders + 1).join('\n');
+ }
+
+ function parseWithHeaders(rawBody) {
+ return {headers: getHeadersFromMailPart(rawBody), body: getBodyFromMailPart(rawBody)};
+ }
+
+ function getMailMultiParts () {
+ var mediaType = this.getMailMediaType();
+ var boundary = '--' + mediaType.params.boundary + '\n';
+ var finalBoundary = '--' + mediaType.params.boundary + '--';
+
+ var bodyParts = this.body.split(finalBoundary)[0].split(boundary);
+
+ bodyParts = _.reject(bodyParts, function(bodyPart) { return _.isEmpty(bodyPart.trim()); });
+
+ return _.map(bodyParts, parseWithHeaders);
+ };
+
+ function getMailMediaType () {
+ return new contentType.MediaType(this.header.content_type);
+ }
+
+ function isMailMultipartAlternative () {
+ return this.getMailMediaType().type === 'multipart/alternative';
+ }
+
+ function availableBodyPartsContentType () {
+ var bodyParts = this.getMailMultiParts();
+
+ return _.pluck(_.pluck(bodyParts, 'headers'), 'Content-Type');
+ }
+
+ function getMailPartByContentType (contentType) {
+ var bodyParts = this.getMailMultiParts();
+
+ return _.findWhere(bodyParts, {headers: {'Content-Type': contentType}});
+ }
+
+ return function () {
+ this.isSentMail = isSentMail;
+ this.isDraftMail = isDraftMail;
+ this.isInTrash = isInTrash;
+ this.setDraftReplyFor = setDraftReplyFor;
+ this.replyToAddress = replyToAddress;
+ this.replyToAllAddress = replyToAllAddress;
+ this.recipients = recipients;
+ this.getMailMediaType = getMailMediaType;
+ this.isMailMultipartAlternative = isMailMultipartAlternative;
+ this.getMailMultiParts = getMailMultiParts;
+ this.availableBodyPartsContentType = availableBodyPartsContentType;
+ this.getMailPartByContentType = getMailPartByContentType;
+ return this;
+ };
+ }());
+
+ return {
+ create: function (mail) {
+ if (mail) {
+ asMail.apply(mail);
+ }
+ return mail;
+ }
+ };
+});