From 5f48abd57a23ede59f30266973e1a97f9666e68e Mon Sep 17 00:00:00 2001 From: Lauryn Menard Date: Tue, 28 Nov 2023 13:55:09 +0100 Subject: [PATCH] analytics: Add support link to remote installations page. Refactors get_page helper function so that the updates to the query data for each row is done in the function that processes the request. Adds columns to the remote installation page for both the support and analytics links. Adds `analytics/views/remote_activity.py` to the files without 100% backend test coverage. --- analytics/views/activity_common.py | 52 ++++++------------------ analytics/views/installation_activity.py | 17 ++++++-- analytics/views/remote_activity.py | 35 ++++++++++++++-- tools/test-backend | 3 +- 4 files changed, 60 insertions(+), 47 deletions(-) diff --git a/analytics/views/activity_common.py b/analytics/views/activity_common.py index c85cdad275..441e33589c 100644 --- a/analytics/views/activity_common.py +++ b/analytics/views/activity_common.py @@ -48,46 +48,22 @@ def make_table( return content -def get_page( - query: Composable, cols: Sequence[str], title: str, totals_columns: Sequence[int] = [] -) -> Dict[str, str]: +def fix_rows( + rows: List[List[Any]], + i: int, + fixup_func: Union[Callable[[str], Markup], Callable[[datetime], str]], +) -> None: + for row in rows: + row[i] = fixup_func(row[i]) + + +def get_query_data(query: Composable) -> List[List[Any]]: cursor = connection.cursor() cursor.execute(query) rows = cursor.fetchall() rows = list(map(list, rows)) cursor.close() - - def fix_rows( - i: int, fixup_func: Union[Callable[[str], Markup], Callable[[datetime], str]] - ) -> None: - for row in rows: - row[i] = fixup_func(row[i]) - - total_row = [] - for i, col in enumerate(cols): - if col == "Realm": - fix_rows(i, realm_activity_link) - elif col in ["Last time", "Last visit"]: - fix_rows(i, format_date_for_activity_reports) - elif col == "Hostname": - for row in rows: - row[i] = remote_installation_stats_link(row[0], row[i]) - if len(totals_columns) > 0: - if i == 0: - total_row.append("Total") - elif i in totals_columns: - total_row.append(str(sum(row[i] for row in rows if row[i] is not None))) - else: - total_row.append("") - if len(totals_columns) > 0: - rows.insert(0, total_row) - - content = make_table(title, cols, rows) - - return dict( - content=content, - title=title, - ) + return rows def dictfetchall(cursor: CursorWrapper) -> List[Dict[str, Any]]: @@ -137,13 +113,11 @@ def realm_url_link(realm_str: str) -> Markup: return Markup('').format(url=url) -def remote_installation_stats_link(server_id: int, hostname: str) -> Markup: +def remote_installation_stats_link(server_id: int) -> Markup: from analytics.views.stats import stats_for_remote_installation url = reverse(stats_for_remote_installation, kwargs=dict(remote_server_id=server_id)) - return Markup(' {hostname}').format( - url=url, hostname=hostname - ) + return Markup('').format(url=url) def remote_installation_support_link(hostname: str) -> Markup: diff --git a/analytics/views/installation_activity.py b/analytics/views/installation_activity.py index 6fc3ec9c8d..337a122e31 100644 --- a/analytics/views/installation_activity.py +++ b/analytics/views/installation_activity.py @@ -13,7 +13,10 @@ from psycopg2.sql import SQL from analytics.lib.counts import COUNT_STATS from analytics.views.activity_common import ( dictfetchall, - get_page, + fix_rows, + format_date_for_activity_reports, + get_query_data, + make_table, realm_activity_link, realm_stats_link, realm_support_link, @@ -327,14 +330,20 @@ def get_integrations_activity(request: HttpRequest) -> HttpResponse: "Last time", ] - integrations_activity = get_page(query, cols, title) + rows = get_query_data(query) + for i, col in enumerate(cols): + if col == "Realm": + fix_rows(rows, i, realm_activity_link) + elif col == "Last time": + fix_rows(rows, i, format_date_for_activity_reports) + content = make_table(title, cols, rows) return render( request, "analytics/activity_details_template.html", context=dict( - data=integrations_activity["content"], - title=integrations_activity["title"], + data=content, + title=title, is_home=False, ), ) diff --git a/analytics/views/remote_activity.py b/analytics/views/remote_activity.py index c246ad128e..9371eaaa01 100644 --- a/analytics/views/remote_activity.py +++ b/analytics/views/remote_activity.py @@ -2,7 +2,14 @@ from django.http import HttpRequest, HttpResponse from django.shortcuts import render from psycopg2.sql import SQL -from analytics.views.activity_common import get_page +from analytics.views.activity_common import ( + fix_rows, + format_date_for_activity_reports, + get_query_data, + make_table, + remote_installation_stats_link, + remote_installation_support_link, +) from zerver.decorator import require_server_admin @@ -48,12 +55,34 @@ def get_remote_server_activity(request: HttpRequest) -> HttpResponse: "Analytics users", "Mobile users", "Last update time", + "Analytics", + "Support", ] - remote_servers = get_page(query, cols, title, totals_columns=[3, 4]) + rows = get_query_data(query) + total_row = [] + totals_columns = [3, 4] + for row in rows: + stats = remote_installation_stats_link(row[0]) + row.append(stats) + for i, col in enumerate(cols): + if col == "Last update time": + fix_rows(rows, i, format_date_for_activity_reports) + if col == "Hostname": + for row in rows: + support = remote_installation_support_link(row[i]) + row.append(support) + if i == 0: + total_row.append("Total") + elif i in totals_columns: + total_row.append(str(sum(row[i] for row in rows if row[i] is not None))) + else: + total_row.append("") + rows.insert(0, total_row) + content = make_table(title, cols, rows) return render( request, "analytics/activity_details_template.html", - context=dict(data=remote_servers["content"], title=remote_servers["title"], is_home=False), + context=dict(data=content, title=title, is_home=False), ) diff --git a/tools/test-backend b/tools/test-backend index 9756e3f184..e802f631c4 100755 --- a/tools/test-backend +++ b/tools/test-backend @@ -50,8 +50,9 @@ not_yet_fully_covered = [ "analytics/lib/fixtures.py", # We have 100% coverage on the new stuff; need to refactor old stuff. "analytics/views/activity_common.py", - "analytics/views/realm_activity.py", "analytics/views/installation_activity.py", + "analytics/views/realm_activity.py", + "analytics/views/remote_activity.py", "analytics/views/stats.py", "analytics/views/support.py", # TODO: This is a work in progress and therefore without