From 28c562d82fd7dbd742e234413b3334f6dac550f9 Mon Sep 17 00:00:00 2001 From: Max Hohlfeld Date: Wed, 13 Mar 2024 23:50:46 +0100 Subject: [PATCH] feat: location overview and creation --- src/endpoints/location/get_new.rs | 38 ++++++++++++++++ src/endpoints/location/get_overview.rs | 22 ++++++--- src/endpoints/location/mod.rs | 2 + src/endpoints/location/post_new.rs | 34 ++++++++++++++ src/endpoints/mod.rs | 2 + templates/location/new.html | 63 ++++++++++++++++++++++++++ templates/location/overview.html | 21 +++++++-- 7 files changed, 170 insertions(+), 12 deletions(-) create mode 100644 src/endpoints/location/get_new.rs create mode 100644 src/endpoints/location/post_new.rs create mode 100644 templates/location/new.html diff --git a/src/endpoints/location/get_new.rs b/src/endpoints/location/get_new.rs new file mode 100644 index 00000000..7e09e0a9 --- /dev/null +++ b/src/endpoints/location/get_new.rs @@ -0,0 +1,38 @@ +use actix_identity::Identity; +use actix_web::{web, HttpResponse, Responder}; +use askama::Template; +use askama_actix::TemplateToResponse; +use sqlx::PgPool; + +use crate::models::{Area, Role, User}; + +#[derive(Template)] +#[template(path = "location/new.html")] +pub struct NewLocationTemplate { + user: User, + areas: Option>, +} + +#[actix_web::get("/locations/new")] +pub async fn get(user: Identity, pool: web::Data) -> impl Responder { + let current_user = User::read_by_id(pool.get_ref(), user.id().unwrap().parse().unwrap()) + .await + .unwrap(); + + if current_user.role == Role::AreaManager || current_user.role == Role::Admin { + let mut areas = None; + + if current_user.role == Role::Admin { + areas = Some(Area::read_all(pool.get_ref()).await.unwrap()); + } + + let template = NewLocationTemplate { + user: current_user, + areas, + }; + + return template.to_response(); + } + + return HttpResponse::Unauthorized().finish(); +} diff --git a/src/endpoints/location/get_overview.rs b/src/endpoints/location/get_overview.rs index 30cb80ba..18d1e057 100644 --- a/src/endpoints/location/get_overview.rs +++ b/src/endpoints/location/get_overview.rs @@ -10,8 +10,7 @@ use crate::models::{Area, Location, Role, User}; #[template(path = "location/overview.html")] pub struct LocationsTemplate { user: User, - area: Option, - locations: Vec + grouped_locations: Vec<(Area, Vec)> } #[actix_web::get("/locations")] @@ -19,20 +18,29 @@ pub async fn get(user: Identity, pool: web::Data) -> impl Responder { let current_user = User::read_by_id(pool.get_ref(), user.id().unwrap().parse().unwrap()).await.unwrap(); if current_user.role == Role::AreaManager || current_user.role == Role::Admin { - let mut area = None; - let locations; + let mut locations; if current_user.role == Role::Admin { locations = Location::read_all_including_area(pool.get_ref()).await.unwrap(); } else { locations = Location::read_by_area(pool.get_ref(), current_user.area_id).await.unwrap(); - area = Some(Area::read_by_id(pool.get_ref(), current_user.area_id).await.unwrap()); } - let template = LocationsTemplate { user: current_user, area, locations}; + let mut grouped_locations = Vec::new(); + + let areas: Vec = locations.iter().map(|l| l.area.clone().unwrap()).collect(); + + for area in areas { + let (locations_in_this_area, rest): (Vec<_>, Vec<_>) = locations.into_iter().partition(|l| l.area_id == area.id); + locations = rest; + + grouped_locations.push((area, locations_in_this_area)) + } + + let template = LocationsTemplate { user: current_user, grouped_locations }; return template.to_response() } - return HttpResponse::BadRequest().body("Fehler beim Zugriff auf die Veranstaltungsorte!"); + return HttpResponse::Unauthorized().finish(); } diff --git a/src/endpoints/location/mod.rs b/src/endpoints/location/mod.rs index c85fc4b5..01438498 100644 --- a/src/endpoints/location/mod.rs +++ b/src/endpoints/location/mod.rs @@ -1 +1,3 @@ pub mod get_overview; +pub mod get_new; +pub mod post_new; diff --git a/src/endpoints/location/post_new.rs b/src/endpoints/location/post_new.rs new file mode 100644 index 00000000..91b92146 --- /dev/null +++ b/src/endpoints/location/post_new.rs @@ -0,0 +1,34 @@ +use actix_identity::Identity; +use actix_web::{http::header::LOCATION, web, HttpResponse, Responder}; +use serde::Deserialize; +use sqlx::PgPool; + +use crate::models::{Location, Role, User}; + +#[derive(Deserialize)] +pub struct NewLocationForm { + name: String, + area: Option, +} + +#[actix_web::post("/locations/new")] +pub async fn post(user: Identity, pool: web::Data, form: web::Form) -> impl Responder { + let current_user = User::read_by_id(pool.get_ref(), user.id().unwrap().parse().unwrap()) + .await + .unwrap(); + + if current_user.role == Role::AreaManager || current_user.role == Role::Admin { + let mut area_id = current_user.area_id; + + if current_user.role == Role::Admin && form.area.is_some() { + area_id = form.area.unwrap(); + } + + match Location::create(pool.get_ref(), &form.name, area_id).await { + Ok(_) => return HttpResponse::Found().insert_header((LOCATION, "/locations")).finish(), + Err(err) => println!("{}", err) + } + } + + return HttpResponse::Unauthorized().finish(); +} diff --git a/src/endpoints/mod.rs b/src/endpoints/mod.rs index 69b229e9..80fbf7f1 100644 --- a/src/endpoints/mod.rs +++ b/src/endpoints/mod.rs @@ -11,6 +11,8 @@ pub struct IdPath { pub fn init(cfg: &mut ServiceConfig) { cfg.service(location::get_overview::get); + cfg.service(location::get_new::get); + cfg.service(location::post_new::post); cfg.service(user::get_overview::get_overview); cfg.service(user::get_new::get_new); diff --git a/templates/location/new.html b/templates/location/new.html new file mode 100644 index 00000000..40d0b588 --- /dev/null +++ b/templates/location/new.html @@ -0,0 +1,63 @@ +{% extends "nav.html" %} + +{% block content %} +
+
+
+

Neuen Ort anlegen

+ +
+
+ +
+
+
+
+ +
+
+
+
+ + {% if user.role == Role::Admin %} +
+
+ +
+
+
+
+
+ +
+
+
+
+
+ {% endif %} + +
+
+
+
+
+ +
+
+ Zurück +
+
+
+
+ +
+
+
+ + +{% endblock %} diff --git a/templates/location/overview.html b/templates/location/overview.html index 2d1092c7..249f969b 100644 --- a/templates/location/overview.html +++ b/templates/location/overview.html @@ -6,22 +6,33 @@

- Veranstaltungsorte im Bereich + Veranstaltungsorte

- {% if locations.len() == 0 %} + {% if grouped_locations.len() == 0 %}
keine Orte vorhanden
{% else %} - {% for location in locations %} + {% for gl in grouped_locations %}
-
{{ location.name }}
+
{{ gl.0.name }}
+ {% for l in gl.1 %} +
+
+ {{ l.name }} +
+ +
+ {% endfor %}
{% endfor %} {% endif %}