Skip to content

Commit

Permalink
Fix activity report by having the user pick months
Browse files Browse the repository at this point in the history
Just jumping back a number of months works fine for the activity _page_,
but not for the activity _report_, since the report actually needs to
deal with months. Instead of trying to be clever with auto-detecting the
months that the user wants, now I just have them pick from the months of
activity that exist in the database with a simple SQL query and multiple
select control.

Given that the user might have mis-selected the months or see data for
a different set of months, I also added a text link and corresponding
endpoint to delete the report from the cache so that the user doesn't
have to wait 6 hours for it to expire.
  • Loading branch information
Celeo committed Jan 1, 2025
1 parent 256f8fc commit 7893945
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 56 deletions.
65 changes: 48 additions & 17 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion vzdv-site/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ vzdv = { path = "../vzdv" }
indexmap = "2.0"
anyhow = "1.0.86"
axum = { version = "0.7.4", features = ["multipart"] }
axum-extra = "0.9.3"
axum-extra = { version = "0.9.3", features = ["query"] }
chrono = { version = "0.4.34", features = ["serde"] }
chrono-tz = "0.9.0"
clap = { version = "4.5.1", features = ["derive"] }
Expand Down
79 changes: 62 additions & 17 deletions vzdv-site/src/endpoints/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,21 @@ use crate::{
},
};
use axum::{
extract::{DefaultBodyLimit, Multipart, Path, Query, State},
extract::{DefaultBodyLimit, Multipart, Path, State},
response::{Html, IntoResponse, Redirect, Response},
routing::{delete, get, post},
Form, Router,
};
use chrono::{DateTime, Months, Utc};
use axum_extra::extract::Query;
use chrono::{DateTime, Utc};
use itertools::Itertools;
use log::{debug, error, warn};
use minijinja::context;
use reqwest::StatusCode;
use rev_buf_reader::RevBufReader;
use serde::{Deserialize, Serialize};
use serde_json::json;
use sqlx::Row;
use std::{collections::HashMap, io::BufRead, path::Path as FilePath, sync::Arc, time::Instant};
use tower_sessions::Session;
use uuid::Uuid;
Expand Down Expand Up @@ -828,13 +831,28 @@ async fn page_activity_report(
if let Some(redirect) = reject_if_not_in(&state, &user_info, PermissionsGroup::Admin).await {
return Ok(redirect.into_response());
}
let months = sqlx::query(sql::SELECT_ACTIVITY_JUST_MONTHS)
.fetch_all(&state.db)
.await?;
let months: Vec<String> = months
.iter()
.map(|row| row.try_get("month").unwrap())
.sorted()
.rev()
.collect();
let template = state
.templates
.get_template("admin/activity_report_container.jinja")?;
let rendered = template.render(context! { user_info })?;
let flashed_messages = flashed_messages::drain_flashed_messages(session).await?;
let rendered = template.render(context! { user_info, months, flashed_messages })?;
Ok(Html(rendered).into_response())
}

#[derive(Debug, Deserialize)]
struct ReportParams {
month: Vec<String>,
}

/// Page to render the activity report.
///
/// May take up to ~30 seconds to load, so will be loaded into the container page
Expand All @@ -844,6 +862,7 @@ async fn page_activity_report(
async fn page_activity_report_generate(
State(state): State<Arc<AppState>>,
session: Session,
months: Query<ReportParams>,
) -> Result<Response, AppError> {
#[derive(Serialize)]
struct BasicInfo {
Expand Down Expand Up @@ -876,18 +895,8 @@ async fn page_activity_report_generate(
true,
)
.await?;
let now = Utc::now();
let months: [String; 3] = [
now.format("%Y-%m").to_string(),
now.checked_sub_months(Months::new(1))
.unwrap()
.format("%Y-%m")
.to_string(),
now.checked_sub_months(Months::new(2))
.unwrap()
.format("%Y-%m")
.to_string(),
];

let months = &months.month;
let controllers: Vec<Controller> = sqlx::query_as(sql::GET_ALL_CONTROLLERS_ON_ROSTER)
.fetch_all(&state.db)
.await?;
Expand All @@ -904,7 +913,6 @@ async fn page_activity_report_generate(
.or_insert(activity.minutes);
acc
});

let rated_violations: Vec<BasicInfo> = controllers
.iter()
.filter(|controller| {
Expand Down Expand Up @@ -946,7 +954,14 @@ async fn page_activity_report_generate(
continue;
}
};
if records.is_empty() {
let in_time_frame = records
.iter()
.filter(|r| {
let month = &r.session_date[0..7];
months.contains(&month.to_string())
})
.count();
if in_time_frame == 0 {
unrated_violations.push(BasicInfo {
cid: controller.cid,
name: format!(
Expand All @@ -973,6 +988,7 @@ async fn page_activity_report_generate(
controllers,
rated_violations,
unrated_violations,
months => months.iter().join(", "),
now_utc => Utc::now().to_rfc2822(),
})?;
state
Expand All @@ -981,6 +997,31 @@ async fn page_activity_report_generate(
Ok(Html(rendered).into_response())
}

/// Clear the existing activity report out of the cache.
async fn page_activity_report_delete(
State(state): State<Arc<AppState>>,
session: Session,
) -> Result<Redirect, AppError> {
let user_info: Option<UserInfo> = session.get(SESSION_USER_INFO_KEY).await?;
if let Some(redirect) = reject_if_not_in(&state, &user_info, PermissionsGroup::Admin).await {
return Ok(redirect);
}
state.cache.invalidate(&"ACTIVITY_REPORT".to_string());
record_log(
format!("{} deleted the activity report", user_info.unwrap().cid),
&state.db,
true,
)
.await?;
flashed_messages::push_flashed_message(
session,
MessageLevel::Success,
"Activity report deleted",
)
.await?;
Ok(Redirect::to("/admin/activity_report"))
}

/// Page to centrally view all active solo certs.
///
/// All staff members only.
Expand Down Expand Up @@ -1282,6 +1323,10 @@ pub fn router() -> Router<Arc<AppState>> {
"/admin/activity_report/generate",
get(page_activity_report_generate),
)
.route(
"/admin/activity_report/delete",
get(page_activity_report_delete),
)
.route("/admin/solo_cert_list", get(page_solo_cert_list))
.route(
"/admin/no_show_list",
Expand Down
10 changes: 9 additions & 1 deletion vzdv-site/templates/admin/activity_report.jinja
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<h2>Activity report</h2>

<p>Months: {{ months }} </p>

<h3>Rated controller violations</h3>
<table class="table table-striped table-hover">
<thead>
Expand Down Expand Up @@ -52,4 +56,8 @@
</tbody>
</table>

<p class="pt-3">Generated at: {{ now_utc }}; cached for 6 hours afterwards</p>
<p class="pt-3">
Generated at: {{ now_utc }}; cached for 6 hours afterwards
<br>
Click <a href="/admin/activity_report/delete" class="text-decoration-none">here</a> to clear that cache.
</p>
Loading

0 comments on commit 7893945

Please sign in to comment.