thread members

main
jerl 2024-05-05 00:47:42 -07:00
parent af690ebea9
commit e9f3b3f15a
5 changed files with 108 additions and 24 deletions

View File

@ -3,21 +3,36 @@ import loadMessages from '/message.js';
import loadSpace from '/space.js';
function chooseThread() {
if (window.threadId) {
if (window.threadId === this.thread.id)
if (window.currentThread) {
if (window.currentThread.id === this.thread.id)
return;
document.getElementById(`thread${window.threadId}`)
document.getElementById(`thread${window.currentThread.id}`)
.classList.remove('active');
}
document.getElementById('threadname').textContent = this.thread.name;
this.classList.add('active');
window.threadId = this.thread.id;
window.currentThread = this.thread;
loadMessages();
if (this.thread.permissions.post)
document.getElementById('msginput').classList.remove('hidden');
else
document.getElementById('msginput').classList.add('hidden');
switchTab(document.getElementById(this.tab));
window.emit('get_thread', { thread: this.thread.id }, msg => {
window.currentThread.members = msg.thread.members;
document.getElementById('visibility').innerText = `${
msg.thread.permissions.everyone?.view.value === 'true' ?
'this thread is visible to everyone' :
'members can view this thread'}
${msg.thread.permissions.everyone?.post.value === 'true' ?
'anyone can post' :
msg.thread.permissions.members?.post.view ?
'only members can post' : 'select members can post'}`;
document.getElementById('memberlist').replaceChildren(
...msg.thread.members.map(member =>
html.node`<p class='member'>${member.name}</p>`)
);
});
}
function switchTab(tab) {
@ -116,7 +131,7 @@ function newThread() {
window.threadmembers = [window.name];
document.getElementById('home')
.insertAdjacentElement('afterend', html.node`
<hr id='createseparator' class='separator' color='#666'>`)
<hr id='createseparator' class='separator' color='#505050'>`)
.insertAdjacentElement('afterend', html.node`
<form id='createthread' class='column' onsubmit=${createThread}>
<h3>create thread</h3>
@ -156,7 +171,7 @@ function newThread() {
function clickedTab(event) {
switchTab(event.target);
document.getElementById(`thread${window.threadId}`).tab = event.target.id;
document.getElementById(`thread${window.currentThread.id}`).tab = event.target.id;
}
// main app html
@ -172,12 +187,12 @@ document.body.append(html.node`
document.getElementById('profile').classList.toggle('hidden')
}>${window.name}</div>
</div>
<hr class='separator' color='#666'>
<hr class='separator' color='#505050'>
<div id='profile' class='column hidden'>
<p><strong>authentication requests</strong></p>
<div id='authrequests'></div>
</div>
<hr class='separator' color='#666'>
<hr class='separator' color='#505050'>
<div id='thread' class='column'>
<div id='content'>
<div id='title'>
@ -195,9 +210,10 @@ document.body.append(html.node`
<div id='message' class='tabcontent'></div>
<div id='space' class='tabcontent hidden'></div>
</div>
<hr class='separator' color='#666'>
<hr class='separator' color='#505050'>
<div id='members' class='hidden'>
<p id='visibility'></p>
<p><strong>members</strong></p>
<div id='memberlist'>
</div>
</div>
@ -220,10 +236,8 @@ window.socket.on('new_thread', thread => {
});
window.emit('list_threads', {}, msg => {
const threadlist = document.getElementById('threadlist')
threadlist.innerHTML = '';
for (let thread of msg.threads)
threadlist.appendChild(makeThread(thread));
const threadlist = document.getElementById('threadlist');
threadlist.replaceChildren(...msg.threads.map(makeThread));
chooseThread.call(threadlist.firstChild);
});

View File

@ -170,15 +170,11 @@
flex: 1;
overflow: auto;
}
#members {
flex: 1;
max-width: 250px;
}
#msginput {
display: flex;
flex-direction: row;
> * {
margin: 3px;
margin: 2px;
}
}
#msg {
@ -191,6 +187,16 @@
#loadmore {
margin-bottom: 10px;
}
#members {
flex: 1;
max-width: 250px;
> * {
margin: 4px;
}
}
#visibility {
white-space: pre-line;
}
.member {
margin: 5px 0;
}

View File

@ -8,7 +8,7 @@ function sendMessage(e) {
return;
window.emit('send_message', {
message: msg.value,
thread: window.threadId
thread: window.currentThread.id
});
msg.value = '';
}
@ -16,7 +16,7 @@ function sendMessage(e) {
let earliestMessage;
window.socket.on('new_message', message => {
if (message.thread !== window.threadId)
if (message.thread !== window.currentThread.id)
return;
const messages = document.getElementById('messages');
let scroll = messages.scrollHeight - messages.scrollTop <= messages.clientHeight;
@ -54,7 +54,7 @@ function loadMessages() {
'get_history',
{
before: earliestMessage,
thread: window.threadId
thread: window.currentThread.id
},
msg => {
if (!msg.success)

View File

@ -144,11 +144,11 @@ export default function loadSpace() {
editing.focus();
};
}
if (spaceId === window.threadId)
if (spaceId === window.window.currentThread.id)
return;
spaceId = window.threadId;
spaceId = window.window.currentThread.id;
space.innerHTML = '';
window.emit('get_space', { thread: window.threadId }, msg => {
window.emit('get_space', { thread: window.window.currentThread.id }, msg => {
if (!msg.success)
console.log('get space failed: ' + msg.message);
for (const span of msg.spans)

64
src/event/get_thread.js Normal file
View File

@ -0,0 +1,64 @@
const db = require('../db');
const authwrap = require('../authwrap');
const check_permission = require('../check_permission');
const get_thread = async (msg, respond) => {
if (!msg.thread) {
return respond({
success: false,
message: 'thread ID required'
});
}
if (!(await check_permission(msg.auth_user.id, msg.thread)).view) {
return respond({
success: false,
message: "you can't view this thread"
});
}
const thread = await db.query(
`select thread.name, user.name as user, user.id from thread
left join member on thread.id = member.thread
left join user on user.id = member.user
where thread.id = ?`,
[msg.thread]
);
const permissions = await db.query(
`select permission.type, permission.user, permission.permission, permission.value, permission.mutable
from thread
join permission on thread.id = permission.thread
where thread.id = ?`,
[msg.thread]
);
let threadperms = {};
let members = Object.fromEntries(thread.rows.map(member => [member.id, member.user]));
for (let permission of permissions.rows) {
const member = members[permission.user];
if (member) {
if (!member.permissions)
member.permissions = {};
member.permissions[permission.permission] = {
value: permission.value,
mutable: permission.mutable
};
}
else
(threadperms[permission.type] || (threadperms[permission.type] = {}))
[permission.permission] = {
value: permission.value,
mutable: permission.mutable
};
}
return respond({
success: true,
thread: {
name: thread.rows[0].name,
permissions: threadperms,
members: Object.entries(members).map(member => ({
id: member[0],
name: member[1]
}))
}
});
};
module.exports = authwrap(get_thread);