mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-02-27 17:11:14 +01:00
refactor: ActivityPub ACP page to its own top-level section with sub-pages
This commit is contained in:
@@ -48,6 +48,13 @@
|
||||
|
||||
"settings.page-title": "%1 Settings",
|
||||
|
||||
"section-federation": "Federation",
|
||||
"federation/general": "General",
|
||||
"federation/rules": "Categorization",
|
||||
"federation/relays": "Relays",
|
||||
"federation/pruning": "Content Pruning",
|
||||
"federation/safety": "Trust & Safety",
|
||||
|
||||
"section-appearance": "Appearance",
|
||||
"appearance/themes": "Themes",
|
||||
"appearance/skins": "Skins",
|
||||
|
||||
70
public/src/admin/federation/relays.js
Normal file
70
public/src/admin/federation/relays.js
Normal file
@@ -0,0 +1,70 @@
|
||||
'use strict';
|
||||
|
||||
import { post, del } from 'api';
|
||||
import { error } from 'alerts';
|
||||
import { render } from 'benchpress';
|
||||
|
||||
export function init() {
|
||||
setupRelays();
|
||||
};
|
||||
|
||||
function setupRelays() {
|
||||
const relaysEl = document.getElementById('relays');
|
||||
if (relaysEl) {
|
||||
relaysEl.addEventListener('click', (e) => {
|
||||
const subselector = e.target.closest('[data-action]');
|
||||
if (subselector) {
|
||||
const action = subselector.getAttribute('data-action');
|
||||
switch (action) {
|
||||
case 'relays.add': {
|
||||
throwModal();
|
||||
break;
|
||||
}
|
||||
|
||||
case 'relays.remove': {
|
||||
const url = subselector.closest('tr').getAttribute('data-url');
|
||||
del(`/admin/activitypub/relays/${encodeURIComponent(url)}`, {}).then(async (data) => {
|
||||
const html = await app.parseAndTranslate('admin/settings/activitypub', 'relays', { relays: data });
|
||||
const tbodyEl = document.querySelector('#relays tbody');
|
||||
if (tbodyEl) {
|
||||
$(tbodyEl).html(html);
|
||||
}
|
||||
}).catch(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function throwModal() {
|
||||
render('admin/partials/activitypub/relays', {}).then(function (html) {
|
||||
const submit = function () {
|
||||
const formEl = modal.find('form').get(0);
|
||||
const payload = Object.fromEntries(new FormData(formEl));
|
||||
|
||||
post('/admin/activitypub/relays', payload).then(async (data) => {
|
||||
const html = await app.parseAndTranslate('admin/settings/activitypub', 'relays', { relays: data });
|
||||
const tbodyEl = document.querySelector('#relays tbody');
|
||||
if (tbodyEl) {
|
||||
$(tbodyEl).html(html);
|
||||
}
|
||||
}).catch(error);
|
||||
};
|
||||
const modal = bootbox.dialog({
|
||||
title: '[[admin/settings/activitypub:relays.add]]',
|
||||
message: html,
|
||||
buttons: {
|
||||
save: {
|
||||
label: '[[global:save]]',
|
||||
className: 'btn-primary',
|
||||
callback: submit,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
modal.on('shown.bs.modal', function () {
|
||||
modal.find('input').focus();
|
||||
});
|
||||
});
|
||||
}
|
||||
122
public/src/admin/federation/rules.js
Normal file
122
public/src/admin/federation/rules.js
Normal file
@@ -0,0 +1,122 @@
|
||||
'use strict';
|
||||
|
||||
import { post, del, put } from 'api';
|
||||
import { error } from 'alerts';
|
||||
import { render } from 'benchpress';
|
||||
import { translate } from 'translator';
|
||||
import * as categorySelector from 'categorySelector';
|
||||
|
||||
export function init() {
|
||||
setupRules();
|
||||
};
|
||||
|
||||
function setupRules() {
|
||||
const rulesEl = document.getElementById('rules');
|
||||
if (!rulesEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
rulesEl.addEventListener('click', (e) => {
|
||||
const subselector = e.target.closest('[data-action]');
|
||||
if (subselector) {
|
||||
const action = subselector.getAttribute('data-action');
|
||||
switch (action) {
|
||||
case 'rules.add': {
|
||||
throwModal();
|
||||
break;
|
||||
}
|
||||
|
||||
case 'rules.delete': {
|
||||
const rid = subselector.closest('tr').getAttribute('data-rid');
|
||||
del(`/admin/activitypub/rules/${rid}`, {}).then(async (data) => {
|
||||
const html = await render('admin/settings/activitypub', { rules: data }, 'rules');
|
||||
const tbodyEl = document.querySelector('#rules tbody');
|
||||
if (tbodyEl) {
|
||||
tbodyEl.innerHTML = html;
|
||||
}
|
||||
}).catch(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const tbodyEl = $(rulesEl).find('tbody');
|
||||
tbodyEl.sortable({
|
||||
handle: '.drag-handle',
|
||||
helper: fixWidthHelper,
|
||||
placeholder: 'ui-state-highlight',
|
||||
axis: 'y',
|
||||
update: function () {
|
||||
const rids = [];
|
||||
tbodyEl.find('tr').each(function () {
|
||||
rids.push($(this).data('rid'));
|
||||
});
|
||||
|
||||
put('/admin/activitypub/rules/order', { rids }).catch(error);
|
||||
},
|
||||
});
|
||||
|
||||
function fixWidthHelper(e, ui) {
|
||||
ui.children().each(function () {
|
||||
$(this).width($(this).width());
|
||||
});
|
||||
return ui;
|
||||
}
|
||||
}
|
||||
|
||||
function throwModal() {
|
||||
render('admin/partials/activitypub/rules', {}).then(function (html) {
|
||||
const submit = function () {
|
||||
const formEl = modal.find('form').get(0);
|
||||
const payload = Object.fromEntries(new FormData(formEl));
|
||||
|
||||
post('/admin/activitypub/rules', payload).then(async (data) => {
|
||||
const html = await render('admin/settings/activitypub', { rules: data }, 'rules');
|
||||
const tbodyEl = document.querySelector('#rules tbody');
|
||||
if (tbodyEl) {
|
||||
tbodyEl.innerHTML = html;
|
||||
}
|
||||
}).catch(error);
|
||||
};
|
||||
const modal = bootbox.dialog({
|
||||
title: '[[admin/settings/activitypub:rules.add]]',
|
||||
message: html,
|
||||
buttons: {
|
||||
save: {
|
||||
label: '[[global:save]]',
|
||||
className: 'btn-primary',
|
||||
callback: submit,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
modal.on('shown.bs.modal', function () {
|
||||
modal.find('input').focus();
|
||||
});
|
||||
|
||||
|
||||
// help text
|
||||
const updateHelp = async (key, el) => {
|
||||
const text = await translate(`[[admin/settings/activitypub:rules.help-${key}]]`);
|
||||
el.innerHTML = text;
|
||||
};
|
||||
const helpTextEl = modal.get(0).querySelector('#help-text');
|
||||
const typeEl = modal.get(0).querySelector('#type');
|
||||
updateHelp(modal.get(0).querySelector('#type option').value, helpTextEl);
|
||||
if (typeEl && helpTextEl) {
|
||||
typeEl.addEventListener('change', function () {
|
||||
updateHelp(this.value, helpTextEl);
|
||||
});
|
||||
}
|
||||
|
||||
// category switcher
|
||||
categorySelector.init(modal.find('[component="category-selector"]'), {
|
||||
onSelect: function (selectedCategory) {
|
||||
modal.find('[name="cid"]').val(selectedCategory.cid);
|
||||
},
|
||||
cacheList: false,
|
||||
showLinks: true,
|
||||
template: 'admin/partials/category/selector-dropdown-right',
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
define('admin/settings/activitypub', [
|
||||
'benchpress',
|
||||
'bootbox',
|
||||
'categorySelector',
|
||||
'api',
|
||||
'alerts',
|
||||
'translator',
|
||||
|
||||
'jquery-ui/widgets/sortable',
|
||||
], function (Benchpress, bootbox, categorySelector, api, alerts, translator) {
|
||||
const ActivityPub = {};
|
||||
|
||||
ActivityPub.init = function () {
|
||||
setupRules();
|
||||
setupRelays();
|
||||
};
|
||||
|
||||
ActivityPub.throwRulesModal = function () {
|
||||
Benchpress.render('admin/partials/activitypub/rules', {}).then(function (html) {
|
||||
const submit = function () {
|
||||
const formEl = modal.find('form').get(0);
|
||||
const payload = Object.fromEntries(new FormData(formEl));
|
||||
|
||||
api.post('/admin/activitypub/rules', payload).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 modal = bootbox.dialog({
|
||||
title: '[[admin/settings/activitypub:rules.add]]',
|
||||
message: html,
|
||||
buttons: {
|
||||
save: {
|
||||
label: '[[global:save]]',
|
||||
className: 'btn-primary',
|
||||
callback: submit,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
modal.on('shown.bs.modal', function () {
|
||||
modal.find('input').focus();
|
||||
});
|
||||
|
||||
|
||||
// help text
|
||||
const updateHelp = async (key, el) => {
|
||||
const text = await translator.translate(`[[admin/settings/activitypub:rules.help-${key}]]`);
|
||||
el.innerHTML = text;
|
||||
};
|
||||
const helpTextEl = modal.get(0).querySelector('#help-text');
|
||||
const typeEl = modal.get(0).querySelector('#type');
|
||||
updateHelp(modal.get(0).querySelector('#type option').value, helpTextEl);
|
||||
if (typeEl && helpTextEl) {
|
||||
typeEl.addEventListener('change', function () {
|
||||
updateHelp(this.value, helpTextEl);
|
||||
});
|
||||
}
|
||||
|
||||
// category switcher
|
||||
categorySelector.init(modal.find('[component="category-selector"]'), {
|
||||
onSelect: function (selectedCategory) {
|
||||
modal.find('[name="cid"]').val(selectedCategory.cid);
|
||||
},
|
||||
cacheList: false,
|
||||
showLinks: true,
|
||||
template: 'admin/partials/category/selector-dropdown-right',
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
ActivityPub.throwRelaysModal = function () {
|
||||
Benchpress.render('admin/partials/activitypub/relays', {}).then(function (html) {
|
||||
const submit = function () {
|
||||
const formEl = modal.find('form').get(0);
|
||||
const payload = Object.fromEntries(new FormData(formEl));
|
||||
|
||||
api.post('/admin/activitypub/relays', payload).then(async (data) => {
|
||||
const html = await app.parseAndTranslate('admin/settings/activitypub', 'relays', { relays: data });
|
||||
const tbodyEl = document.querySelector('#relays tbody');
|
||||
if (tbodyEl) {
|
||||
$(tbodyEl).html(html);
|
||||
}
|
||||
}).catch(alerts.error);
|
||||
};
|
||||
const modal = bootbox.dialog({
|
||||
title: '[[admin/settings/activitypub:relays.add]]',
|
||||
message: html,
|
||||
buttons: {
|
||||
save: {
|
||||
label: '[[global:save]]',
|
||||
className: 'btn-primary',
|
||||
callback: submit,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
modal.on('shown.bs.modal', function () {
|
||||
modal.find('input').focus();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function setupRules() {
|
||||
const rulesEl = document.getElementById('rules');
|
||||
if (!rulesEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
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 () {
|
||||
const 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;
|
||||
}
|
||||
}
|
||||
|
||||
function setupRelays() {
|
||||
const relaysEl = document.getElementById('relays');
|
||||
if (relaysEl) {
|
||||
relaysEl.addEventListener('click', (e) => {
|
||||
const subselector = e.target.closest('[data-action]');
|
||||
if (subselector) {
|
||||
const action = subselector.getAttribute('data-action');
|
||||
switch (action) {
|
||||
case 'relays.add': {
|
||||
ActivityPub.throwRelaysModal();
|
||||
break;
|
||||
}
|
||||
|
||||
case 'relays.remove': {
|
||||
const url = subselector.closest('tr').getAttribute('data-url');
|
||||
api.del(`/admin/activitypub/relays/${encodeURIComponent(url)}`, {}).then(async (data) => {
|
||||
const html = await app.parseAndTranslate('admin/settings/activitypub', 'relays', { relays: data });
|
||||
const tbodyEl = document.querySelector('#relays tbody');
|
||||
if (tbodyEl) {
|
||||
$(tbodyEl).html(html);
|
||||
}
|
||||
}).catch(alerts.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return ActivityPub;
|
||||
});
|
||||
@@ -14,6 +14,7 @@ const adminController = {
|
||||
groups: require('./admin/groups'),
|
||||
digest: require('./admin/digest'),
|
||||
appearance: require('./admin/appearance'),
|
||||
federation: require('./admin/federation'),
|
||||
extend: {
|
||||
widgets: require('./admin/widgets'),
|
||||
rewards: require('./admin/rewards'),
|
||||
|
||||
43
src/controllers/admin/federation.js
Normal file
43
src/controllers/admin/federation.js
Normal file
@@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
const activitypub = require('../../activitypub');
|
||||
|
||||
const federationController = module.exports;
|
||||
|
||||
federationController.general = function (req, res) {
|
||||
res.render(`admin/federation/general`, {
|
||||
title: '[[admin/menu:federation/general]]',
|
||||
});
|
||||
};
|
||||
|
||||
federationController.rules = async function (req, res) {
|
||||
const rules = await activitypub.rules.list();
|
||||
|
||||
res.render(`admin/federation/rules`, {
|
||||
title: '[[admin/menu:federation/rules]]',
|
||||
rules,
|
||||
hideSave: true,
|
||||
});
|
||||
};
|
||||
|
||||
federationController.relays = async function (req, res) {
|
||||
const relays = await activitypub.relays.list();
|
||||
|
||||
res.render(`admin/federation/relays`, {
|
||||
title: '[[admin/menu:federation/relays]]',
|
||||
relays,
|
||||
hideSave: true,
|
||||
});
|
||||
};
|
||||
|
||||
federationController.pruning = function (req, res) {
|
||||
res.render(`admin/federation/pruning`, {
|
||||
title: '[[admin/menu:federation/pruning]]',
|
||||
});
|
||||
};
|
||||
|
||||
federationController.safety = function (req, res) {
|
||||
res.render(`admin/federation/safety`, {
|
||||
title: '[[admin/menu:federation/safety]]',
|
||||
});
|
||||
};
|
||||
@@ -52,6 +52,12 @@ module.exports = function (app, name, middleware, controllers) {
|
||||
helpers.setupAdminPageRoute(app, `/${name}/settings/web-crawler`, middlewares, controllers.admin.settings.webCrawler);
|
||||
helpers.setupAdminPageRoute(app, `/${name}/settings/advanced`, middlewares, controllers.admin.settings.advanced);
|
||||
|
||||
helpers.setupAdminPageRoute(app, `/${name}/federation/general`, middlewares, controllers.admin.federation.general);
|
||||
helpers.setupAdminPageRoute(app, `/${name}/federation/rules`, middlewares, controllers.admin.federation.rules);
|
||||
helpers.setupAdminPageRoute(app, `/${name}/federation/relays`, middlewares, controllers.admin.federation.relays);
|
||||
helpers.setupAdminPageRoute(app, `/${name}/federation/pruning`, middlewares, controllers.admin.federation.pruning);
|
||||
helpers.setupAdminPageRoute(app, `/${name}/federation/safety`, middlewares, controllers.admin.federation.safety);
|
||||
|
||||
helpers.setupAdminPageRoute(app, `/${name}/appearance/themes`, middlewares, controllers.admin.appearance.themes);
|
||||
helpers.setupAdminPageRoute(app, `/${name}/appearance/skins`, middlewares, controllers.admin.appearance.skins);
|
||||
helpers.setupAdminPageRoute(app, `/${name}/appearance/customise`, middlewares, controllers.admin.appearance.customise);
|
||||
|
||||
49
src/views/admin/federation/general.tpl
Normal file
49
src/views/admin/federation/general.tpl
Normal file
@@ -0,0 +1,49 @@
|
||||
<div class="acp-page-container">
|
||||
<!-- IMPORT admin/partials/settings/header.tpl -->
|
||||
|
||||
<div class="row settings m-0">
|
||||
<div id="spy-container" class="col-12 col-md-8 px-0 mb-4" tabindex="0">
|
||||
|
||||
<p class="lead">[[admin/settings/activitypub:intro-lead]]</p>
|
||||
<p>[[admin/settings/activitypub:intro-body]]</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<div id="general" class="mb-4">
|
||||
<h5 class="fw-bold tracking-tight settings-header">[[admin/settings/activitypub:general]]</h5>
|
||||
<form>
|
||||
<div class="form-check form-switch mb-3">
|
||||
<input class="form-check-input" type="checkbox" data-field="activitypubEnabled">
|
||||
<label class="form-check-label">[[admin/settings/activitypub:enabled]]</label>
|
||||
<p class="form-text">[[admin/settings/activitypub:enabled-help]]</p>
|
||||
</div>
|
||||
<div class="form-check form-switch mb-3">
|
||||
<input class="form-check-input" type="checkbox" data-field="activitypubAllowLoopback">
|
||||
<label class="form-check-label">[[admin/settings/activitypub:allowLoopback]]</label>
|
||||
<p class="form-text">[[admin/settings/activitypub:allowLoopback-help]]</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="probe" class="mb-4">
|
||||
<h5 class="fw-bold tracking-tight settings-header">[[admin/settings/activitypub:probe]]</h5>
|
||||
<form>
|
||||
<div class="form-check form-switch mb-3">
|
||||
<input class="form-check-input" type="checkbox" data-field="activitypubProbe">
|
||||
<label class="form-check-label">[[admin/settings/activitypub:probe-enabled]]</label>
|
||||
<p class="form-text">[[admin/settings/activitypub:probe-enabled-help]]</p>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="activitypubProbeTimeout">[[admin/settings/activitypub:probe-timeout]]</label>
|
||||
<input type="number" id="activitypubProbeTimeout" name="activitypubProbeTimeout" data-field="activitypubProbeTimeout" title="[[admin/settings/activitypub:probe-timeout]]" class="form-control" />
|
||||
<div class="form-text">
|
||||
[[admin/settings/activitypub:probe-timeout-help]]
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- IMPORT admin/partials/settings/toc.tpl -->
|
||||
</div>
|
||||
</div>
|
||||
28
src/views/admin/federation/pruning.tpl
Normal file
28
src/views/admin/federation/pruning.tpl
Normal file
@@ -0,0 +1,28 @@
|
||||
<div class="acp-page-container">
|
||||
<!-- IMPORT admin/partials/settings/header.tpl -->
|
||||
|
||||
<div class="row settings m-0">
|
||||
<div id="spy-container" class="col-12 col-md-8 px-0 mb-4" tabindex="0">
|
||||
<div id="pruning" class="mb-4">
|
||||
<form>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="activitypubContentPruneDays">[[admin/settings/activitypub:content-pruning]]</label>
|
||||
<input type="number" id="activitypubContentPruneDays" name="activitypubContentPruneDays" data-field="activitypubContentPruneDays" title="[[admin/settings/activitypub:content-pruning]]" class="form-control" />
|
||||
<div class="form-text">
|
||||
[[admin/settings/activitypub:content-pruning-help]]
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="activitypubUserPruneDays">[[admin/settings/activitypub:user-pruning]]</label>
|
||||
<input type="number" id="activitypubUserPruneDays" name="activitypubUserPruneDays" data-field="activitypubUserPruneDays" title="[[admin/settings/activitypub:user-pruning]]" class="form-control" />
|
||||
<div class="form-text">
|
||||
[[admin/settings/activitypub:user-pruning-help]]
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- IMPORT admin/partials/settings/toc.tpl -->
|
||||
</div>
|
||||
</div>
|
||||
39
src/views/admin/federation/relays.tpl
Normal file
39
src/views/admin/federation/relays.tpl
Normal file
@@ -0,0 +1,39 @@
|
||||
<div class="acp-page-container">
|
||||
<!-- IMPORT admin/partials/settings/header.tpl -->
|
||||
|
||||
<div class="row settings m-0">
|
||||
<div id="spy-container" class="col-12 col-md-8 px-0 mb-4" tabindex="0">
|
||||
<div id="relays" class="mb-4">
|
||||
<p class="lead">[[admin/settings/activitypub:relays.intro]]</p>
|
||||
<p class="text-warning">[[admin/settings/activitypub:relays.warning]]</p>
|
||||
<div class="mb-3">
|
||||
<table class="table table-striped" id="relays">
|
||||
<thead>
|
||||
<th>[[admin/settings/activitypub:relays.relay]]</th>
|
||||
<th>[[admin/settings/activitypub:relays.state]]</th>
|
||||
<th></th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{{ each relays }}}
|
||||
<tr data-url="{./url}">
|
||||
<td>{./url}</td>
|
||||
<td>{./label}</td>
|
||||
<td><a href="#" data-action="relays.remove"><i class="fa fa-trash link-danger"></i></a></td>
|
||||
</tr>
|
||||
{{{ end }}}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<button class="btn btn-sm btn-primary" data-action="relays.add">[[admin/settings/activitypub:relays.add]]</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- IMPORT admin/partials/settings/toc.tpl -->
|
||||
</div>
|
||||
</div>
|
||||
45
src/views/admin/federation/rules.tpl
Normal file
45
src/views/admin/federation/rules.tpl
Normal file
@@ -0,0 +1,45 @@
|
||||
<div class="acp-page-container">
|
||||
<!-- IMPORT admin/partials/settings/header.tpl -->
|
||||
|
||||
<div class="row settings m-0">
|
||||
<div id="spy-container" class="col-12 col-md-8 px-0 mb-4" tabindex="0">
|
||||
<div id="rules" class="mb-4">
|
||||
<p class="lead">[[admin/settings/activitypub:rules-intro]]</p>
|
||||
|
||||
<div class="mb-3">
|
||||
<table class="table table-striped" id="rules">
|
||||
<thead>
|
||||
<th></th>
|
||||
<th>[[admin/settings/activitypub:rules.type]]</th>
|
||||
<th>[[admin/settings/activitypub:rules.value]]</th>
|
||||
<th>[[admin/settings/activitypub:rules.cid]]</th>
|
||||
<th></th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{{ each rules }}}
|
||||
<tr data-rid="{./rid}">
|
||||
<td class="align-items-center" style="cursor: move;">
|
||||
<i class="fa fa-grip-lines text-muted drag-handle"></i>
|
||||
</td>
|
||||
<td>{./type}</td>
|
||||
<td>{./value}</td>
|
||||
<td>{./cid}</td>
|
||||
<td><a href="#" data-action="rules.delete"><i class="fa fa-trash link-danger"></i></a></td>
|
||||
</tr>
|
||||
{{{ end }}}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<button class="btn btn-sm btn-primary" data-action="rules.add">[[admin/settings/activitypub:rules.add]]</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- IMPORT admin/partials/settings/toc.tpl -->
|
||||
</div>
|
||||
</div>
|
||||
26
src/views/admin/federation/safety.tpl
Normal file
26
src/views/admin/federation/safety.tpl
Normal file
@@ -0,0 +1,26 @@
|
||||
<div class="acp-page-container">
|
||||
<!-- IMPORT admin/partials/settings/header.tpl -->
|
||||
|
||||
<div class="row settings m-0">
|
||||
<div id="spy-container" class="col-12 col-md-8 px-0 mb-4" tabindex="0">
|
||||
<div id="server-filtering" class="mb-4">
|
||||
<h5 class="fw-bold tracking-tight settings-header">[[admin/settings/activitypub:server-filtering]]</h5>
|
||||
<form>
|
||||
<div class="mb-3">
|
||||
<p>[[admin/settings/activitypub:server.filter-help]]</p>
|
||||
<p>[[admin/settings/activitypub:server.filter-help-hostname]]</p>
|
||||
<p>[[admin/settings/activitypub:count, {instanceCount}]]</p>
|
||||
<label for="activitypubFilterList" class="form-label">Filtering list</label>
|
||||
<textarea class="form-control" id="activitypubFilterList" data-field="activitypubFilterList" rows="10"></textarea>
|
||||
</div>
|
||||
<div class="form-check form-switch mb-3">
|
||||
<input class="form-check-input" type="checkbox" id="activitypubFilter" data-field="activitypubFilter" />
|
||||
<label class="form-check-label" for="activitypubFilter">[[admin/settings/activitypub:server.filter-allow-list]]</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- IMPORT admin/partials/settings/toc.tpl -->
|
||||
</div>
|
||||
</div>
|
||||
@@ -63,8 +63,8 @@
|
||||
</div>
|
||||
{{{ end }}}
|
||||
|
||||
<!-- settings menu -->
|
||||
{{{ if user.privileges.admin:settings }}}
|
||||
<!-- settings menu -->
|
||||
<div class="d-flex flex-column">
|
||||
<button class="btn btn-ghost btn-sm d-flex gap-2 align-items-center" type="button" data-bs-toggle="collapse" data-bs-target="#collapseSettings" aria-expanded="true" aria-controls="collapseSettings">
|
||||
<i class="fa fa-fw fa-sliders"></i>
|
||||
@@ -86,7 +86,6 @@
|
||||
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/pagination">[[admin/menu:settings/pagination]]</a>
|
||||
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/notifications">[[admin/menu:settings/notifications]]</a>
|
||||
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/api">[[admin/menu:settings/api]]</a>
|
||||
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/activitypub">[[admin/menu:settings/activitypub]]</a>
|
||||
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/cookies">[[admin/menu:settings/cookies]]</a>
|
||||
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/web-crawler">[[admin/menu:settings/web-crawler]]</a>
|
||||
<a class="btn btn-ghost btn-sm text-start" href="{relative_path}/admin/settings/advanced">[[admin/menu:settings/advanced]]</a>
|
||||
@@ -95,6 +94,25 @@
|
||||
</div>
|
||||
|
||||
|
||||
<!-- federation menu -->
|
||||
<div class="d-flex flex-column">
|
||||
<button class="btn btn-ghost btn-sm d-flex gap-2 align-items-center" type="button" data-bs-toggle="collapse" data-bs-target="#collapseFederation" aria-expanded="true" aria-controls="collapseFederation">
|
||||
<i class="fa fa-fw fa-circle-nodes"></i>
|
||||
<div class="flex-1 font-serif text-sm fw-semibold text-start">[[admin/menu:section-federation]]</div>
|
||||
</button>
|
||||
|
||||
<div id="collapseFederation" class="accordion-collapse collapse" data-bs-parent="#accordionACP">
|
||||
<div class="accordion-body p-0 d-grid">
|
||||
<a class="btn btn-ghost btn-sm text-start" id="federation-general" href="{relative_path}/admin/federation/general">[[admin/menu:federation/general]]</a>
|
||||
<a class="btn btn-ghost btn-sm text-start" id="federation-rules" href="{relative_path}/admin/federation/rules">[[admin/menu:federation/rules]]</a>
|
||||
<a class="btn btn-ghost btn-sm text-start" id="federation-relays" href="{relative_path}/admin/federation/relays">[[admin/menu:federation/relays]]</a>
|
||||
<a class="btn btn-ghost btn-sm text-start" id="federation-pruning" href="{relative_path}/admin/federation/pruning">[[admin/menu:federation/pruning]]</a>
|
||||
<a class="btn btn-ghost btn-sm text-start" id="federation-safety" href="{relative_path}/admin/federation/safety">[[admin/menu:federation/safety]]</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- appearance menu -->
|
||||
<div class="d-flex flex-column">
|
||||
<button class="btn btn-ghost btn-sm d-flex gap-2 align-items-center" type="button" data-bs-toggle="collapse" data-bs-target="#collapseAppearance" aria-expanded="true" aria-controls="collapseAppearance">
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
<div class="col-12 col-md-8 px-0 mb-1 mb-md-0">
|
||||
<h4 class="fw-bold tracking-tight mb-0">{title}</h4>
|
||||
</div>
|
||||
{{{ if !hideSave }}}
|
||||
<div class="col-12 col-md-4 px-0 px-md-3">
|
||||
<button id="save" class="btn btn-primary btn-sm fw-semibold ff-secondary w-100 text-center text-nowrap">[[admin/admin:save-changes]]</button>
|
||||
</div>
|
||||
{{{ end }}}
|
||||
</div>
|
||||
@@ -1,153 +0,0 @@
|
||||
<div class="acp-page-container">
|
||||
<!-- IMPORT admin/partials/settings/header.tpl -->
|
||||
|
||||
<div class="row settings m-0">
|
||||
<div id="spy-container" class="col-12 col-md-8 px-0 mb-4" tabindex="0">
|
||||
|
||||
<p class="lead">[[admin/settings/activitypub:intro-lead]]</p>
|
||||
<p>[[admin/settings/activitypub:intro-body]]</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<div id="general" class="mb-4">
|
||||
<h5 class="fw-bold tracking-tight settings-header">[[admin/settings/activitypub:general]]</h5>
|
||||
<form>
|
||||
<div class="form-check form-switch mb-3">
|
||||
<input class="form-check-input" type="checkbox" data-field="activitypubEnabled">
|
||||
<label class="form-check-label">[[admin/settings/activitypub:enabled]]</label>
|
||||
<p class="form-text">[[admin/settings/activitypub:enabled-help]]</p>
|
||||
</div>
|
||||
<div class="form-check form-switch mb-3">
|
||||
<input class="form-check-input" type="checkbox" data-field="activitypubAllowLoopback">
|
||||
<label class="form-check-label">[[admin/settings/activitypub:allowLoopback]]</label>
|
||||
<p class="form-text">[[admin/settings/activitypub:allowLoopback-help]]</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="probe" class="mb-4">
|
||||
<h5 class="fw-bold tracking-tight settings-header">[[admin/settings/activitypub:probe]]</h5>
|
||||
<form>
|
||||
<div class="form-check form-switch mb-3">
|
||||
<input class="form-check-input" type="checkbox" data-field="activitypubProbe">
|
||||
<label class="form-check-label">[[admin/settings/activitypub:probe-enabled]]</label>
|
||||
<p class="form-text">[[admin/settings/activitypub:probe-enabled-help]]</p>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="activitypubProbeTimeout">[[admin/settings/activitypub:probe-timeout]]</label>
|
||||
<input type="number" id="activitypubProbeTimeout" name="activitypubProbeTimeout" data-field="activitypubProbeTimeout" title="[[admin/settings/activitypub:probe-timeout]]" class="form-control" />
|
||||
<div class="form-text">
|
||||
[[admin/settings/activitypub:probe-timeout-help]]
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="rules" class="mb-4">
|
||||
<h5 class="fw-bold tracking-tight settings-header">[[admin/settings/activitypub:rules]]</h5>
|
||||
<div class="mb-3">
|
||||
<p>[[admin/settings/activitypub:rules-intro]]</p>
|
||||
<table class="table table-striped" id="rules">
|
||||
<thead>
|
||||
<th></th>
|
||||
<th>[[admin/settings/activitypub:rules.type]]</th>
|
||||
<th>[[admin/settings/activitypub:rules.value]]</th>
|
||||
<th>[[admin/settings/activitypub:rules.cid]]</th>
|
||||
<th></th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{{ each rules }}}
|
||||
<tr data-rid="{./rid}">
|
||||
<td class="align-items-center" style="cursor: move;">
|
||||
<i class="fa fa-grip-lines text-muted drag-handle"></i>
|
||||
</td>
|
||||
<td>{./type}</td>
|
||||
<td>{./value}</td>
|
||||
<td>{./cid}</td>
|
||||
<td><a href="#" data-action="rules.delete"><i class="fa fa-trash link-danger"></i></a></td>
|
||||
</tr>
|
||||
{{{ end }}}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<button class="btn btn-sm btn-primary" data-action="rules.add">[[admin/settings/activitypub:rules.add]]</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="relays" class="mb-4">
|
||||
<h5 class="fw-bold tracking-tight settings-header">[[admin/settings/activitypub:relays]]</h5>
|
||||
<p>[[admin/settings/activitypub:relays.intro]]</p>
|
||||
<p class="text-warning">[[admin/settings/activitypub:relays.warning]]</p>
|
||||
<div class="mb-3">
|
||||
<table class="table table-striped" id="relays">
|
||||
<thead>
|
||||
<th>[[admin/settings/activitypub:relays.relay]]</th>
|
||||
<th>[[admin/settings/activitypub:relays.state]]</th>
|
||||
<th></th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{{ each relays }}}
|
||||
<tr data-url="{./url}">
|
||||
<td>{./url}</td>
|
||||
<td>{./label}</td>
|
||||
<td><a href="#" data-action="relays.remove"><i class="fa fa-trash link-danger"></i></a></td>
|
||||
</tr>
|
||||
{{{ end }}}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<button class="btn btn-sm btn-primary" data-action="relays.add">[[admin/settings/activitypub:relays.add]]</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="pruning" class="mb-4">
|
||||
<h5 class="fw-bold tracking-tight settings-header">[[admin/settings/activitypub:pruning]]</h5>
|
||||
<form>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="activitypubContentPruneDays">[[admin/settings/activitypub:content-pruning]]</label>
|
||||
<input type="number" id="activitypubContentPruneDays" name="activitypubContentPruneDays" data-field="activitypubContentPruneDays" title="[[admin/settings/activitypub:content-pruning]]" class="form-control" />
|
||||
<div class="form-text">
|
||||
[[admin/settings/activitypub:content-pruning-help]]
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="activitypubUserPruneDays">[[admin/settings/activitypub:user-pruning]]</label>
|
||||
<input type="number" id="activitypubUserPruneDays" name="activitypubUserPruneDays" data-field="activitypubUserPruneDays" title="[[admin/settings/activitypub:user-pruning]]" class="form-control" />
|
||||
<div class="form-text">
|
||||
[[admin/settings/activitypub:user-pruning-help]]
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="server-filtering" class="mb-4">
|
||||
<h5 class="fw-bold tracking-tight settings-header">[[admin/settings/activitypub:server-filtering]]</h5>
|
||||
<form>
|
||||
<div class="mb-3">
|
||||
<p>[[admin/settings/activitypub:server.filter-help]]</p>
|
||||
<p>[[admin/settings/activitypub:server.filter-help-hostname]]</p>
|
||||
<p>[[admin/settings/activitypub:count, {instanceCount}]]</p>
|
||||
<label for="activitypubFilterList" class="form-label">Filtering list</label>
|
||||
<textarea class="form-control" id="activitypubFilterList" data-field="activitypubFilterList" rows="10"></textarea>
|
||||
</div>
|
||||
<div class="form-check form-switch mb-3">
|
||||
<input class="form-check-input" type="checkbox" id="activitypubFilter" data-field="activitypubFilter" />
|
||||
<label class="form-check-label" for="activitypubFilter">[[admin/settings/activitypub:server.filter-allow-list]]</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- IMPORT admin/partials/settings/toc.tpl -->
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user