From a3db0a9fc07c2c203c62381adc5492fae8633051 Mon Sep 17 00:00:00 2001 From: Beverly Nguyen Date: Mon, 6 Jan 2025 16:31:52 -0800 Subject: [PATCH 01/63] first round --- app/assets/javascripts/activityChart.js | 24 +++++--- app/formatters.py | 2 +- app/main/views/dashboard.py | 63 ++++++++++++-------- app/main/views/jobs.py | 14 ++++- app/notify_client/job_api_client.py | 2 +- app/templates/components/big-number.html | 1 + app/templates/components/pill.html | 1 + app/templates/partials/count.html | 1 + app/templates/partials/jobs/status.html | 2 +- app/templates/views/dashboard/dashboard.html | 7 +-- 10 files changed, 74 insertions(+), 43 deletions(-) diff --git a/app/assets/javascripts/activityChart.js b/app/assets/javascripts/activityChart.js index 62c1e6e3e..1c1238c6b 100644 --- a/app/assets/javascripts/activityChart.js +++ b/app/assets/javascripts/activityChart.js @@ -5,6 +5,7 @@ const COLORS = { delivered: '#0076d6', failed: '#fa9441', + pending: '#808080', text: '#666' }; @@ -45,7 +46,8 @@ // Show legend if there are messages const legendData = [ { label: 'Delivered', color: COLORS.delivered }, - { label: 'Failed', color: COLORS.failed } + { label: 'Failed', color: COLORS.failed }, + { label: 'Pending', color: COLORS.pending } ]; const legendItem = legendContainer.selectAll('.legend-item') @@ -100,12 +102,13 @@ const stackData = labels.map((label, i) => ({ label: label, delivered: deliveredData[i], - failed: failedData[i] || 0 // Ensure there's a value for failed, even if it's 0 + failed: failedData[i] || 0, // Ensure there's a value for failed, even if it's 0 + pending: pendingData[i] || 0 })); // Stack the data const stack = d3.stack() - .keys(['delivered', 'failed']) + .keys(['delivered', 'failed', 'pending']) .order(d3.stackOrderNone) .offset(d3.stackOffsetNone); @@ -113,8 +116,8 @@ // Color scale const color = d3.scaleOrdinal() - .domain(['delivered', 'failed']) - .range([COLORS.delivered, COLORS.failed]); + .domain(['delivered', 'failed', 'pending']) + .range([COLORS.delivered, COLORS.failed, COLORS.pending]); // Create bars with animation const barGroups = svg.selectAll('.bar-group') @@ -164,7 +167,7 @@ // Create table header const headerRow = document.createElement('tr'); - const headers = ['Day', 'Delivered', 'Failed']; + const headers = ['Day', 'Delivered', 'Failed', 'Pending']; headers.forEach(headerText => { const th = document.createElement('th'); th.textContent = headerText; @@ -187,6 +190,10 @@ cellFailed.textContent = failedData[index]; row.appendChild(cellFailed); + const cellPending = document.createElement('td'); + cellPending.textContent = pendingData[index]; + row.appendChild(cellPending); + tbody.appendChild(row); }); @@ -213,6 +220,7 @@ labels = []; deliveredData = []; failedData = []; + pendingData = []; let totalMessages = 0; @@ -224,7 +232,7 @@ labels.push(formattedDate); deliveredData.push(data[dateString].sms.delivered); failedData.push(data[dateString].sms.failure); - + pendingData.push(data[dateString].sms.pending || 0); // Calculate the total number of messages totalMessages += data[dateString].sms.delivered + data[dateString].sms.failure; } @@ -260,7 +268,7 @@ }) .catch(error => console.error('Error fetching daily stats:', error)); }; - + // setInterval(() => fetchData('service'), 1000); const handleDropdownChange = function(event) { const selectedValue = event.target.value; const subTitle = document.querySelector(`#activityChartContainer .chart-subtitle`); diff --git a/app/formatters.py b/app/formatters.py index c427c2a9a..448e5d6cb 100644 --- a/app/formatters.py +++ b/app/formatters.py @@ -493,7 +493,7 @@ def message_count_noun(count, template_type): def message_count(count, template_type): - return f"{format_thousands(count)} " f"{message_count_noun(count, template_type)}" + return f"format_message_count{format_thousands(count)} " f"{message_count_noun(count, template_type)}" def recipient_count_label(count, template_type): diff --git a/app/main/views/dashboard.py b/app/main/views/dashboard.py index 8013acb9d..ce10d5f77 100644 --- a/app/main/views/dashboard.py +++ b/app/main/views/dashboard.py @@ -48,16 +48,8 @@ def service_dashboard(service_id): if not current_user.has_permissions("view_activity"): return redirect(url_for("main.choose_template", service_id=service_id)) - yearly_usage = billing_api_client.get_annual_usage_for_service( - service_id, - get_current_financial_year(), - ) - free_sms_allowance = billing_api_client.get_free_sms_fragment_limit_for_year( - current_service.id, - ) - usage_data = get_annual_usage_breakdown(yearly_usage, free_sms_allowance) - sms_sent = usage_data["sms_sent"] - sms_allowance_remaining = usage_data["sms_allowance_remaining"] + + job_response = job_api_client.get_jobs(service_id)["data"] service_data_retention_days = 7 @@ -89,24 +81,11 @@ def service_dashboard(service_id): partials=get_dashboard_partials(service_id), jobs=jobs, service_data_retention_days=service_data_retention_days, - sms_sent=sms_sent, - sms_allowance_remaining=sms_allowance_remaining, ) -@main.route("/daily_stats.json") -def get_daily_stats(): - service_id = session.get("service_id") - date_range = get_stats_date_range() - - stats = service_api_client.get_service_notification_statistics_by_day( - service_id, start_date=date_range["start_date"], days=date_range["days"] - ) - return jsonify(stats) - - -@main.route("/daily_stats_by_user.json") -def get_daily_stats_by_user(): +@main.route("/services//daily_stats_by_user.json") +def get_daily_stats_by_user(service_id): service_id = session.get("service_id") date_range = get_stats_date_range() user_id = current_user.id @@ -360,7 +339,35 @@ def aggregate_notifications_stats(template_statistics): return notifications +def fetch_daily_stats(service_id): + date_range = get_stats_date_range() + stats = service_api_client.get_service_notification_statistics_by_day( + service_id, start_date='2024-12-31', days=date_range["days"] + ) + return stats + +# Route using the helper +@main.route("/daily_stats.json") +def get_daily_stats(): + service_id = session.get("service_id") + stats = fetch_daily_stats(service_id) # Use the helper + return jsonify(stats) + + def get_dashboard_partials(service_id): + date_range = get_stats_date_range() + yearly_usage = billing_api_client.get_annual_usage_for_service( + service_id, + get_current_financial_year(), + ) + free_sms_allowance = billing_api_client.get_free_sms_fragment_limit_for_year( + current_service.id, + ) + + usage_data = get_annual_usage_breakdown(yearly_usage, free_sms_allowance) + sms_sent = usage_data["sms_sent"] + sms_allowance_remaining = usage_data["sms_allowance_remaining"] + activityStats = fetch_daily_stats all_statistics = template_statistics_client.get_template_statistics_for_service( service_id, limit_days=7 ) @@ -384,6 +391,12 @@ def get_dashboard_partials(service_id): get_current_financial_year(), ) return { + "activity": render_template( + "views/dashboard/_activity.html", + activityStats=activityStats, + sms_sent=sms_sent, + sms_allowance_remaining=sms_allowance_remaining, + ), "upcoming": render_template( "views/dashboard/_upcoming.html", ), diff --git a/app/main/views/jobs.py b/app/main/views/jobs.py index dddf838a1..784a37835 100644 --- a/app/main/views/jobs.py +++ b/app/main/views/jobs.py @@ -334,6 +334,18 @@ def get_status_filters(service, message_type, statistics): def _get_job_counts(job): + print(''' + + + + job + + + + + ''', dir(job)) + print(job.notifications_sending) + job_type = job.template_type return [ ( @@ -358,7 +370,7 @@ def _get_job_counts(job): ], [ Markup( - f"""pending + f"""pending--fdsjfisodj {message_count_noun(job.notifications_sending, job_type)}""" ), "pending", diff --git a/app/notify_client/job_api_client.py b/app/notify_client/job_api_client.py index 9a06e16bf..2cf8f9b6d 100644 --- a/app/notify_client/job_api_client.py +++ b/app/notify_client/job_api_client.py @@ -28,7 +28,7 @@ class JobApiClient(NotifyAdminAPIClient): def get_job(self, service_id, job_id): params = {} job = self.get(url=f"/service/{service_id}/job/{job_id}", params=params) - + # comment return job def get_jobs(self, service_id, *, limit_days=None, statuses=None, page=1): diff --git a/app/templates/components/big-number.html b/app/templates/components/big-number.html index fcb89b7e9..ff050d15c 100644 --- a/app/templates/components/big-number.html +++ b/app/templates/components/big-number.html @@ -2,6 +2,7 @@ {% if link %} {% endif %} + big number {% if number is number %} diff --git a/app/templates/components/pill.html b/app/templates/components/pill.html index bb1bb033a..8570d6fa9 100644 --- a/app/templates/components/pill.html +++ b/app/templates/components/pill.html @@ -8,6 +8,7 @@ ) %}