Skip to content

Added internal statistics page#819

Open
ba11e-mos wants to merge 6 commits into
mainfrom
feature/statistics-page
Open

Added internal statistics page#819
ba11e-mos wants to merge 6 commits into
mainfrom
feature/statistics-page

Conversation

@ba11e-mos
Copy link
Copy Markdown

Builds on the work started in #669. Re-implemented on top of current main with per-section time-range filters, AJAX updates, mobile-responsive layout and tests.

Proposed changes

Adds an internal-only statistics page (/statistics/ on the internal subdomain) that contains:

  • Site traffic — total page views, unique visitors and the top viewed paths, gathered by a new PageViewMiddleware that records every successful GET.
  • Average reservations by hour of day — line chart of reservations active per hour, averaged across observed days. Inspiration from OV's door status.
  • Per-machine-type usage — for each machine type with at least one machine, a section showing total reservations, total reserved hours, and per-machine breakdowns (hours and counts) as bar charts.

Each chart section has its own time-range filter (last week / month / year / custom interval). Filter changes update the section in place via an AJAX call to a new JSON endpoint, i thought it would be nice with a seamless transition:)

New project-root web models PageView and Visitor back the traffic stats. Language-prefixed paths (/en/foo/) are normalized to their canonical form (/foo/) before being stored, so traffic aggregates per page rather than per language. It should be possible to separate statistics by language in the future if wanted.

Future work

  • Physical people-counter integration, extend the page with a section showing visitor counts from on-site sensors (e.g. door counters), so the workshop can correlate digital activity with actual foot traffic. This would likely add a new model (PhysicalVisit or similar) plus an ingestion endpoint or scheduled import, then reuse the same per-section filter UI.
  • Mainsail/Moonraker integration for live Voron printer status and per-print metrics.

Review guidance

  • Statistics view + JSON endpoint live in src/internal/views.py (StatisticsView + APIStatisticsDataView). The JSON endpoint reuses the same filtering helpers as the page render, so behaviour stays in sync.
  • Site-traffic infra (models, middleware, admin) sits in the web app to keep this PR small. Could move to a dedicated app later if needed. Two consequences worth knowing: model registration runs from WebAdminConfig.ready() to dodge an admin.site LazyObject race, and WebAdminSite.get_app_list() regroups PageView/Visitor under a synthetic "Statistics" header so they don't sit under "Web".
  • Access is gated by the existing internal.is_internal permission via the decorator_include wrap in internal/urls.py — i.e. any internal-site member can view the page. No stricter per-view permission was added since the data shown (reservation usage, page-view counts) isn't sensitive in the same way as e.g. member or quote data. If a tighter gate is wanted later, a new internal.view_statistics permission can be added without touching the view code.
  • AJAX glue lives in src/internal/static/internal/js/statistics_charts.js. It updates the existing Chart.js instances via a lookup table (chartRegistry) instead of re-rendering the canvases.
  • The Fomantic-UI Calendar is reused for date inputs to match the rest of the codebase (see semantic_date.html).
  • Mobile/tablet layouts use grid + media queries down to 320 px; the section heading wraps before the filter when narrow.

Deployment notes

  • Run migrations to create web_pageview and web_visitor (web/0001_pageview_visitor).
  • The new web.middleware.PageViewMiddleware is registered in MIDDLEWARE and starts collecting traffic automatically when the deploy goes live — no environment variables, management commands or manual data steps required.

Checklist

  • I've run makemigrations, makemessages and compilemessages
  • I've written tests that fail without these changes (if relevant/possible)
  • I've manually tested the website UI with different device layouts
  • I've manually tested with different users locally
  • I've made sure that my code conforms to the code style guides
  • I've attempted to minimize the number of common code smells
  • I've added documentation
  • I've added my changes to the "Unreleased" section of the changelog, together with a link to this PR
  • I've added a "Deployment notes" section above and labelled the PR with has-deployment-notes
  • I've structured my commits reasonably

ba11e-mos added 5 commits May 15, 2026 15:55
Define two minimal models on the project-root `web` app to record total
visits per URL path and unique visitor sessions/users. Both expose admin
classes (read-only fields, sensible orderings) so the data can be
inspected without going through the statistics page.
Increment the path's `PageView.count` and upsert the visitor identifier
on every successful `GET` response. The path is normalized by stripping
any leading language prefix so `/en/foo/` and `/foo/` aggregate to the
same row, and a small set of non-page prefixes (`/static/`, `/api/`,
`/jsi18n/`, etc.) is excluded so they don't drown out real traffic.
Render an internal-only page summarizing site traffic, average
reservations per hour of day and per-machine-type usage. Each section
exposes its own time-range filter (last week/month/year/custom interval)
that updates the corresponding charts via an AJAX call to a new JSON
endpoint, keeping the rest of the page intact.
Cover access control (anonymous, non-member, internal user, superuser),
template context shape, the per-section date-range filter (week/all/
custom and per-section isolation) and the AJAX JSON endpoint
(machine-type and time payloads, error responses, range filter respect).
@ba11e-mos ba11e-mos added feature New functionality on the page has-deployment-notes labels May 18, 2026
@make-bot make-bot Bot added this to web May 18, 2026
@make-bot make-bot Bot moved this to Ready for Review in web May 18, 2026
@ba11e-mos ba11e-mos force-pushed the feature/statistics-page branch from 532a41d to 293338d Compare May 18, 2026 11:43
@codecov
Copy link
Copy Markdown

codecov Bot commented May 18, 2026

Codecov Report

❌ Patch coverage is 97.95918% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.29%. Comparing base (787ea4b) to head (293338d).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/web/models.py 90.47% 2 Missing ⚠️
src/web/admin.py 96.77% 1 Missing ⚠️
src/web/middleware.py 96.87% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #819      +/-   ##
==========================================
+ Coverage   87.99%   88.29%   +0.29%     
==========================================
  Files         153      155       +2     
  Lines        6249     6443     +194     
==========================================
+ Hits         5499     5689     +190     
- Misses        750      754       +4     
Files with missing lines Coverage Δ
src/internal/urls.py 100.00% <ø> (ø)
src/internal/views.py 94.01% <100.00%> (+3.25%) ⬆️
src/web/apps.py 100.00% <100.00%> (ø)
src/web/admin.py 97.72% <96.77%> (-2.28%) ⬇️
src/web/middleware.py 96.87% <96.87%> (ø)
src/web/models.py 90.47% <90.47%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New functionality on the page has-deployment-notes

Projects

Status: Ready for Review

Development

Successfully merging this pull request may close these issues.

1 participant