Add JID validation and error messages to the add contact form

This commit is contained in:
JC Brand 2017-07-17 22:01:23 +02:00
parent 5c487d2faf
commit 6fea88fcc3
10 changed files with 117 additions and 110 deletions

View File

@ -1769,9 +1769,6 @@
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .picked, #converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .picked,
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .picked { #conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .picked {
background-color: #DCF9F6; } background-color: #DCF9F6; }
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .emoji-category-picker,
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .emoji-category-picker {
margin-right: 5em; }
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar li, #converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar li,
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar li { #conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar li {
height: 30px; height: 30px;
@ -2028,37 +2025,37 @@
padding: 0.3em 0; padding: 0.3em 0;
clear: left; clear: left;
width: 100%; } width: 100%; }
#conversejs #controlbox .dropdown { #conversejs #controlbox .dropdown a {
/* Custom addition for CSP */ } width: 143px;
#conversejs #controlbox .dropdown a { display: inline-block; }
width: 143px; #conversejs #controlbox .dropdown li {
display: inline-block; } list-style: none;
#conversejs #controlbox .dropdown li { padding-left: 0; }
list-style: none; #conversejs #controlbox .dropdown dd ul {
padding-left: 0; } padding: 0;
#conversejs #controlbox .dropdown dd ul { list-style: none;
padding: 0; position: absolute;
list-style: none; left: 0;
top: 0;
width: 100%;
z-index: 21;
background-color: #FCFDFD; }
#conversejs #controlbox .dropdown dd ul li:hover {
background-color: #DCF9F6; }
#conversejs #controlbox .dropdown dd.search-xmpp {
height: 0; }
#conversejs #controlbox .dropdown dd.search-xmpp .contact-form-container {
position: absolute; position: absolute;
left: 0; z-index: 22; }
top: 0; #conversejs #controlbox .dropdown dd.search-xmpp .contact-form-container form {
border: 1px solid #B1BFC4; box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4);
width: 100%; background-color: white; }
z-index: 21; #conversejs #controlbox .dropdown dd.search-xmpp li:hover {
background-color: #FCFDFD; } background-color: #FCFDFD; }
#conversejs #controlbox .dropdown dd ul li:hover { #conversejs #controlbox .dropdown dt a span {
background-color: #DCF9F6; } cursor: pointer;
#conversejs #controlbox .dropdown dd.search-xmpp { display: block;
display: none; padding: 4px 7px 0 5px; }
width: 100%; }
#conversejs #controlbox .dropdown dd.search-xmpp ul {
box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4); }
#conversejs #controlbox .dropdown dd.search-xmpp ul li:hover {
background-color: #FCFDFD; }
#conversejs #controlbox .dropdown dt a span {
cursor: pointer;
display: block;
padding: 4px 7px 0 5px; }
#conversejs #controlbox #select-xmpp-status { #conversejs #controlbox #select-xmpp-status {
display: none; display: none;
float: right; float: right;
@ -2175,7 +2172,6 @@
#conversejs #controlbox #users { #conversejs #controlbox #users {
overflow-y: hidden; } overflow-y: hidden; }
#conversejs #controlbox .add-xmpp-contact { #conversejs #controlbox .add-xmpp-contact {
background: none;
padding: 1em 0.5em; } padding: 1em 0.5em; }
#conversejs #controlbox .add-xmpp-contact input { #conversejs #controlbox .add-xmpp-contact input {
margin: 0 0 1rem; margin: 0 0 1rem;

View File

