Add tests for contact removal via modal

This commit is contained in:
JC Brand 2018-05-10 22:14:37 +02:00
parent b1a54e626d
commit 09db3eddb0
10 changed files with 102 additions and 58 deletions

View File

@ -7055,9 +7055,6 @@ body.reset {
opacity: 0; }
100% {
opacity: 1; } }
#conversejs .fade {
opacity: 0;
transition: opacity 0.20s linear; }
#conversejs .fade-in {
opacity: 0;
/* make things invisible upon start */
@ -7273,7 +7270,7 @@ body.reset {
border-radius: 25%;
border: none;
cursor: pointer;
font-size: 16px;
font-size: 14px;
margin: 0 0.2em;
padding: 0 0 0 0.5em;
text-decoration: none; }
@ -7299,8 +7296,8 @@ body.reset {
min-height: 1px;
padding-right: 15px;
padding-left: 15px;
flex: 0 0 25%;
max-width: 25%;
flex: 0 0 33.3333333333%;
max-width: 33.3333333333%;
padding: 0; }
#conversejs .chat-head .user-custom-message {
color: white;
@ -7585,6 +7582,9 @@ body.reset {
top: 0;
left: 0; }
#conversejs.converse-fullscreen .chatbox-btn {
font-size: 16px; }
@media screen and (max-width: 767px) {
#conversejs:not(.converse-embedded) > .row {
flex-direction: row-reverse; }

View File

@ -7055,9 +7055,6 @@ body.reset {
opacity: 0; }
100% {
opacity: 1; } }
#conversejs .fade {
opacity: 0;
transition: opacity 0.20s linear; }
#conversejs .fade-in {
opacity: 0;
/* make things invisible upon start */
@ -7324,7 +7321,7 @@ body {
border-radius: 25%;
border: none;
cursor: pointer;
font-size: 16px;
font-size: 14px;
margin: 0 0.2em;
padding: 0 0 0 0.5em;
text-decoration: none; }
@ -7350,8 +7347,8 @@ body {
min-height: 1px;
padding-right: 15px;
padding-left: 15px;
flex: 0 0 25%;
max-width: 25%;
flex: 0 0 33.3333333333%;
max-width: 33.3333333333%;
padding: 0; }
#conversejs .chat-head .user-custom-message {
color: white;
@ -7636,6 +7633,9 @@ body {
top: 0;
left: 0; }
#conversejs.converse-fullscreen .chatbox-btn {
font-size: 16px; }
@media screen and (max-width: 767px) {
#conversejs:not(.converse-embedded) > .row {
flex-direction: row-reverse; }

View File

