muc-views: replace VDOMView with HTMLView
This commit is contained in:
parent
9fb2d279e9
commit
d32c4c1f61
11
spec/muc.js
11
spec/muc.js
@ -1528,9 +1528,8 @@
|
||||
.c('value').t('cauldronburn');
|
||||
_converse.connection._dataRecv(test_utils.createRequest(config_stanza));
|
||||
|
||||
await u.waitUntil(() => view.el.querySelectorAll('form.chatroom-form').length)
|
||||
expect(view.el.querySelectorAll('form.chatroom-form').length).toBe(1);
|
||||
expect(view.el.querySelectorAll('form.chatroom-form fieldset').length).toBe(2);
|
||||
const form = await u.waitUntil(() => view.el.querySelector('.muc-config-form'));
|
||||
expect(form.querySelectorAll('fieldset').length).toBe(2);
|
||||
const membersonly = view.el.querySelectorAll('input[name="muc#roomconfig_membersonly"]');
|
||||
expect(membersonly.length).toBe(1);
|
||||
expect(membersonly[0].getAttribute('type')).toBe('checkbox');
|
||||
@ -2336,7 +2335,7 @@
|
||||
|
||||
await u.waitUntil(() => view.el.querySelectorAll('li .occupant-nick').length, 500);
|
||||
let occupants = view.el.querySelector('.occupant-list');
|
||||
expect(occupants.childNodes.length).toBe(1);
|
||||
expect(occupants.childElementCount).toBe(1);
|
||||
expect(occupants.firstElementChild.querySelector('.occupant-nick').textContent.trim()).toBe("oldnick");
|
||||
|
||||
expect(chat_content.querySelectorAll('div.chat-info').length).toBe(1);
|
||||
@ -2368,7 +2367,7 @@
|
||||
expect(view.model.session.get('connection_status')).toBe(converse.ROOMSTATUS.ENTERED);
|
||||
|
||||
occupants = view.el.querySelector('.occupant-list');
|
||||
expect(occupants.childNodes.length).toBe(1);
|
||||
expect(occupants.childElementCount).toBe(1);
|
||||
|
||||
presence = $pres().attrs({
|
||||
from:'lounge@montague.lit/newnick',
|
||||
@ -2394,7 +2393,7 @@
|
||||
__(_converse.muc.new_nickname_messages["303"], "newnick")
|
||||
);
|
||||
occupants = view.el.querySelector('.occupant-list');
|
||||
expect(occupants.childNodes.length).toBe(1);
|
||||
expect(occupants.childElementCount).toBe(1);
|
||||
expect(sizzle('.occupant-nick:first', occupants).pop().textContent.trim()).toBe("newnick");
|
||||
done();
|
||||
}));
|
||||
|
@ -5,12 +5,11 @@
|
||||
* @license Mozilla Public License (MPLv2)
|
||||
*/
|
||||
import "converse-modal";
|
||||
import "backbone.vdomview";
|
||||
import "formdata-polyfill";
|
||||
import "@converse/headless/utils/muc";
|
||||
import { get, head, isString, isUndefined, pick } from "lodash";
|
||||
import { get, head, isString, isUndefined } from "lodash";
|
||||
import { HTMLView } from 'skeletor.js/src/htmlview.js';
|
||||
import { Model } from 'skeletor.js/src/model.js';
|
||||
import { OrderedListView } from "skeletor.js/src/overview";
|
||||
import { View } from "skeletor.js/src/view";
|
||||
import { __ } from '@converse/headless/i18n';
|
||||
import converse from "@converse/headless/converse-core";
|
||||
@ -22,17 +21,15 @@ import tpl_chatroom_bottom_panel from "templates/chatroom_bottom_panel.html";
|
||||
import tpl_chatroom_destroyed from "templates/chatroom_destroyed.html";
|
||||
import tpl_chatroom_details_modal from "templates/chatroom_details_modal.js";
|
||||
import tpl_chatroom_disconnect from "templates/chatroom_disconnect.html";
|
||||
import tpl_chatroom_features from "templates/chatroom_features.html";
|
||||
import tpl_chatroom_form from "templates/chatroom_form.html";
|
||||
import tpl_muc_config_form from "templates/muc_config_form.js";
|
||||
import tpl_chatroom_head from "templates/chatroom_head.html";
|
||||
import tpl_chatroom_invite from "templates/chatroom_invite.html";
|
||||
import tpl_chatroom_nickname_form from "templates/chatroom_nickname_form.html";
|
||||
import tpl_chatroom_password_form from "templates/chatroom_password_form.html";
|
||||
import tpl_chatroom_sidebar from "templates/chatroom_sidebar.html";
|
||||
import tpl_muc_password_form from "templates/muc_password_form.js";
|
||||
import tpl_muc_sidebar from "templates/muc_sidebar.js";
|
||||
import tpl_info from "templates/info.html";
|
||||
import tpl_list_chatrooms_modal from "templates/list_chatrooms_modal.js";
|
||||
import tpl_moderator_tools_modal from "templates/moderator_tools_modal.js";
|
||||
import tpl_occupant from "templates/occupant.html";
|
||||
import tpl_room_description from "templates/room_description.html";
|
||||
import tpl_room_item from "templates/room_item.html";
|
||||
import tpl_room_panel from "templates/room_panel.html";
|
||||
@ -40,7 +37,7 @@ import tpl_rooms_results from "templates/rooms_results.html";
|
||||
import tpl_spinner from "templates/spinner.html";
|
||||
import xss from "xss/dist/xss";
|
||||
|
||||
const { Backbone, Strophe, sizzle, $iq, $pres } = converse.env;
|
||||
const { Strophe, sizzle, $iq, $pres } = converse.env;
|
||||
const u = converse.env.utils;
|
||||
|
||||
const ROLES = ['moderator', 'participant', 'visitor'];
|
||||
@ -1593,10 +1590,12 @@ converse.plugins.add('converse-muc-views', {
|
||||
u.safeSave(this.model.session, {'connection_status': converse.ROOMSTATUS.NICKNAME_REQUIRED});
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the configuration form without submitting and return to the chat view.
|
||||
* @private
|
||||
* @method _converse.ChatRoomView#closeForm
|
||||
*/
|
||||
closeForm () {
|
||||
/* Remove the configuration form without submitting and
|
||||
* return to the chat view.
|
||||
*/
|
||||
sizzle('.chatroom-form-container', this.el).forEach(e => u.addClass('hidden', e));
|
||||
this.renderAfterTransition();
|
||||
},
|
||||
@ -2040,12 +2039,8 @@ converse.plugins.add('converse-muc-views', {
|
||||
});
|
||||
|
||||
|
||||
_converse.MUCConfigForm = Backbone.VDOMView.extend({
|
||||
className: 'muc-config-form',
|
||||
events: {
|
||||
'submit .chatroom-form': 'submitConfigForm',
|
||||
'click .button-cancel': 'closeConfigForm'
|
||||
},
|
||||
_converse.MUCConfigForm = HTMLView.extend({
|
||||
className: 'chatroom-form-container muc-config-form',
|
||||
|
||||
initialize (attrs) {
|
||||
this.chatroomview = attrs.chatroomview;
|
||||
@ -2066,11 +2061,12 @@ converse.plugins.add('converse-muc-views', {
|
||||
'new_password': !password_protected,
|
||||
'fixed_username': this.model.get('jid')
|
||||
};
|
||||
return tpl_chatroom_form({
|
||||
'__': __,
|
||||
'title': get(stanza.querySelector('title'), 'textContent'),
|
||||
return tpl_muc_config_form({
|
||||
'closeConfigForm': ev => this.closeConfigForm(ev),
|
||||
'fields': fields.map(f => u.xForm2webForm(f, stanza, options)),
|
||||
'instructions': get(stanza.querySelector('instructions'), 'textContent'),
|
||||
'fields': fields.map(f => u.xForm2webForm(f, stanza, options))
|
||||
'submitConfigForm': ev => this.submitConfigForm(ev),
|
||||
'title': get(stanza.querySelector('title'), 'textContent')
|
||||
});
|
||||
},
|
||||
|
||||
@ -2098,11 +2094,8 @@ converse.plugins.add('converse-muc-views', {
|
||||
});
|
||||
|
||||
|
||||
_converse.MUCPasswordForm = Backbone.VDOMView.extend({
|
||||
className: 'muc-password-form',
|
||||
events: {
|
||||
'submit form': 'submitPassword',
|
||||
},
|
||||
_converse.MUCPasswordForm = HTMLView.extend({
|
||||
className: 'chatroom-form-container muc-password-form',
|
||||
|
||||
initialize (attrs) {
|
||||
this.chatroomview = attrs.chatroomview;
|
||||
@ -2111,14 +2104,10 @@ converse.plugins.add('converse-muc-views', {
|
||||
},
|
||||
|
||||
toHTML () {
|
||||
const err_msg = this.model.get('validation_message');
|
||||
return tpl_chatroom_password_form({
|
||||
return tpl_muc_password_form({
|
||||
'jid': this.model.get('jid'),
|
||||
'heading': __('This groupchat requires a password'),
|
||||
'label_password': __('Password: '),
|
||||
'label_submit': __('Submit'),
|
||||
'error_class': err_msg ? 'error' : '',
|
||||
'validation_message': err_msg
|
||||
'submitPassword': ev => this.submitPassword(ev),
|
||||
'validation_message': this.model.get('validation_message')
|
||||
});
|
||||
},
|
||||
|
||||
@ -2131,67 +2120,42 @@ converse.plugins.add('converse-muc-views', {
|
||||
});
|
||||
|
||||
|
||||
_converse.ChatRoomOccupantView = Backbone.VDOMView.extend({
|
||||
tagName: 'li',
|
||||
initialize () {
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
},
|
||||
|
||||
toHTML () {
|
||||
const show = this.model.get('show');
|
||||
return tpl_occupant(
|
||||
Object.assign({
|
||||
__,
|
||||
show,
|
||||
'jid': '',
|
||||
'hint_show': _converse.PRETTY_CHAT_STATUS[show],
|
||||
'hint_occupant': __('Click to mention %1$s in your message.', this.model.get('nick'))
|
||||
}, this.model.toJSON())
|
||||
);
|
||||
},
|
||||
|
||||
destroy () {
|
||||
this.el.parentElement.removeChild(this.el);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
_converse.ChatRoomOccupantsView = OrderedListView.extend({
|
||||
_converse.ChatRoomOccupantsView = HTMLView.extend({
|
||||
tagName: 'div',
|
||||
className: 'occupants col-md-3 col-4',
|
||||
listItems: 'model',
|
||||
sortEvent: 'change:role',
|
||||
listSelector: '.occupant-list',
|
||||
|
||||
ItemView: _converse.ChatRoomOccupantView,
|
||||
|
||||
async initialize () {
|
||||
OrderedListView.prototype.initialize.apply(this, arguments);
|
||||
|
||||
this.listenTo(this.model, 'add', this.maybeRenderInviteWidget);
|
||||
this.listenTo(this.model, 'change:affiliation', this.maybeRenderInviteWidget);
|
||||
|
||||
this.chatroomview = this.model.chatroomview;
|
||||
this.listenTo(this.chatroomview.model.features, 'change', this.renderRoomFeatures);
|
||||
this.listenTo(this.model, 'add', this.maybeRenderInviteWidget);
|
||||
this.listenTo(this.model, 'add', this.render);
|
||||
this.listenTo(this.model, 'remove', this.render);
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
this.listenTo(this.model, 'change:affiliation', this.maybeRenderInviteWidget);
|
||||
this.listenTo(this.chatroomview.model.features, 'change', this.render);
|
||||
this.listenTo(this.chatroomview.model.features, 'change:open', this.renderInviteWidget);
|
||||
this.listenTo(this.chatroomview.model, 'change:hidden_occupants', this.setVisibility);
|
||||
this.render();
|
||||
await this.model.fetched;
|
||||
this.sortAndPositionAllItems();
|
||||
},
|
||||
|
||||
render () {
|
||||
this.el.innerHTML = tpl_chatroom_sidebar(
|
||||
toHTML () {
|
||||
return tpl_muc_sidebar(
|
||||
Object.assign(this.chatroomview.model.toJSON(), {
|
||||
'allow_muc_invitations': _converse.allow_muc_invitations,
|
||||
'label_occupants': __('Participants')
|
||||
'features': this.chatroomview.model.features,
|
||||
'label_occupants': __('Participants'),
|
||||
'occupants': this.model.models
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
afterRender () {
|
||||
if (_converse.allow_muc_invitations) {
|
||||
// TODO: the invite widget needs to be rendered via a directive
|
||||
_converse.api.waitUntil('rosterContactsFetched').then(() => this.renderInviteWidget());
|
||||
}
|
||||
this.setVisibility();
|
||||
return this.renderRoomFeatures();
|
||||
this.setOccupantsHeight();
|
||||
},
|
||||
|
||||
setVisibility () {
|
||||
@ -2210,6 +2174,7 @@ converse.plugins.add('converse-muc-views', {
|
||||
},
|
||||
|
||||
renderInviteWidget () {
|
||||
// TODO: this needs to be rendered inside muc_sidebar.js
|
||||
const widget = this.el.querySelector('.room-invite');
|
||||
if (this.shouldInviteWidgetBeShown()) {
|
||||
if (widget === null) {
|
||||
@ -2229,26 +2194,14 @@ converse.plugins.add('converse-muc-views', {
|
||||
return this;
|
||||
},
|
||||
|
||||
renderRoomFeatures () {
|
||||
const features = this.chatroomview.model.features,
|
||||
picks = pick(features.attributes, converse.ROOM_FEATURES),
|
||||
iteratee = (a, v) => a || v;
|
||||
|
||||
if (Object.values(picks).reduce(iteratee)) {
|
||||
const el = this.el.querySelector('.chatroom-features');
|
||||
el.innerHTML = tpl_chatroom_features(Object.assign(features.toJSON(), {__}));
|
||||
this.setOccupantsHeight();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
setOccupantsHeight () {
|
||||
const el = this.el.querySelector('.chatroom-features');
|
||||
this.el.querySelector('.occupant-list').style.cssText =
|
||||
`height: calc(100% - ${el.offsetHeight}px - 5em);`;
|
||||
if (el) {
|
||||
this.el.querySelector('.occupant-list').style.cssText =
|
||||
`height: calc(100% - ${el.offsetHeight}px - 5em);`;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
promptForInvite (suggestion) {
|
||||
let reason = '';
|
||||
if (!_converse.auto_join_on_invite) {
|
||||
@ -2417,7 +2370,7 @@ converse.plugins.add('converse-muc-views', {
|
||||
* @method _converse.api.roomviews.get
|
||||
* @param {String|string[]} name - e.g. 'coven@conference.shakespeare.lit' or
|
||||
* ['coven@conference.shakespeare.lit', 'cave@conference.shakespeare.lit']
|
||||
* @returns {Backbone.View} Backbone.View representing the groupchat
|
||||
* @returns {View} View representing the groupchat
|
||||
*
|
||||
* @example
|
||||
* // To return a single view, provide the JID of the groupchat
|
||||
|
@ -3,6 +3,7 @@
|
||||
* @copyright 2020, the Converse.js contributors
|
||||
* @license Mozilla Public License (MPLv2)
|
||||
*/
|
||||
import "backbone.vdomview";
|
||||
import "@converse/headless/converse-chatboxes";
|
||||
import "@converse/headless/converse-roster";
|
||||
import "converse-modal";
|
||||
|
@ -145,15 +145,6 @@ _converse.STATUS_WEIGHTS = {
|
||||
'chat': 1, // We currently don't differentiate between "chat" and "online"
|
||||
'online': 1
|
||||
};
|
||||
_converse.PRETTY_CHAT_STATUS = {
|
||||
'offline': 'Offline',
|
||||
'unavailable': 'Unavailable',
|
||||
'xa': 'Extended Away',
|
||||
'away': 'Away',
|
||||
'dnd': 'Do not disturb',
|
||||
'chat': 'Chattty',
|
||||
'online': 'Online'
|
||||
};
|
||||
_converse.ANONYMOUS = 'anonymous';
|
||||
_converse.CLOSED = 'closed';
|
||||
_converse.EXTERNAL = 'external';
|
||||
|
@ -1,42 +0,0 @@
|
||||
<p class="occupants-heading">{{{o.__('Features')}}}</p>
|
||||
<ul class="features-list">
|
||||
{[ if (o.passwordprotected) { ]}
|
||||
<li class="feature" title="{{{ o.__('This groupchat requires a password before entry') }}}"><span class="fa fa-lock"></span>{{{ o.__('Password protected') }}}</li>
|
||||
{[ } ]}
|
||||
{[ if (o.unsecured) { ]}
|
||||
<li class="feature" title="{{{ o.__('This groupchat does not require a password upon entry') }}}"><span class="fa fa-unlock"></span>{{{ o.__('No password') }}}</li>
|
||||
{[ } ]}
|
||||
{[ if (o.hidden) { ]}
|
||||
<li class="feature" title="{{{ o.__('This groupchat is not publicly searchable') }}}"><span class="fa fa-eye-slash"></span>{{{ o.__('Hidden') }}}</li>
|
||||
{[ } ]}
|
||||
{[ if (o.public_room) { ]}
|
||||
<li class="feature" title="{{{ o.__('This groupchat is publicly searchable') }}}"><span class="fa fa-eye"></span>{{{ o.__('Public') }}}</li>
|
||||
{[ } ]}
|
||||
{[ if (o.membersonly) { ]}
|
||||
<li class="feature" title="{{{ o.__('this groupchat is restricted to members only') }}}"><span class="fa fa-address-book"></span>{{{ o.__('Members only') }}}</li>
|
||||
{[ } ]}
|
||||
{[ if (o.open) { ]}
|
||||
<li class="feature" title="{{{ o.__('Anyone can join this groupchat') }}}"><span class="fa fa-globe"></span>{{{ o.__('Open') }}}</li>
|
||||
{[ } ]}
|
||||
{[ if (o.persistent) { ]}
|
||||
<li class="feature" title="{{{ o.__('This groupchat persists even if it\'s unoccupied') }}}"><span class="fa fa-save"></span>{{{ o.__('Persistent') }}}</li>
|
||||
{[ } ]}
|
||||
{[ if (o.temporary) { ]}
|
||||
<li class="feature" title="{{{ o.__('This groupchat will disappear once the last person leaves') }}}"><span class="fa fa-snowflake"></span>{{{ o.__('Temporary') }}}</li>
|
||||
{[ } ]}
|
||||
{[ if (o.nonanonymous) { ]}
|
||||
<li class="feature" title="{{{ o.__('All other groupchat participants can see your XMPP address') }}}"><span class="fa fa-id-card"></span>{{{ o.__('Not anonymous') }}}</li>
|
||||
{[ } ]}
|
||||
{[ if (o.semianonymous) { ]}
|
||||
<li class="feature" title="{{{ o.__('Only moderators can see your XMPP address') }}}"><span class="fa fa-user-secret"></span>{{{ o.__('Semi-anonymous') }}}</li>
|
||||
{[ } ]}
|
||||
{[ if (o.moderated) { ]}
|
||||
<li class="feature" title="{{{ o.__('Participants entering this groupchat need to request permission to write') }}}"><span class="fa fa-gavel"></span>{{{ o.__('Moderated') }}}</li>
|
||||
{[ } ]}
|
||||
{[ if (o.unmoderated) { ]}
|
||||
<li class="feature" title="{{{ o.__('Participants entering this groupchat can write right away') }}}"><span class="fa fa-info-circle"></span>{{{ o.__('Not moderated') }}}</li>
|
||||
{[ } ]}
|
||||
{[ if (o.mam_enabled) { ]}
|
||||
<li class="feature" title="{{{ o.__('Messages are archived on the server') }}}"><span class="fa fa-database"></span>{{{ o.__('Message archiving') }}}</li>
|
||||
{[ } ]}
|
||||
</ul>
|
@ -1,16 +0,0 @@
|
||||
<div class="chatroom-form-container muc-config-form">
|
||||
<form class="converse-form chatroom-form" autocomplete="off">
|
||||
<fieldset class="form-group">
|
||||
<legend>{{{o.title}}}</legend>
|
||||
{[ if (o.title !== o.instructions) { ]}
|
||||
<p class="form-help">{{{o.instructions}}}</p>
|
||||
{[ } ]}
|
||||
<!-- Fields are generated internally, with xForm2webForm -->
|
||||
{[ o.fields.forEach(function (field) { ]} {{ field }} {[ }) ]}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<input type="submit" class="btn btn-primary" value="{{{o.__('Save')}}}"/>
|
||||
<input type="button" class="btn btn-secondary .button-cancel" value="{{{o.__('Cancel')}}}"/>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
@ -1,14 +0,0 @@
|
||||
<div class="chatroom-form-container muc-password-form">
|
||||
<form class="converse-form chatroom-form converse-centered-form">
|
||||
<fieldset class="form-group">
|
||||
<label>{{{o.heading}}}</label>
|
||||
<p class="validation-message">{{{o.validation_message}}}</p>
|
||||
<input class="hidden-username" type="text" autocomplete="username" value="{{{o.jid}}}"></input>
|
||||
<input type="password" name="password" required="required"
|
||||
class="form-control {{o.error_class}}" placeholder="{{{o.label_password}}}"/>
|
||||
</fieldset>
|
||||
<fieldset class="form-group">
|
||||
<input class="btn btn-primary" type="submit" value="{{{o.label_submit}}}"/>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
@ -1,9 +0,0 @@
|
||||
<!-- <div class="occupants"> -->
|
||||
<div class="occupants-header">
|
||||
<i class="hide-occupants fa fa-times"></i>
|
||||
<p class="occupants-heading">{{{o.label_occupants}}}</p>
|
||||
</div>
|
||||
<div class="dragresize dragresize-occupants-left"></div>
|
||||
<ul class="occupant-list"></ul>
|
||||
<div class="chatroom-features"></div>
|
||||
<!-- </div> -->
|
21
src/templates/muc_config_form.js
Normal file
21
src/templates/muc_config_form.js
Normal file
@ -0,0 +1,21 @@
|
||||
import { html } from "lit-html";
|
||||
import { __ } from '@converse/headless/i18n';
|
||||
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
|
||||
|
||||
const i18n_save = __('Save');
|
||||
const i18n_cancel = __('Cancel');
|
||||
|
||||
export default (o) => html`
|
||||
<form class="converse-form chatroom-form" autocomplete="off" @submit=${o.submitConfigForm}>
|
||||
<fieldset class="form-group">
|
||||
<legend>${o.title}</legend>
|
||||
${ (o.title !== o.instructions) ? html`<p class="form-help">${o.instructions}</p>` : '' }
|
||||
<!-- Fields are generated internally, with xForm2webForm -->
|
||||
${ o.fields.map(field => unsafeHTML(field)) }
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<input type="submit" class="btn btn-primary" value="${i18n_save}">
|
||||
<input type="button" class="btn btn-secondary button-cancel" value="${i18n_cancel}" @click=${o.closeConfigForm}>
|
||||
</fieldset>
|
||||
</form>
|
||||
`;
|
25
src/templates/muc_password_form.js
Normal file
25
src/templates/muc_password_form.js
Normal file
@ -0,0 +1,25 @@
|
||||
import { html } from "lit-html";
|
||||
import { __ } from '@converse/headless/i18n';
|
||||
|
||||
const i18n_heading = __('This groupchat requires a password');
|
||||
const i18n_password = __('Password: ');
|
||||
const i18n_submit = __('Submit');
|
||||
|
||||
|
||||
export default (o) => html`
|
||||
<form class="converse-form chatroom-form converse-centered-form" @submit=${o.submitPassword}>
|
||||
<fieldset class="form-group">
|
||||
<label>${i18n_heading}</label>
|
||||
<p class="validation-message">${o.validation_message}</p>
|
||||
<input class="hidden-username" type="text" autocomplete="username" value="${o.jid}"></input>
|
||||
<input type="password"
|
||||
name="password"
|
||||
required="required"
|
||||
class="form-control ${o.validation_message ? 'error': ''}"
|
||||
placeholder="${i18n_password}"/>
|
||||
</fieldset>
|
||||
<fieldset class="form-group">
|
||||
<input class="btn btn-primary" type="submit" value="${i18n_submit}"/>
|
||||
</fieldset>
|
||||
</form>
|
||||
`;
|
99
src/templates/muc_sidebar.js
Normal file
99
src/templates/muc_sidebar.js
Normal file
@ -0,0 +1,99 @@
|
||||
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',
|
||||
'xa': 'Extended Away',
|
||||
'away': 'Away',
|
||||
'dnd': 'Do not disturb',
|
||||
'chat': 'Chattty',
|
||||
'online': 'Online'
|
||||
};
|
||||
|
||||
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_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_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>
|
||||
`;
|
||||
|
||||
|
||||
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>
|
||||
<div class="dragresize dragresize-occupants-left"></div>
|
||||
<ul class="occupant-list">
|
||||
${ o.occupants.map(occupant => {
|
||||
return tpl_occupant(
|
||||
Object.assign({
|
||||
'jid': '',
|
||||
'hint_show': PRETTY_CHAT_STATUS[occupant.get('show')],
|
||||
'hint_occupant': occupant_hint(occupant)
|
||||
}, occupant.toJSON())
|
||||
);
|
||||
}) }
|
||||
</ul>
|
||||
${ renderFeatures(o) }
|
||||
`;
|
@ -1,40 +0,0 @@
|
||||
<li class="occupant" id="{{{ o.id }}}"
|
||||
{[ if (o.role === "moderator") { ]}
|
||||
title="{{{ o.jid }}} {{{ o.__('This user is a moderator.') }}} {{{ o.hint_occupant }}}"
|
||||
{[ } ]}
|
||||
{[ if (o.role === "participant") { ]}
|
||||
title="{{{ o.jid }}} {{{ o.__('This user can send messages in this groupchat.') }}} {{{ o.hint_occupant }}}"
|
||||
{[ } ]}
|
||||
{[ if (o.role === "visitor") { ]}
|
||||
title="{{{ o.jid }}} {{{ o.__('This user can NOT send messages in this groupchat.') }}} {{{ o.hint_occupant }}}"
|
||||
{[ } ]}
|
||||
{[ if (!["visitor", "participant", "moderator"].includes(o.role)) { ]}
|
||||
title="{{{ o.jid }}} {{{ o.hint_occupant }}}"
|
||||
{[ } ]}>
|
||||
<div class="row no-gutters">
|
||||
<div class="col-auto">
|
||||
<div class="occupant-status occupant-{{{o.show}}} circle" title="{{{o.hint_show}}}"></div>
|
||||
</div>
|
||||
<div class="col occupant-nick-badge">
|
||||
<span class="occupant-nick">{{{o.nick || o.jid}}}</span>
|
||||
<span class="occupant-badges">
|
||||
{[ if (o.affiliation === "owner") { ]}
|
||||
<span class="badge badge-groupchat">{{{o.__('Owner')}}}</span>
|
||||
{[ } ]}
|
||||
{[ if (o.affiliation === "admin") { ]}
|
||||
<span class="badge badge-info">{{{o.__('Admin')}}}</span>
|
||||
{[ } ]}
|
||||
{[ if (o.affiliation === "member") { ]}
|
||||
<span class="badge badge-info">{{{o.__('Member')}}}</span>
|
||||
{[ } ]}
|
||||
|
||||
{[ if (o.role === "moderator") { ]}
|
||||
<span class="badge badge-info">{{{o.__('Moderator')}}}</span>
|
||||
{[ } ]}
|
||||
{[ if (o.role === "visitor") { ]}
|
||||
<span class="badge badge-secondary">{{{o.__('Visitor')}}}</span>
|
||||
{[ } ]}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
45
src/templates/occupant.js
Normal file
45
src/templates/occupant.js
Normal file
@ -0,0 +1,45 @@
|
||||
import { html } from "lit-html";
|
||||
import { __ } from '@converse/headless/i18n';
|
||||
|
||||
|
||||
const i18n_moderator_hint = ('This user is a moderator.');
|
||||
const i18n_participant_hint = __('This user can send messages in this groupchat.');
|
||||
const i18n_visitor_hint = __('This user can NOT send messages in this groupchat.')
|
||||
const i18n_owner = __('Owner');
|
||||
const i18n_admin = __('Admin');
|
||||
const i18n_member = __('Member');
|
||||
const i18n_moderator = __('Moderator');
|
||||
const i18n_visitor = __('Visitor');
|
||||
|
||||
const occupant_title = (o) => {
|
||||
if (o.role === "moderator") {
|
||||
return `${o.jid} ${i18n_moderator_hint} ${o.hint_occupant}`;
|
||||
} else if (o.role === "participant") {
|
||||
return `${o.jid} ${i18n_participant_hint} ${o.hint_occupant}`;
|
||||
} else if (o.role === "visitor") {
|
||||
return `${o.jid} ${i18n_visitor_hint} ${o.hint_occupant}`;
|
||||
} else if (!["visitor", "participant", "moderator"].includes(o.role)) {
|
||||
return `${o.jid} ${o.hint_occupant}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default (o) => html`
|
||||
<li class="occupant" id="${o.id}" title="${occupant_title(o)}">
|
||||
<div class="row no-gutters">
|
||||
<div class="col-auto">
|
||||
<div class="occupant-status occupant-${o.show} circle" title="${o.hint_show}"></div>
|
||||
</div>
|
||||
<div class="col occupant-nick-badge">
|
||||
<span class="occupant-nick">${o.nick || o.jid}</span>
|
||||
<span class="occupant-badges">
|
||||
${ (o.affiliation === "owner") ? html`<span class="badge badge-groupchat">${i18n_owner}</span>` : '' }
|
||||
${ (o.affiliation === "admin") ? html`<span class="badge badge-info">${i18n_admin}</span>` : '' }
|
||||
${ (o.affiliation === "member") ? html`<span class="badge badge-info">${i18n_member}</span>` : '' }
|
||||
${ (o.role === "moderator") ? html`<span class="badge badge-info">${i18n_moderator}</span>` : '' }
|
||||
${ (o.role === "visitor") ? html`<span class="badge badge-secondary">${i18n_visitor}</span>` : '' }
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
`;
|
Loading…
Reference in New Issue
Block a user