Skip to content

Commit f4af36d

Browse files
committed
Merge branch 'feature/dashboard' into develop
2 parents 1ffbf71 + 3ffbec9 commit f4af36d

8 files changed

Lines changed: 853 additions & 17 deletions

File tree

app/modules/public/templates/public/index.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,12 @@ <h2 class="fs-2 fw-bold text-body mb-6">
283283
<div class="text-muted">Model downloads</div>
284284
</div>
285285
</div>
286+
<div class="text-end mt-4">
287+
<a href="{{ url_for('statistics.index') }}" class="btn btn-sm btn-light text-muted">
288+
<i data-feather="bar-chart-2" class="me-1" style="width:14px;height:14px;"></i>
289+
View full dashboard
290+
</a>
291+
</div>
286292
</div>
287293
</div>
288294
</div>
Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,93 @@
1-
console.log("Hi, I am a script loaded from statistics module");
1+
// Dashboard chart bootstrap. The server renders the series as JSON inside
2+
// `<script id="dashboard-data">` so this module has a single parse step and
3+
// no template-interpolation inside JS (safer, easier to cache, no CSP hacks).
4+
5+
import Chart from "chart.js/auto";
6+
7+
function readData() {
8+
const el = document.getElementById("dashboard-data");
9+
if (!el) return null;
10+
try {
11+
return JSON.parse(el.textContent || "{}");
12+
} catch (e) {
13+
console.error("dashboard: bad JSON payload", e);
14+
return null;
15+
}
16+
}
17+
18+
function renderUploads(data) {
19+
const canvas = document.getElementById("uploadsChart");
20+
if (!canvas || !data.months?.length) return;
21+
new Chart(canvas.getContext("2d"), {
22+
type: "bar",
23+
data: {
24+
labels: data.months,
25+
datasets: [
26+
{
27+
label: "Datasets uploaded",
28+
data: data.uploads || [],
29+
backgroundColor: "rgba(54, 153, 255, 0.2)",
30+
borderColor: "rgba(54, 153, 255, 1)",
31+
borderWidth: 2,
32+
borderRadius: 4,
33+
},
34+
],
35+
},
36+
options: {
37+
responsive: true,
38+
plugins: { legend: { display: false } },
39+
scales: { y: { beginAtZero: true, ticks: { stepSize: 1 } } },
40+
},
41+
});
42+
}
43+
44+
function renderActivity(data) {
45+
const canvas = document.getElementById("activityChart");
46+
if (!canvas || !data.months?.length) return;
47+
new Chart(canvas.getContext("2d"), {
48+
type: "line",
49+
data: {
50+
labels: data.months,
51+
datasets: [
52+
{
53+
label: "Downloads",
54+
data: data.downloads || [],
55+
backgroundColor: "rgba(246, 78, 96, 0.1)",
56+
borderColor: "rgba(246, 78, 96, 1)",
57+
borderWidth: 2,
58+
tension: 0.3,
59+
fill: true,
60+
pointRadius: 4,
61+
},
62+
{
63+
label: "Views",
64+
data: data.views || [],
65+
backgroundColor: "rgba(80, 205, 137, 0.1)",
66+
borderColor: "rgba(80, 205, 137, 1)",
67+
borderWidth: 2,
68+
tension: 0.3,
69+
fill: true,
70+
pointRadius: 4,
71+
},
72+
],
73+
},
74+
options: {
75+
responsive: true,
76+
plugins: { legend: { display: true, position: "top" } },
77+
scales: { y: { beginAtZero: true, ticks: { stepSize: 1 } } },
78+
},
79+
});
80+
}
81+
82+
function init() {
83+
const data = readData();
84+
if (!data) return;
85+
renderUploads(data);
86+
renderActivity(data);
87+
}
88+
89+
if (document.readyState === "loading") {
90+
document.addEventListener("DOMContentLoaded", init, { once: true });
91+
} else {
92+
init();
93+
}
Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
const path = require('path');
1+
const path = require("path");
22

33
module.exports = {
4-
entry: path.resolve(__dirname, './scripts.js'),
5-
output: {
6-
filename: 'statistics.bundle.js',
7-
path: path.resolve(__dirname, '../dist'),
8-
},
9-
resolve: {
10-
fallback: {
11-
"fs": false
12-
}
13-
},
14-
mode: 'development',
4+
entry: path.resolve(__dirname, "./scripts.js"),
5+
output: {
6+
filename: "statistics.bundle.js",
7+
path: path.resolve(__dirname, "../dist"),
8+
module: true,
9+
},
10+
experiments: {
11+
outputModule: true,
12+
},
13+
resolve: {
14+
fallback: { fs: false },
15+
},
16+
mode: "development",
17+
devtool: "source-map",
1518
};

app/modules/statistics/routes.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
from flask import render_template
22

33
from app.modules.statistics import statistics_bp
4+
from app.modules.statistics.services import DashboardService
45

56

67
@statistics_bp.route("/statistics", methods=["GET"])
78
def index():
8-
return render_template("statistics/index.html")
9+
dashboard = DashboardService().build_dashboard()
10+
return render_template("statistics/index.html", dashboard=dashboard)

0 commit comments

Comments
 (0)