feat: delete event and list assignments in overview
This commit is contained in:
parent
0bb5f54f16
commit
ee9c4b1ac1
14
.sqlx/query-4bfce344fc6f0bfbb2b460677ce3eba3793ecf697355e81012e721357ba351b9.json
generated
Normal file
14
.sqlx/query-4bfce344fc6f0bfbb2b460677ce3eba3793ecf697355e81012e721357ba351b9.json
generated
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM event WHERE id = $1;",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "4bfce344fc6f0bfbb2b460677ce3eba3793ecf697355e81012e721357ba351b9"
|
||||
}
|
@ -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<i32>,
|
||||
areas: Vec<Area>,
|
||||
events: Vec<Event>,
|
||||
events_and_assignments: Vec<(Event, Vec<String>, Option<String>, Option<String>)>,
|
||||
availabillities: Vec<Availabillity>,
|
||||
}
|
||||
|
||||
@ -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<Assignment>, Vec<Assignment>) = assignments
|
||||
.into_iter()
|
||||
.partition(|a| a.function == Function::Posten);
|
||||
let (wachhabender, fuehrungsassistent): (Vec<Assignment>, Vec<Assignment>) = 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,
|
||||
};
|
||||
|
||||
|
40
web/src/endpoints/events/delete.rs
Normal file
40
web/src/endpoints/events/delete.rs
Normal file
@ -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<User>,
|
||||
pool: web::Data<PgPool>,
|
||||
path: web::Path<IdPath>,
|
||||
) -> Result<impl Responder, ApplicationError> {
|
||||
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())
|
||||
}
|
@ -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)]
|
||||
|
@ -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())
|
||||
|
@ -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);
|
||||
|
@ -16,7 +16,7 @@ impl Assignment {
|
||||
pool: &PgPool,
|
||||
event_id: i32,
|
||||
availabillity_id: i32,
|
||||
changeset: AssignmentChangeset
|
||||
changeset: AssignmentChangeset,
|
||||
) -> Result<()> {
|
||||
query!(
|
||||
r##"
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -30,13 +30,21 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button is-danger" type="button">
|
||||
{% let delete_disabled = amount_of_planned_posten > 0 || is_wachhabender_planned ||
|
||||
is_fuehrungsassistent_planned %}
|
||||
<button class="button is-danger" type="button" hx-delete="/events/{{ event.id }}" {{
|
||||
delete_disabled|cond_show("disabled") }} hx-trigger="confirmed">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#x-circle" />
|
||||
</svg>
|
||||
<span>Löschen</span>
|
||||
</button>
|
||||
</div>
|
||||
{% if delete_disabled %}
|
||||
<p class="help is-align-content-center">
|
||||
Löschen nicht möglich, da bereits eine Planung existiert.
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -69,12 +69,12 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if events.len() == 0 %}
|
||||
{% if events_and_assignments.len() == 0 %}
|
||||
<div class="box">
|
||||
<h5 class="subtitle is-5">keine Events geplant</h5>
|
||||
</div>
|
||||
{% else %}
|
||||
{% for event in events %}
|
||||
{% for (event, posten, fuehrungsassistent, wachhabender) in events_and_assignments %}
|
||||
<div class="box">
|
||||
<div class="fixed-grid has-1-cols-mobile">
|
||||
<div class="grid content">
|
||||
@ -135,6 +135,28 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="cell is-col-span-2">
|
||||
<hr class="my-1">
|
||||
</div>
|
||||
|
||||
{% if let Some(wh) = wachhabender %}
|
||||
<div class="cell">
|
||||
<p><b>Wachhabender geplant:</b> {{ wh }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if let Some(fa) = fuehrungsassistent %}
|
||||
<div class="cell">
|
||||
<p><b>fuehrungsassistent geplant:</b> {{ fa }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if posten.len() > 0 %}
|
||||
<div class="cell is-col-span-2">
|
||||
<p><b>Posten:</b> {{ posten.join(", ")}}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user