This commit is contained in:
Philipp Hofer 2025-04-06 23:12:50 +02:00
parent 865760d81a
commit af2e6d72a5
4 changed files with 86 additions and 46 deletions

View File

@ -1,4 +1,4 @@
use axum::{body::Body, response::Response, routing::get, Router}; use axum::{Router, body::Body, response::Response, routing::get};
use sqlx::SqlitePool; use sqlx::SqlitePool;
use std::sync::Arc; use std::sync::Arc;
use tokio::net::TcpListener; use tokio::net::TcpListener;

View File

@ -1,5 +1,5 @@
use dotenv::dotenv; use dotenv::dotenv;
use sqlx::{pool::PoolOptions, SqlitePool}; use sqlx::{SqlitePool, pool::PoolOptions};
use std::env; use std::env;
#[tokio::main] #[tokio::main]

View File

@ -1,4 +1,4 @@
use maud::{html, Markup, DOCTYPE}; use maud::{DOCTYPE, Markup, html};
use tower_sessions::Session; use tower_sessions::Session;
pub(crate) async fn page(content: Markup, session: Session, leaflet: bool) -> Markup { pub(crate) async fn page(content: Markup, session: Session, leaflet: bool) -> Markup {

View File

@ -1,11 +1,11 @@
use crate::{err, partials::page, station::Station, succ}; use crate::{err, partials::page, station::Station, succ};
use axum::{ use axum::{
Form, Router,
extract::State, extract::State,
response::{IntoResponse, Redirect}, response::{IntoResponse, Redirect},
routing::{get, post}, routing::{get, post},
Form, Router,
}; };
use maud::{html, Markup}; use maud::{Markup, html};
use serde::Deserialize; use serde::Deserialize;
use sqlx::SqlitePool; use sqlx::SqlitePool;
use std::sync::Arc; use std::sync::Arc;
@ -21,17 +21,19 @@ async fn create(
session: Session, session: Session,
Form(form): Form<CreateForm>, Form(form): Form<CreateForm>,
) -> impl IntoResponse { ) -> impl IntoResponse {
match Station::create(&db, &form.name).await{ match Station::create(&db, &form.name).await {
Ok(_) => Ok(_) => session
session .insert(
.insert( "succ",
"succ", &format!("Station '{}' erfolgreich erstellt!", form.name),
&format!("Station '{}' erfolgreich erstellt!", form.name), )
) .await
.await .unwrap(),
.unwrap(), Err(e) => err!(
Err(e) => err!(session, "Station '{}' konnte _NICHT_ erstellt werden, da es bereits eine Station mit diesem Namen gibt ({e})!", form.name) session,
"Station '{}' konnte _NICHT_ erstellt werden, da es bereits eine Station mit diesem Namen gibt ({e})!",
form.name
),
} }
Redirect::to("/station") Redirect::to("/station")
@ -43,7 +45,10 @@ async fn delete(
axum::extract::Path(id): axum::extract::Path<i64>, axum::extract::Path(id): axum::extract::Path<i64>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(station) = Station::find_by_id(&db, id).await else { let Some(station) = Station::find_by_id(&db, id).await else {
err!(session, "Station mit ID {id} konnte nicht gelöscht werden, da sie nicht existiert"); err!(
session,
"Station mit ID {id} konnte nicht gelöscht werden, da sie nicht existiert"
);
return Redirect::to("/station"); return Redirect::to("/station");
}; };
@ -55,27 +60,31 @@ async fn delete(
Redirect::to("/station") Redirect::to("/station")
} }
async fn view(State(db): State<Arc<SqlitePool>>, session: Session, axum::extract::Path(id): axum::extract::Path<i64> async fn view(
) -> Result<Markup, impl IntoResponse> { State(db): State<Arc<SqlitePool>>,
session: Session,
axum::extract::Path(id): axum::extract::Path<i64>,
) -> Result<Markup, impl IntoResponse> {
let Some(station) = Station::find_by_id(&db, id).await else { let Some(station) = Station::find_by_id(&db, id).await else {
err!(session,"Station mit ID {id} konnte nicht geöffnet werden, da sie nicht existiert"); err!(
session,
"Station mit ID {id} konnte nicht geöffnet werden, da sie nicht existiert"
);
return Err(Redirect::to("/station")); return Err(Redirect::to("/station"));
}; };
// maybe switch to maud-display impl of station // maybe switch to maud-display impl of station
let content = html! { let content = html! {
h1 { h1 {
a href="/station" { "↩️" } a href="/station" { "↩️" }
"Station " (station.name) "Station " (station.name)
} }
table { table {
tbody { tbody {
tr { tr {
th scope="row" { "Notizen" }; th scope="row" { "Notizen" };
td { td {
@match station.notes { @match station.notes {
Some(notes) => { Some(notes) => {
(notes) (notes)
@ -99,7 +108,7 @@ async fn view(State(db): State<Arc<SqlitePool>>, session: Session, axum::extract
} }
tr { tr {
th scope="row" { "Stations-Code" }; th scope="row" { "Stations-Code" };
td { td {
(station.pw) (station.pw)
article class="warning" { article class="warning" {
(format!("Diesen Code nur Betreuern der Station {} geben! Mit diesem Code erhält man die Berechtigung, Gruppen zu bewerten.", station.name)) (format!("Diesen Code nur Betreuern der Station {} geben! Mit diesem Code erhält man die Berechtigung, Gruppen zu bewerten.", station.name))
@ -108,7 +117,7 @@ async fn view(State(db): State<Arc<SqlitePool>>, session: Session, axum::extract
} }
tr { tr {
th scope="row" { "Anzahl Stationsbetreuer" }; th scope="row" { "Anzahl Stationsbetreuer" };
td { td {
@match station.amount_people { @match station.amount_people {
Some(amount) => (amount), Some(amount) => (amount),
None => "?", None => "?",
@ -131,7 +140,7 @@ async fn view(State(db): State<Arc<SqlitePool>>, session: Session, axum::extract
} }
tr { tr {
th scope="row" { "Letzter Login eines Stationsbetreuers" }; th scope="row" { "Letzter Login eines Stationsbetreuers" };
td { td {
@match station.last_login { @match station.last_login {
Some(last_login) => (last_login), Some(last_login) => (last_login),
None => "noch nicht eingeloggt :-(", None => "noch nicht eingeloggt :-(",
@ -217,7 +226,6 @@ async fn view(State(db): State<Arc<SqlitePool>>, session: Session, axum::extract
Ok(page(content, session, true).await) Ok(page(content, session, true).await)
} }
#[derive(Deserialize)] #[derive(Deserialize)]
struct UpdateNotesForm { struct UpdateNotesForm {
notes: String, notes: String,
@ -226,17 +234,24 @@ async fn update_notes(
State(db): State<Arc<SqlitePool>>, State(db): State<Arc<SqlitePool>>,
session: Session, session: Session,
axum::extract::Path(id): axum::extract::Path<i64>, axum::extract::Path(id): axum::extract::Path<i64>,
Form(form): Form<UpdateNotesForm> Form(form): Form<UpdateNotesForm>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(station) = Station::find_by_id(&db, id).await else { let Some(station) = Station::find_by_id(&db, id).await else {
err!(session, "Station mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"); err!(
session,
"Station mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"
);
return Redirect::to("/station"); return Redirect::to("/station");
}; };
station.update_notes(&db, &form.notes).await; station.update_notes(&db, &form.notes).await;
succ!(session,"Notizen für die Station '{}' wurden erfolgreich bearbeitet!", station.name); succ!(
session,
"Notizen für die Station '{}' wurden erfolgreich bearbeitet!",
station.name
);
Redirect::to(&format!("/station/{id}")) Redirect::to(&format!("/station/{id}"))
} }
@ -249,17 +264,24 @@ async fn update_amount_people(
State(db): State<Arc<SqlitePool>>, State(db): State<Arc<SqlitePool>>,
session: Session, session: Session,
axum::extract::Path(id): axum::extract::Path<i64>, axum::extract::Path(id): axum::extract::Path<i64>,
Form(form): Form<UpdateAmountPeopleForm> Form(form): Form<UpdateAmountPeopleForm>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(station) = Station::find_by_id(&db, id).await else { let Some(station) = Station::find_by_id(&db, id).await else {
err!(session, "Station mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"); err!(
session,
"Station mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"
);
return Redirect::to("/station"); return Redirect::to("/station");
}; };
station.update_amount_people(&db, form.amount_people).await; station.update_amount_people(&db, form.amount_people).await;
succ!(session, "Anzahl an Betreuer für die Station '{}' wurden erfolgreich bearbeitet!", station.name); succ!(
session,
"Anzahl an Betreuer für die Station '{}' wurden erfolgreich bearbeitet!",
station.name
);
Redirect::to(&format!("/station/{id}")) Redirect::to(&format!("/station/{id}"))
} }
@ -270,14 +292,21 @@ async fn update_amount_people_reset(
axum::extract::Path(id): axum::extract::Path<i64>, axum::extract::Path(id): axum::extract::Path<i64>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(station) = Station::find_by_id(&db, id).await else { let Some(station) = Station::find_by_id(&db, id).await else {
err!(session, "Station mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"); err!(
session,
"Station mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"
);
return Redirect::to("/station"); return Redirect::to("/station");
}; };
station.update_amount_people_reset(&db).await; station.update_amount_people_reset(&db).await;
succ!(session, "Anzahl an Betreuer für die Station '{}' wurden erfolgreich bearbeitet!", station.name); succ!(
session,
"Anzahl an Betreuer für die Station '{}' wurden erfolgreich bearbeitet!",
station.name
);
Redirect::to(&format!("/station/{id}")) Redirect::to(&format!("/station/{id}"))
} }
@ -291,45 +320,56 @@ async fn update_location(
State(db): State<Arc<SqlitePool>>, State(db): State<Arc<SqlitePool>>,
session: Session, session: Session,
axum::extract::Path(id): axum::extract::Path<i64>, axum::extract::Path(id): axum::extract::Path<i64>,
Form(form): Form<UpdateLocationForm> Form(form): Form<UpdateLocationForm>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(station) = Station::find_by_id(&db, id).await else { let Some(station) = Station::find_by_id(&db, id).await else {
err!(session, "Station mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"); err!(
session,
"Station mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"
);
return Redirect::to("/station"); return Redirect::to("/station");
}; };
station.update_location(&db, form.lat, form.lng).await; station.update_location(&db, form.lat, form.lng).await;
succ!(session, "Standort für die Station '{}' wurden erfolgreich bearbeitet!", station.name); succ!(
session,
"Standort für die Station '{}' wurden erfolgreich bearbeitet!",
station.name
);
Redirect::to(&format!("/station/{id}")) Redirect::to(&format!("/station/{id}"))
} }
async fn update_location_clear ( async fn update_location_clear(
State(db): State<Arc<SqlitePool>>, State(db): State<Arc<SqlitePool>>,
session: Session, session: Session,
axum::extract::Path(id): axum::extract::Path<i64>, axum::extract::Path(id): axum::extract::Path<i64>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let Some(station) = Station::find_by_id(&db, id).await else { let Some(station) = Station::find_by_id(&db, id).await else {
err!(session, "Station mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"); err!(
session,
"Station mit ID {id} konnte nicht bearbeitet werden, da sie nicht existiert"
);
return Redirect::to("/station"); return Redirect::to("/station");
}; };
station.update_location_clear(&db).await; station.update_location_clear(&db).await;
succ!(
succ!(session, "Standort für die Station '{}' wurden erfolgreich gelöscht!", station.name); session,
"Standort für die Station '{}' wurden erfolgreich gelöscht!",
station.name
);
Redirect::to(&format!("/station/{id}")) Redirect::to(&format!("/station/{id}"))
} }
async fn index(State(db): State<Arc<SqlitePool>>, session: Session) -> Markup { async fn index(State(db): State<Arc<SqlitePool>>, session: Session) -> Markup {
let stations = Station::all(&db).await; let stations = Station::all(&db).await;
let content = html! { let content = html! {
h1 { "Stationen" } h1 { "Stationen" }
ol { ol {