diff --git a/public/src/admin/federation/relays.js b/public/src/admin/federation/relays.js index 77fade6c1b..1b76100930 100644 --- a/public/src/admin/federation/relays.js +++ b/public/src/admin/federation/relays.js @@ -3,9 +3,53 @@ import { post, del } from 'api'; import { error } from 'alerts'; import { render } from 'benchpress'; +import { get } from 'api'; +import { translate } from 'translator'; +import { + Chart, + LineController, + CategoryScale, + LinearScale, + LineElement, + PointElement, + Tooltip, + Filler, + Legend, +} from 'chart.js'; -export function init() { +Chart.register( + LineController, + CategoryScale, + LinearScale, + LineElement, + PointElement, + Tooltip, + Filler, + Legend +); + +let chart; +const labels = new Map([ + ['hourly', utils.getHoursArray().map(function (text, idx) { + return idx % 3 ? '' : text; + })], + ['daily', utils.getDaysArray().map(function (text, idx) { + return idx % 3 ? '' : text; + })], +]); + +export async function init() { setupRelays(); + chart = await initializeCharts(); + + const hostFilterEl = document.getElementById('hostFilter'); + const termEl = document.getElementById('term'); + if (hostFilterEl) { + hostFilterEl.addEventListener('change', updateCharts); + } + if (termEl) { + termEl.addEventListener('change', updateCharts); + } }; function setupRelays() { @@ -70,4 +114,79 @@ function throwModal() { modal.find('input').focus(); }); }); -} \ No newline at end of file +} + +async function updateCharts() { + const hostFilterEl = document.getElementById('hostFilter'); + const termEl = document.getElementById('term'); + console.log(hostFilterEl.value, termEl.value); + const data = await get(`/api${ajaxify.data.url}?host=${hostFilterEl.value}&term=${termEl.value}`); + + chart.data.labels = labels.get(termEl.value || 'hourly'); + chart.data.datasets[0].data = data.data.in; + chart.data.datasets[1].data = data.data.out; + chart.update(); +} + +async function initializeCharts() { + const canvas = document.querySelector('canvas'); + + if (utils.isMobile()) { + Chart.defaults.plugins.tooltip.enabled = false; + } + + const commonDataSetOpts = { + label: '', + fill: true, + tension: 0.25, + pointHoverBackgroundColor: '#fff', + pointBorderColor: '#fff', + }; + + const data = { + labels: labels.get('hourly'), + datasets: [ + { + ...commonDataSetOpts, + label: await translate('[[admin/settings/activitypub:analytics.in]]'), + backgroundColor: 'rgba(161,181,108,0.2)', + borderColor: 'rgba(161,181,108,1)', + pointBackgroundColor: 'rgba(161,181,108,1)', + pointHoverBorderColor: 'rgba(161,181,108,1)', + data: ajaxify.data.data.in, + }, + { + ...commonDataSetOpts, + label: await translate('[[admin/settings/activitypub:analytics.out]]'), + backgroundColor: 'rgba(151,187,205,0.2)', + borderColor: 'rgba(151,187,205,1)', + pointBackgroundColor: 'rgba(151,187,205,1)', + pointHoverBorderColor: 'rgba(151,187,205,1)', + data: ajaxify.data.data.out, + }, + ], + }; + + canvas.width = $(canvas).parent().width(); + + const chartOpts = { + responsive: true, + animation: false, + scales: { + y: { + beginAtZero: true, + }, + }, + plugins: { + legend: { + position: 'bottom', + }, + }, + }; + + return new Chart(canvas.getContext('2d'), { + type: 'line', + data, + options: chartOpts, + }); +} diff --git a/src/controllers/admin/federation.js b/src/controllers/admin/federation.js index 4445a55ab2..f2289f6f12 100644 --- a/src/controllers/admin/federation.js +++ b/src/controllers/admin/federation.js @@ -32,11 +32,27 @@ federationController.rules = async function (req, res) { federationController.relays = async function (req, res) { const relays = await activitypub.relays.list(); + const urls = relays.map(({ url }) => url); + + let { host, term } = req.query; + if (!urls.includes(host)) { + host = undefined; + } + let method = 'getHourlyStatsForSet'; + let count = 24; + if (term === 'daily') { + method = 'getDailyStatsForSet'; + count = 30; + } + const inSet = host ? `ap.relayIn:byHost:${host}` : 'ap.relayIn'; + const outSet = host ? `ap.relayOut:byHost:${host}` : 'ap.relayOut'; + const incoming = await analytics[method](inSet, Date.now(), count); + const out = await analytics[method](outSet, Date.now(), count); res.render(`admin/federation/relays`, { title: '[[admin/menu:federation/relays]]', relays, - hideSave: true, + data: { in: incoming, out }, }); }; diff --git a/src/views/admin/federation/relays.tpl b/src/views/admin/federation/relays.tpl index 51abb78597..e7d6939413 100644 --- a/src/views/admin/federation/relays.tpl +++ b/src/views/admin/federation/relays.tpl @@ -1,39 +1,62 @@ -
- - -
-
-
-

[[admin/settings/activitypub:relays.intro]]

-

[[admin/settings/activitypub:relays.warning]]

-
- - - - - - - - {{{ each relays }}} - - - - - - {{{ end }}} - - - - - - -
[[admin/settings/activitypub:relays.relay]][[admin/settings/activitypub:relays.state]]
{./url}{./label}
- -
-
-
-
- - +
+
+

{title}

+
+
+ +
+
+

[[admin/settings/activitypub:relays.intro]]

+

[[admin/settings/activitypub:relays.warning]]

+
+ + + + + + + + {{{ each relays }}} + + + + + + {{{ end }}} + + + + + + +
[[admin/settings/activitypub:relays.relay]][[admin/settings/activitypub:relays.state]]
{./url}{./label}
+ +
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+ +
+