From ee9c4b1ac1ce9e9798e5fcba5355e7f192c3969b Mon Sep 17 00:00:00 2001 From: Max Hohlfeld Date: Fri, 17 Jan 2025 22:44:17 +0100 Subject: [PATCH] feat: delete event and list assignments in overview --- ...3eba3793ecf697355e81012e721357ba351b9.json | 14 ++++ .../endpoints/availability/get_overview.rs | 79 ++++++++++++++++--- web/src/endpoints/events/delete.rs | 40 ++++++++++ web/src/endpoints/events/mod.rs | 3 +- web/src/endpoints/events/put_cancelation.rs | 2 - web/src/endpoints/mod.rs | 1 + web/src/models/assignement.rs | 2 +- web/src/models/event.rs | 16 +++- web/templates/events/new_or_edit.html | 10 ++- web/templates/index.html | 26 +++++- 10 files changed, 175 insertions(+), 18 deletions(-) create mode 100644 .sqlx/query-4bfce344fc6f0bfbb2b460677ce3eba3793ecf697355e81012e721357ba351b9.json create mode 100644 web/src/endpoints/events/delete.rs diff --git a/.sqlx/query-4bfce344fc6f0bfbb2b460677ce3eba3793ecf697355e81012e721357ba351b9.json b/.sqlx/query-4bfce344fc6f0bfbb2b460677ce3eba3793ecf697355e81012e721357ba351b9.json new file mode 100644 index 00000000..eaa739ca --- /dev/null +++ b/.sqlx/query-4bfce344fc6f0bfbb2b460677ce3eba3793ecf697355e81012e721357ba351b9.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM event WHERE id = $1;", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4" + ] + }, + "nullable": [] + }, + "hash": "4bfce344fc6f0bfbb2b460677ce3eba3793ecf697355e81012e721357ba351b9" +} diff --git a/web/src/endpoints/availability/get_overview.rs b/web/src/endpoints/availability/get_overview.rs index 680a76e4..01436353 100644 --- a/web/src/endpoints/availability/get_overview.rs +++ b/web/src/endpoints/availability/get_overview.rs @@ -1,4 +1,8 @@ -use crate::{filters, utils::ApplicationError}; +use crate::{ + filters, + models::{Assignment, Function}, + utils::ApplicationError, +}; use actix_web::{web, HttpResponse, Responder}; use chrono::{NaiveDate, Utc}; use rinja::Template; @@ -20,7 +24,7 @@ struct CalendarTemplate { date: NaiveDate, selected_area: Option, areas: Vec, - events: Vec, + events_and_assignments: Vec<(Event, Vec, Option, Option)>, availabillities: Vec, } @@ -48,13 +52,6 @@ async fn get( None => None, }; - let events = Event::read_all_by_date_and_area_including_location( - pool.get_ref(), - date, - query.area.unwrap_or(user.area_id), - ) - .await?; - let availabillities = Availabillity::read_by_date_and_area_including_user( pool.get_ref(), date, @@ -62,12 +59,74 @@ async fn get( ) .await?; + let mut events_and_assignments = Vec::new(); + for e in Event::read_all_by_date_and_area_including_location( + pool.get_ref(), + date, + query.area.unwrap_or(user.area_id), + ) + .await? + .into_iter() + { + let assignments = Assignment::read_all_by_event(pool.get_ref(), e.id).await?; + let (posten, rest): (Vec, Vec) = assignments + .into_iter() + .partition(|a| a.function == Function::Posten); + let (wachhabender, fuehrungsassistent): (Vec, Vec) = rest + .into_iter() + .partition(|a| a.function == Function::Wachhabender); + + events_and_assignments.push(( + e, + posten + .into_iter() + .map(|p| { + availabillities + .iter() + .find(|a| a.id == p.availabillity_id) + .unwrap() + .user + .as_ref() + .unwrap() + .name + .clone() + }) + .collect(), + fuehrungsassistent.first().and_then(|fa| { + Some( + availabillities + .iter() + .find(|a| a.id == fa.availabillity_id) + .unwrap() + .user + .as_ref() + .unwrap() + .name + .clone(), + ) + }), + wachhabender.first().and_then(|wh| { + Some( + availabillities + .iter() + .find(|a| a.id == wh.availabillity_id) + .unwrap() + .user + .as_ref() + .unwrap() + .name + .clone(), + ) + }), + )); + } + let template = CalendarTemplate { user: user.into_inner(), date, selected_area, areas, - events, + events_and_assignments, availabillities, }; diff --git a/web/src/endpoints/events/delete.rs b/web/src/endpoints/events/delete.rs new file mode 100644 index 00000000..359a5438 --- /dev/null +++ b/web/src/endpoints/events/delete.rs @@ -0,0 +1,40 @@ +use actix_web::{web, HttpResponse, Responder}; +use sqlx::PgPool; + +use crate::{ + endpoints::IdPath, + models::{Assignment, Event, Role, User}, + utils::{self, ApplicationError}, +}; + +#[actix_web::delete("/events/{id}")] +pub async fn delete( + user: web::ReqData, + pool: web::Data, + path: web::Path, +) -> Result { + if user.role != Role::Admin && user.role != Role::AreaManager { + return Err(ApplicationError::Unauthorized); + } + + let Some(event) = Event::read_by_id_including_location(pool.get_ref(), path.id).await? else { + return Ok(HttpResponse::NotFound().finish()); + }; + + if user.role != Role::Admin && user.area_id != event.location.as_ref().unwrap().area_id { + return Ok(HttpResponse::BadRequest().body("Can't use location outside of your area")); + } + + let assignments_for_event = Assignment::read_all_by_event(pool.get_ref(), event.id).await?; + + if assignments_for_event.len() > 0 { + return Ok(HttpResponse::BadRequest().body("Can't delete event when people are assigned")); + } + + Event::delete(pool.get_ref(), event.id).await?; + + let url = utils::get_return_url_for_date(&event.date); + Ok(HttpResponse::Ok() + .insert_header(("HX-LOCATION", url)) + .finish()) +} diff --git a/web/src/endpoints/events/mod.rs b/web/src/endpoints/events/mod.rs index 9b067bdd..e7f2e081 100644 --- a/web/src/endpoints/events/mod.rs +++ b/web/src/endpoints/events/mod.rs @@ -4,11 +4,12 @@ use rinja::Template; use crate::models::{Event, Location, Role, User}; +pub mod delete; pub mod get_edit; pub mod get_new; pub mod get_plan; -pub mod post_new; pub mod post_edit; +pub mod post_new; pub mod put_cancelation; #[derive(Template)] diff --git a/web/src/endpoints/events/put_cancelation.rs b/web/src/endpoints/events/put_cancelation.rs index 5f7c90e6..40df4a60 100644 --- a/web/src/endpoints/events/put_cancelation.rs +++ b/web/src/endpoints/events/put_cancelation.rs @@ -1,4 +1,3 @@ -use actix_http::header::LOCATION; use actix_web::{web, HttpResponse, Responder}; use sqlx::PgPool; @@ -49,7 +48,6 @@ async fn handle_set_event_cancelation_to( } let url = utils::get_return_url_for_date(&event.date); - println!("redirecto to {url}"); Ok(HttpResponse::Ok() .insert_header(("HX-LOCATION", url)) .finish()) diff --git a/web/src/endpoints/mod.rs b/web/src/endpoints/mod.rs index 8777faa7..25899586 100644 --- a/web/src/endpoints/mod.rs +++ b/web/src/endpoints/mod.rs @@ -63,6 +63,7 @@ pub fn init(cfg: &mut ServiceConfig) { cfg.service(events::get_plan::get); cfg.service(events::get_edit::get); cfg.service(events::post_edit::post); + cfg.service(events::delete::delete); cfg.service(assignment::post_new::post); cfg.service(assignment::delete::delete); diff --git a/web/src/models/assignement.rs b/web/src/models/assignement.rs index 592ef65d..3d83adbd 100644 --- a/web/src/models/assignement.rs +++ b/web/src/models/assignement.rs @@ -16,7 +16,7 @@ impl Assignment { pool: &PgPool, event_id: i32, availabillity_id: i32, - changeset: AssignmentChangeset + changeset: AssignmentChangeset, ) -> Result<()> { query!( r##" diff --git a/web/src/models/event.rs b/web/src/models/event.rs index db7f982b..99b893cd 100644 --- a/web/src/models/event.rs +++ b/web/src/models/event.rs @@ -160,7 +160,21 @@ impl Event { } pub async fn update_cancelation(pool: &PgPool, id: i32, canceled: bool) -> Result<()> { - query!("UPDATE event SET canceled = $1 WHERE id = $2;", canceled, id).execute(pool).await?; + query!( + "UPDATE event SET canceled = $1 WHERE id = $2;", + canceled, + id + ) + .execute(pool) + .await?; + + Ok(()) + } + + pub async fn delete(pool: &PgPool, id: i32) -> Result<()> { + query!("DELETE FROM event WHERE id = $1;", id) + .execute(pool) + .await?; Ok(()) } diff --git a/web/templates/events/new_or_edit.html b/web/templates/events/new_or_edit.html index 606e6d12..dff47b76 100644 --- a/web/templates/events/new_or_edit.html +++ b/web/templates/events/new_or_edit.html @@ -30,13 +30,21 @@
-
+ {% if delete_disabled %} +

+ Löschen nicht möglich, da bereits eine Planung existiert. +

+ {% endif %} diff --git a/web/templates/index.html b/web/templates/index.html index 560ec2b1..2f5bd047 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -69,12 +69,12 @@ {% endif %} - {% if events.len() == 0 %} + {% if events_and_assignments.len() == 0 %}
keine Events geplant
{% else %} - {% for event in events %} + {% for (event, posten, fuehrungsassistent, wachhabender) in events_and_assignments %}
@@ -135,6 +135,28 @@
{% endif %} +
+
+
+ + {% if let Some(wh) = wachhabender %} +
+

Wachhabender geplant: {{ wh }}

+
+ {% endif %} + + {% if let Some(fa) = fuehrungsassistent %} +
+

fuehrungsassistent geplant: {{ fa }}

+
+ {% endif %} + + {% if posten.len() > 0 %} +
+

Posten: {{ posten.join(", ")}}

+
+ {% endif %} +