diff --git a/src/index.js b/src/index.js index 17abb8f..8e57f2a 100644 --- a/src/index.js +++ b/src/index.js @@ -107,6 +107,7 @@ const SCOPES = [ 'threads_read_replies', 'threads_keyword_search', 'threads_manage_mentions', + 'threads_delete', ]; app.use(express.static('public')); @@ -634,6 +635,30 @@ app.get('/threads/:threadId/replies', loggedInUserChecker, (req, res) => { showReplies(req, res, true); }); +app.post('/threads/delete', loggedInUserChecker, (req, res) => { + const { thread_ids } = req.body; + const threadIds = Array.isArray(thread_ids) ? thread_ids : [thread_ids]; + + const deletePromises = threadIds.map(threadId => { + if (threadId) { + const deleteThreadUrl = buildGraphAPIURL(`${threadId}`, {}, req.session.access_token); + return axios.delete(deleteThreadUrl, { httpsAgent: agent }); + } + }).filter(Boolean); + + Promise.all(deletePromises) + .then(() => { + res.redirect('/threads'); + }) + .catch((e) => { + console.error(e?.response?.data?.error?.message ?? e.message); + res.json({ + error: true, + message: `Error deleting thread(s): ${e}`, + }); + }); +}); + app.get('/threads/:threadId/conversation', loggedInUserChecker, (req, res) => { showReplies(req, res, false); }); diff --git a/views/thread_replies.pug b/views/thread_replies.pug index ab77407..36d3e85 100644 --- a/views/thread_replies.pug +++ b/views/thread_replies.pug @@ -7,4 +7,14 @@ block content block scripts script(src='/scripts/form.js' type='text/javascript') - script(src='/scripts/hide-reply.js', type='text/javascript') + script(src='/scripts/hide-reply.js' type='text/javascript') + script. + const selectAllCheckbox = document.getElementById('select-all-replies'); + if (selectAllCheckbox) { + selectAllCheckbox.addEventListener('change', function (e) { + const checkboxes = document.querySelectorAll('.reply-checkbox'); + checkboxes.forEach(checkbox => { + checkbox.checked = e.target.checked; + }); + }); + } diff --git a/views/thread_replies_layout.pug b/views/thread_replies_layout.pug index 2ff4596..78435fa 100644 --- a/views/thread_replies_layout.pug +++ b/views/thread_replies_layout.pug @@ -31,6 +31,83 @@ table.thread-replies +div.paging + if paging.nextUrl + div.paging-next + a(href=paging.nextUrl) Next + + if paging.previousUrl + div.paging-previous + a(href=paging.previousUrl) Previous + +if manage + form(action='/threads/replies/delete' method='POST') + input(type='hidden' name='threadId' value=threadId) + table.thread-replies + thead + tr + th + input(type='checkbox' id='select-all-replies') + th ID + th Created On + th Media Type + th Text + th Permalink + th Manage + th Reply + tbody + each reply in replies + tr.thread-replies-list-item + td + input(type='checkbox' name='reply_ids' value=reply.id class='reply-checkbox') + td.reply-id + a(href=`/threads/${reply.id}`)=reply.id + td.reply-timestamp=reply.timestamp + td.reply-type=reply.media_type + td.reply-text=reply.text + td.reply-permalink + a(href=reply.permalink target='_blank') View on Threads + td.manage-reply + if username !== reply.username + form.hide-reply(action=`/manage_reply/${reply.id}?hide=${reply.hide_status!=='HIDDEN'}&username=${username}`, method='POST') + input(type='submit', value=`${reply.hide_status==='HIDDEN' ? 'Unhide' : 'Hide'}`) + else + p(title='Cannot hide your own replies.') ⓘ + td + button(onclick=`location.href='/upload?replyToId=${reply.id}'`) Reply + button.delete-button(type='submit') Delete Selected +else + table.thread-replies + thead + tr + th ID + th Created On + th Media Type + th Text + th Permalink + th Manage + th Reply + tbody + each reply in replies + tr.thread-replies-list-item + td.reply-id + a(href=`/threads/${reply.id}`)=reply.id + td.reply-timestamp=reply.timestamp + td.reply-type=reply.media_type + td.reply-text=reply.text + td.reply-permalink + a(href=reply.permalink target='_blank') View on Threads + td.manage-reply + if username !== reply.username + form.hide-reply(action=`/manage_reply/${reply.id}?hide=${reply.hide_status!=='HIDDEN'}&username=${username}`, method='POST') + input(type='submit', value=`${reply.hide_status==='HIDDEN' ? 'Unhide' : 'Hide'}`) + else + p(title='Cannot hide your own replies.') ⓘ + td + button(onclick=`location.href='/upload?replyToId=${reply.id}'`) Reply + + + div.paging if paging.nextUrl div.paging-next diff --git a/views/threads.pug b/views/threads.pug index bb6b596..5c35f1c 100644 --- a/views/threads.pug +++ b/views/threads.pug @@ -1,26 +1,33 @@ extends layout_with_account block content - table.threads-list - thead - tr - th ID - th Created On - th Media Type - th Text - th Permalink - th Reply Audience - tbody - each thread in threads - tr.threads-list-item - td.thread-id - a(href=`/threads/${thread.id}`)=thread.id - td.thread-timestamp=thread.timestamp - td.thread-type=thread.media_type - td.thread-text=thread.text - td.thread-permalink - a(href=thread.permalink target='_blank') View on Threads - td.thread-reply-audience=thread.reply_audience + form(action='/threads/delete' method='POST') + table.threads-list + thead + tr + th + input(type='checkbox' id='select-all') + th ID + th Created On! + th Media Type + th Text + th Permalink + th Reply Audience + tbody + each thread in threads + tr.threads-list-item + td + input(type='checkbox' name='thread_ids' value=thread.id class='thread-checkbox') + td.thread-id + a(href=`/threads/${thread.id}`)=thread.id + td.thread-timestamp=thread.timestamp + td.thread-type=thread.media_type + td.thread-text=thread.text + td.thread-permalink + a(href=thread.permalink target='_blank') View on Threads + td.thread-reply-audience=thread.reply_audience + + button.delete-button(type='submit') Delete Selected div.paging if paging.nextUrl @@ -30,3 +37,11 @@ block content if paging.previousUrl div.paging-previous a(href=paging.previousUrl) Previous + + script. + document.getElementById('select-all').addEventListener('change', function (e) { + const checkboxes = document.querySelectorAll('.thread-checkbox'); + checkboxes.forEach(checkbox => { + checkbox.checked = e.target.checked; + }); + });