Add charts

This commit is contained in:
jude 2023-06-21 15:09:24 +01:00
parent c3c0dbbbae
commit 3d627b5bf0
6 changed files with 184 additions and 2 deletions

View File

@ -68,5 +68,22 @@ pub async fn bot_data(cookies: &CookieJar<'_>, pool: &State<Pool<MySql>>) -> Jso
.await
.unwrap();
Ok(json!({ "backlog": backlog.backlog, "schedule": schedule }))
let schedule_long = sqlx::query_as_unchecked!(
TimeFrame,
"SELECT
FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(`utc_time`) / 86400) * 86400) AS `time_key`,
COUNT(1) AS `count`
FROM reminders
WHERE
`utc_time` < DATE_ADD(NOW(), INTERVAL 31 DAY) AND
`utc_time` >= NOW() AND
`enabled` = 1
GROUP BY `time_key`
ORDER BY `time_key`"
)
.fetch_all(pool.inner())
.await
.unwrap();
Ok(json!({ "backlog": backlog.backlog, "schedule": schedule, "scheduleLong": schedule_long }))
}

View File

@ -580,3 +580,27 @@ input.default-width {
.is-locked .field:last-of-type {
display: none;
}
.stat-row {
display: flex;
flex-direction: row;
}
.stat-box {
flex-grow: 1;
border-radius: 6px;
background-color: #fcfcfc;
border-color: #efefef;
border-style: solid;
border-width: 1px;
margin: 4px;
padding: 4px;
}
.figure {
text-align: center;
}
.figure-num {
font-size: 2em;
}

61
web/static/js/admin.js Normal file
View File

@ -0,0 +1,61 @@
document.addEventListener("DOMContentLoaded", () => {
fetch("/admin/data")
.then((resp) => resp.json())
.then((data) => {
document.querySelector("#backlog").textContent = data.backlog;
new Chart(document.getElementById("schedule"), {
type: "bar",
data: {
labels: data.schedule.map((row) =>
luxon.DateTime.fromISO(row.time_key)
),
datasets: [
{
label: "Reminders",
data: data.schedule.map((row) => row.count),
},
],
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
type: "time",
time: {
unit: "minute",
},
},
},
},
});
new Chart(document.getElementById("scheduleLong"), {
type: "bar",
data: {
labels: data.scheduleLong.map((row) =>
luxon.DateTime.fromISO(row.time_key)
),
datasets: [
{
label: "Reminders",
data: data.scheduleLong.map((row) => row.count),
},
],
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
type: "time",
time: {
unit: "day",
},
},
},
},
});
});
});

20
web/static/js/chart.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
/*!
* chartjs-adapter-luxon v1.3.1
* https://www.chartjs.org
* (c) 2023 chartjs-adapter-luxon Contributors
* Released under the MIT license
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(require("chart.js"),require("luxon")):"function"==typeof define&&define.amd?define(["chart.js","luxon"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Chart,e.luxon)}(this,(function(e,t){"use strict";const n={datetime:t.DateTime.DATETIME_MED_WITH_SECONDS,millisecond:"h:mm:ss.SSS a",second:t.DateTime.TIME_WITH_SECONDS,minute:t.DateTime.TIME_SIMPLE,hour:{hour:"numeric"},day:{day:"numeric",month:"short"},week:"DD",month:{month:"short",year:"numeric"},quarter:"'Q'q - yyyy",year:{year:"numeric"}};e._adapters._date.override({_id:"luxon",_create:function(e){return t.DateTime.fromMillis(e,this.options)},init(e){this.options.locale||(this.options.locale=e.locale)},formats:function(){return n},parse:function(e,n){const i=this.options,r=typeof e;return null===e||"undefined"===r?null:("number"===r?e=this._create(e):"string"===r?e="string"==typeof n?t.DateTime.fromFormat(e,n,i):t.DateTime.fromISO(e,i):e instanceof Date?e=t.DateTime.fromJSDate(e,i):"object"!==r||e instanceof t.DateTime||(e=t.DateTime.fromObject(e,i)),e.isValid?e.valueOf():null)},format:function(e,t){const n=this._create(e);return"string"==typeof t?n.toFormat(t):n.toLocaleString(t)},add:function(e,t,n){const i={};return i[n]=t,this._create(e).plus(i).valueOf()},diff:function(e,t,n){return this._create(e).diff(this._create(t)).as(n).valueOf()},startOf:function(e,t,n){if("isoWeek"===t){n=Math.trunc(Math.min(Math.max(0,n),6));const t=this._create(e);return t.minus({days:(t.weekday-n+7)%7}).startOf("day").valueOf()}return t?this._create(e).startOf(t).valueOf():e},endOf:function(e,t){return this._create(e).endOf(t).valueOf()}})}));

View File

@ -1,9 +1,62 @@
<!DOCTYPE html>
<html lang="EN">
<head>
<script src="/static/js/reporter.js" type="application/javascript"></script>
<meta name="description" content="The most powerful Discord Reminders Bot">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="UTF-8">
<meta name="yandex-verification" content="bb77b8681eb64a90"/>
<meta name="google-site-verification" content="7h7UVTeEe0AOzHiH3cFtsqMULYGN-zCZdMT_YCkW1Ho"/>
<!-- <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src *; font-src fonts.gstatic.com 'self'"> -->
<!-- favicon -->
<link rel="apple-touch-icon" sizes="180x180"
href="/static/favicon/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32"
href="/static/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16"
href="/static/favicon/favicon-16x16.png">
<link rel="manifest" href="/static/favicon/site.webmanifest">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<title>Reminder Bot | Admin</title>
<!-- styles -->
<link rel="stylesheet" href="/static/css/bulma.min.css">
<link rel="stylesheet" href="/static/css/fa.css">
<link rel="stylesheet" href="/static/css/font.css">
<link rel="stylesheet" href="/static/css/style.css">
<link rel="stylesheet" href="/static/css/dtsel.css">
<script src="/static/js/luxon.min.js"></script>
</head>
<body>
<body style="width: 100%;">
<p class="title pageTitle">Admin dashboard</p>
<section id="main">
<div class="stat-row">
<div class="stat-box" style="height: 400px;">
<canvas id="schedule"></canvas>
</div>
</div>
<div class="stat-row">
<div class="stat-box figure">
<p>Backlog</p>
<p class="figure-num" id="backlog">?</p>
</div>
</div>
<div class="stat-row">
<div class="stat-box" style="height: 400px;">
<canvas id="scheduleLong"></canvas>
</div>
</div>
</section>
<script src="/static/js/chart.js" defer></script>
<script src="/static/js/chartjs-adapter-luxon.js" defer></script>
<script src="/static/js/admin.js" defer></script>
</body>
</html>