CSV generation in the webserver

This commit is contained in:
Niklas Kapelle 2025-04-16 23:02:28 +02:00
parent 880e8f24a7
commit 0f189b8e98
Signed by: niklas
GPG Key ID: 4EB651B36D841D16
3 changed files with 30 additions and 15 deletions

View File

@ -58,6 +58,7 @@ impl IDStore {
}
pub fn export_csv(&self) -> Result<String, Box<dyn Error>> {
let mut csv = String::new();
let seperator = ";";
let mut user_ids: HashSet<TallyID> = HashSet::new();
@ -74,23 +75,22 @@ impl IDStore {
days.sort();
let header = days.join(seperator);
println!("ID,{}", header);
csv.push_str(&format!("ID{}{}\n", seperator, header));
for user_id in user_ids.iter() {
print!("{},", user_id.0);
csv.push_str(&user_id.0.to_string());
for day in days.iter() {
let was_there: bool = self.days.get(day).unwrap().ids.contains(user_id);
let was_there: bool = self.days.get(day).ok_or("Failed to access day")?.ids.contains(user_id);
if was_there {
print!("{}x", seperator);
csv.push_str(&format!("{}x", seperator));
} else {
print!("{}", seperator);
csv.push_str(seperator);
}
}
println!();
csv.push('\n');
}
Ok("".to_owned())
Ok(csv)
}
}

View File

@ -26,15 +26,15 @@ async fn main() {
});
let store:Arc<Mutex<IDStore>> = Arc::new(Mutex::new(id_store::IDStore::new()));
let channel_store = store.clone();
tokio::spawn(async move {
while let Some(tally_id_string) = rx.recv().await {
println!("Got from channel: {}", tally_id_string);
store.lock().await.add_id(id_store::TallyID(tally_id_string));
channel_store.lock().await.add_id(id_store::TallyID(tally_id_string));
}
});
match start_webserver().await {
match start_webserver(store.clone()).await {
Ok(()) => {}
Err(e) => {
eprintln!("Failed to start webserver: {}", e);

View File

@ -1,15 +1,19 @@
use rocket::Config;
use rocket::http::Status;
use rocket::{Config, State};
use rocket::{get, http::ContentType, response::content::RawHtml, routes};
use rust_embed::Embed;
use std::borrow::Cow;
use std::ffi::OsStr;
use std::sync::Arc;
use tokio::sync::Mutex;
use crate::id_store::IDStore;
#[derive(Embed)]
#[folder = "web/dist"]
struct Asset;
pub async fn start_webserver() -> Result<(), rocket::Error> {
pub async fn start_webserver(store: Arc<Mutex<IDStore>>) -> Result<(), rocket::Error> {
let config = Config {
address: "0.0.0.0".parse().unwrap(), // Listen on all interfaces
port: 8000,
@ -17,13 +21,13 @@ pub async fn start_webserver() -> Result<(), rocket::Error> {
};
rocket::custom(config)
.mount("/", routes![static_files,index])
.mount("/", routes![static_files, index, export_csv])
.manage(store)
.launch()
.await?;
Ok(())
}
#[get("/")]
fn index() -> Option<RawHtml<Cow<'static, [u8]>>> {
let asset = Asset::get("index.html")?;
@ -42,3 +46,14 @@ fn static_files(file: std::path::PathBuf) -> Option<(ContentType, Vec<u8>)> {
Some((content_type, asset.data.into_owned()))
}
#[get("/api/csv")]
async fn export_csv(manager: &State<Arc<Mutex<IDStore>>>) -> Result<String, Status> {
match manager.lock().await.export_csv() {
Ok(csv) => Ok(csv),
Err(e) => {
eprintln!("Failed to generate csv: {}", e);
Err(Status::InternalServerError)
}
}
}