Changeset 0.37.14 (#226)
Co-authored-by: gobha <jasafpro@gmail.com> Co-committed-by: gobha <jasafpro@gmail.com>
This commit is contained in:
104
src/js/sw/surfaces/chat/channel-members-panel.js
Normal file
104
src/js/sw/surfaces/chat/channel-members-panel.js
Normal file
@@ -0,0 +1,104 @@
|
||||
// ==========================================
|
||||
// Chat Surface — Channel Members Panel
|
||||
// ==========================================
|
||||
// Drawer showing channel participants with role management.
|
||||
// Uses Drawer primitive + channels.participants API.
|
||||
|
||||
import { Drawer } from '../../primitives/drawer.js';
|
||||
import { UserPicker } from '../../primitives/user-picker.js';
|
||||
|
||||
const { html } = window;
|
||||
const { useState, useEffect, useCallback } = hooks;
|
||||
|
||||
const ROLES = ['owner', 'member', 'observer'];
|
||||
|
||||
function _initials(name) {
|
||||
if (!name) return '?';
|
||||
return name.split(/\s+/).map(w => w[0]).join('').toUpperCase().slice(0, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ open: boolean, channelId: string, onClose: () => void }} props
|
||||
*/
|
||||
export function ChannelMembersPanel({ open, channelId, onClose }) {
|
||||
const [members, setMembers] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [adding, setAdding] = useState(false);
|
||||
|
||||
const load = useCallback(async () => {
|
||||
if (!channelId) return;
|
||||
setLoading(true);
|
||||
try {
|
||||
const data = await sw.api.channels.participants(channelId);
|
||||
setMembers(data || []);
|
||||
} catch (e) { sw.toast(e.message, 'error'); }
|
||||
finally { setLoading(false); }
|
||||
}, [channelId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (open && channelId) load();
|
||||
}, [open, channelId, load]);
|
||||
|
||||
async function updateRole(pid, role) {
|
||||
try {
|
||||
await sw.api.channels.updateParticipant(channelId, pid, { role });
|
||||
sw.toast('Role updated', 'success');
|
||||
load();
|
||||
} catch (e) { sw.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
async function remove(pid) {
|
||||
const ok = await sw.confirm('Remove this participant?', true);
|
||||
if (!ok) return;
|
||||
try {
|
||||
await sw.api.channels.removeParticipant(channelId, pid);
|
||||
sw.toast('Participant removed', 'success');
|
||||
load();
|
||||
} catch (e) { sw.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
const _onUserSelect = useCallback(async (user) => {
|
||||
setAdding(true);
|
||||
try {
|
||||
await sw.api.channels.addParticipant(channelId, {
|
||||
participant_type: 'user',
|
||||
participant_id: user.id,
|
||||
});
|
||||
sw.toast('Participant added', 'success');
|
||||
load();
|
||||
} catch (e) { sw.toast(e.message, 'error'); }
|
||||
finally { setAdding(false); }
|
||||
}, [channelId, load]);
|
||||
|
||||
if (!open) return null;
|
||||
|
||||
return html`
|
||||
<${Drawer} open=${open} side="right" width="340px" title="Members" onClose=${onClose}>
|
||||
${loading && !members.length
|
||||
? html`<div class="sw-panel-loading">Loading\u2026</div>`
|
||||
: html`
|
||||
<div class="sw-members-list">
|
||||
${members.map(m => html`
|
||||
<div class="sw-members-row" key=${m.id}>
|
||||
<span class="sw-members-avatar">${_initials(m.display_name || m.participant_id)}</span>
|
||||
<div class="sw-members-info">
|
||||
<span class="sw-members-name">${m.display_name || m.participant_id}</span>
|
||||
<span class="sw-members-type">${m.participant_type}</span>
|
||||
</div>
|
||||
<select class="sw-members-role" value=${m.role || 'member'}
|
||||
onChange=${e => updateRole(m.id, e.target.value)}>
|
||||
${ROLES.map(r => html`<option key=${r} value=${r}>${r}</option>`)}
|
||||
</select>
|
||||
<button class="sw-members-remove" onClick=${() => remove(m.id)}
|
||||
title="Remove">\u00d7</button>
|
||||
</div>`)}
|
||||
${members.length === 0 && html`
|
||||
<div class="sw-panel-empty">No participants</div>`}
|
||||
</div>
|
||||
<div class="sw-members-add">
|
||||
<${UserPicker}
|
||||
onSelect=${_onUserSelect}
|
||||
placeholder=${adding ? 'Adding\u2026' : 'Add participant\u2026'} />
|
||||
</div>`}
|
||||
<//>`;
|
||||
}
|
||||
Reference in New Issue
Block a user