diff --git a/public/src/admin/settings/activitypub.js b/public/src/admin/settings/activitypub.js index b364c9c194..652b1bcd3d 100644 --- a/public/src/admin/settings/activitypub.js +++ b/public/src/admin/settings/activitypub.js @@ -7,6 +7,8 @@ define('admin/settings/activitypub', [ 'api', 'alerts', 'translator', + + 'jquery-ui/widgets/sortable', ], function (Benchpress, bootbox, categorySelector, api, alerts, translator) { const ActivityPub = {}; @@ -106,30 +108,55 @@ define('admin/settings/activitypub', [ function setupRules() { const rulesEl = document.getElementById('rules'); - if (rulesEl) { - rulesEl.addEventListener('click', (e) => { - const subselector = e.target.closest('[data-action]'); - if (subselector) { - const action = subselector.getAttribute('data-action'); - switch (action) { - case 'rules.add': { - ActivityPub.throwRulesModal(); - break; - } + if (!rulesEl) { + return; + } - case 'rules.delete': { - const rid = subselector.closest('tr').getAttribute('data-rid'); - api.del(`/admin/activitypub/rules/${rid}`, {}).then(async (data) => { - const html = await Benchpress.render('admin/settings/activitypub', { rules: data }, 'rules'); - const tbodyEl = document.querySelector('#rules tbody'); - if (tbodyEl) { - tbodyEl.innerHTML = html; - } - }).catch(alerts.error); - } + rulesEl.addEventListener('click', (e) => { + const subselector = e.target.closest('[data-action]'); + if (subselector) { + const action = subselector.getAttribute('data-action'); + switch (action) { + case 'rules.add': { + ActivityPub.throwRulesModal(); + break; + } + + case 'rules.delete': { + const rid = subselector.closest('tr').getAttribute('data-rid'); + api.del(`/admin/activitypub/rules/${rid}`, {}).then(async (data) => { + const html = await Benchpress.render('admin/settings/activitypub', { rules: data }, 'rules'); + const tbodyEl = document.querySelector('#rules tbody'); + if (tbodyEl) { + tbodyEl.innerHTML = html; + } + }).catch(alerts.error); } } + } + }); + + const tbodyEl = $(rulesEl).find('tbody'); + tbodyEl.sortable({ + handle: '.drag-handle', + helper: fixWidthHelper, + placeholder: 'ui-state-highlight', + axis: 'y', + update: function () { + var rids = []; + tbodyEl.find('tr').each(function () { + rids.push($(this).data('rid')); + }); + + api.put('/admin/activitypub/rules/order', { rids }).catch(alerts.error); + }, + }); + + function fixWidthHelper(e, ui) { + ui.children().each(function () { + $(this).width($(this).width()); }); + return ui; } } diff --git a/src/activitypub/rules.js b/src/activitypub/rules.js index 9b3a002aab..656f03e2de 100644 --- a/src/activitypub/rules.js +++ b/src/activitypub/rules.js @@ -41,4 +41,12 @@ Rules.delete = async (rid) => { db.sortedSetRemove('categorization:rid', rid), db.delete(`rid:${rid}`), ]); +}; + +Rules.reorder = async (rids) => { + const exists = await db.isSortedSetMembers('categorization:rid', rids); + rids = rids.filter((_, idx) => exists[idx]); + const scores = Array.from({ length: rids.length }, (_, idx) => idx); + + await db.sortedSetAdd('categorization:rid', scores, rids); }; \ No newline at end of file diff --git a/src/controllers/write/admin.js b/src/controllers/write/admin.js index 8fc7151dc0..53662f6b34 100644 --- a/src/controllers/write/admin.js +++ b/src/controllers/write/admin.js @@ -104,6 +104,12 @@ Admin.activitypub.deleteRule = async (req, res) => { helpers.formatApiResponse(200, res, await activitypub.rules.list()); }; +Admin.activitypub.reorderRules = async (req, res) => { + const { rids } = req.body; + await activitypub.rules.reorder(rids); + helpers.formatApiResponse(200, res, await activitypub.rules.list()); +}; + Admin.activitypub.addRelay = async (req, res) => { const { url } = req.body; diff --git a/src/routes/write/admin.js b/src/routes/write/admin.js index 050e1ecf7a..2121953efe 100644 --- a/src/routes/write/admin.js +++ b/src/routes/write/admin.js @@ -27,6 +27,7 @@ module.exports = function () { setupApiRoute(router, 'post', '/activitypub/rules', [...middlewares, middleware.checkRequired.bind(null, ['cid', 'value', 'type'])], controllers.write.admin.activitypub.addRule); setupApiRoute(router, 'delete', '/activitypub/rules/:rid', [...middlewares], controllers.write.admin.activitypub.deleteRule); + setupApiRoute(router, 'put', '/activitypub/rules/order', [...middlewares, middleware.checkRequired.bind(null, ['rids'])], controllers.write.admin.activitypub.reorderRules); setupApiRoute(router, 'post', '/activitypub/relays', [...middlewares, middleware.checkRequired.bind(null, ['url'])], controllers.write.admin.activitypub.addRelay); setupApiRoute(router, 'delete', '/activitypub/relays/:url', [...middlewares], controllers.write.admin.activitypub.removeRelay); diff --git a/src/views/admin/settings/activitypub.tpl b/src/views/admin/settings/activitypub.tpl index 9a7e3493bf..130e4ca8fc 100644 --- a/src/views/admin/settings/activitypub.tpl +++ b/src/views/admin/settings/activitypub.tpl @@ -51,14 +51,18 @@

[[admin/settings/activitypub:rules-intro]]

+ - + {{{ each rules }}} +
[[admin/settings/activitypub:rules.type]] [[admin/settings/activitypub:rules.value]] [[admin/settings/activitypub:rules.cid]]
+ + {./type} {./value} {./cid}