diff --git a/src/endpoints/area/get_new.rs b/src/endpoints/area/get_new.rs index f0484611..58cb4e68 100644 --- a/src/endpoints/area/get_new.rs +++ b/src/endpoints/area/get_new.rs @@ -1,4 +1,4 @@ -use actix_web::{web, Responder}; +use actix_web::{web, HttpResponse, Responder}; use askama::Template; use askama_actix::TemplateToResponse; @@ -12,6 +12,10 @@ struct NewAreaTemplate { #[actix_web::get("/area/new")] async fn get(user: web::ReqData) -> impl Responder { + if user.role != Role::Admin { + return HttpResponse::Unauthorized().finish(); + } + let template = NewAreaTemplate { user: user.into_inner(), }; diff --git a/src/endpoints/area/mod.rs b/src/endpoints/area/mod.rs index a9cb9a44..661e73cf 100644 --- a/src/endpoints/area/mod.rs +++ b/src/endpoints/area/mod.rs @@ -1 +1,2 @@ pub mod get_new; +pub mod post_new; diff --git a/src/endpoints/area/post_new.rs b/src/endpoints/area/post_new.rs new file mode 100644 index 00000000..e78ba562 --- /dev/null +++ b/src/endpoints/area/post_new.rs @@ -0,0 +1,34 @@ +use actix_web::{http::header::LOCATION, web, HttpResponse, Responder}; +use serde::Deserialize; +use sqlx::PgPool; + +use crate::models::{Area, Role, User}; + +#[derive(Deserialize)] +struct NewAreaForm { + name: String, +} + +#[actix_web::post("/area/new")] +pub async fn post( + user: web::ReqData, + pool: web::Data, + form: web::Form, +) -> impl Responder { + if user.role != Role::Admin { + return HttpResponse::Unauthorized().finish(); + } + + match Area::create(pool.get_ref(), &form.name).await { + Ok(_) => { + return HttpResponse::Found() + .insert_header((LOCATION, "/locations")) + .insert_header(("HX-LOCATION", "/locations")) + .finish() + } + Err(err) => { + println!("{}", err); + return HttpResponse::InternalServerError().finish(); + } + } +} diff --git a/src/endpoints/location/get_new.rs b/src/endpoints/location/get_new.rs index 7e09e0a9..9ea7a715 100644 --- a/src/endpoints/location/get_new.rs +++ b/src/endpoints/location/get_new.rs @@ -1,4 +1,3 @@ -use actix_identity::Identity; use actix_web::{web, HttpResponse, Responder}; use askama::Template; use askama_actix::TemplateToResponse; @@ -14,20 +13,16 @@ pub struct NewLocationTemplate { } #[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 { +pub async fn get(user: web::ReqData, pool: web::Data) -> impl Responder { + if user.role == Role::AreaManager || user.role == Role::Admin { let mut areas = None; - if current_user.role == Role::Admin { + if user.role == Role::Admin { areas = Some(Area::read_all(pool.get_ref()).await.unwrap()); } let template = NewLocationTemplate { - user: current_user, + user: user.into_inner(), areas, }; diff --git a/src/endpoints/location/get_overview.rs b/src/endpoints/location/get_overview.rs index 18d1e057..97d7ea96 100644 --- a/src/endpoints/location/get_overview.rs +++ b/src/endpoints/location/get_overview.rs @@ -1,4 +1,3 @@ -use actix_identity::Identity; use actix_web::{web, HttpResponse, Responder}; use askama::Template; use askama_actix::TemplateToResponse; @@ -10,36 +9,48 @@ use crate::models::{Area, Location, Role, User}; #[template(path = "location/overview.html")] pub struct LocationsTemplate { user: User, - grouped_locations: Vec<(Area, Vec)> + grouped_locations: Vec<(Area, Vec)>, } #[actix_web::get("/locations")] -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 { +pub async fn get(user: web::ReqData, pool: web::Data) -> impl Responder { + if user.role == Role::AreaManager || user.role == Role::Admin { let mut locations; + let mut grouped_locations: Vec<(Area, Vec)>; - if current_user.role == Role::Admin { - locations = Location::read_all_including_area(pool.get_ref()).await.unwrap(); + if user.role == Role::Admin { + locations = Location::read_all(pool.get_ref()).await.unwrap(); + grouped_locations = Area::read_all(pool.get_ref()) + .await + .unwrap() + .into_iter() + .map(|a| (a, Vec::new())) + .collect(); } else { - locations = Location::read_by_area(pool.get_ref(), current_user.area_id).await.unwrap(); + locations = Location::read_by_area(pool.get_ref(), user.area_id) + .await + .unwrap(); + let area = Area::read_by_id(pool.get_ref(), user.area_id) + .await + .unwrap(); + + grouped_locations = vec![(area, Vec::new())]; } - 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); + for entry in grouped_locations.iter_mut() { + let (mut locations_in_this_area, rest): (Vec<_>, Vec<_>) = + locations.into_iter().partition(|l| l.area_id == entry.0.id); locations = rest; - grouped_locations.push((area, locations_in_this_area)) + entry.1.append(&mut locations_in_this_area); } - let template = LocationsTemplate { user: current_user, grouped_locations }; + let template = LocationsTemplate { + user: user.into_inner(), + grouped_locations, + }; - return template.to_response() + return template.to_response(); } return HttpResponse::Unauthorized().finish(); diff --git a/src/endpoints/location/post_new.rs b/src/endpoints/location/post_new.rs index 91b92146..1c1bade2 100644 --- a/src/endpoints/location/post_new.rs +++ b/src/endpoints/location/post_new.rs @@ -1,4 +1,3 @@ -use actix_identity::Identity; use actix_web::{http::header::LOCATION, web, HttpResponse, Responder}; use serde::Deserialize; use sqlx::PgPool; @@ -12,21 +11,30 @@ pub struct NewLocationForm { } #[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(); +pub async fn post( + user: web::ReqData, + pool: web::Data, + form: web::Form, +) -> impl Responder { - if current_user.role == Role::AreaManager || current_user.role == Role::Admin { - let mut area_id = current_user.area_id; + if user.role == Role::AreaManager || user.role == Role::Admin { + let mut area_id = user.area_id; - if current_user.role == Role::Admin && form.area.is_some() { + if 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) + Ok(_) => { + return HttpResponse::Found() + .insert_header((LOCATION, "/locations")) + .insert_header(("HX-LOCATION", "/locations")) + .finish() + } + Err(err) => { + println!("{}", err); + return HttpResponse::InternalServerError().finish(); + } } } diff --git a/src/endpoints/mod.rs b/src/endpoints/mod.rs index 29c68d17..b0d3c5d4 100644 --- a/src/endpoints/mod.rs +++ b/src/endpoints/mod.rs @@ -52,6 +52,7 @@ pub fn init(cfg: &mut ServiceConfig) { cfg.service(assignment::post_new::post); cfg.service(area::get_new::get); + cfg.service(area::post_new::post); cfg.service(get_export::get); } diff --git a/src/models/location.rs b/src/models/location.rs index 4b454b55..e388e5c0 100644 --- a/src/models/location.rs +++ b/src/models/location.rs @@ -40,6 +40,24 @@ impl Location { Ok(locations) } + pub async fn read_all(pool: &PgPool) -> anyhow::Result> { + let records = query!("SELECT * FROM location") + .fetch_all(pool) + .await?; + + let locations = records + .iter() + .map(|lr| Location { + id: lr.id, + name: lr.name.to_string(), + area_id: lr.areaid, + area: None, + }) + .collect(); + + Ok(locations) + } + pub async fn read_all_including_area(pool: &PgPool) -> anyhow::Result> { let records = query!("SELECT location.id AS locationId, location.name, location.areaId, area.id, area.name AS areaName FROM location JOIN area ON location.areaId = area.id;") .fetch_all(pool) diff --git a/static/feather-sprite.svg b/static/feather-sprite.svg new file mode 100644 index 00000000..b66f76f3 --- /dev/null +++ b/static/feather-sprite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/area/new.html b/templates/area/new.html index 7d8eb976..a0d40ea4 100644 --- a/templates/area/new.html +++ b/templates/area/new.html @@ -13,7 +13,7 @@
- +
@@ -24,10 +24,24 @@
- +
diff --git a/templates/base.html b/templates/base.html index 065a7289..6dc1a333 100644 --- a/templates/base.html +++ b/templates/base.html @@ -8,11 +8,37 @@ + + - {% block body %} - {% endblock %} + {% block body %} + {% endblock %} diff --git a/templates/location/new.html b/templates/location/new.html index 40d0b588..df82e7f7 100644 --- a/templates/location/new.html +++ b/templates/location/new.html @@ -13,7 +13,7 @@
- +
@@ -28,7 +28,7 @@
- {% for area in areas.as_ref().unwrap() %} {% endfor %} @@ -45,10 +45,24 @@
- +
diff --git a/templates/location/overview.html b/templates/location/overview.html index d4262214..9814dadb 100644 --- a/templates/location/overview.html +++ b/templates/location/overview.html @@ -10,27 +10,57 @@
{% if grouped_locations.len() == 0 %}
-
keine Orte vorhanden
+
keine Bereiche gefunden
{% else %} {% for gl in grouped_locations %}
-
{{ gl.0.name }}
+
Bereich {{ gl.0.name }}
{% for l in gl.1 %} {% endfor %} diff --git a/templates/nav.html b/templates/nav.html index 57c0d63b..79029684 100644 --- a/templates/nav.html +++ b/templates/nav.html @@ -50,7 +50,7 @@