From 08cab3b8150f750f809d6c1d3d90e5ba99488ed0 Mon Sep 17 00:00:00 2001 From: Amirhossein Khalili Date: Mon, 15 Jun 2026 17:33:30 +0330 Subject: [PATCH] feat(analytics): expose full dashboard result groups --- apps/analytics/api/schemas.py | 2 ++ apps/analytics/api/views.py | 34 ++++++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/apps/analytics/api/schemas.py b/apps/analytics/api/schemas.py index 5a77d6c..b32d5bd 100644 --- a/apps/analytics/api/schemas.py +++ b/apps/analytics/api/schemas.py @@ -9,6 +9,7 @@ class AnalyticsPointSchema(Schema): class AnalyticsPointGroupSchema(Schema): + items: list[AnalyticsPointSchema] top_items: list[AnalyticsPointSchema] other_count: int = 0 total_count: int = 0 @@ -46,6 +47,7 @@ class AnalyticsPostPopularitySchema(Schema): class AnalyticsPostPopularityGroupSchema(Schema): + items: list[AnalyticsPostPopularitySchema] top_items: list[AnalyticsPostPopularitySchema] other_count: int = 0 total_count: int = 0 diff --git a/apps/analytics/api/views.py b/apps/analytics/api/views.py index cb87c21..c109dcf 100644 --- a/apps/analytics/api/views.py +++ b/apps/analytics/api/views.py @@ -114,13 +114,14 @@ def _normalize_entry_year(value) -> str: def _point_group_from_rows(rows: list[dict], *, limit: int = TOP_ITEMS_LIMIT): sorted_rows = sorted(rows, key=lambda item: (-int(item["value"] or 0), str(item["label"]))) - top_rows = sorted_rows[:limit] other_rows = sorted_rows[limit:] + items = [ + {"label": _label(item["label"]), "value": int(item["value"] or 0)} + for item in sorted_rows + ] return { - "top_items": [ - {"label": _label(item["label"]), "value": int(item["value"] or 0)} - for item in top_rows - ], + "items": items, + "top_items": items[:limit], "other_count": len(other_rows), "total_count": len(sorted_rows), } @@ -147,13 +148,14 @@ def _point_group_queryset(queryset, label_field: str, *, limit: int = TOP_ITEMS_ .order_by("-value", label_field) ) total_count = len(rows) - top_rows = rows[:limit] other_rows = rows[limit:] + items = [ + {"label": _label(item.get(label_field)), "value": int(item["value"] or 0)} + for item in rows + ] return { - "top_items": [ - {"label": _label(item.get(label_field)), "value": int(item["value"] or 0)} - for item in top_rows - ], + "items": items, + "top_items": items[:limit], "other_count": len(other_rows), "total_count": total_count, } @@ -502,6 +504,17 @@ def admin_blog_analytics(request, date_from: str | None = None, date_to: str | N } for post in post_popularity_all[:TOP_ITEMS_LIMIT] ] + post_popularity_items = [ + { + "id": post.id, + "title": post.title, + "slug": post.slug, + "likes": post.likes_total, + "saves": post.saves_total, + "comments": post.comments_total, + } + for post in post_popularity_all + ] top_posts = [ { **post, @@ -537,6 +550,7 @@ def admin_blog_analytics(request, date_from: str | None = None, date_to: str | N }, "activity_trend": list(activity_buckets.values()), "post_popularity": { + "items": post_popularity_items, "top_items": post_popularity, "other_count": max(len(post_popularity_all) - TOP_ITEMS_LIMIT, 0), "total_count": len(post_popularity_all),