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.
This commit is contained in:
Lauryn Menard 2023-11-28 13:55:09 +01:00 committed by Tim Abbott
parent 4fc639cead
commit 5f48abd57a
4 changed files with 60 additions and 47 deletions

View File

@ -48,46 +48,22 @@ def make_table(
return content return content
def get_page( def fix_rows(
query: Composable, cols: Sequence[str], title: str, totals_columns: Sequence[int] = [] rows: List[List[Any]],
) -> Dict[str, str]: 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 = connection.cursor()
cursor.execute(query) cursor.execute(query)
rows = cursor.fetchall() rows = cursor.fetchall()
rows = list(map(list, rows)) rows = list(map(list, rows))
cursor.close() cursor.close()
return rows
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,
)
def dictfetchall(cursor: CursorWrapper) -> List[Dict[str, Any]]: def dictfetchall(cursor: CursorWrapper) -> List[Dict[str, Any]]:
@ -137,13 +113,11 @@ def realm_url_link(realm_str: str) -> Markup:
return Markup('<a href="{url}"><i class="fa fa-home"></i></a>').format(url=url) return Markup('<a href="{url}"><i class="fa fa-home"></i></a>').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 from analytics.views.stats import stats_for_remote_installation
url = reverse(stats_for_remote_installation, kwargs=dict(remote_server_id=server_id)) url = reverse(stats_for_remote_installation, kwargs=dict(remote_server_id=server_id))
return Markup('<a href="{url}"><i class="fa fa-pie-chart"></i></a> {hostname}').format( return Markup('<a href="{url}"><i class="fa fa-pie-chart"></i></a>').format(url=url)
url=url, hostname=hostname
)
def remote_installation_support_link(hostname: str) -> Markup: def remote_installation_support_link(hostname: str) -> Markup:

View File

@ -13,7 +13,10 @@ from psycopg2.sql import SQL
from analytics.lib.counts import COUNT_STATS from analytics.lib.counts import COUNT_STATS
from analytics.views.activity_common import ( from analytics.views.activity_common import (
dictfetchall, dictfetchall,
get_page, fix_rows,
format_date_for_activity_reports,
get_query_data,
make_table,
realm_activity_link, realm_activity_link,
realm_stats_link, realm_stats_link,
realm_support_link, realm_support_link,
@ -327,14 +330,20 @@ def get_integrations_activity(request: HttpRequest) -> HttpResponse:
"Last time", "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( return render(
request, request,
"analytics/activity_details_template.html", "analytics/activity_details_template.html",
context=dict( context=dict(
data=integrations_activity["content"], data=content,
title=integrations_activity["title"], title=title,
is_home=False, is_home=False,
), ),
) )

View File

@ -2,7 +2,14 @@ from django.http import HttpRequest, HttpResponse
from django.shortcuts import render from django.shortcuts import render
from psycopg2.sql import SQL 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 from zerver.decorator import require_server_admin
@ -48,12 +55,34 @@ def get_remote_server_activity(request: HttpRequest) -> HttpResponse:
"Analytics users", "Analytics users",
"Mobile users", "Mobile users",
"Last update time", "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( return render(
request, request,
"analytics/activity_details_template.html", "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),
) )

View File

@ -50,8 +50,9 @@ not_yet_fully_covered = [
"analytics/lib/fixtures.py", "analytics/lib/fixtures.py",
# We have 100% coverage on the new stuff; need to refactor old stuff. # We have 100% coverage on the new stuff; need to refactor old stuff.
"analytics/views/activity_common.py", "analytics/views/activity_common.py",
"analytics/views/realm_activity.py",
"analytics/views/installation_activity.py", "analytics/views/installation_activity.py",
"analytics/views/realm_activity.py",
"analytics/views/remote_activity.py",
"analytics/views/stats.py", "analytics/views/stats.py",
"analytics/views/support.py", "analytics/views/support.py",
# TODO: This is a work in progress and therefore without # TODO: This is a work in progress and therefore without