Allow setting a nickname when adding a roster contact
This commit is contained in:
parent
108bd03e3a
commit
4f2b040f22
@ -197,12 +197,27 @@
|
|||||||
return test_utils.waitUntil(function () {
|
return test_utils.waitUntil(function () {
|
||||||
return u.isVisible(modal.el);
|
return u.isVisible(modal.el);
|
||||||
}, 1000).then(function () {
|
}, 1000).then(function () {
|
||||||
|
var sendIQ = _converse.connection.sendIQ;
|
||||||
|
var sent_stanza, IQ_id;
|
||||||
|
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
|
||||||
|
sent_stanza = iq;
|
||||||
|
IQ_id = sendIQ.bind(this)(iq, callback, errback);
|
||||||
|
});
|
||||||
|
|
||||||
expect(!_.isNull(modal.el.querySelector('form.add-xmpp-contact'))).toBeTruthy();
|
expect(!_.isNull(modal.el.querySelector('form.add-xmpp-contact'))).toBeTruthy();
|
||||||
var input_el = modal.el.querySelector('input[name="jid"]');
|
var input_jid = modal.el.querySelector('input[name="jid"]');
|
||||||
input_el.value = 'someone@';
|
var input_name = modal.el.querySelector('input[name="name"]');
|
||||||
|
input_jid.value = 'someone@';
|
||||||
var evt = new Event('input');
|
var evt = new Event('input');
|
||||||
input_el.dispatchEvent(evt);
|
input_jid.dispatchEvent(evt);
|
||||||
expect(modal.el.querySelector('.awesomplete li').textContent).toBe('someone@localhost');
|
expect(modal.el.querySelector('.awesomplete li').textContent).toBe('someone@localhost');
|
||||||
|
input_jid.value = 'someone@localhost';
|
||||||
|
input_name.value = 'Someone';
|
||||||
|
modal.el.querySelector('button[type="submit"]').click();
|
||||||
|
expect(sent_stanza.toLocaleString()).toEqual(
|
||||||
|
"<iq type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+
|
||||||
|
"<query xmlns='jabber:iq:roster'><item jid='someone@localhost' name='Someone'/></query>"+
|
||||||
|
"</iq>");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
@ -231,6 +246,7 @@
|
|||||||
return xhr;
|
return xhr;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var input_el;
|
||||||
var panel = _converse.chatboxviews.get('controlbox').contactspanel;
|
var panel = _converse.chatboxviews.get('controlbox').contactspanel;
|
||||||
var cbview = _converse.chatboxviews.get('controlbox');
|
var cbview = _converse.chatboxviews.get('controlbox');
|
||||||
cbview.el.querySelector('.add-contact').click()
|
cbview.el.querySelector('.add-contact').click()
|
||||||
@ -238,15 +254,40 @@
|
|||||||
return test_utils.waitUntil(function () {
|
return test_utils.waitUntil(function () {
|
||||||
return u.isVisible(modal.el);
|
return u.isVisible(modal.el);
|
||||||
}, 1000).then(function () {
|
}, 1000).then(function () {
|
||||||
var input_el = modal.el.querySelector('input[name="jid"]');
|
input_el = modal.el.querySelector('input[name="name"]');
|
||||||
input_el.value = 'marty@';
|
input_el.value = 'marty';
|
||||||
var evt = new Event('input');
|
var evt = new Event('input');
|
||||||
input_el.dispatchEvent(evt);
|
input_el.dispatchEvent(evt);
|
||||||
return test_utils.waitUntil(function () {
|
return test_utils.waitUntil(function () {
|
||||||
return modal.el.querySelector('.awesomplete li');
|
return modal.el.querySelector('.awesomplete li');
|
||||||
});
|
}, 1000);
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
expect(modal.el.querySelector('.awesomplete li').textContent).toBe('marty@mcfly.net');
|
var sendIQ = _converse.connection.sendIQ;
|
||||||
|
var sent_stanza, IQ_id;
|
||||||
|
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
|
||||||
|
sent_stanza = iq;
|
||||||
|
IQ_id = sendIQ.bind(this)(iq, callback, errback);
|
||||||
|
});
|
||||||
|
expect(modal.el.querySelectorAll('.awesomplete li').length).toBe(1);
|
||||||
|
const suggestion = modal.el.querySelector('.awesomplete li');
|
||||||
|
expect(suggestion.textContent).toBe('Marty McFly');
|
||||||
|
|
||||||
|
// Can't trigger "mousedown" event so trigger the Awesomplete
|
||||||
|
// custom event which would have been triggered upon mousedown.
|
||||||
|
var evt = document.createEvent("HTMLEvents");
|
||||||
|
evt.initEvent('awesomplete-selectcomplete', true, true );
|
||||||
|
evt.text = {
|
||||||
|
'label': 'Marty McFly',
|
||||||
|
'value': 'marty@mcfly.net'
|
||||||
|
}
|
||||||
|
modal.el.dispatchEvent(evt);
|
||||||
|
expect(input_el.value).toBe('Marty McFly');
|
||||||
|
expect(modal.el.querySelector('input[name="jid"]').value).toBe('marty@mcfly.net');
|
||||||
|
modal.el.querySelector('button[type="submit"]').click();
|
||||||
|
expect(sent_stanza.toLocaleString()).toEqual(
|
||||||
|
"<iq type='set' xmlns='jabber:client' id='"+IQ_id+"'>"+
|
||||||
|
"<query xmlns='jabber:iq:roster'><item jid='marty@mcfly.net' name='Marty McFly'/></query>"+
|
||||||
|
"</iq>");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
@ -131,8 +131,7 @@
|
|||||||
|
|
||||||
_converse.AddContactModal = _converse.BootstrapModal.extend({
|
_converse.AddContactModal = _converse.BootstrapModal.extend({
|
||||||
events: {
|
events: {
|
||||||
'submit form': 'addContactFromForm',
|
'submit form': 'addContactFromForm'
|
||||||
'submit form.search-xmpp-contact': 'searchContacts'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize () {
|
initialize () {
|
||||||
@ -141,49 +140,66 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
toHTML () {
|
toHTML () {
|
||||||
|
const label_nickname = _converse.xhr_user_search_url ? __('Contact name') : __('Optional nickname');
|
||||||
return tpl_add_contact_modal(_.extend(this.model.toJSON(), {
|
return tpl_add_contact_modal(_.extend(this.model.toJSON(), {
|
||||||
|
'_converse': _converse,
|
||||||
'heading_new_contact': __('Add a Contact'),
|
'heading_new_contact': __('Add a Contact'),
|
||||||
'label_xmpp_address': __('XMPP Address'),
|
'label_xmpp_address': __('XMPP Address'),
|
||||||
'label_nickname': __('Optional nickname'),
|
'label_nickname': label_nickname,
|
||||||
'contact_placeholder': __('name@example.org'),
|
'contact_placeholder': __('name@example.org'),
|
||||||
'label_add': __('Add'),
|
'label_add': __('Add'),
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
afterRender () {
|
afterRender () {
|
||||||
const input_el = this.el.querySelector('input[name="jid"]');
|
|
||||||
if (_converse.xhr_user_search_url && _.isString(_converse.xhr_user_search_url)) {
|
if (_converse.xhr_user_search_url && _.isString(_converse.xhr_user_search_url)) {
|
||||||
const awesomplete = new Awesomplete(input_el, {'list': []});
|
this.initXHRAutoComplete();
|
||||||
const xhr = new window.XMLHttpRequest();
|
|
||||||
// `open` must be called after `onload` for mock/testing purposes.
|
|
||||||
xhr.onload = function () {
|
|
||||||
if (xhr.responseText) {
|
|
||||||
awesomplete.list = JSON.parse(xhr.responseText).map((i) => {
|
|
||||||
return {'label': i.fullname, 'value': i.jid};
|
|
||||||
});
|
|
||||||
awesomplete.evaluate();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
input_el.addEventListener('input', _.debounce(() => {
|
|
||||||
xhr.open("GET", `${_converse.xhr_user_search_url}?q=${input_el.value}`, true);
|
|
||||||
xhr.send()
|
|
||||||
} , 500));
|
|
||||||
} else {
|
} else {
|
||||||
const list = _.uniq(_converse.roster.map((item) => Strophe.getDomainFromJid(item.get('jid'))));
|
this.initJIDAutoComplete();
|
||||||
new Awesomplete(input_el, {
|
|
||||||
'list': list,
|
|
||||||
'data': function (text, input) {
|
|
||||||
return input.slice(0, input.indexOf("@")) + "@" + text;
|
|
||||||
},
|
|
||||||
'filter': Awesomplete.FILTER_STARTSWITH
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
initJIDAutoComplete () {
|
||||||
|
const input_el = this.el.querySelector('input[name="jid"]');
|
||||||
|
const list = _.uniq(_converse.roster.map((item) => Strophe.getDomainFromJid(item.get('jid'))));
|
||||||
|
new Awesomplete(input_el, {
|
||||||
|
'list': list,
|
||||||
|
'data': function (text, input) {
|
||||||
|
return input.slice(0, input.indexOf("@")) + "@" + text;
|
||||||
|
},
|
||||||
|
'filter': Awesomplete.FILTER_STARTSWITH
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
initXHRAutoComplete () {
|
||||||
|
const name_input = this.el.querySelector('input[name="name"]');
|
||||||
|
const jid_input = this.el.querySelector('input[name="jid"]');
|
||||||
|
const awesomplete = new Awesomplete(name_input, {'list': []});
|
||||||
|
const xhr = new window.XMLHttpRequest();
|
||||||
|
// `open` must be called after `onload` for mock/testing purposes.
|
||||||
|
xhr.onload = function () {
|
||||||
|
if (xhr.responseText) {
|
||||||
|
awesomplete.list = JSON.parse(xhr.responseText).map((i) => { //eslint-disable-line arrow-body-style
|
||||||
|
return {'label': i.fullname, 'value': i.jid};
|
||||||
|
});
|
||||||
|
awesomplete.evaluate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
name_input.addEventListener('input', _.debounce(() => {
|
||||||
|
xhr.open("GET", `${_converse.xhr_user_search_url}?q=${name_input.value}`, true);
|
||||||
|
xhr.send()
|
||||||
|
} , 300));
|
||||||
|
this.el.addEventListener('awesomplete-selectcomplete', (ev) => {
|
||||||
|
jid_input.value = ev.text.value;
|
||||||
|
name_input.value = ev.text.label;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
addContactFromForm (ev) {
|
addContactFromForm (ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
const data = new FormData(ev.target),
|
const data = new FormData(ev.target),
|
||||||
jid = data.get('jid');
|
jid = data.get('jid'),
|
||||||
|
name = data.get('name');
|
||||||
|
|
||||||
if (!jid || _.compact(jid.split('@')).length < 2) {
|
if (!jid || _.compact(jid.split('@')).length < 2) {
|
||||||
this.model.set({
|
this.model.set({
|
||||||
@ -191,7 +207,7 @@
|
|||||||
'jid': jid
|
'jid': jid
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
_converse.roster.addAndSubscribe(jid);
|
_converse.roster.addAndSubscribe(jid, name);
|
||||||
this.model.clear();
|
this.model.clear();
|
||||||
this.modal.hide();
|
this.modal.hide();
|
||||||
}
|
}
|
||||||
|
@ -8,15 +8,21 @@
|
|||||||
</div>
|
</div>
|
||||||
<form class="converse-form add-xmpp-contact">
|
<form class="converse-form add-xmpp-contact">
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="form-group">
|
<div class="form-group {[ if (o._converse.xhr_user_search_url) { ]} hidden {[ } ]}">
|
||||||
<label class="clearfix" for="jid">{{{o.label_xmpp_address}}}:</label>
|
<label class="clearfix" for="jid">{{{o.label_xmpp_address}}}:</label>
|
||||||
<input type="text" name="jid" required="required" value="{{{o.jid}}}"
|
<input type="text" name="jid" required="required" value="{{{o.jid}}}"
|
||||||
class="form-control {[ if (o.error_message) { ]} is-invalid {[ } ]}"
|
class="form-control {[ if (o.error_message) { ]} is-invalid {[ } ]}"
|
||||||
placeholder="{{{o.contact_placeholder}}}">
|
placeholder="{{{o.contact_placeholder}}}"/>
|
||||||
{[ if (o.error_message) { ]}
|
{[ if (o.error_message) { ]}
|
||||||
<div class="invalid-feedback">{{{o.error_message}}}</div>
|
<div class="invalid-feedback">{{{o.error_message}}}</div>
|
||||||
{[ } ]}
|
{[ } ]}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="clearfix" for="name">{{{o.label_nickname}}}:</label>
|
||||||
|
<input type="text" name="name" value="{{{o.nickname}}}"
|
||||||
|
class="form-control {[ if (o.error_message) { ]} is-invalid {[ } ]}"
|
||||||
|
placeholder="{{{o.nickname_placeholder}}}"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" class="btn btn-primary">{{{o.label_add}}}</button>
|
<button type="submit" class="btn btn-primary">{{{o.label_add}}}</button>
|
||||||
|
Loading…
Reference in New Issue
Block a user