diff --git a/public/assets/pages/adminpage/ctrl_activity.js b/public/assets/pages/adminpage/ctrl_activity.js index 2c245cde..a86e68bb 100644 --- a/public/assets/pages/adminpage/ctrl_activity.js +++ b/public/assets/pages/adminpage/ctrl_activity.js @@ -3,6 +3,7 @@ import { createElement, createRender } from "../../lib/skeleton/index.js"; import { initConfig } from "./model_config.js"; import componentLogForm from "./ctrl_activity_form.js"; import componentLogViewer from "./ctrl_activity_viewer.js"; +import componentLogGraph from "./ctrl_activity_graph.js"; import componentAuditor from "./ctrl_activity_audit.js"; import transition from "./animate.js"; import AdminHOC from "./decorator.js"; @@ -10,11 +11,12 @@ import AdminHOC from "./decorator.js"; export default AdminHOC(async function(render) { const $page = createElement(`
-

Events

+

System Logs

+
-

Activity Report

+

Audit Report

`); @@ -23,5 +25,6 @@ export default AdminHOC(async function(render) { componentLogViewer(createRender($page.querySelector(".component_logviewer"))); componentLogForm(createRender($page.querySelector(".component_logger"))); + componentLogGraph(createRender($page.querySelector(".component_stats"))); componentAuditor(createRender($page.querySelector(".component_audit"))); }); diff --git a/public/assets/pages/adminpage/ctrl_activity_graph.css b/public/assets/pages/adminpage/ctrl_activity_graph.css new file mode 100644 index 00000000..52f41f08 --- /dev/null +++ b/public/assets/pages/adminpage/ctrl_activity_graph.css @@ -0,0 +1,29 @@ +.component_stats { + clear: both; +} +.component_stats .chart { + display: flex; + align-items: flex-end; + height: 100px; +} +.component_stats .chart .bar { + display: flex; + flex: 1; + cursor: pointer; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + border-bottom: 1px solid var(--light); + + background: var(--border); + border: 2px solid var(--border); +} +.component_stats .chart .bar[title="0"], .component_stats .chart .bar[title="1"], .component_stats .chart .bar[title="2"] { + border-top-left-radius: 0px; + border-top-right-radius: 0px; +} +.component_stats .legend { + display: flex; + justify-content: space-between; + color: var(--light); + font-size: 0.8rem; +} diff --git a/public/assets/pages/adminpage/ctrl_activity_graph.js b/public/assets/pages/adminpage/ctrl_activity_graph.js new file mode 100644 index 00000000..684669e9 --- /dev/null +++ b/public/assets/pages/adminpage/ctrl_activity_graph.js @@ -0,0 +1,48 @@ +import { createElement } from "../../lib/skeleton/index.js"; +import rxjs, { effect } from "../../lib/rx.js"; +import { get as getLogs } from "./model_log.js"; +import { loadCSS } from "../../helpers/loader.js"; + +export default async function(render) { + await loadCSS(import.meta.url, "./ctrl_activity_graph.css"); + + effect(getLogs().pipe( + rxjs.map((log) => { + const times = log.trim().split("\n").map((line) => new Date(line.substring(0, 19)).getTime()); + const start = times[0]; + const end = times[times.length - 1]; + + const size = 30 + const bars = Array(size).fill(0); + const width = (end - start) / size; + for (const t of times) { + const idx = Math.min(size - 1, Math.max(0, Math.floor((t - start) / width))); + bars[idx] += 1; + } + return { + bars, + start: new Date(start).toLocaleTimeString(), + end: new Date(end).toLocaleTimeString(), + }; + }), + rxjs.tap(({ bars, start, end }) => { + const max = Math.max(1, ...bars); + const $root = document.createDocumentFragment(); + const $chart = createElement(`
`); + for (let i = 0; i < bars.length; i++) { + const $bar = createElement(`
`) + $bar.style.height = Math.sqrt(bars[i]) / Math.sqrt(max) * 100 + "%"; + $chart.appendChild($bar); + } + $root.appendChild($chart); + $root.appendChild(createElement(` +
+ ${start} + ${end} +
+ `)); + render($root); + }), + rxjs.catchError(() => rxjs.EMPTY), + )); +} diff --git a/public/assets/pages/adminpage/ctrl_activity_viewer.js b/public/assets/pages/adminpage/ctrl_activity_viewer.js index 01057f35..25abe402 100644 --- a/public/assets/pages/adminpage/ctrl_activity_viewer.js +++ b/public/assets/pages/adminpage/ctrl_activity_viewer.js @@ -13,7 +13,7 @@ export default async function(render) { -

+

`); const $log = qs($page, "pre");