2020-01-23 10:18:41 +01:00
|
|
|
import { html } from "lit-html";
|
|
|
|
import { __ } from '@converse/headless/i18n';
|
|
|
|
import spinner from "./spinner.js";
|
|
|
|
import { modal_header_close_button } from "./buttons"
|
|
|
|
|
|
|
|
|
|
|
|
const i18n_affiliation = __('Affiliation');
|
|
|
|
const i18n_change_affiliation = __('Change affiliation');
|
|
|
|
const i18n_change_role = __('Change role');
|
|
|
|
const i18n_moderator_tools = __('Moderator Tools');
|
|
|
|
const i18n_new_affiliation = __('New affiliation');
|
|
|
|
const i18n_new_role = __('New Role');
|
|
|
|
const i18n_no_users_with_aff = __('No users with that affiliation found.')
|
|
|
|
const i18n_no_users_with_role = __('No users with that role found.');
|
|
|
|
const i18n_reason = __('Reason');
|
2020-03-23 13:14:18 +01:00
|
|
|
const i18n_filter = __('Type here to filter the search results');
|
2020-01-23 10:18:41 +01:00
|
|
|
const i18n_role = __('Role');
|
|
|
|
const i18n_show_users = __('Show users');
|
|
|
|
|
|
|
|
const i18n_helptext_role = __(
|
|
|
|
"Roles are assigned to users to grant or deny them certain abilities in a multi-user chat. "+
|
|
|
|
"They're assigned either explicitly or implicitly as part of an affiliation. "+
|
|
|
|
"A role that's not due to an affiliation, is only valid for the duration of the user's session."
|
|
|
|
);
|
|
|
|
|
|
|
|
const i18n_helptext_affiliation = __(
|
|
|
|
"An affiliation is a long-lived entitlement which typically implies a certain role and which "+
|
|
|
|
"grants privileges and responsibilities. For example admins and owners automatically have the "+
|
|
|
|
"moderator role."
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
function getRoleHelpText (role) {
|
|
|
|
if (role === 'moderator') {
|
|
|
|
return __("Moderators are privileged users who can change the roles of other users (except those with admin or owner affiliations.");
|
|
|
|
} else if (role === 'participant') {
|
|
|
|
return __("The default role, implies that you can read and write messages.");
|
|
|
|
} else if (role == 'visitor') {
|
|
|
|
return __("Visitors aren't allowed to write messages in a moderated multi-user chat.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function getAffiliationHelpText (aff) {
|
|
|
|
if (aff === 'owner') {
|
|
|
|
return __("Owner is the highest affiliation. Owners can modify roles and affiliations of all other users.");
|
|
|
|
} else if (aff === 'admin') {
|
|
|
|
return __("Admin is the 2nd highest affiliation. Admins can modify roles and affiliations of all other users except owners.");
|
|
|
|
} else if (aff === 'outcast') {
|
|
|
|
return __("To ban a user, you give them the affiliation of \"outcast\".");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const role_option = (o) => html`
|
|
|
|
<option value="${o.item || ''}"
|
|
|
|
?selected=${o.item === o.role}
|
|
|
|
title="${getRoleHelpText(o.item)}">${o.item}</option>
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
|
|
const affiliation_option = (o) => html`
|
|
|
|
<option value="${o.item || ''}"
|
|
|
|
?selected=${o.item === o.affiliation}
|
|
|
|
title="${getAffiliationHelpText(o.item)}">${o.item}</option>
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
2020-02-22 21:12:40 +01:00
|
|
|
const tpl_set_role_form = (o) => html`
|
|
|
|
<form class="role-form hidden" @submit=${o.assignRole}>
|
|
|
|
<div class="form-group">
|
|
|
|
<input type="hidden" name="jid" value="${o.item.jid}"/>
|
|
|
|
<input type="hidden" name="nick" value="${o.item.nick}"/>
|
|
|
|
<div class="row">
|
|
|
|
<div class="col">
|
|
|
|
<label><strong>${i18n_new_role}:</strong></label>
|
|
|
|
<select class="custom-select select-role" name="role">
|
|
|
|
${ o.assignable_roles.map(role => html`<option value="${role}" ?selected=${role === o.item.role}>${role}</option>`) }
|
|
|
|
</select>
|
|
|
|
</div>
|
|
|
|
<div class="col">
|
|
|
|
<label><strong>${i18n_reason}:</strong></label>
|
|
|
|
<input class="form-control" type="text" name="reason"/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
|
|
<input type="submit" class="btn btn-primary" value="${i18n_change_role}"/>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
2020-01-23 10:18:41 +01:00
|
|
|
const role_list_item = (o) => html`
|
2020-03-23 17:55:11 +01:00
|
|
|
<li class="list-group-item" data-nick="${o.item.nick}">
|
2020-01-23 10:18:41 +01:00
|
|
|
<ul class="list-group">
|
|
|
|
<li class="list-group-item active">
|
|
|
|
<div><strong>JID:</strong> ${o.item.jid}</div>
|
|
|
|
</li>
|
|
|
|
<li class="list-group-item">
|
|
|
|
<div><strong>Nickname:</strong> ${o.item.nick}</div>
|
|
|
|
</li>
|
|
|
|
<li class="list-group-item">
|
2020-02-22 21:12:40 +01:00
|
|
|
<div><strong>Role:</strong> ${o.item.role} ${o.assignable_roles.length ? html`<a href="#" data-form="role-form" class="toggle-form right fa fa-wrench" @click=${o.toggleForm}></a>` : ''}</div>
|
|
|
|
${o.assignable_roles.length ? tpl_set_role_form(o) : ''}
|
2020-01-23 10:18:41 +01:00
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
2020-02-22 21:12:40 +01:00
|
|
|
const tpl_set_affiliation_form = (o) => html`
|
|
|
|
<form class="affiliation-form hidden" @submit=${o.assignAffiliation}>
|
|
|
|
<div class="form-group">
|
|
|
|
<input type="hidden" name="jid" value="${o.item.jid}"/>
|
|
|
|
<input type="hidden" name="nick" value="${o.item.nick}"/>
|
|
|
|
<div class="row">
|
|
|
|
<div class="col">
|
|
|
|
<label><strong>${i18n_new_affiliation}:</strong></label>
|
|
|
|
<select class="custom-select select-affiliation" name="affiliation">
|
|
|
|
${ o.assignable_affiliations.map(aff => html`<option value="${aff}" ?selected=${aff === o.item.affiliation}>${aff}</option>`) }
|
|
|
|
</select>
|
|
|
|
</div>
|
|
|
|
<div class="col">
|
|
|
|
<label><strong>${i18n_reason}:</strong></label>
|
|
|
|
<input class="form-control" type="text" name="reason"/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
|
|
<input type="submit" class="btn btn-primary" name="change" value="${i18n_change_affiliation}"/>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
2020-01-23 10:18:41 +01:00
|
|
|
const affiliation_list_item = (o) => html`
|
2020-03-23 17:55:11 +01:00
|
|
|
<li class="list-group-item" data-nick="${o.item.nick}">
|
2020-01-23 10:18:41 +01:00
|
|
|
<ul class="list-group">
|
|
|
|
<li class="list-group-item active">
|
|
|
|
<div><strong>JID:</strong> ${o.item.jid}</div>
|
|
|
|
</li>
|
|
|
|
<li class="list-group-item">
|
|
|
|
<div><strong>Nickname:</strong> ${o.item.nick}</div>
|
|
|
|
</li>
|
|
|
|
<li class="list-group-item">
|
2020-02-22 21:12:40 +01:00
|
|
|
<div><strong>Affiliation:</strong> ${o.item.affiliation} ${o.assignable_affiliations.length ? html`<a href="#" data-form="affiliation-form" class="toggle-form right fa fa-wrench" @click=${o.toggleForm}></a>` : ''}</div>
|
|
|
|
${o.assignable_affiliations.length ? tpl_set_affiliation_form(o) : ''}
|
2020-01-23 10:18:41 +01:00
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
2020-02-22 21:12:40 +01:00
|
|
|
const tpl_navigation = (o) => html`
|
|
|
|
<ul class="nav nav-pills justify-content-center">
|
|
|
|
<li role="presentation" class="nav-item">
|
|
|
|
<a class="nav-link active" id="affiliations-tab" href="#affiliations-tabpanel" aria-controls="affiliations-tabpanel" role="tab" data-toggle="tab" @click=${o.switchTab}>Affiliations</a>
|
|
|
|
</li>
|
|
|
|
<li role="presentation" class="nav-item">
|
|
|
|
<a class="nav-link" id="roles-tab" href="#roles-tabpanel" aria-controls="roles-tabpanel" role="tab" data-toggle="tab" @click=${o.switchTab}>Roles</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
|
|
export default (o) => {
|
|
|
|
const show_both_tabs = o.queryable_roles.length && o.queryable_affiliations.length;
|
|
|
|
return html`
|
2020-01-23 10:18:41 +01:00
|
|
|
<div class="modal-dialog" role="document">
|
|
|
|
<div class="modal-content">
|
|
|
|
<div class="modal-header">
|
|
|
|
<h5 class="modal-title" id="converse-modtools-modal-label">${i18n_moderator_tools}</h5>
|
|
|
|
${modal_header_close_button}
|
|
|
|
</div>
|
|
|
|
<div class="modal-body d-flex flex-column">
|
|
|
|
<span class="modal-alert"></span>
|
|
|
|
|
2020-02-22 21:12:40 +01:00
|
|
|
${ show_both_tabs ? tpl_navigation(o) : '' }
|
|
|
|
|
2020-01-23 10:18:41 +01:00
|
|
|
<div class="tab-content">
|
2020-02-22 21:12:40 +01:00
|
|
|
<div class="tab-pane tab-pane--columns ${ o.queryable_affiliations.length ? 'active' : ''}" id="affiliations-tabpanel" role="tabpanel" aria-labelledby="affiliations-tab">
|
2020-02-21 15:22:59 +01:00
|
|
|
<form class="converse-form query-affiliation" @submit=${o.queryAffiliation}>
|
2020-02-21 15:01:19 +01:00
|
|
|
<p class="helptext pb-3">${i18n_helptext_affiliation}</p>
|
2020-01-23 10:18:41 +01:00
|
|
|
<div class="form-group">
|
2020-02-21 15:01:19 +01:00
|
|
|
<label for="affiliation">
|
|
|
|
<strong>${i18n_affiliation}:</strong>
|
|
|
|
</label>
|
2020-01-23 10:18:41 +01:00
|
|
|
<div class="row">
|
|
|
|
<div class="col">
|
2020-02-21 15:01:19 +01:00
|
|
|
<select class="custom-select select-affiliation" name="affiliation">
|
2020-02-22 21:12:40 +01:00
|
|
|
${o.queryable_affiliations.map(item => affiliation_option(Object.assign({item}, o)))}
|
2020-01-23 10:18:41 +01:00
|
|
|
</select>
|
|
|
|
</div>
|
|
|
|
<div class="col">
|
2020-02-21 15:01:19 +01:00
|
|
|
<input type="submit" class="btn btn-primary" name="users_with_affiliation" value="${i18n_show_users}"/>
|
2020-01-23 10:18:41 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="row">
|
2020-03-23 13:14:18 +01:00
|
|
|
<div class="col mt-3">
|
|
|
|
${ (Array.isArray(o.users_with_affiliation) && o.users_with_affiliation.length > 5) ?
|
|
|
|
html`<input class="form-control" .value="${o.affiliations_filter}" @keyup=${o.filterAffiliationResults} type="text" name="filter" placeholder="${i18n_filter}"/>` : '' }
|
|
|
|
</div>
|
2020-01-23 10:18:41 +01:00
|
|
|
</div>
|
2020-03-23 13:14:18 +01:00
|
|
|
|
|
|
|
${ getAffiliationHelpText(o.affiliation) ?
|
|
|
|
html`<div class="row"><div class="col pt-2"><p class="helptext pb-3">${getAffiliationHelpText(o.affiliation)}</p></div></div>` : '' }
|
2020-01-23 10:18:41 +01:00
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
<div class="scrollable-container">
|
|
|
|
<ul class="list-group list-group--users">
|
2020-02-21 15:01:19 +01:00
|
|
|
${ (o.loading_users_with_affiliation) ? html`<li class="list-group-item"> ${spinner()} </li>` : '' }
|
2020-03-23 13:14:18 +01:00
|
|
|
${ (Array.isArray(o.users_with_affiliation) && o.users_with_affiliation.length === 0) ?
|
|
|
|
html`<li class="list-group-item">${i18n_no_users_with_aff}</li>` : '' }
|
|
|
|
|
2020-02-21 15:01:19 +01:00
|
|
|
${ (o.users_with_affiliation instanceof Error) ?
|
|
|
|
html`<li class="list-group-item">${o.users_with_affiliation.message}</li>` :
|
2020-03-25 09:00:34 +01:00
|
|
|
(o.users_with_affiliation || []).map(item => ((item.nick || item.jid).match(o.affiliations_filter) ? affiliation_list_item(Object.assign({item}, o)) : '')) }
|
2020-01-23 10:18:41 +01:00
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2020-02-22 21:12:40 +01:00
|
|
|
<div class="tab-pane tab-pane--columns ${ !show_both_tabs && o.queryable_roles.length ? 'active' : ''}" id="roles-tabpanel" role="tabpanel" aria-labelledby="roles-tab">
|
2020-02-21 15:22:59 +01:00
|
|
|
<form class="converse-form query-role" @submit=${o.queryRole}>
|
2020-02-21 15:01:19 +01:00
|
|
|
<p class="helptext pb-3">${i18n_helptext_role}</p>
|
2020-01-23 10:18:41 +01:00
|
|
|
<div class="form-group">
|
2020-02-21 15:01:19 +01:00
|
|
|
<label for="role"><strong>${i18n_role}:</strong></label>
|
2020-01-23 10:18:41 +01:00
|
|
|
<div class="row">
|
|
|
|
<div class="col">
|
2020-02-21 15:01:19 +01:00
|
|
|
<select class="custom-select select-role" name="role">
|
2020-02-22 21:12:40 +01:00
|
|
|
${o.queryable_roles.map(item => role_option(Object.assign({item}, o)))}
|
2020-01-23 10:18:41 +01:00
|
|
|
</select>
|
|
|
|
</div>
|
|
|
|
<div class="col">
|
2020-02-21 15:01:19 +01:00
|
|
|
<input type="submit" class="btn btn-primary" name="users_with_role" value="${i18n_show_users}"/>
|
2020-01-23 10:18:41 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="row">
|
2020-03-23 13:14:18 +01:00
|
|
|
<div class="col mt-3">
|
|
|
|
${ (Array.isArray(o.users_with_role) && o.users_with_role.length > 5) ?
|
|
|
|
html`<input class="form-control" .value="${o.roles_filter}" @keyup=${o.filterRoleResults} type="text" name="filter" placeholder="${i18n_filter}"/>` : '' }
|
|
|
|
</div>
|
2020-01-23 10:18:41 +01:00
|
|
|
</div>
|
2020-03-23 13:14:18 +01:00
|
|
|
|
|
|
|
${ getRoleHelpText(o.role) ? html`<div class="row"><div class="col pt-2"><p class="helptext pb-3">${getRoleHelpText(o.role)}</p></div></div>` : ''}
|
2020-01-23 10:18:41 +01:00
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
<div class="scrollable-container">
|
|
|
|
<ul class="list-group list-group--users">
|
2020-02-21 15:01:19 +01:00
|
|
|
${ o.loading_users_with_role ? html`<li class="list-group-item"> ${spinner()} </li>` : '' }
|
|
|
|
${ (o.users_with_role && o.users_with_role.length === 0) ? html`<li class="list-group-item">${i18n_no_users_with_role}</li>` : '' }
|
2020-03-23 13:14:18 +01:00
|
|
|
${ (o.users_with_role || []).map(item => (item.nick.match(o.roles_filter) ? role_list_item(Object.assign({item}, o)) : '')) }
|
2020-01-23 10:18:41 +01:00
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2020-02-22 21:12:40 +01:00
|
|
|
</div>`;
|
|
|
|
}
|