@ -1815,9 +1815,6 @@ body {
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .picked, #converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .picked,
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .picked { #conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .picked {
background-color: #DCF9F6; } background-color: #DCF9F6; }
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .emoji-category-picker,
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar .emoji-category-picker {
margin-right: 5em; }
#converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar li, #converse-embedded-chat .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar li,
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar li { #conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar li {
height: 32px; height: 32px;
@ -1939,6 +1936,8 @@ body {
width: 100%; } width: 100%; }
#conversejs .chatbox form.sendXMPPMessage .toggle-smiley { #conversejs .chatbox form.sendXMPPMessage .toggle-smiley {
padding-left: 0.5em; } padding-left: 0.5em; }
#conversejs .chatbox form.sendXMPPMessage .toggle-smiley ul.emoji-toolbar .emoji-category-picker {
margin-right: 5em; }
#conversejs .chatbox form.sendXMPPMessage .toggle-smiley ul.emoji-toolbar .emoji-category { #conversejs .chatbox form.sendXMPPMessage .toggle-smiley ul.emoji-toolbar .emoji-category {
padding-left: 10px; padding-left: 10px;
padding-right: 10px; } padding-right: 10px; }
@ -2106,37 +2105,37 @@ body {
padding: 0.3em 0; padding: 0.3em 0;
clear: left; clear: left;
width: 100%; } width: 100%; }
#conversejs #controlbox .dropdown { #conversejs #controlbox .dropdown a {
/* Custom addition for CSP */ } width: 143px;
#conversejs #controlbox .dropdown a { display: inline-block; }
width: 143px; #conversejs #controlbox .dropdown li {
display: inline-block; } list-style: none;
#conversejs #controlbox .dropdown li { padding-left: 0; }
list-style: none; #conversejs #controlbox .dropdown dd ul {
padding-left: 0; } padding: 0;
#conversejs #controlbox .dropdown dd ul { list-style: none;
padding: 0; position: absolute;
list-style: none; left: 0;
top: 0;
width: 100%;
z-index: 21;
background-color: #FCFDFD; }
#conversejs #controlbox .dropdown dd ul li:hover {
background-color: #DCF9F6; }
#conversejs #controlbox .dropdown dd.search-xmpp {
height: 0; }
#conversejs #controlbox .dropdown dd.search-xmpp .contact-form-container {
position: absolute; position: absolute;
left: 0; z-index: 22; }
top: 0; #conversejs #controlbox .dropdown dd.search-xmpp .contact-form-container form {
border: 1px solid #B1BFC4; box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4);
width: 100%; background-color: white; }
z-index: 21; #conversejs #controlbox .dropdown dd.search-xmpp li:hover {
background-color: #FCFDFD; } background-color: #FCFDFD; }
#conversejs #controlbox .dropdown dd ul li:hover { #conversejs #controlbox .dropdown dt a span {
background-color: #DCF9F6; } cursor: pointer;
#conversejs #controlbox .dropdown dd.search-xmpp { display: block;
display: none; padding: 4px 7px 0 5px; }
width: 100%; }
#conversejs #controlbox .dropdown dd.search-xmpp ul {
box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4); }
#conversejs #controlbox .dropdown dd.search-xmpp ul li:hover {
background-color: #FCFDFD; }
#conversejs #controlbox .dropdown dt a span {
cursor: pointer;
display: block;
padding: 4px 7px 0 5px; }
#conversejs #controlbox #select-xmpp-status { #conversejs #controlbox #select-xmpp-status {
display: none; display: none;
float: right; float: right;
@ -2253,7 +2252,6 @@ body {
#conversejs #controlbox #users { #conversejs #controlbox #users {
overflow-y: hidden; } overflow-y: hidden; }
#conversejs #controlbox .add-xmpp-contact { #conversejs #controlbox .add-xmpp-contact {
background: none;
padding: 1em 0.5em; } padding: 1em 0.5em; }
#conversejs #controlbox .add-xmpp-contact input { #conversejs #controlbox .add-xmpp-contact input {
margin: 0 0 1rem; margin: 0 0 1rem;

View File

