Browse Source

Update modtools component...

to accept jid and affiliation and to not use a Model to store state
JC Brand 4 years ago
parent
commit
106cde9262

+ 2 - 1
src/plugins/muc-views/modals/moderator-tools.js

@@ -7,7 +7,8 @@ const ModeratorToolsModal = BootstrapModal.extend({
     persistent: true,
 
     initialize (attrs) {
-        this.muc = attrs.muc;
+        this.jid = attrs.jid;
+        this.affiliation = attrs.affiliation;
         BootstrapModal.prototype.initialize.apply(this, arguments);
     },
 

+ 1 - 1
src/plugins/muc-views/modals/templates/moderator-tools.js

@@ -12,7 +12,7 @@ export default (o) => {
                     ${modal_header_close_button}
                 </div>
                 <div class="modal-body d-flex flex-column">
-                    <converse-modtools .muc=${o.muc} .model=${o.model}></converse-modtools>
+                    <converse-modtools jid=${o.jid} affiliation=${o.affiliation}></converse-modtools>
                 </div>
             </div>
         </div>`;

+ 48 - 26
src/plugins/muc-views/modtools.js

@@ -5,6 +5,7 @@ import { CustomElement } from 'shared/components/element.js';
 import { __ } from 'i18n';
 import { _converse, api, converse } from '@converse/headless/core';
 import { getAssignableRoles } from '@converse/headless/plugins/muc/utils.js';
+import { getOpenPromise } from '@converse/openpromise';
 import {
     getAffiliationList,
     getAssignableAffiliations,
@@ -16,11 +17,13 @@ const { Strophe, sizzle, u } = converse.env;
 export default class ModeratorTools extends CustomElement {
     static get properties () {
         return {
+            affiliation: { type: String },
             affiliations_filter: { type: String, attribute: false },
             alert_message: { type: String, attribute: false },
             alert_type: { type: String, attribute: false },
-            model: { type: Object },
-            muc: { type: Object },
+            jid: { type: String },
+            muc: { type: Object, attribute: false },
+            role: { type: String },
             roles_filter: { type: String, attribute: false },
             users_with_affiliation: { type: Array, attribute: false },
             users_with_role: { type: Array, attribute: false },
@@ -29,7 +32,9 @@ export default class ModeratorTools extends CustomElement {
 
     constructor () {
         super();
+        this.affiliation = '';
         this.affiliations_filter = '';
+        this.role = '';
         this.roles_filter = '';
     }
 
@@ -38,15 +43,24 @@ export default class ModeratorTools extends CustomElement {
         this.initialize();
     }
 
-    initialize () {
-        this.listenTo(this.model, 'change:role', this.onSearchRoleChange, this);
-        this.listenTo(this.model, 'change:affiliation', this.onSearchAffiliationChange, this);
+    updated (changed) {
+        changed.has('role') && this.onSearchRoleChange();
+        changed.has('affiliation') && this.onSearchAffiliationChange();
+        changed.has('jid') && changed.get('jid') && this.initialize();
+    }
+
+    async initialize () {
+        this.initialized = getOpenPromise();
+        const muc = await api.rooms.get(this.jid);
+        await muc.initialized;
+        this.muc = muc;
+        this.initialized.resolve();
     }
 
     render () {
-        const occupant = this.muc.occupants.findWhere({ 'jid': _converse.bare_jid });
-        return tpl_moderator_tools(
-            Object.assign(this.model.toJSON(), {
+        if (this.muc?.occupants) {
+            const occupant = this.muc.occupants.findWhere({ 'jid': _converse.bare_jid });
+            return tpl_moderator_tools({
                 'affiliations_filter': this.affiliations_filter,
                 'alert_message': this.alert_message,
                 'alert_type': this.alert_type,
@@ -67,18 +81,22 @@ export default class ModeratorTools extends CustomElement {
                 'users_with_affiliation': this.users_with_affiliation,
                 'users_with_role': this.users_with_role,
             })
-        );
+        } else {
+            return '';
+        }
     }
 
     async onSearchAffiliationChange () {
+        if (!this.affiliation) {
+            return;
+        }
+        await this.initialized;
         this.clearAlert();
         this.loading_users_with_affiliation = true;
         this.users_with_affiliation = null;
 
-        const affiliation = this.model.get('affiliation');
         if (this.shouldFetchAffiliationsList()) {
-            const muc_jid = this.muc.get('jid');
-            const result = await getAffiliationList(affiliation, muc_jid);
+            const result = await getAffiliationList(this.affiliation, this.jid);
             if (result instanceof Error) {
                 this.alert(result.message, 'danger');
                 this.users_with_affiliation = [];
@@ -86,18 +104,22 @@ export default class ModeratorTools extends CustomElement {
                 this.users_with_affiliation = result;
             }
         } else {
-            this.users_with_affiliation = this.muc.getOccupantsWithAffiliation(affiliation);
+            this.users_with_affiliation = this.muc.getOccupantsWithAffiliation(this.affiliation);
         }
         this.loading_users_with_affiliation = false;
     }
 
-    onSearchRoleChange () {
+    async onSearchRoleChange () {
+        if (!this.role) {
+            return;
+        }
+        await this.initialized;
         this.clearAlert();
-        this.users_with_role = this.muc.getOccupantsWithRole(this.model.get('role'));
+        this.users_with_role = this.muc.getOccupantsWithRole(this.role);
     }
 
     shouldFetchAffiliationsList () {
-        const affiliation = this.model.get('affiliation');
+        const affiliation = this.affiliation;
         if (affiliation === 'none') {
             return false;
         }
@@ -136,8 +158,8 @@ export default class ModeratorTools extends CustomElement {
         ev.preventDefault();
         const data = new FormData(ev.target);
         const role = data.get('role');
-        this.model.set({ 'role': null }, { 'silent': true });
-        this.model.set({ 'role': role });
+        this.role = null;
+        this.role = role;
     }
 
     queryAffiliation (ev) {
@@ -145,8 +167,8 @@ export default class ModeratorTools extends CustomElement {
         ev.preventDefault();
         const data = new FormData(ev.target);
         const affiliation = data.get('affiliation');
-        this.model.set({ 'affiliation': null }, { 'silent': true });
-        this.model.set({ 'affiliation': affiliation });
+        this.affiliation = null;
+        this.affiliation = affiliation;
     }
 
     alert (message, type) {
@@ -169,7 +191,7 @@ export default class ModeratorTools extends CustomElement {
             'jid': data.get('jid'),
             'reason': data.get('reason'),
         };
-        const current_affiliation = this.model.get('affiliation');
+        const current_affiliation = this.affiliation;
         const muc_jid = this.muc.get('jid');
         try {
             await setAffiliation(affiliation, muc_jid, [attrs]);
@@ -185,8 +207,8 @@ export default class ModeratorTools extends CustomElement {
             return;
         }
         await this.muc.occupants.fetchMembers();
-        this.model.set({ 'affiliation': null }, { 'silent': true });
-        this.model.set({ 'affiliation': current_affiliation });
+        this.affiliation = null;
+        this.affiliation = current_affiliation;
         this.alert(__('Affiliation changed'), 'primary');
     }
 
@@ -198,15 +220,15 @@ export default class ModeratorTools extends CustomElement {
         const occupant = this.muc.getOccupant(data.get('jid') || data.get('nick'));
         const role = data.get('role');
         const reason = data.get('reason');
-        const current_role = this.model.get('role');
+        const current_role = this.role;
         this.muc.setRole(
             occupant,
             role,
             reason,
             () => {
                 this.alert(__('Role changed'), 'primary');
-                this.model.set({ 'role': null }, { 'silent': true });
-                this.model.set({ 'role': current_role });
+                this.role = null;
+                this.role = current_role;
             },
             e => {
                 if (sizzle(`not-allowed[xmlns="${Strophe.NS.STANZAS}"]`, e).length) {

+ 5 - 2
src/plugins/muc-views/templates/moderator-tools.js

@@ -169,6 +169,8 @@ export default (o) => {
         ${ show_both_tabs ? tpl_navigation() : '' }
 
         <div class="tab-content">
+
+            ${ o.queryable_affiliations.length ? html`
             <div class="tab-pane tab-pane--columns ${ o.queryable_affiliations.length ? 'active' : ''}" id="affiliations-tabpanel" role="tabpanel" aria-labelledby="affiliations-tab">
                 <form class="converse-form query-affiliation" @submit=${o.queryAffiliation}>
                     <p class="helptext pb-3">${i18n_helptext_affiliation}</p>
@@ -208,8 +210,9 @@ export default (o) => {
                                 (o.users_with_affiliation || []).map(item => ((item.nick || item.jid).match(new RegExp(o.affiliations_filter, 'i')) ? affiliation_list_item(Object.assign({item}, o)) : '')) }
                     </ul>
                 </div>
-            </div>
+            </div>` : '' }
 
+            ${ o.queryable_roles.length ? html`
             <div class="tab-pane tab-pane--columns ${ !show_both_tabs && o.queryable_roles.length ? 'active' : ''}" id="roles-tabpanel" role="tabpanel" aria-labelledby="roles-tab">
                 <form class="converse-form query-role" @submit=${o.queryRole}>
                     <p class="helptext pb-3">${i18n_helptext_role}</p>
@@ -242,6 +245,6 @@ export default (o) => {
                         ${ (o.users_with_role || []).map(item => (item.nick.match(o.roles_filter) ? role_list_item(Object.assign({item}, o)) : '')) }
                     </ul>
                 </div>
-            </div>
+            </div>`: '' }
         </div>`;
 }

+ 11 - 11
src/plugins/muc-views/tests/modtools.js

@@ -47,6 +47,7 @@ describe("The groupchat moderator tool", function () {
         let button = modal.el.querySelector('.btn-primary[name="users_with_affiliation"]');
         button.click();
         await u.waitUntil(() => !modal.loading_users_with_affiliation);
+        await u.waitUntil(() => modal.el.querySelectorAll('.list-group--users > li').length);
         let user_els = modal.el.querySelectorAll('.list-group--users > li');
         expect(user_els.length).toBe(1);
         expect(user_els[0].querySelector('.list-group-item.active').textContent.trim()).toBe('JID: wiccarocks@shakespeare.lit');
@@ -57,6 +58,7 @@ describe("The groupchat moderator tool", function () {
         select.value = 'owner';
         button.click();
         await u.waitUntil(() => !modal.loading_users_with_affiliation);
+        await u.waitUntil(() => modal.el.querySelectorAll('.list-group--users > li').length === 2);
         user_els = modal.el.querySelectorAll('.list-group--users > li');
         expect(user_els.length).toBe(2);
         expect(user_els[0].querySelector('.list-group-item.active').textContent.trim()).toBe('JID: romeo@montague.lit');
@@ -113,6 +115,7 @@ describe("The groupchat moderator tool", function () {
         const alert = modal.el.querySelector('.alert-primary');
         expect(alert.textContent.trim()).toBe('Affiliation changed');
 
+        await u.waitUntil(() => modal.el.querySelectorAll('.list-group--users > li').length === 1);
         user_els = modal.el.querySelectorAll('.list-group--users > li');
         expect(user_els.length).toBe(1);
         expect(user_els[0].querySelector('.list-group-item.active').textContent.trim()).toBe('JID: romeo@montague.lit');
@@ -132,9 +135,8 @@ describe("The groupchat moderator tool", function () {
         select.value = 'participant';
         button.click();
         await u.waitUntil(() => !modal.loading_users_with_affiliation);
-        user_els = roles_panel.querySelectorAll('.list-group--users > li')
-        expect(user_els.length).toBe(1);
-        expect(user_els[0].textContent.trim()).toBe('No users with that role found.');
+        await u.waitUntil(() => roles_panel.querySelectorAll('.list-group--users > li')[0]?.textContent.trim() === 'No users with that role found.');
+
     }));
 
     it("allows you to filter affiliation search results",
@@ -162,8 +164,7 @@ describe("The groupchat moderator tool", function () {
         const button = modal.el.querySelector('.btn-primary[name="users_with_affiliation"]');
         button.click();
         await u.waitUntil(() => !modal.loading_users_with_affiliation);
-        const user_els = modal.el.querySelectorAll('.list-group--users > li');
-        expect(user_els.length).toBe(6);
+        await u.waitUntil(() => modal.el.querySelectorAll('.list-group--users > li').length === 6);
 
         const nicks = Array.from(modal.el.querySelectorAll('.list-group--users > li')).map(el => el.getAttribute('data-nick'));
         expect(nicks.join(' ')).toBe('gower juliet romeo thirdwitch wiccan witch');
@@ -273,8 +274,7 @@ describe("The groupchat moderator tool", function () {
         const button = modal.el.querySelector('.btn-primary[name="users_with_role"]');
         button.click();
         await u.waitUntil(() => !modal.loading_users_with_role);
-        const user_els = modal.el.querySelectorAll('.list-group--users > li');
-        expect(user_els.length).toBe(6);
+        await u.waitUntil(() => modal.el.querySelectorAll('.list-group--users > li').length === 6);
 
         const nicks = Array.from(modal.el.querySelectorAll('.list-group--users > li')).map(el => el.getAttribute('data-nick'));
         expect(nicks.join(' ')).toBe('crone newb nomorenicks oldhag some1 tux');
@@ -368,9 +368,9 @@ describe("The groupchat moderator tool", function () {
         const button = modal.el.querySelector('.btn-primary[name="users_with_affiliation"]');
         button.click();
         await u.waitUntil(() => !modal.loading_users_with_affiliation);
-        const user_els = modal.el.querySelectorAll('.list-group--users > li');
-        expect(user_els.length).toBe(1);
+        await u.waitUntil(() => modal.el.querySelectorAll('.list-group--users > li').length === 1);
 
+        const user_els = modal.el.querySelectorAll('.list-group--users > li');
         const toggle = user_els[0].querySelector('.list-group-item:nth-child(3n) .toggle-form');
         const form = user_els[0].querySelector('.list-group-item:nth-child(3n) .affiliation-form');
         expect(u.hasClass('hidden', form)).toBeTruthy();
@@ -432,9 +432,9 @@ describe("The groupchat moderator tool", function () {
         button.click();
 
         await u.waitUntil(() => !modal.loading_users_with_affiliation);
-        const user_els = modal.el.querySelectorAll('.list-group--users > li');
-        expect(user_els.length).toBe(2);
+        await u.waitUntil(() => modal.el.querySelectorAll('.list-group--users > li').length === 2);
 
+        const user_els = modal.el.querySelectorAll('.list-group--users > li');
         let change_affiliation_dropdown = user_els[0].querySelector('.select-affiliation');
         expect(Array.from(change_affiliation_dropdown.options).map(o => o.value)).toEqual(['member', 'outcast', 'none']);
 

+ 3 - 4
src/plugins/muc-views/utils.js

@@ -1,7 +1,6 @@
 import ModeratorToolsModal from './modals/moderator-tools.js';
 import log from "@converse/headless/log";
 import tpl_spinner from 'templates/spinner.js';
-import { Model } from '@converse/skeletor/src/model.js';
 import { __ } from 'i18n';
 import { _converse, api, converse } from "@converse/headless/core";
 import { html } from "lit";
@@ -284,10 +283,10 @@ export function showModeratorToolsModal (muc, affiliation) {
     }
     let modal = api.modal.get(ModeratorToolsModal.id);
     if (modal) {
-        modal.model.set({ affiliation });
+        modal.affiliation = affiliation;
+        modal.render();
     } else {
-        const model = new Model({ affiliation });
-        modal = api.modal.create(ModeratorToolsModal, { model, muc });
+        modal = api.modal.create(ModeratorToolsModal, { affiliation, 'jid': muc.get('jid') });
     }
     modal.show();
 }