muc-views: Remove features section...
and replace with button to open invite modal
This commit is contained in:
parent
9fb2056753
commit
30d08d2bfe
@ -181,9 +181,10 @@
|
||||
margin-bottom: 0.5em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
.fa-user-plus {
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
}
|
||||
|
||||
.fa-user-plus {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.occupants-heading {
|
||||
|
@ -541,6 +541,22 @@ body.converse-fullscreen {
|
||||
}
|
||||
}
|
||||
|
||||
.btn-circle {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
text-align: center;
|
||||
padding: 0.5em 0;
|
||||
font-size: var(--font-size-small);
|
||||
line-height: 1.428571429;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.btn {
|
||||
&.fa {
|
||||
color: white !important;
|
||||
}
|
||||
}
|
||||
|
||||
.badge-groupchat {
|
||||
background-color: var(--chatroom-badge-color);
|
||||
border-color: transparent;
|
||||
|
104
spec/muc.js
104
spec/muc.js
@ -1944,16 +1944,16 @@
|
||||
expect(view.model.getOwnAffiliation()).toBe('owner');
|
||||
expect(view.model.features.get('open')).toBe(false);
|
||||
|
||||
expect(view.el.querySelector('.occupants-header .fa-user-plus')).not.toBe(null);
|
||||
expect(view.el.querySelector('.open-invite-modal')).not.toBe(null);
|
||||
|
||||
// Members can't invite if the room isn't open
|
||||
view.model.getOwnOccupant().set('affiliation', 'member');
|
||||
await u.waitUntil(() => view.el.querySelector('.occupants-header .fa-user-plus') === null);
|
||||
await u.waitUntil(() => view.el.querySelector('.open-invite-modal') === null);
|
||||
|
||||
view.model.features.set('open', 'true');
|
||||
await u.waitUntil(() => view.el.querySelector('.occupants-header .fa-user-plus'));
|
||||
await u.waitUntil(() => view.el.querySelector('.open-invite-modal'));
|
||||
|
||||
view.el.querySelector('.occupants-header .fa-user-plus').click();
|
||||
view.el.querySelector('.open-invite-modal').click();
|
||||
const modal = view.sidebar_view.muc_invite_modal;
|
||||
await u.waitUntil(() => u.isVisible(modal.el), 1000)
|
||||
|
||||
@ -2506,26 +2506,38 @@
|
||||
];
|
||||
await test_utils.openAndEnterChatRoom(_converse, 'room@conference.example.org', 'romeo', features);
|
||||
const jid = 'room@conference.example.org';
|
||||
const chatroomview = _converse.chatboxviews.get(jid);
|
||||
let features_list = chatroomview.el.querySelector('.features-list');
|
||||
let features_shown = features_list.textContent.split('\n').map(s => s.trim()).filter(s => s);
|
||||
expect(_.difference(["Password protected", "Open", "Temporary", "Not anonymous", "Not moderated"], features_shown).length).toBe(0);
|
||||
expect(chatroomview.model.features.get('hidden')).toBe(false);
|
||||
expect(chatroomview.model.features.get('mam_enabled')).toBe(false);
|
||||
expect(chatroomview.model.features.get('membersonly')).toBe(false);
|
||||
expect(chatroomview.model.features.get('moderated')).toBe(false);
|
||||
expect(chatroomview.model.features.get('nonanonymous')).toBe(true);
|
||||
expect(chatroomview.model.features.get('open')).toBe(true);
|
||||
expect(chatroomview.model.features.get('passwordprotected')).toBe(true);
|
||||
expect(chatroomview.model.features.get('persistent')).toBe(false);
|
||||
expect(chatroomview.model.features.get('publicroom')).toBe(true);
|
||||
expect(chatroomview.model.features.get('semianonymous')).toBe(false);
|
||||
expect(chatroomview.model.features.get('temporary')).toBe(true);
|
||||
expect(chatroomview.model.features.get('unmoderated')).toBe(true);
|
||||
expect(chatroomview.model.features.get('unsecured')).toBe(false);
|
||||
expect(chatroomview.el.querySelector('.chatbox-title__text').textContent.trim()).toBe('Room');
|
||||
const view = _converse.chatboxviews.get(jid);
|
||||
|
||||
chatroomview.el.querySelector('.configure-chatroom-button').click();
|
||||
const info_el = view.el.querySelector(".show-room-details-modal");
|
||||
info_el.click();
|
||||
const modal = view.model.room_details_modal;
|
||||
await u.waitUntil(() => u.isVisible(modal.el), 1000);
|
||||
|
||||
let features_list = modal.el.querySelector('.features-list');
|
||||
let features_shown = features_list.textContent.split('\n').map(s => s.trim()).filter(s => s);
|
||||
|
||||
expect(features_shown.join(' ')).toBe(
|
||||
'Password protected - This groupchat requires a password before entry '+
|
||||
'Open - Anyone can join this groupchat '+
|
||||
'Temporary - This groupchat will disappear once the last person leaves '+
|
||||
'Not anonymous - All other groupchat participants can see your XMPP address '+
|
||||
'Not moderated - Participants entering this groupchat can write right away');
|
||||
expect(view.model.features.get('hidden')).toBe(false);
|
||||
expect(view.model.features.get('mam_enabled')).toBe(false);
|
||||
expect(view.model.features.get('membersonly')).toBe(false);
|
||||
expect(view.model.features.get('moderated')).toBe(false);
|
||||
expect(view.model.features.get('nonanonymous')).toBe(true);
|
||||
expect(view.model.features.get('open')).toBe(true);
|
||||
expect(view.model.features.get('passwordprotected')).toBe(true);
|
||||
expect(view.model.features.get('persistent')).toBe(false);
|
||||
expect(view.model.features.get('publicroom')).toBe(true);
|
||||
expect(view.model.features.get('semianonymous')).toBe(false);
|
||||
expect(view.model.features.get('temporary')).toBe(true);
|
||||
expect(view.model.features.get('unmoderated')).toBe(true);
|
||||
expect(view.model.features.get('unsecured')).toBe(false);
|
||||
expect(view.el.querySelector('.chatbox-title__text').textContent.trim()).toBe('Room');
|
||||
|
||||
view.el.querySelector('.configure-chatroom-button').click();
|
||||
|
||||
const IQs = _converse.connection.IQ_stanzas;
|
||||
let iq = await u.waitUntil(() => _.filter(
|
||||
@ -2602,9 +2614,9 @@
|
||||
_converse.connection._dataRecv(test_utils.createRequest(response_el));
|
||||
const el = await u.waitUntil(() => document.querySelector('.chatroom-form legend'));
|
||||
expect(el.textContent.trim()).toBe("Configuration for room@conference.example.org");
|
||||
sizzle('[name="muc#roomconfig_membersonly"]', chatroomview.el).pop().click();
|
||||
sizzle('[name="muc#roomconfig_roomname"]', chatroomview.el).pop().value = "New room name"
|
||||
chatroomview.el.querySelector('.chatroom-form input[type="submit"]').click();
|
||||
sizzle('[name="muc#roomconfig_membersonly"]', view.el).pop().click();
|
||||
sizzle('[name="muc#roomconfig_roomname"]', view.el).pop().value = "New room name"
|
||||
view.el.querySelector('.chatroom-form input[type="submit"]').click();
|
||||
|
||||
iq = await u.waitUntil(() => _.filter(IQs, iq => u.matchesSelector(iq, `iq[to="${jid}"][type="set"]`)).pop());
|
||||
const result = $iq({
|
||||
@ -2656,24 +2668,30 @@
|
||||
|
||||
_converse.connection._dataRecv(test_utils.createRequest(features_stanza));
|
||||
|
||||
await u.waitUntil(() => new Promise(success => chatroomview.model.features.on('change', success)));
|
||||
features_list = chatroomview.el.querySelector('.features-list');
|
||||
await u.waitUntil(() => new Promise(success => view.model.features.on('change', success)));
|
||||
features_list = modal.el.querySelector('.features-list');
|
||||
features_shown = features_list.textContent.split('\n').map(s => s.trim()).filter(s => s);
|
||||
expect(_.difference(["Password protected", "Hidden", "Members only", "Temporary", "Not anonymous", "Not moderated"], features_shown).length).toBe(0);
|
||||
expect(chatroomview.model.features.get('hidden')).toBe(true);
|
||||
expect(chatroomview.model.features.get('mam_enabled')).toBe(false);
|
||||
expect(chatroomview.model.features.get('membersonly')).toBe(true);
|
||||
expect(chatroomview.model.features.get('moderated')).toBe(false);
|
||||
expect(chatroomview.model.features.get('nonanonymous')).toBe(true);
|
||||
expect(chatroomview.model.features.get('open')).toBe(false);
|
||||
expect(chatroomview.model.features.get('passwordprotected')).toBe(true);
|
||||
expect(chatroomview.model.features.get('persistent')).toBe(false);
|
||||
expect(chatroomview.model.features.get('publicroom')).toBe(false);
|
||||
expect(chatroomview.model.features.get('semianonymous')).toBe(false);
|
||||
expect(chatroomview.model.features.get('temporary')).toBe(true);
|
||||
expect(chatroomview.model.features.get('unmoderated')).toBe(true);
|
||||
expect(chatroomview.model.features.get('unsecured')).toBe(false);
|
||||
expect(chatroomview.el.querySelector('.chatbox-title__text').textContent.trim()).toBe('New room name');
|
||||
expect(features_shown.join(' ')).toBe(
|
||||
'Password protected - This groupchat requires a password before entry '+
|
||||
'Hidden - This groupchat is not publicly searchable '+
|
||||
'Members only - This groupchat is restricted to members only '+
|
||||
'Temporary - This groupchat will disappear once the last person leaves '+
|
||||
'Not anonymous - All other groupchat participants can see your XMPP address '+
|
||||
'Not moderated - Participants entering this groupchat can write right away');
|
||||
expect(view.model.features.get('hidden')).toBe(true);
|
||||
expect(view.model.features.get('mam_enabled')).toBe(false);
|
||||
expect(view.model.features.get('membersonly')).toBe(true);
|
||||
expect(view.model.features.get('moderated')).toBe(false);
|
||||
expect(view.model.features.get('nonanonymous')).toBe(true);
|
||||
expect(view.model.features.get('open')).toBe(false);
|
||||
expect(view.model.features.get('passwordprotected')).toBe(true);
|
||||
expect(view.model.features.get('persistent')).toBe(false);
|
||||
expect(view.model.features.get('publicroom')).toBe(false);
|
||||
expect(view.model.features.get('semianonymous')).toBe(false);
|
||||
expect(view.model.features.get('temporary')).toBe(true);
|
||||
expect(view.model.features.get('unmoderated')).toBe(true);
|
||||
expect(view.model.features.get('unsecured')).toBe(false);
|
||||
expect(view.el.querySelector('.chatbox-title__text').textContent.trim()).toBe('New room name');
|
||||
done();
|
||||
}));
|
||||
|
||||
|
@ -615,6 +615,7 @@ converse.plugins.add('converse-muc-views', {
|
||||
initialize () {
|
||||
_converse.BootstrapModal.prototype.initialize.apply(this, arguments);
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
this.listenTo(this.model.features, 'change', this.render);
|
||||
this.listenTo(this.model.occupants, 'add', this.render);
|
||||
this.listenTo(this.model.occupants, 'change', this.render);
|
||||
},
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { html } from "lit-html";
|
||||
import { __ } from '@converse/headless/i18n';
|
||||
import { pick } from "lodash";
|
||||
import converse from "@converse/headless/converse-core";
|
||||
import tpl_occupant from "./occupant.js";
|
||||
|
||||
|
||||
const PRETTY_CHAT_STATUS = {
|
||||
'offline': 'Offline',
|
||||
'unavailable': 'Unavailable',
|
||||
@ -16,77 +15,21 @@ const PRETTY_CHAT_STATUS = {
|
||||
|
||||
const occupant_hint = (occupant) => __('Click to mention %1$s in your message.', occupant.get('nick'))
|
||||
|
||||
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');
|
||||
const i18n_moderated_hint = __('Participants entering this groupchat need to request permission to write');
|
||||
const i18n_no_password = __('No password');
|
||||
const i18n_no_password_hint = __('This groupchat does not require a password upon entry');
|
||||
const i18n_non_anon_hint = __('All other groupchat participants can see your XMPP address');
|
||||
const i18n_not_anon = __('Not anonymous');
|
||||
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_invite_hint = __('Invite someone');
|
||||
const i18n_participants = __('Participants');
|
||||
const i18n_password = __('Password protected')
|
||||
const i18n_password_hint = __('This groupchat requires a password before entry');
|
||||
const i18n_persistent = __('Persistent');
|
||||
const i18n_persistent_hint = __('This groupchat persists even if it\'s unoccupied');
|
||||
const i18n_public = __('Public');
|
||||
const i18n_searchable_hint = __('This groupchat is publicly searchable');
|
||||
const i18n_semi_anon = __('Semi-anonymous');
|
||||
const i18n_semi_anon_hint = __('Only moderators can see your XMPP address');
|
||||
const i18n_temporary = __('Temporary');
|
||||
const i18n_temporary_hint = __('This groupchat will disappear once the last person leaves');
|
||||
const i18n_unmoderated_hint = __('Participants entering this groupchat can write right away');
|
||||
|
||||
|
||||
function renderFeatures (o) {
|
||||
const picks = pick(o.features.attributes, converse.ROOM_FEATURES);
|
||||
const iteratee = (a, v) => a || v;
|
||||
if (Object.values(picks).reduce(iteratee)) {
|
||||
return tpl_features(o.features.toJSON());
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const tpl_features = (o) => html`
|
||||
<div class="chatroom-features">
|
||||
<p class="occupants-heading">${i18n_features}</p>
|
||||
<ul class="features-list">
|
||||
${ (o.passwordprotected) ? html`<li class="feature" title="${ i18n_password_hint }"><span class="fa fa-lock"></span>${ i18n_password }</li>` : '' }
|
||||
${ (o.unsecured) ? html`<li class="feature" title="${ i18n_no_password_hint }"><span class="fa fa-unlock"></span>${ i18n_no_password }</li>` : '' }
|
||||
${ (o.hidden) ? html`<li class="feature" title="${ i18n_not_searchable_hint }"><span class="fa fa-eye-slash"></span>${ i18n_hidden }</li>` : '' }
|
||||
${ (o.public_room) ? html`<li class="feature" title="${ i18n_searchable_hint }"><span class="fa fa-eye"></span>${ i18n_public }</li>` : '' }
|
||||
${ (o.membersonly) ? html`<li class="feature" title="${ i18n_members_only_hint }"><span class="fa fa-address-book"></span>${ i18n_members_only }</li>` : '' }
|
||||
${ (o.open) ? html`<li class="feature" title="${ i18n_open_hint }"><span class="fa fa-globe"></span>${ i18n_open }</li>` : '' }
|
||||
${ (o.persistent) ? html`<li class="feature" title="${ i18n_persistent_hint }"><span class="fa fa-save"></span>${ i18n_persistent }</li>` : '' }
|
||||
${ (o.temporary) ? html`<li class="feature" title="${ i18n_temporary_hint }"><span class="fa fa-snowflake"></span>${ i18n_temporary }</li>` : '' }
|
||||
${ (o.nonanonymous) ? html`<li class="feature" title="${ i18n_non_anon_hint }"><span class="fa fa-id-card"></span>${ i18n_not_anon }</li>` : '' }
|
||||
${ (o.semianonymous) ? html`<li class="feature" title="${ i18n_semi_anon_hint }"><span class="fa fa-user-secret"></span>${ i18n_semi_anon }</li>` : '' }
|
||||
${ (o.moderated) ? html`<li class="feature" title="${ i18n_moderated_hint }"><span class="fa fa-gavel"></span>${ i18n_moderated }</li>` : '' }
|
||||
${ (o.unmoderated) ? html`<li class="feature" title="${ i18n_unmoderated_hint }"><span class="fa fa-info-circle"></span>${ i18n_not_moderated }</li>` : '' }
|
||||
${ (o.mam_enabled) ? html`<li class="feature" title="${ i18n_archived_hint }"><span class="fa fa-database"></span>${ i18n_archived }</li>` : '' }
|
||||
</ul>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const invite_button = (o) => {
|
||||
const invite_widget = (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>`;
|
||||
<a class="open-invite-modal"
|
||||
title="${i18n_invite_hint}"
|
||||
data-toggle="modal"
|
||||
data-target="#muc-invite-modal"
|
||||
@click=${o.showInviteModal}>
|
||||
<i class="btn btn-primary btn-circle fa fa-user-plus"></i>
|
||||
${i18n_invite_hint}
|
||||
</a>`;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
@ -98,7 +41,6 @@ export default (o) => html`
|
||||
<i class="hide-occupants fa fa-times"></i>
|
||||
<div class="occupants-header--title">
|
||||
<span class="occupants-heading">${i18n_participants}</span>
|
||||
${ invite_button(o) }
|
||||
</div>
|
||||
</div>
|
||||
<div class="dragresize dragresize-occupants-left"></div>
|
||||
@ -113,5 +55,5 @@ export default (o) => html`
|
||||
);
|
||||
}) }
|
||||
</ul>
|
||||
${ renderFeatures(o) }
|
||||
${ invite_widget(o) }
|
||||
`;
|
||||
|
Loading…
Reference in New Issue
Block a user