@ -337,9 +337,6 @@
.picked { .picked {
background-color: $highlight-color; background-color: $highlight-color;
} }
.emoji-category-picker {
margin-right: 5em;
}
li { li {
height: $emoji_height + 2*5px; height: $emoji_height + 2*5px;
padding: 4px; padding: 4px;

View File

@ -236,7 +236,6 @@
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
border: 1px solid $light-background-border-color;
width: 100%; width: 100%;
z-index: 21; z-index: 21;
background-color: $light-background-color; background-color: $light-background-color;
@ -246,14 +245,16 @@
} }
} }
/* Custom addition for CSP */
dd.search-xmpp { dd.search-xmpp {
display: none; height: 0;
width: 100%; .contact-form-container {
} position: absolute;
z-index: 22;
dd.search-xmpp ul { form {
box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4); box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4);
background-color: white;
}
}
li:hover { li:hover {
background-color: $light-background-color; background-color: $light-background-color;
} }
@ -420,7 +421,6 @@
} }
.add-xmpp-contact { .add-xmpp-contact {
background: none;
padding: 1em 0.5em; padding: 1em 0.5em;
input { input {
margin: 0 0 1rem; margin: 0 0 1rem;

View File

@ -74,6 +74,9 @@
padding-left: 0.5em; padding-left: 0.5em;
ul { ul {
&.emoji-toolbar { &.emoji-toolbar {
.emoji-category-picker {
margin-right: 5em;
}
.emoji-category { .emoji-category {
padding-left: 10px; padding-left: 10px;
padding-right: 10px; padding-right: 10px;

View File

@ -635,31 +635,32 @@
this.parent_el.appendChild(this.render().el); this.parent_el.appendChild(this.render().el);
this.tabs = this.parent_el.parentNode.querySelector('#controlbox-tabs'); this.tabs = this.parent_el.parentNode.querySelector('#controlbox-tabs');
this.tabs.appendChild(this.tab_el); this.tabs.appendChild(this.tab_el);
this.$('.search-xmpp ul').append(
this.generateAddContactHTML()
);
return this; return this;
}, },
generateAddContactHTML () { generateAddContactHTML (settings={}) {
if (_converse.xhr_user_search) { if (_converse.xhr_user_search) {
return tpl_search_contact({ return tpl_search_contact({
label_contact_name: __('Contact name'), label_contact_name: __('Contact name'),
label_search: __('Search') label_search: __('Search')
}); });
} else { } else {
return tpl_add_contact_form({ return tpl_add_contact_form(_.assign({
error_message: null,
label_contact_username: __('e.g. user@example.org'), label_contact_username: __('e.g. user@example.org'),
label_add: __('Add') label_add: __('Add'),
}); value: ''
}, settings));
} }
}, },
toggleContactForm (ev) { toggleContactForm (ev) {
ev.preventDefault(); ev.preventDefault();
this.$el.find('.search-xmpp').toggle('fast', function () { this.el.querySelector('.search-xmpp div').innerHTML = this.generateAddContactHTML();
if ($(this).is(':visible')) { var dropdown = this.el.querySelector('.contact-form-container');
$(this).find('input.username').focus(); utils.slideToggleElement(dropdown).then(() => {
if ($(dropdown).is(':visible')) {
$(dropdown).find('input.username').focus();
} }
}); });
}, },
@ -690,13 +691,18 @@
ev.preventDefault(); ev.preventDefault();
const $input = $(ev.target).find('input'); const $input = $(ev.target).find('input');
const jid = $input.val(); const jid = $input.val();
if (! jid) { if (!jid || _.filter(jid.split('@')).length < 2) {
// this is not a valid JID this.el.querySelector('.search-xmpp div').innerHTML =
$input.addClass('error'); this.generateAddContactHTML({
error_message: __('Please enter a valid XMPP username'),
label_contact_username: __('e.g. user@example.org'),
label_add: __('Add'),
value: jid
});
return; return;
} }
_converse.roster.addAndSubscribe(jid); _converse.roster.addAndSubscribe(jid);
$('.search-xmpp').hide(); utils.slideIn(this.el.querySelector('.contact-form-container'));
}, },
addContactFromList (ev) { addContactFromList (ev) {
@ -706,7 +712,7 @@
name = $target.text(); name = $target.text();
_converse.roster.addAndSubscribe(jid, name); _converse.roster.addAndSubscribe(jid, name);
$target.parent().remove(); $target.parent().remove();
$('.search-xmpp').hide(); utils.slideIn(this.el.querySelector('.contact-form-container'));
} }
}); });

View File

@ -1417,15 +1417,12 @@
} }
}); });
this.Messages = Backbone.Collection.extend({ this.Messages = Backbone.Collection.extend({
model: _converse.Message, model: _converse.Message,
comparator: 'time' comparator: 'time'
}); });
this.ChatBox = Backbone.Model.extend({ this.ChatBox = Backbone.Model.extend({
defaults: { defaults: {
'type': 'chatbox', 'type': 'chatbox',
'bookmarked': false, 'bookmarked': false,

View File

@ -2,5 +2,8 @@
<dt id="xmpp-contact-search" class="fancy-dropdown"> <dt id="xmpp-contact-search" class="fancy-dropdown">
<a class="toggle-xmpp-contact-form icon-plus" href="#" title="{{{label_click_to_chat}}}"> {{{label_add_contact}}}</a> <a class="toggle-xmpp-contact-form icon-plus" href="#" title="{{{label_click_to_chat}}}"> {{{label_add_contact}}}</a>
</dt> </dt>
<dd class="search-xmpp"><ul></ul></dd> <dd class="search-xmpp">
<div class="contact-form-container collapsed"></div>
<ul></ul>
</dd>
</dl> </dl>

View File

@ -1,9 +1,11 @@
<li> <form class="pure-form add-xmpp-contact">
<form class="pure-form add-xmpp-contact"> {[ if (error_message) { ]}
<input type="text" <span class="pure-form-message error">{{{error_message}}}</span>
name="identifier" {[ } ]}
class="username" <input type="text"
placeholder="{{{label_contact_username}}}"/> name="identifier"
<button class="pure-button button-primary" type="submit">{{{label_add}}}</button> value="{{{value}}}"
</form> class="username {[ if (error_message) { ]} error {[ } ]}"
</li> placeholder="{{{label_contact_username}}}"/>
<button class="pure-button button-primary" type="submit">{{{label_add}}}</button>
</form>

View File

@ -214,6 +214,13 @@
); );
} }
function wrapup (el) {
el.removeAttribute('data-slider-marker');
el.classList.remove('collapsed');
el.style.overflow = "";
el.style.height = "";
}
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (_.isNil(el)) { if (_.isNil(el)) {
const err = "Undefined or null element passed into slideOut" const err = "Undefined or null element passed into slideOut"
@ -229,6 +236,7 @@
const end_height = calculateEndHeight(el); const end_height = calculateEndHeight(el);
if ($.fx.off) { // Effects are disabled (for tests) if ($.fx.off) { // Effects are disabled (for tests)
el.style.height = end_height + 'px'; el.style.height = end_height + 'px';
wrapup(el);
resolve(); resolve();
return; return;
} }
@ -247,10 +255,7 @@
// offsetHeight beforehand. // offsetHeight beforehand.
el.style.height = calculateEndHeight(el) + 'px'; el.style.height = calculateEndHeight(el) + 'px';
window.clearInterval(interval_marker); window.clearInterval(interval_marker);
el.removeAttribute('data-slider-marker'); wrapup(el);
el.classList.remove('collapsed');
el.style.overflow = "";
el.style.height = "";
resolve(); resolve();
} }
}, interval); }, interval);