@ -23,7 +23,7 @@
border-radius: 25%;
border: none;
cursor: pointer;
font-size: $box-close-font-size;
font-size: $chatbox-button-size;
margin: 0 0.2em;
padding: 0 0 0 0.5em;
text-decoration: none;
@ -54,7 +54,7 @@
.chatbox-buttons {
flex-direction: row-reverse;
@include make-col-ready();
@include make-col(3);
@include make-col(4);
padding: 0;
}
@ -431,6 +431,12 @@
}
}
#conversejs.converse-fullscreen {
.chatbox-btn {
font-size: $fullpage-chatbox-button-size;
}
}
@media screen and (max-width: 767px) {
#conversejs:not(.converse-embedded) {
> .row {

View File

@ -287,11 +287,6 @@ body.reset {
100% { opacity: 1 }
}
.fade {
opacity: 0;
transition: opacity 0.20s linear;
}
.fade-in {
@include fade-in;
}

View File

@ -116,4 +116,6 @@ $box-close-button-padding-top: 4px !default;
$box-close-button-padding-bottom: 4px !default;
$box-close-button-padding-left: 4px !default;
$box-close-button-padding-right: 4px !default;
$box-close-font-size: 16px !default;
$chatbox-button-size: 14px !default;
$fullpage-chatbox-button-size: 16px !default;

View File

@ -239,9 +239,8 @@
this.vcard = _converse.vcards.create({'jid': this.get('jid')});
}
_converse.api.waitUntil('rosterContactsFetched').then(() => {
this.contact = _converse.roster.findWhere({'jid': this.get('jid')});
this.addRelatedContact(_converse.roster.findWhere({'jid': this.get('jid')}));
});
this.messages = new _converse.Messages();
this.messages.browserStorage = new Backbone.BrowserStorage[_converse.message_storage](
b64_sha1(`converse.messages${this.get('jid')}${_converse.bare_jid}`));
@ -264,6 +263,13 @@
});
},
addRelatedContact (contact) {
if (!_.isUndefined(contact)) {
this.contact = contact;
this.trigger('contactAdded', contact);
}
},
getDisplayName () {
return this.vcard.get('fullname') || this.get('jid');
},
@ -774,9 +780,22 @@
_converse.emit('privateChatsAutoJoined');
}
/************************ BEGIN Event Handlers ************************/
_converse.on('chatBoxesFetched', autoJoinChats);
_converse.api.waitUntil('rosterContactsFetched').then(() => {
_converse.roster.on('add', (contact) => {
/* When a new contact is added, check if we already have a
* chatbox open for it, and if so attach it to the chatbox.
*/
const chatbox = _converse.chatboxes.findWhere({'jid': contact.get('jid')});
chatbox.addRelatedContact(contact);
});
});
_converse.on('addClientFeatures', () => {
_converse.api.disco.addFeature(Strophe.NS.HTTPUPLOAD);
_converse.api.disco.addFeature(Strophe.NS.OUTOFBAND);

View File

@ -240,40 +240,60 @@
'click button.remove-contact': 'removeContact'
},
initialize () {
_converse.BootstrapModal.prototype.initialize.apply(this, arguments);
this.model.on('contactAdded', this.registerContactEventHandlers, this);
this.registerContactEventHandlers();
},
toHTML () {
return tpl_user_details_modal(_.extend(
this.model.toJSON(),
this.model.vcard.toJSON(), {
'allow_contact_removal': _converse.allow_contact_removal,
'alt_profile_image': __("The User's Profile Image"),
'display_name': this.model.getDisplayName(),
'is_roster_contact': !_.isUndefined(this.model.contact),
'label_close': __('Close'),
'label_email': __('Email'),
'label_fullname': __('Full Name'),
'label_jid': __('Jabber ID'),
'label_nickname': __('Nickname'),
'label_role': __('Role'),
'label_remove': __('Remove as contact'),
'label_url': __('URL'),
'allow_contact_removal': _converse.allow_contact_removal,
'is_roster_contact': !_.isUndefined(this.model.contact)
'label_role': __('Role'),
'label_url': __('URL')
}));
},
registerContactEventHandlers () {
if (!_.isUndefined(this.model.contact)) {
this.model.contact.on('change', this.render, this);
this.model.contact.vcard.on('change', this.render, this);
this.model.contact.on('destroy', () => {
delete this.model.contact;
this.render();
});
}
},
removeContact (ev) {
if (ev && ev.preventDefault) { ev.preventDefault(); }
if (!_converse.allow_contact_removal) { return; }
const result = confirm(__("Are you sure you want to remove this contact?"));
if (result === true) {
this.modal.hide();
this.model.contact.removeFromRoster(
(iq) => {
this.model.contact.destroy();
delete this.model.contact;
},
(err) => {
_converse.log(err, Strophe.LogLevel.ERROR);
_converse.api.alert.show(
Strophe.LogLevel.ERROR,
__('Error'),
[__('Sorry, there was an error while trying to remove %1$s as a contact.', name)]
[__('Sorry, there was an error while trying to remove %1$s as a contact.',
this.model.contact.getDisplayName())
]
)
}
);

View File

@ -401,15 +401,15 @@
addAndSubscribe (jid, name, groups, message, attributes) {
/* Add a roster contact and then once we have confirmation from
* the XMPP server we subscribe to that contact's presence updates.
* Parameters:
* (String) jid - The Jabber ID of the user being added and subscribed to.
* (String) name - The name of that user
* (Array of Strings) groups - Any roster groups the user might belong to
* (String) message - An optional message to explain the
* reason for the subscription request.
* (Object) attributes - Any additional attributes to be stored on the user's model.
*/
* the XMPP server we subscribe to that contact's presence updates.
* Parameters:
* (String) jid - The Jabber ID of the user being added and subscribed to.
* (String) name - The name of that user
* (Array of Strings) groups - Any roster groups the user might belong to
* (String) message - An optional message to explain the
* reason for the subscription request.
* (Object) attributes - Any additional attributes to be stored on the user's model.
*/
const handler = (contact) => {
if (contact instanceof _converse.RosterContact) {
contact.subscribe(message);
@ -420,14 +420,14 @@
sendContactAddIQ (jid, name, groups, callback, errback) {
/* Send an IQ stanza to the XMPP server to add a new roster contact.
*
* Parameters:
* (String) jid - The Jabber ID of the user being added
* (String) name - The name of that user
* (Array of Strings) groups - Any roster groups the user might belong to
* (Function) callback - A function to call once the IQ is returned
* (Function) errback - A function to call if an error occured
*/
*
* Parameters:
* (String) jid - The Jabber ID of the user being added
* (String) name - The name of that user
* (Array of Strings) groups - Any roster groups the user might belong to
* (Function) callback - A function to call once the IQ is returned
* (Function) errback - A function to call if an error occured
*/
name = _.isEmpty(name)? jid: name;
const iq = $iq({type: 'set'})
.c('query', {xmlns: Strophe.NS.ROSTER})
@ -438,16 +438,16 @@
addContactToRoster (jid, name, groups, attributes) {
/* Adds a RosterContact instance to _converse.roster and
* registers the contact on the XMPP server.
* Returns a promise which is resolved once the XMPP server has
* responded.
*
* Parameters:
* (String) jid - The Jabber ID of the user being added and subscribed to.
* (String) name - The name of that user
* (Array of Strings) groups - Any roster groups the user might belong to
* (Object) attributes - Any additional attributes to be stored on the user's model.
*/
* registers the contact on the XMPP server.
* Returns a promise which is resolved once the XMPP server has
* responded.
*
* Parameters:
* (String) jid - The Jabber ID of the user being added and subscribed to.
* (String) name - The name of that user
* (Array of Strings) groups - Any roster groups the user might belong to
* (Object) attributes - Any additional attributes to be stored on the user's model.
*/
return new Promise((resolve, reject) => {
groups = groups || [];
this.sendContactAddIQ(jid, name, groups,

View File

@ -7,13 +7,14 @@
</div>
<div class="modal-body">
{[ if (o.image) { ]}
<img alt="{{{o.alt_profile_image}}}"
class="img-thumbnail avatar align-self-center"
height="100" width="100" src="data:{{{o.image_type}}};base64,{{{o.image}}}"/>
<img alt="{{{o.alt_profile_image}}}"
class="img-thumbnail avatar align-self-center mb-3"
height="100" width="100" src="data:{{{o.image_type}}};base64,{{{o.image}}}"/>
{[ } ]}
{[ if (o.fullname) { ]}
<p><label>{{{o.label_fullname}}}:</label>&nbsp;{{{o.fullname}}}</p>
{[ } ]}
<p><label>{{{o.label_jid}}}:</label>&nbsp;{{{o.jid}}}</p>
{[ if (o.nickname) { ]}
<p><label>{{{o.label_nickname}}}:</label>&nbsp;{{{o.nickname}}}</p>
{[ } ]}

View File

@ -51,6 +51,7 @@ var specs = [
"spec/controlbox",
"spec/roster",
"spec/chatbox",
"spec/user-details-modal",
"spec/messages",
"spec/chatroom",
"spec/minchats",