From 72e332e2969d4eb36c9cd64336c1f1d89b6185f1 Mon Sep 17 00:00:00 2001 From: Giovane Date: Fri, 23 Oct 2015 12:19:19 -0200 Subject: Add invalid address sinalization on tokens #492 --- web-ui/app/js/mail_view/ui/recipients/recipient.js | 10 ++++++- .../app/js/mail_view/ui/recipients/recipients.js | 6 ++++ .../js/mail_view/ui/recipients/recipients_input.js | 32 ++++++++++++++++------ web-ui/app/js/page/events.js | 1 + web-ui/app/scss/_mixins.scss | 9 ++++-- .../mail_view/ui/recipients/recipients.spec.js | 21 +++++++++++++- .../ui/recipients/recipients_input.spec.js | 29 ++++++++++++++++++++ 7 files changed, 95 insertions(+), 13 deletions(-) diff --git a/web-ui/app/js/mail_view/ui/recipients/recipient.js b/web-ui/app/js/mail_view/ui/recipients/recipient.js index 487ca9a0..f3db5d4e 100644 --- a/web-ui/app/js/mail_view/ui/recipients/recipient.js +++ b/web-ui/app/js/mail_view/ui/recipients/recipient.js @@ -72,6 +72,10 @@ define( return this.$node.find('.recipient-value').hasClass('selected'); }; + this.sinalizeInvalid = function () { + this.$node.find('.recipient-value>span').addClass('invalid-format'); + }; + this.discoverEncryption = function () { this.$node.addClass('discorver-encryption'); var p = $.getJSON('/keys?search=' + this.attr.address).promise(); @@ -96,8 +100,12 @@ define( this.after('initialize', function () { this.recipientDelActions(); - this.discoverEncryption(); this.on('dblclick', this.editRecipient); + if (this.attr.invalidAddress){ + this.sinalizeInvalid(); + } else { + this.discoverEncryption(); + } }); } } diff --git a/web-ui/app/js/mail_view/ui/recipients/recipients.js b/web-ui/app/js/mail_view/ui/recipients/recipients.js index f5d51d31..7072c09e 100644 --- a/web-ui/app/js/mail_view/ui/recipients/recipients.js +++ b/web-ui/app/js/mail_view/ui/recipients/recipients.js @@ -70,6 +70,11 @@ define( this.addressesUpdated(); }; + this.invalidRecipientEntered = function(event, recipient) { + recipient.invalidAddress = true; + this.addRecipient(recipient); + }; + this.deleteRecipient = function (event, recipient) { var iter = new Iterator(this.attr.recipients, /*startingIndex=*/-1); @@ -150,6 +155,7 @@ define( this.on(events.ui.recipients.deleteLast, this.deleteLastRecipient); this.on(events.ui.recipients.selectLast, this.selectLastRecipient); this.on(events.ui.recipients.entered, this.recipientEntered); + this.on(events.ui.recipients.enteredInvalid, this.invalidRecipientEntered); this.on(document, events.ui.recipients.doCompleteInput, this.doCompleteRecipients); diff --git a/web-ui/app/js/mail_view/ui/recipients/recipients_input.js b/web-ui/app/js/mail_view/ui/recipients/recipients_input.js index 4c70e180..54c8fed9 100644 --- a/web-ui/app/js/mail_view/ui/recipients/recipients_input.js +++ b/web-ui/app/js/mail_view/ui/recipients/recipients_input.js @@ -42,6 +42,10 @@ define([ }, self; + var simpleAddressMatch = /[^<\w,;]?([^\s<;,]+@[^\s>;,]+)/; + var canonicalAddressMatch = /([^,;\s][^,;@]+<[^\s;,]+@[^\s;,]+>)/; + var emailAddressMatch = new RegExp([simpleAddressMatch.source, '|', canonicalAddressMatch.source].join(''), 'g'); + var extractContactNames = function (response) { return _.map(response, function(a) { return { value: a }; }); }; @@ -109,20 +113,30 @@ define([ this.recipientSelected = function (event, data) { var value = (data && data.value) || this.$node.val(); var that = this; - var addresses = this.extractAdresses(value); - _.each(addresses, function(address) { + + function triggerEventForEach(addresses, event) { + _.each(addresses, function(address) { if (!_.isEmpty(address.trim())) { - that.trigger(that.$node, events.ui.recipients.entered, { name: that.attr.name, address: address.trim() }); + that.trigger(that.$node, event, { name: that.attr.name, address: address.trim() }); } - }); + }); + } + + var validAddresses = this.extractValidAddresses(value); + var invalidAddresses = this.extractInvalidAddresses(value); + + triggerEventForEach(validAddresses, events.ui.recipients.entered); + triggerEventForEach(invalidAddresses, events.ui.recipients.enteredInvalid); + reset(this.$node); }; - this.extractAdresses = function(rawAddresses){ - var simpleAddressMatch = /[^<\w,;]?([^\s<;,]+@[^\s>;,]+)/; - var canonicalAddressMatch = /([^,;\s][^,;]+<[^\s;,]+@[^\s;,]+>)/; - var addressMatch = new RegExp([simpleAddressMatch.source, '|', canonicalAddressMatch.source].join(''), 'g'); - return rawAddresses.match(addressMatch); + this.extractValidAddresses = function(rawAddresses) { + return rawAddresses.match(emailAddressMatch); + }; + + this.extractInvalidAddresses = function(rawAddresses) { + return rawAddresses.replace(emailAddressMatch, '').split(' '); }; this.init = function () { diff --git a/web-ui/app/js/page/events.js b/web-ui/app/js/page/events.js index cfc3d7db..df062495 100644 --- a/web-ui/app/js/page/events.js +++ b/web-ui/app/js/page/events.js @@ -81,6 +81,7 @@ define(function () { }, recipients: { entered: 'ui:recipients:entered', + enteredInvalid: 'ui:recipients:enteredInvalid', updated: 'ui:recipients:updated', deleteRecipient: 'ui:recipients:deleteRecipient', deleteLast: 'ui:recipients:deleteLast', diff --git a/web-ui/app/scss/_mixins.scss b/web-ui/app/scss/_mixins.scss index c629bbe6..ba0ab525 100644 --- a/web-ui/app/scss/_mixins.scss +++ b/web-ui/app/scss/_mixins.scss @@ -185,6 +185,10 @@ flex: 1 1 50px; } + .invalid-format { + border-bottom: 1px dotted $error; + } + input[type=text] { vertical-align: top; height: 35px; @@ -210,7 +214,7 @@ } &.encrypted { border-bottom-color: $will_be_encrypted; - + &:before { color: $will_be_encrypted; content: "\f023 "; @@ -218,12 +222,13 @@ } &.not-encrypted { border-bottom-color: $wont_be_encrypted; - + &:before { color: $wont_be_encrypted; content: "\f13e "; } } + &.deleting span { text-decoration: line-through; } diff --git a/web-ui/test/spec/mail_view/ui/recipients/recipients.spec.js b/web-ui/test/spec/mail_view/ui/recipients/recipients.spec.js index 7dd9000f..a3b3381f 100644 --- a/web-ui/test/spec/mail_view/ui/recipients/recipients.spec.js +++ b/web-ui/test/spec/mail_view/ui/recipients/recipients.spec.js @@ -26,15 +26,34 @@ describeComponent('mail_view/ui/recipients/recipients',function () { beforeEach(function () { this.setupComponent(); recipientsUpdatedEvent = spyOnEvent(document, Pixelated.events.ui.recipients.updated); - this.component.trigger(Pixelated.events.ui.recipients.entered, {name: 'to', addresses: ['foobar@gmail.com'] }); }); it('triggers recipients updated', function() { + this.component.trigger(Pixelated.events.ui.recipients.entered, {name: 'to', addresses: ['foobar@gmail.com'] }); expect(recipientsUpdatedEvent).toHaveBeenTriggeredOn(document); }); it('adds recipients', function() { + this.component.trigger(Pixelated.events.ui.recipients.entered, {name: 'to', addresses: ['foobar@gmail.com'] }); + expect(this.component.attr.recipients.length).toBe(1); + }); + }); + + describe('adding invalid recipients from the ui', function() { + beforeEach(function () { + this.setupComponent(); + recipientsUpdatedEvent = spyOnEvent(document, Pixelated.events.ui.recipients.updated); + this.component.trigger(Pixelated.events.ui.recipients.enteredInvalid, {name: 'to', addresses: ['invalid.com'] }); + }); + + it('does not trigger recipients updated', function() { + expect(recipientsUpdatedEvent).not.toHaveBeenTriggeredOn(document); + }); + + it('adds recipients with invalid indication', function() { expect(this.component.attr.recipients.length).toBe(1); + expect(this.component.attr.recipients[0].attr.invalidAddress).toBe(true); }); }); + }); diff --git a/web-ui/test/spec/mail_view/ui/recipients/recipients_input.spec.js b/web-ui/test/spec/mail_view/ui/recipients/recipients_input.spec.js index 6b05d1b6..1656a83a 100644 --- a/web-ui/test/spec/mail_view/ui/recipients/recipients_input.spec.js +++ b/web-ui/test/spec/mail_view/ui/recipients/recipients_input.spec.js @@ -158,4 +158,33 @@ describeComponent('mail_view/ui/recipients/recipients_input',function () { expect(addressEnteredEvent.calls[3].data).toEqual({name: 'to', address: 'g@h.i'}); }); }); + + describe('when entering an invalid address', function() { + var invalidAddressEnteredEvent, addressEnteredEvent, blurEvent; + + beforeEach(function () { + invalidAddressEnteredEvent = spyOnEvent(this.$node, Pixelated.events.ui.recipients.enteredInvalid); + addressEnteredEvent = spyOnEvent(this.$node, Pixelated.events.ui.recipients.entered); + blurEvent = $.Event('blur'); + spyOn(blurEvent, 'preventDefault'); + }); + + it('displays it as an invalid address token', function() { + this.$node.val('invalid'); + this.$node.trigger(blurEvent); + + expect(blurEvent.preventDefault).toHaveBeenCalled(); + expect(invalidAddressEnteredEvent).toHaveBeenTriggeredOnAndWith(this, { name: 'to', address: 'invalid' }); + }); + + it('displays it as an invalid address token when cannot parse', function() { + this.$node.val('invalid_format email@example.com'); + this.$node.trigger(blurEvent); + + expect(blurEvent.preventDefault).toHaveBeenCalled(); + expect(invalidAddressEnteredEvent.calls[0].data).toEqual({name: 'to', address: 'invalid_format'}); + expect(addressEnteredEvent.calls[0].data).toEqual({name: 'to', address: 'email@example.com'}); + }); + + }); }); -- cgit v1.2.3