Commit 6fea88fc authored by JC Brand's avatar JC Brand

Add JID validation and error messages to the `add contact` form

parent 5c487d2f
......@@ -1769,9 +1769,6 @@
#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 {
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,
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar li {
height: 30px;
......@@ -2028,37 +2025,37 @@
padding: 0.3em 0;
clear: left;
width: 100%; }
#conversejs #controlbox .dropdown {
/* Custom addition for CSP */ }
#conversejs #controlbox .dropdown a {
width: 143px;
display: inline-block; }
#conversejs #controlbox .dropdown li {
list-style: none;
padding-left: 0; }
#conversejs #controlbox .dropdown dd ul {
padding: 0;
list-style: none;
#conversejs #controlbox .dropdown a {
width: 143px;
display: inline-block; }
#conversejs #controlbox .dropdown li {
list-style: none;
padding-left: 0; }
#conversejs #controlbox .dropdown dd ul {
padding: 0;
list-style: none;
position: absolute;
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;
left: 0;
top: 0;
border: 1px solid #B1BFC4;
width: 100%;
z-index: 21;
z-index: 22; }
#conversejs #controlbox .dropdown dd.search-xmpp .contact-form-container form {
box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4);
background-color: white; }
#conversejs #controlbox .dropdown dd.search-xmpp li:hover {
background-color: #FCFDFD; }
#conversejs #controlbox .dropdown dd ul li:hover {
background-color: #DCF9F6; }
#conversejs #controlbox .dropdown dd.search-xmpp {
display: none;
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 .dropdown dt a span {
cursor: pointer;
display: block;
padding: 4px 7px 0 5px; }
#conversejs #controlbox #select-xmpp-status {
display: none;
float: right;
......@@ -2175,7 +2172,6 @@
#conversejs #controlbox #users {
overflow-y: hidden; }
#conversejs #controlbox .add-xmpp-contact {
background: none;
padding: 1em 0.5em; }
#conversejs #controlbox .add-xmpp-contact input {
margin: 0 0 1rem;
......
......@@ -1815,9 +1815,6 @@ body {
#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 {
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,
#conversejs .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu ul.emoji-toolbar li {
height: 32px;
......@@ -1939,6 +1936,8 @@ body {
width: 100%; }
#conversejs .chatbox form.sendXMPPMessage .toggle-smiley {
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 {
padding-left: 10px;
padding-right: 10px; }
......@@ -2106,37 +2105,37 @@ body {
padding: 0.3em 0;
clear: left;
width: 100%; }
#conversejs #controlbox .dropdown {
/* Custom addition for CSP */ }
#conversejs #controlbox .dropdown a {
width: 143px;
display: inline-block; }
#conversejs #controlbox .dropdown li {
list-style: none;
padding-left: 0; }
#conversejs #controlbox .dropdown dd ul {
padding: 0;
list-style: none;
#conversejs #controlbox .dropdown a {
width: 143px;
display: inline-block; }
#conversejs #controlbox .dropdown li {
list-style: none;
padding-left: 0; }
#conversejs #controlbox .dropdown dd ul {
padding: 0;
list-style: none;
position: absolute;
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;
left: 0;
top: 0;
border: 1px solid #B1BFC4;
width: 100%;
z-index: 21;
z-index: 22; }
#conversejs #controlbox .dropdown dd.search-xmpp .contact-form-container form {
box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4);
background-color: white; }
#conversejs #controlbox .dropdown dd.search-xmpp li:hover {
background-color: #FCFDFD; }
#conversejs #controlbox .dropdown dd ul li:hover {
background-color: #DCF9F6; }
#conversejs #controlbox .dropdown dd.search-xmpp {
display: none;
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 .dropdown dt a span {
cursor: pointer;
display: block;
padding: 4px 7px 0 5px; }
#conversejs #controlbox #select-xmpp-status {
display: none;
float: right;
......@@ -2253,7 +2252,6 @@ body {
#conversejs #controlbox #users {
overflow-y: hidden; }
#conversejs #controlbox .add-xmpp-contact {
background: none;
padding: 1em 0.5em; }
#conversejs #controlbox .add-xmpp-contact input {
margin: 0 0 1rem;
......
......@@ -337,9 +337,6 @@
.picked {
background-color: $highlight-color;
}
.emoji-category-picker {
margin-right: 5em;
}
li {
height: $emoji_height + 2*5px;
padding: 4px;
......
......@@ -236,7 +236,6 @@
position: absolute;
left: 0;
top: 0;
border: 1px solid $light-background-border-color;
width: 100%;
z-index: 21;
background-color: $light-background-color;
......@@ -246,14 +245,16 @@
}
}
/* Custom addition for CSP */
dd.search-xmpp {
display: none;
width: 100%;
}
dd.search-xmpp ul {
box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4);
height: 0;
.contact-form-container {
position: absolute;
z-index: 22;
form {
box-shadow: 1px 4px 10px 1px rgba(0, 0, 0, 0.4);
background-color: white;
}
}
li:hover {
background-color: $light-background-color;
}
......@@ -420,7 +421,6 @@
}
.add-xmpp-contact {
background: none;
padding: 1em 0.5em;
input {
margin: 0 0 1rem;
......
......@@ -74,6 +74,9 @@
padding-left: 0.5em;
ul {
&.emoji-toolbar {
.emoji-category-picker {
margin-right: 5em;
}
.emoji-category {
padding-left: 10px;
padding-right: 10px;
......
......@@ -635,31 +635,32 @@
this.parent_el.appendChild(this.render().el);
this.tabs = this.parent_el.parentNode.querySelector('#controlbox-tabs');
this.tabs.appendChild(this.tab_el);
this.$('.search-xmpp ul').append(
this.generateAddContactHTML()
);
return this;
},
generateAddContactHTML () {
generateAddContactHTML (settings={}) {
if (_converse.xhr_user_search) {
return tpl_search_contact({
label_contact_name: __('Contact name'),
label_search: __('Search')
});
} else {
return tpl_add_contact_form({
return tpl_add_contact_form(_.assign({
error_message: null,
label_contact_username: __('e.g. user@example.org'),
label_add: __('Add')
});
label_add: __('Add'),
value: ''
}, settings));
}
},
toggleContactForm (ev) {
ev.preventDefault();
this.$el.find('.search-xmpp').toggle('fast', function () {
if ($(this).is(':visible')) {
$(this).find('input.username').focus();
this.el.querySelector('.search-xmpp div').innerHTML = this.generateAddContactHTML();
var dropdown = this.el.querySelector('.contact-form-container');
utils.slideToggleElement(dropdown).then(() => {
if ($(dropdown).is(':visible')) {
$(dropdown).find('input.username').focus();
}
});
},
......@@ -690,13 +691,18 @@
ev.preventDefault();
const $input = $(ev.target).find('input');
const jid = $input.val();
if (! jid) {
// this is not a valid JID
$input.addClass('error');
if (!jid || _.filter(jid.split('@')).length < 2) {
this.el.querySelector('.search-xmpp div').innerHTML =
this.generateAddContactHTML({
error_message: __('Please enter a valid XMPP username'),
label_contact_username: __('e.g. user@example.org'),
label_add: __('Add'),
value: jid
});
return;
}
_converse.roster.addAndSubscribe(jid);
$('.search-xmpp').hide();
utils.slideIn(this.el.querySelector('.contact-form-container'));
},
addContactFromList (ev) {
......@@ -706,7 +712,7 @@
name = $target.text();
_converse.roster.addAndSubscribe(jid, name);
$target.parent().remove();
$('.search-xmpp').hide();
utils.slideIn(this.el.querySelector('.contact-form-container'));
}
});
......
......@@ -1417,15 +1417,12 @@
}
});
this.Messages = Backbone.Collection.extend({
model: _converse.Message,
comparator: 'time'
});
this.ChatBox = Backbone.Model.extend({
defaults: {
'type': 'chatbox',
'bookmarked': false,
......
......@@ -2,5 +2,8 @@
<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>
</dt>
<dd class="search-xmpp"><ul></ul></dd>
<dd class="search-xmpp">
<div class="contact-form-container collapsed"></div>
<ul></ul>
</dd>
</dl>
<li>
<form class="pure-form add-xmpp-contact">
<input type="text"
name="identifier"
class="username"
placeholder="{{{label_contact_username}}}"/>
<button class="pure-button button-primary" type="submit">{{{label_add}}}</button>
</form>
</li>
<form class="pure-form add-xmpp-contact">
{[ if (error_message) { ]}
<span class="pure-form-message error">{{{error_message}}}</span>
{[ } ]}
<input type="text"
name="identifier"
value="{{{value}}}"
class="username {[ if (error_message) { ]} error {[ } ]}"
placeholder="{{{label_contact_username}}}"/>
<button class="pure-button button-primary" type="submit">{{{label_add}}}</button>
</form>
......@@ -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) => {
if (_.isNil(el)) {
const err = "Undefined or null element passed into slideOut"
......@@ -229,6 +236,7 @@
const end_height = calculateEndHeight(el);
if ($.fx.off) { // Effects are disabled (for tests)
el.style.height = end_height + 'px';
wrapup(el);
resolve();
return;
}
......@@ -247,10 +255,7 @@
// offsetHeight beforehand.
el.style.height = calculateEndHeight(el) + 'px';
window.clearInterval(interval_marker);
el.removeAttribute('data-slider-marker');
el.classList.remove('collapsed');
el.style.overflow = "";
el.style.height = "";
wrapup(el);
resolve();
}
}, interval);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment