/* * Copyright (c) 2014 ThoughtWorks, Inc. * * Pixelated is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pixelated is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pixelated. If not, see . */ define( [ 'flight/lib/compose', 'helpers/view_helper', 'mail_view/ui/recipients/recipients', 'mail_view/ui/draft_save_status', 'page/events', 'views/i18n', 'mail_view/ui/send_button', 'mail_view/ui/attachment_icon', 'mail_view/ui/attachment_list', 'flight/lib/utils' ], function (compose, viewHelper, Recipients, DraftSaveStatus, events, i18n, SendButton, AttachmentIcon, attachmentList, utils) { 'use strict'; function withMailEditBase() { this.defaultAttrs({ bodyBox: '#text-box', sendButton: '#send-button', attachmentButton: '#attachment-button', attachmentList: '#attachment-list', cancelButton: '#cancel-button', trashButton: '#trash-button', toArea: '#recipients-to-area', toBox: '#recipients-to-box', ccArea: '#recipients-cc-area', bccArea: '#recipients-bcc-area', ccsTrigger: '#ccs-trigger', bccsTrigger: '#bccs-trigger', toTrigger: '#to-trigger', subjectBox: '#subject', tipMsg: '.tip-msg', draftSaveStatus: '#draft-save-status', recipientsFields: '#recipients-fields', currentTag: '', recipientValues: {to: [], cc: [], bcc: []}, saveDraftInterval: 3000 }); this.attachRecipients = function (context) { Recipients.attachTo(this.select('toArea'), {name: 'to', addresses: context.recipients.to}); Recipients.attachTo(this.select('ccArea'), {name: 'cc', addresses: context.recipients.cc || []}); Recipients.attachTo(this.select('bccArea'), {name: 'bcc', addresses: context.recipients.bcc || []}); }; function thereAreRecipientsToDisplay() { var allRecipients = _.chain(this.attr.recipientValues). values(). flatten(). remove(undefined). value(); return !_.isEmpty(allRecipients); } this.warnSendButtonOfRecipients = function () { if (thereAreRecipientsToDisplay.call(this)) { _.forOwn(this.attr.recipientValues, function (recipients, recipientsType) { if (!_.isUndefined(recipients) && !_.isEmpty(recipients)) { var recipientsUpdatedData = { newRecipients: recipients, recipientsName: recipientsType }; this.trigger(document, events.ui.recipients.updated, recipientsUpdatedData); } }.bind(this)); } }; this.render = function (template, context) { this.$node.html(template(context)); if (!context || _.isEmpty(context)) { context.recipients = {to: [], cc: [], bcc: []}; } this.attr.recipientValues = context.recipients; this.attr.attachments = context.attachments || []; this.attachRecipients(context); this.on(this.select('trashButton'), 'click', this.discardMail); SendButton.attachTo(this.select('sendButton')); AttachmentIcon.attachTo(this.select('attachmentButton')); this.warnSendButtonOfRecipients(); }; this.enableAutoSave = function () { this.select('bodyBox').on('input', this.monitorInput.bind(this)); this.select('subjectBox').on('input', this.monitorInput.bind(this)); this.on(document, events.mail.appendAttachment, this.monitorInput.bind(this)); this.on(document, events.mail.removeAttachment, this.monitorInput.bind(this)); DraftSaveStatus.attachTo(this.select('draftSaveStatus')); }; this.monitorInput = function () { this.trigger(events.ui.mail.changedSinceLastSave); this.cancelPostponedSaveDraft(); var mail = this.buildMail(); this.postponeSaveDraft(mail); }; this.discardMail = function () { this.cancelPostponedSaveDraft(); if (this.attr.ident) { var mail = this.buildMail(); this.trigger(document, events.ui.mail.delete, {mail: mail}); } else { this.trigger(document, events.ui.mail.discard); } }; this.trim_recipient = function (recipients) { return recipients.map(function (recipient) { return recipient.trim(); }); }; this.sendMail = function () { this.cancelPostponedSaveDraft(); var mail = this.buildMail('sent'); if (allRecipientsAreEmails(mail)) { mail.header.to = this.trim_recipient(mail.header.to); mail.header.cc = this.trim_recipient(mail.header.cc); mail.header.bcc = this.trim_recipient(mail.header.bcc); this.trigger(events.mail.send, mail); } else { this.trigger( events.ui.userAlerts.displayMessage, {message: i18n.t('recipients-not-valid')} ); this.trigger(events.mail.send_failed); } }; this.buildAndSaveDraft = function () { var mail = this.buildMail(); this.saveDraft(mail); }; this.recipientsUpdated = function (ev, data) { this.attr.recipientValues[data.recipientsName] = data.newRecipients; this.trigger(document, events.ui.mail.recipientsUpdated); if (data.skipSaveDraft) { return; } var mail = this.buildMail(); this.postponeSaveDraft(mail); }; this.saveDraft = function (mail) { this.cancelPostponedSaveDraft(); this.trigger(document, events.mail.saveDraft, mail); }; this.cancelPostponedSaveDraft = function () { clearTimeout(this.attr.timeout); }; this.postponeSaveDraft = function (mail) { this.cancelPostponedSaveDraft(); this.attr.timeout = window.setTimeout(_.bind(function () { this.saveDraft(mail); }, this), this.attr.saveDraftInterval); }; this.draftSaved = function (event, data) { this.attr.ident = data.ident; }; this.validateAnyRecipient = function () { return !_.isEmpty(_.flatten(_.values(this.attr.recipientValues))); }; function allRecipientsAreEmails(mail) { var allRecipients = mail.header.to.concat(mail.header.cc).concat(mail.header.bcc); return _.isEmpty(allRecipients) ? false : _.all(allRecipients, emailFormatChecker); } function emailFormatChecker(email) { var emailFormat = /[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailFormat.test(email); } this.saveTag = function (ev, data) { this.attr.currentTag = data.tag; }; this.mailSent = function () { this.trigger(document, events.ui.userAlerts.displayMessage, {message: 'Your message was sent!'}); }; this.enableFloatlabel = function (element) { var showClass = 'showfloatlabel'; $(element).bind('keyup', function () { var label = $(this).prev('label'); if (this.value !== '') { label.addClass(showClass); $(this).addClass(showClass); } else { label.removeClass(showClass); $(this).removeClass(showClass); } }); }; this.toggleRecipientsArrows = function () { $('#cc-bcc-collapse').toggleClass('fa-angle-down'); $('#cc-bcc-collapse').toggleClass('fa-angle-up'); }; this.before('initialize', function () { if (!this.discardDraft) { this.discardDraft = function () { }; } }); this.bindCollapse = function () { this.on($('#cc-bcc-collapse'), 'click', this.toggleRecipientsArrows); }; this.after('initialize', function () { this.on(document, events.dispatchers.rightPane.clear, this.teardown); this.on(document, events.ui.recipients.updated, this.recipientsUpdated); this.on(document, events.mail.draftSaved, this.draftSaved); this.on(document, events.mail.sent, this.mailSent); this.on(document, events.ui.mail.send, this.sendMail); this.on(document, events.ui.mail.discard, this.discardDraft); this.on(document, events.ui.tag.selected, this.saveTag); this.on(document, events.ui.tag.select, this.saveTag); this.bindCollapse(); }); compose.mixin(this, [attachmentList]); } return withMailEditBase; });