From 259625353561e2934f25fa534012a1eb8120cb9a Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Thu, 15 Jun 2023 08:45:28 +0100 Subject: [PATCH] Stats: Improve summaries when range is selected Fixes #446 --- app/public/static/package_charts.js | 61 +++++++++++++++++++++++++---- app/templates/macros/stats.html | 58 +++++++++------------------ app/templates/packages/stats.html | 2 +- app/templates/users/stats.html | 2 +- app/utils/flask.py | 18 ++++++++- 5 files changed, 91 insertions(+), 50 deletions(-) diff --git a/app/public/static/package_charts.js b/app/public/static/package_charts.js index 87b9d8b2..2f96c36d 100644 --- a/app/public/static/package_charts.js +++ b/app/public/static/package_charts.js @@ -1,3 +1,6 @@ +// @author rubenwardy +// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later + "use strict"; @@ -58,9 +61,45 @@ const chartColorsBg = chartColors.map(color => `rgba(${hexToRgb(color.slice(1))} const SECONDS_IN_A_DAY = 1000 * 3600 * 24; + +function format_message(id, values) { + let format = document.getElementById(id).textContent; + values.forEach((value, i) => { + format = format.replace("$" + (i + 1), value); + }) + return format; +} + + +function add_summary_card(title, icon, value, extra) { + const ele = document.createElement("div"); + ele.innerHTML = ` +
+
+
+
+ + +
+
+ + +
+
+
+
`; + + ele.querySelector(".summary-title").textContent = title; + ele.querySelector(".summary-value").textContent = value; + ele.querySelector(".summary-extra").textContent = extra; + + document.getElementById("stats-summaries").appendChild(ele.children[0]); +} + async function load_data() { const root = document.getElementById("stats-root"); const source = root.getAttribute("data-source"); + const is_range = root.getAttribute("data-is-range") == "true"; const response = await fetch(source); const json = await response.json(); @@ -79,16 +118,22 @@ async function load_data() { return date.toISOString().split("T")[0]; }); - const total7 = sum(json.platform_minetest.slice(-7)) + sum(json.platform_other.slice(-7)); - document.getElementById("downloads_total7d").textContent = total7; - document.getElementById("downloads_avg7d").textContent = (total7 / 7).toFixed(0); + if (!is_range) { + if (json.platform_minetest.length >= 30) { + const total30 = sum(json.platform_minetest.slice(-30)) + sum(json.platform_other.slice(-30)); + add_summary_card(format_message("downloads-30days", []), "download", total30, + format_message("downloads-per-day", [ (total30 / 30).toFixed(0) ])); + } - if (json.platform_minetest.length >= 30) { - const total30 = sum(json.platform_minetest.slice(-30)) + sum(json.platform_other.slice(-30)); - document.getElementById("downloads_total30d").textContent = total30; - document.getElementById("downloads_avg30d").textContent = (total30 / 30).toFixed(0); + const total7 = sum(json.platform_minetest.slice(-7)) + sum(json.platform_other.slice(-7)); + add_summary_card(format_message("downloads-7days", []), "download", total7, + format_message("downloads-per-day", [ (total7 / 7).toFixed(0) ])); } else { - document.getElementById("downloads30").style.display = "none"; + const total = sum(json.platform_minetest) + sum(json.platform_other); + const days = Math.max(json.platform_minetest.length, json.platform_other.length); + const title = format_message("downloads-range", [ json.start, json.end ]); + add_summary_card(title, "download", total, + format_message("downloads-per-day", [ (total / days).toFixed(0) ])); } const jsonOther = json.platform_minetest.map((value, i) => diff --git a/app/templates/macros/stats.html b/app/templates/macros/stats.html index 79ebd2ee..6648a698 100644 --- a/app/templates/macros/stats.html +++ b/app/templates/macros/stats.html @@ -2,7 +2,7 @@ - + {% endmacro %} @@ -44,14 +44,28 @@ {% endmacro %} -{% macro render_package_stats(source, downloads) %} +{% macro render_package_stats(source, downloads, is_range) %} +
+ + {{ _("Downloads, past 7 days") }} + + + {{ _("Downloads, past 30 days") }} + + + {{ _("Downloads from $1 to $2") }} + + + {{ _("$1 per day") }} + +
-
-
+
+
@@ -64,40 +78,6 @@
- -
-
-
-
- - {{ _("Downloads, past 7 days") }} -
-
- - - ({{ _("%(downloads)s per day", downloads=("" | safe)) }}) - -
-
-
-
- -
-
-
-
- - {{ _("Downloads, past 30 days") }} -
-
- - - ({{ _("%(downloads)s per day", downloads=("" | safe)) }}) - -
-
-
-
{{ _("Loading...") }}
@@ -106,7 +86,7 @@ {{ _("No data") }}
-

{{ self.title() }}

- {{ render_package_stats(url_for("api.user_stats", username=user.username, start=start, end=end), downloads) }} + {{ render_package_stats(url_for("api.user_stats", username=user.username, start=start, end=end), downloads, start or end) }} {% endblock %} diff --git a/app/utils/flask.py b/app/utils/flask.py index 96ff818d..0a4a4bd9 100644 --- a/app/utils/flask.py +++ b/app/utils/flask.py @@ -38,13 +38,16 @@ def abs_url_for(endpoint: str, **kwargs): scheme = "https" if app.config["BASE_URL"][:5] == "https" else "http" return url_for(endpoint, _external=True, _scheme=scheme, **kwargs) + def abs_url(path): return urljoin(app.config["BASE_URL"], path) + def abs_url_samesite(path): base = urlparse(app.config["BASE_URL"]) return urlunparse(base._replace(path=path)) + def url_current(abs=False): if request.args is None or request.view_args is None: return None @@ -57,12 +60,25 @@ def url_current(abs=False): else: return url_for(request.endpoint, **dargs) + +def url_clear_query(): + if request.endpoint is None: + return None + + dargs = dict() + if request.view_args: + dargs.update(request.view_args) + + return url_for(request.endpoint, **dargs) + + def url_set_anchor(anchor): args = MultiDict(request.args) dargs = dict(args.lists()) dargs.update(request.view_args) return url_for(request.endpoint, **dargs) + "#" + anchor + def url_set_query(**kwargs): if request.endpoint is None: return None @@ -130,7 +146,7 @@ def get_daterange_options() -> List[Tuple[LazyString, str]]: last_year_end = datetime.date(now.year - 1, 12, 31) return [ - (lazy_gettext("All time"), url_set_query(start="2022-10-23", end=now.isoformat())), + (lazy_gettext("All time"), url_clear_query()), (lazy_gettext("Last 7 days"), url_set_query(start=days7.isoformat(), end=now.isoformat())), (lazy_gettext("Last 30 days"), url_set_query(start=days30.isoformat(), end=now.isoformat())), (lazy_gettext("Last 90 days"), url_set_query(start=days90.isoformat(), end=now.isoformat())),