summaryrefslogtreecommitdiff
path: root/web-ui
diff options
context:
space:
mode:
Diffstat (limited to 'web-ui')
-rw-r--r--web-ui/app/js/mail_view/ui/recipients/recipient.js10
-rw-r--r--web-ui/app/js/mail_view/ui/recipients/recipients.js6
-rw-r--r--web-ui/app/js/mail_view/ui/recipients/recipients_input.js32
-rw-r--r--web-ui/app/js/page/events.js1
-rw-r--r--web-ui/app/scss/_mixins.scss9
-rw-r--r--web-ui/test/spec/mail_view/ui/recipients/recipients.spec.js21
-rw-r--r--web-ui/test/spec/mail_view/ui/recipients/recipients_input.spec.js29
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'});
+ });
+
+ });
});