Commit 9fb20567 authored by JC Brand's avatar JC Brand

Move MUC invite widget into a modal

parent c6ac03e9
......@@ -16094,8 +16094,8 @@
"dev": true
},
"skeletor.js": {
"version": "github:skeletorjs/skeletor#29a6d8f707076e865133b8f36f07c76ba4b4b582",
"from": "github:skeletorjs/skeletor#29a6d8f707076e865133b8f36f07c76ba4b4b582",
"version": "github:skeletorjs/skeletor#9a4487496bd2810b2f0847acbca136333cf9cfb0",
"from": "github:skeletorjs/skeletor#9a4487496bd2810b2f0847acbca136333cf9cfb0",
"requires": {
"lodash": "^4.17.14"
}
......
......@@ -172,12 +172,25 @@
.hide-occupants {
align-self: flex-end;
cursor: pointer;
font-size: var(--font-size-small);
}
}
.occupants-header--title {
margin-top: 0.5em;
margin-bottom: 0.5em;
display: flex;
flex-direction: row;
.fa-user-plus {
margin-top: 0.2em;
}
}
.occupants-heading {
font-family: var(--heading-font);
margin-bottom: 0.5em;
color: var(--chatroom-head-color);
padding-left: 0;
margin-right: 1em;
}
.chatroom-features {
display: var(--occupants-features-display);
......
......@@ -1940,36 +1940,54 @@
'muc_anonymous'
]
await test_utils.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo', features);
spyOn(_converse.api, "trigger").and.callThrough();
spyOn(window, 'prompt').and.callFake(() => "Please join!");
const view = _converse.chatboxviews.get('lounge@montague.lit');
expect(view.model.getOwnAffiliation()).toBe('owner');
expect(view.model.features.get('open')).toBe(false);
expect(view.el.querySelectorAll('input.invited-contact').length).toBe(1);
expect(view.el.querySelector('.occupants-header .fa-user-plus')).not.toBe(null);
// Members can't invite if the room isn't open
view.model.getOwnOccupant().set('affiliation', 'member');
await u.waitUntil(() => view.el.querySelectorAll('input.invited-contact').length === 0);
await u.waitUntil(() => view.el.querySelector('.occupants-header .fa-user-plus') === null);
view.model.features.set('open', 'true');
await u.waitUntil(() => view.el.querySelector('.occupants-header .fa-user-plus'));
view.el.querySelector('.occupants-header .fa-user-plus').click();
const modal = view.sidebar_view.muc_invite_modal;
await u.waitUntil(() => u.isVisible(modal.el), 1000)
expect(modal.el.querySelectorAll('#invitee_jids').length).toBe(1);
expect(modal.el.querySelectorAll('textarea').length).toBe(1);
spyOn(view.model, 'directInvite').and.callThrough();
await u.waitUntil(() => view.el.querySelectorAll('input.invited-contact').length);
const input = view.el.querySelector('input.invited-contact');
expect(input.getAttribute('placeholder')).toBe('Invite');
const input = modal.el.querySelector('#invitee_jids');
input.value = "Balt";
modal.el.querySelector('button[type="submit"]').click();
await u.waitUntil(() => modal.el.querySelector('.error'));
const error = modal.el.querySelector('.error');
expect(error.textContent).toBe('Please enter a valid XMPP address');
let evt = new Event('input');
input.dispatchEvent(evt);
let sent_stanza;
spyOn(_converse.connection, 'send').and.callFake(stanza => (sent_stanza = stanza));
const hint = await u.waitUntil(() => view.el.querySelector('.suggestion-box__results li'));
const hint = await u.waitUntil(() => modal.el.querySelector('.suggestion-box__results li'));
expect(input.value).toBe('Balt');
expect(hint.textContent.trim()).toBe('Balthasar');
evt = new Event('mousedown', {'bubbles': true});
evt.button = 0;
hint.dispatchEvent(evt);
expect(window.prompt).toHaveBeenCalled();
const textarea = modal.el.querySelector('textarea');
textarea.value = "Please join!";
modal.el.querySelector('button[type="submit"]').click();
expect(view.model.directInvite).toHaveBeenCalled();
expect(sent_stanza.toLocaleString()).toBe(
`<message from="romeo@montague.lit/orchard" `+
......
This diff is collapsed.
......@@ -26,7 +26,7 @@
},
"gitHead": "9641dcdc820e029b05930479c242d2b707bbe8e2",
"devDependencies": {
"skeletor.js": "skeletorjs/skeletor#29a6d8f707076e865133b8f36f07c76ba4b4b582",
"skeletor.js": "skeletorjs/skeletor#9a4487496bd2810b2f0847acbca136333cf9cfb0",
"backbone": "1.4",
"backbone.browserStorage": "conversejs/backbone.browserStorage#674ba3aa0e4d0f0b0dcac48fcc7dea531012828f",
"filesize": "^4.1.2",
......
<div class="suggestion-box room-invite">
<form>
{[ if (o.error_message) { ]} <div class="error error-feedback">{{{o.error_message}}}</div> {[ } ]}
<div class="form-group">
<input class="form-control invited-contact suggestion-box__input"
placeholder="{{{o.label_invitation}}}"
type="text"/>
<span class="suggestion-box__additions visually-hidden" role="status" aria-live="assertive" aria-relevant="additions"></span>
</div>
</form>
<ul class="suggestion-box__results suggestion-box__results--below" hidden=""></ul>
</div>
import { html } from "lit-html";
import { __ } from '@converse/headless/i18n';
import { modal_header_close_button } from "./buttons"
const i18n_invite = __('Invite');
const i18n_invite_heading = __('Invite someone to this groupchat');
const error_message = __('Please enter a valid XMPP address');
const i18n_invite_label = __('XMPP Address');
const i18n_reason = __('Optional reason for the invitation');
export default (o) => html`
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="add-chatroom-modal-label">${i18n_invite_heading}</h5>
${modal_header_close_button}
</div>
<div class="modal-body">
<span class="modal-alert"></span>
<div class="suggestion-box room-invite">
<form @submit=${o.submitInviteForm}>
<div class="form-group">
<label class="clearfix" for="invitee_jids">${i18n_invite_label}:</label>
${ o.invalid_invite_jid ? html`<div class="error error-feedback">${error_message}</div>` : '' }
<input class="form-control suggestion-box__input"
required="required"
name="invitee_jids"
id="invitee_jids"
type="text"/>
<span class="suggestion-box__additions visually-hidden" role="status" aria-live="assertive" aria-relevant="additions"></span>
<ul class="suggestion-box__results suggestion-box__results--below" hidden=""></ul>
</div>
<div class="form-group">
<label>${i18n_reason}:</label>
<textarea class="form-control" name="reason"></textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">${i18n_invite}</button>
</div>
</form>
</div>
</div>
</div>
</div>
`;
......@@ -20,6 +20,7 @@ const i18n_archived = __('Message archiving');
const i18n_archived_hint = __('Messages are archived on the server');
const i18n_features = __('Features');
const i18n_hidden = __('Hidden');
const i18n_invite_hint = __('Invite people to join this groupchat');
const i18n_members_only = __('Members only');
const i18n_members_only_hint = __('this groupchat is restricted to members only');
const i18n_moderated = __('Moderated');
......@@ -32,6 +33,7 @@ const i18n_not_moderated = __('Not moderated');
const i18n_not_searchable_hint = __('This groupchat is not publicly searchable');
const i18n_open = __('Open');
const i18n_open_hint = __('Anyone can join this groupchat');
const i18n_participants = __('Participants');
const i18n_password = __('Password protected')
const i18n_password_hint = __('This groupchat requires a password before entry');
const i18n_persistent = __('Persistent');
......@@ -77,11 +79,27 @@ const tpl_features = (o) => html`
</div>
`;
const invite_button = (o) => {
if (o.invitesAllowed()) {
return html`
<a class="fa fa-user-plus"
title="${i18n_invite_hint}"
@click=${o.showInviteModal}
data-toggle="modal"
data-target="#muc-invite-modal"></a>`;
} else {
return '';
}
}
export default (o) => html`
<div class="occupants-header">
<i class="hide-occupants fa fa-times"></i>
<p class="occupants-heading">${o.label_occupants}</p>
<div class="occupants-header--title">
<span class="occupants-heading">${i18n_participants}</span>
${ invite_button(o) }
</div>
</div>
<div class="dragresize dragresize-occupants-left"></div>
<ul class="occupant-list">
......
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