diff options
-rw-r--r-- | service/pixelated/adapter/mail.py | 7 | ||||
-rw-r--r-- | service/pixelated/adapter/mail_service.py | 3 | ||||
-rw-r--r-- | service/pixelated/controllers/mails_controller.py | 7 | ||||
-rw-r--r-- | service/test/unit/adapter/mail_test.py | 24 | ||||
-rw-r--r-- | web-ui/app/js/mail_list/ui/mail_items/generic_mail_item.js | 3 | ||||
-rw-r--r-- | web-ui/app/js/mail_list/ui/mail_items/mail_item.js | 3 | ||||
-rw-r--r-- | web-ui/app/js/tags/ui/tag.js | 6 | ||||
-rw-r--r-- | web-ui/app/js/tags/ui/tag_list.js | 4 | ||||
-rw-r--r-- | web-ui/app/js/tags/ui/tag_shortcut.js | 29 | ||||
-rw-r--r-- | web-ui/test/spec/mail_list/ui/mail_items/generic_mail_item.spec.js | 8 | ||||
-rw-r--r-- | web-ui/test/spec/tags/ui/tag.spec.js | 51 | ||||
-rw-r--r-- | web-ui/test/test_data.js | 3 |
12 files changed, 113 insertions, 35 deletions
diff --git a/service/pixelated/adapter/mail.py b/service/pixelated/adapter/mail.py index 513a07d8..5cafa36a 100644 --- a/service/pixelated/adapter/mail.py +++ b/service/pixelated/adapter/mail.py @@ -52,6 +52,10 @@ class Mail: return self.fdoc.content.get('flags') @property + def mailbox_name(self): + return self.fdoc.content.get('mbox') + + @property def _mime_multipart(self): if self._mime: return self._mime @@ -75,7 +79,8 @@ class Mail: 'tags': list(self.tags), 'status': list(self.status), 'security_casing': {}, - 'body': self.body + 'body': self.body, + 'mailbox': self.mailbox_name.lower() } diff --git a/service/pixelated/adapter/mail_service.py b/service/pixelated/adapter/mail_service.py index e908feb7..cc03ab3a 100644 --- a/service/pixelated/adapter/mail_service.py +++ b/service/pixelated/adapter/mail_service.py @@ -35,7 +35,8 @@ class MailService: if len(reserved_words): raise ValueError('None of the following words can be used as tags: ' + ' '.join(reserved_words)) mail = self.mail(mail_id) - return mail.update_tags(set(new_tags)) + mail.update_tags(set(new_tags)) + return mail def mail(self, mail_id): return self.mailboxes.mail(mail_id) diff --git a/service/pixelated/controllers/mails_controller.py b/service/pixelated/controllers/mails_controller.py index 6bd2fe99..f6414f27 100644 --- a/service/pixelated/controllers/mails_controller.py +++ b/service/pixelated/controllers/mails_controller.py @@ -92,11 +92,12 @@ class MailsController: def mail_tags(self, mail_id): new_tags = map(lambda tag: tag.lower(), request.get_json()['newtags']) try: - tags = self._mail_service.update_tags(mail_id, new_tags) - self._search_engine.index_mail(self._mail_service.mail(mail_id)) + self._mail_service.update_tags(mail_id, new_tags) + mail = self._mail_service.mail(mail_id) + self._search_engine.index_mail(mail) except ValueError as ve: return respond_json(ve.message, 403) - return respond_json(list(tags)) + return respond_json(mail.as_dict()) def update_draft(self): _mail = InputMail.from_dict(request.json) diff --git a/service/test/unit/adapter/mail_test.py b/service/test/unit/adapter/mail_test.py index 20038e96..94578a05 100644 --- a/service/test/unit/adapter/mail_test.py +++ b/service/test/unit/adapter/mail_test.py @@ -19,10 +19,10 @@ import pixelated.support.date from pixelated.adapter.mail import PixelatedMail, InputMail from mockito import * from test.support import test_helper +import dateutil.parser as dateparser class TestPixelatedMail(unittest.TestCase): - def setUp(self): self.querier = mock() @@ -68,6 +68,28 @@ class TestPixelatedMail(unittest.TestCase): self.assertEquals(mail.fdoc.content['flags'], []) + def test_as_dict(self): + fdoc, hdoc, bdoc = test_helper.leap_mail(flags=['\\Recent']) + hdoc.content['headers']['Subject'] = 'The subject' + hdoc.content['headers']['From'] = 'me@pixelated.org' + + mail = PixelatedMail.from_soledad(fdoc, hdoc, bdoc, soledad_querier=self.querier) + + _dict = mail.as_dict() + + self.assertEquals(_dict, {'body': 'body', + 'header': { + 'date': dateparser.parse(hdoc.content['date']).isoformat(), + 'from': 'me@pixelated.org', + 'subject': 'The subject' + }, + 'ident': 'chash', + 'mailbox': 'inbox', + 'security_casing': {}, + 'status': ['recent'], + 'tags': []} + ) + class InputMailTest(unittest.TestCase): mail_dict = lambda x: { diff --git a/web-ui/app/js/mail_list/ui/mail_items/generic_mail_item.js b/web-ui/app/js/mail_list/ui/mail_items/generic_mail_item.js index 3d426447..d5dfbf28 100644 --- a/web-ui/app/js/mail_list/ui/mail_items/generic_mail_item.js +++ b/web-ui/app/js/mail_list/ui/mail_items/generic_mail_item.js @@ -51,7 +51,8 @@ define( function updateMailStatusToRead() { if (!_.contains(this.attr.mail.status, this.status.READ)) { - this.trigger(document, events.mail.read, { ident: this.attr.ident, tags: this.attr.mail.tags }); + var mail_read_data = { ident: this.attr.ident, tags: this.attr.tags, mailbox: this.attr.mailbox }; + this.trigger(document, events.mail.read, mail_read_data); this.attr.mail.status.push(this.status.READ); this.$node.addClass(viewHelpers.formatStatusClasses(this.attr.mail.status)); } diff --git a/web-ui/app/js/mail_list/ui/mail_items/mail_item.js b/web-ui/app/js/mail_list/ui/mail_items/mail_item.js index 5a4192e6..5f1f354a 100644 --- a/web-ui/app/js/mail_list/ui/mail_items/mail_item.js +++ b/web-ui/app/js/mail_list/ui/mail_items/mail_item.js @@ -1,6 +1,6 @@ /* * 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 @@ -64,6 +64,7 @@ define( this.attr.ident = mail.ident; this.attr.statuses = viewHelper.formatStatusClasses(mail.status); this.attr.tags = mail.tags; + this.attr.mailbox = mail.mailbox; this.attr.header.formattedDate = this.formattedDate(mail.header.date); }; diff --git a/web-ui/app/js/tags/ui/tag.js b/web-ui/app/js/tags/ui/tag.js index c2b7f588..2cf45764 100644 --- a/web-ui/app/js/tags/ui/tag.js +++ b/web-ui/app/js/tags/ui/tag.js @@ -52,9 +52,13 @@ define( }; this.decreaseReadCountIfMatchingTag = function (ev, data) { - if (_.contains(data.tags, this.attr.tag.name)) { + var mailbox_and_tags = _.flatten([data.tags, data.mailbox]); + if (_.contains(mailbox_and_tags, this.attr.tag.name)) { this.attr.tag.counts.read++; this.$node.html(this.viewFor(this.attr.tag, templates.tags.tagInner)); + if (!_.isUndefined(this.attr.shortcut)) { + this.attr.shortcut.reRender(); + } } }; diff --git a/web-ui/app/js/tags/ui/tag_list.js b/web-ui/app/js/tags/ui/tag_list.js index 5bbac8ca..b5b4d555 100644 --- a/web-ui/app/js/tags/ui/tag_list.js +++ b/web-ui/app/js/tags/ui/tag_list.js @@ -55,7 +55,7 @@ define( }); this.renderShortcut = function (tag, tagComponent) { - TagShortcut.appendedTo($('#tags-shortcuts'), { linkTo: tag, trigger: tagComponent}); + return TagShortcut.appendedTo($('#tags-shortcuts'), { linkTo: tag, trigger: tagComponent}); }; function renderTag(tag, defaultList, customList) { @@ -63,7 +63,7 @@ define( var tagComponent = Tag.appendedTo(list, {tag: tag}); if (_.contains(_.keys(ORDER), tag.name)) { - this.renderShortcut(tag, tagComponent); + tagComponent.attr.shortcut = this.renderShortcut(tag, tagComponent); } } diff --git a/web-ui/app/js/tags/ui/tag_shortcut.js b/web-ui/app/js/tags/ui/tag_shortcut.js index 5710592e..0fe92550 100644 --- a/web-ui/app/js/tags/ui/tag_shortcut.js +++ b/web-ui/app/js/tags/ui/tag_shortcut.js @@ -26,7 +26,7 @@ define( function (describeComponent, templates, events, tagBase, utils) { - var TagShortcut = describeComponent(tagShortcut, tagBase); + var TagShortcut = describeComponent(tagShortcut, tagBase); TagShortcut.appendedTo = function (parent, data) { var res = new this(); @@ -38,9 +38,7 @@ define( function tagShortcut() { - this.renderAndAttach = function (parent, options) { - var linkTo = options.linkTo; - + this.renderTemplate = function (linkTo) { var model = { tagName: linkTo.name, displayBadge: this.displayBadge(linkTo), @@ -48,11 +46,16 @@ define( count: this.badgeType(linkTo) === 'total' ? linkTo.counts.total : (linkTo.counts.total - linkTo.counts.read), icon: iconFor[linkTo.name] }; + return templates.tags.shortcut(model); + }; - var rendered = templates.tags.shortcut(model); - parent.append(rendered); + this.renderAndAttach = function (parent, options) { + parent.append(this.renderTemplate(options.linkTo)); + this.initialize(parent.children().last(), options); + }; - this.initialize(parent.children().last(),options); + this.reRender = function () { + this.$node.html(this.renderTemplate(this.attr.linkTo)); }; var iconFor = { @@ -64,8 +67,12 @@ define( }; this.selectTag = function (ev, data) { - if(data.tag === this.attr.linkTo.name) { this.doSelect(); } - else { this.doUnselect(); } + if (data.tag === this.attr.linkTo.name) { + this.doSelect(); + } + else { + this.doUnselect(); + } }; this.doUnselect = function () { @@ -83,7 +90,9 @@ define( }; this.after('initialize', function () { - this.on('click', function () { this.attr.trigger.triggerSelect(); }); + this.on('click', function () { + this.attr.trigger.triggerSelect(); + }); this.on(document, events.ui.tag.select, this.selectTag); this.on(document, events.tags.shortcuts.teardown, this.doTeardown); }); diff --git a/web-ui/test/spec/mail_list/ui/mail_items/generic_mail_item.spec.js b/web-ui/test/spec/mail_list/ui/mail_items/generic_mail_item.spec.js index ecb2b854..b03babb5 100644 --- a/web-ui/test/spec/mail_list/ui/mail_items/generic_mail_item.spec.js +++ b/web-ui/test/spec/mail_list/ui/mail_items/generic_mail_item.spec.js @@ -5,7 +5,8 @@ describeComponent('mail_list/ui/mail_items/generic_mail_item', function () { beforeEach(function () { mail = Pixelated.testData().parsedMail.simpleTextPlain; - mail.tags = ['inbox']; + mail.tags = []; + mail.mailbox = 'inbox'; setupComponent('<li></li>', { mail: mail, @@ -95,7 +96,7 @@ describeComponent('mail_list/ui/mail_items/generic_mail_item', function () { expect(this.component.attr.mail.status).toContain(this.component.status.READ); expect(this.$node.attr('class')).toMatch('status-read'); - expect(mailReadEvent).toHaveBeenTriggeredOnAndWith(document, { ident: mail.ident, tags: ['inbox'] }); + expect(mailReadEvent).toHaveBeenTriggeredOnAndWith(document, { ident: mail.ident, tags: [], mailbox: 'inbox' }); }); }); @@ -110,7 +111,8 @@ describeComponent('mail_list/ui/mail_items/generic_mail_item', function () { this.$node.find('a').click(); - expect(mailReadEvent).toHaveBeenTriggeredOnAndWith(document, jasmine.objectContaining({ident: mail.ident})); + var expectedEventData = {ident: mail.ident}; + expect(mailReadEvent).toHaveBeenTriggeredOnAndWith(document, jasmine.objectContaining(expectedEventData)); }); it('should not trigger mail:read event when clicking mail that is already read', function () { diff --git a/web-ui/test/spec/tags/ui/tag.spec.js b/web-ui/test/spec/tags/ui/tag.spec.js index de78ba75..48f761da 100644 --- a/web-ui/test/spec/tags/ui/tag.spec.js +++ b/web-ui/test/spec/tags/ui/tag.spec.js @@ -4,7 +4,7 @@ describeComponent('tags/ui/tag', function () { 'use strict'; - describe('inbox tag', function() { + describe('inbox tag', function () { beforeEach(function () { setupComponent('<li></li>', { tag: { @@ -46,11 +46,42 @@ describeComponent('tags/ui/tag', function () { expect(tagSelectedEvent).toHaveBeenTriggeredOnAndWith(document, { tag: 'drafts'}); }); - it('increases the read count when there is an email read and the email has that tag', function () { + describe('increasing count read when email is read', function () { + it('doesnt update if mail.tags or mail.mailbox dont match the tag name', function () { + setupComponent('<li></li>', { + tag: { name: 'sometag', ident: '1', counts: { total: 100, read: 0 } } + }); + + $(document).trigger(Pixelated.events.mail.read, { tags: ['someothertag'], mailbox: 'inbox' }); + + expect(this.component.attr.tag.counts.read).toEqual(0); + }); + + it('looks at the mail mailbox attr for default tags', function () { + $(document).trigger(Pixelated.events.mail.read, { tags: [], mailbox: 'inbox' }); + + expect(this.component.attr.tag.counts.read).toEqual(1); + expect(this.$node.html()).toMatch('<span class="unread-count">99</span>'); + }); + + it('looks at the mail tags for non default tags', function () { + setupComponent('<li></li>', { + tag: { name: 'tag', ident: '1', counts: { total: 100, read: 0 } } + }); + + $(document).trigger(Pixelated.events.mail.read, { tags: ['tag'], mailbox: 'inbox' }); + + expect(this.component.attr.tag.counts.read).toEqual(1); + expect(this.$node.html()).toMatch('<span class="unread-count">99</span>'); + }); + }); + + it('re-renders the tag shortcut linked to it when increasing the read count if there is a shortcut', function () { + this.component.attr.shortcut = jasmine.createSpyObj('shortcut', ['reRender']); + $(document).trigger(Pixelated.events.mail.read, { tags: ['inbox'] }); - expect(this.component.attr.tag.counts.read).toEqual(1); - expect(this.$node.html()).toMatch('<span class="unread-count">99</span>'); + expect(this.component.attr.shortcut.reRender).toHaveBeenCalled(); }); it('doesnt increase the read count when the read email doesnt have the tag', function () { @@ -89,7 +120,7 @@ describeComponent('tags/ui/tag', function () { }); }); - describe('all tag', function(){ + describe('all tag', function () { beforeEach(function () { setupComponent('<li></li>', { tag: { @@ -103,18 +134,18 @@ describeComponent('tags/ui/tag', function () { }); }); - it('adds searching class when user is doing a search', function(){ + it('adds searching class when user is doing a search', function () { $(document).trigger(Pixelated.events.search.perform, {}); expect(this.$node.attr('class')).toMatch('searching'); }); - it('removes searching class when user searches for empty string', function(){ + it('removes searching class when user searches for empty string', function () { $(document).trigger(Pixelated.events.search.perform, {}); $(document).trigger(Pixelated.events.search.empty); expect(this.$node.attr('class')).not.toMatch('searching'); }); - it('removes searching class when user clicks in any tag', function(){ + it('removes searching class when user clicks in any tag', function () { $(document).trigger(Pixelated.events.search.perform, {}); this.$node.click(); expect(this.$node.attr('class')).not.toMatch('searching'); @@ -122,8 +153,8 @@ describeComponent('tags/ui/tag', function () { }); - _.each(['sent', 'trash'], function(tag_name) { - describe(tag_name + ' tag', function() { + _.each(['sent', 'trash'], function (tag_name) { + describe(tag_name + ' tag', function () { beforeEach(function () { setupComponent('<li></li>', { tag: { diff --git a/web-ui/test/test_data.js b/web-ui/test/test_data.js index bf3626bb..194cd02d 100644 --- a/web-ui/test/test_data.js +++ b/web-ui/test/test_data.js @@ -84,7 +84,8 @@ define(function() { date:'2014-06-04T14:41:13-03:00' }, ident:1, - tags:['textplain','inbox'], + tags:['textplain'], + mailbox: ['inbox'], status:[], body: 'Hello Everyone', isSentMail: function() { return false; }, |