feat: differentiate area in overview

This commit is contained in:
Max Hohlfeld 2024-06-29 13:51:33 +02:00
parent 7d47b38037
commit 43169b585a
7 changed files with 96 additions and 70 deletions

View File

@ -1,4 +1,5 @@
use actix_web::{web, Responder}; use crate::filters;
use actix_web::{web, HttpResponse, Responder};
use askama::Template; use askama::Template;
use askama_actix::TemplateToResponse; use askama_actix::TemplateToResponse;
use chrono::{NaiveDate, Utc}; use chrono::{NaiveDate, Utc};
@ -10,6 +11,7 @@ use crate::models::{Area, Availabillity, Event, Function, Role, User};
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct CalendarQuery { pub struct CalendarQuery {
date: Option<NaiveDate>, date: Option<NaiveDate>,
area: Option<i32>,
} }
#[derive(Template)] #[derive(Template)]
@ -17,6 +19,7 @@ pub struct CalendarQuery {
struct CalendarTemplate { struct CalendarTemplate {
user: User, user: User,
date: NaiveDate, date: NaiveDate,
selected_area: Option<i32>,
areas: Vec<Area>, areas: Vec<Area>,
events: Vec<Event>, events: Vec<Event>,
availabillities: Vec<Availabillity>, availabillities: Vec<Availabillity>,
@ -32,19 +35,40 @@ async fn get(
Some(given_date) => given_date, Some(given_date) => given_date,
None => Utc::now().date_naive(), None => Utc::now().date_naive(),
}; };
let areas = Area::read_all(pool.get_ref()).await.unwrap(); let areas = Area::read_all(pool.get_ref()).await.unwrap();
let events = Event::read_by_date_including_location(pool.get_ref(), date) let selected_area = match query.area {
.await Some(id) => {
.unwrap(); if !areas.iter().any(|a| a.id == id) {
return HttpResponse::BadRequest().finish();
}
let availabillities = Availabillity::read_by_date_including_user(pool.get_ref(), date) Some(id)
.await }
.unwrap(); None => None,
};
let events = Event::read_by_date_and_area_including_location(
pool.get_ref(),
date,
query.area.unwrap_or(user.area_id),
)
.await
.unwrap();
let availabillities = Availabillity::read_by_date_and_area_including_user(
pool.get_ref(),
date,
query.area.unwrap_or(user.area_id),
)
.await
.unwrap();
let template = CalendarTemplate { let template = CalendarTemplate {
user: user.into_inner(), user: user.into_inner(),
date, date,
selected_area,
areas, areas,
events, events,
availabillities, availabillities,

View File

@ -1,4 +1,3 @@
use actix_identity::Identity;
use actix_web::{web, HttpResponse, Responder}; use actix_web::{web, HttpResponse, Responder};
use serde::Deserialize; use serde::Deserialize;
use serde_json::value::Value; use serde_json::value::Value;

7
src/filters.rs Normal file
View File

@ -0,0 +1,7 @@
pub fn show_area_query(a: &Option<i32>) -> ::askama::Result<String> {
if let Some(a) = a {
return Ok(format!("&area={}", a));
} else {
return Ok(String::new());
}
}

View File

@ -19,8 +19,10 @@ mod endpoints;
mod models; mod models;
mod middleware; mod middleware;
mod filters;
mod postgres_session_store; mod postgres_session_store;
pub enum Command { pub enum Command {
Migrate, Migrate,
CreateAdmin, CreateAdmin,

View File

@ -33,33 +33,10 @@ impl Availabillity {
Ok(result) Ok(result)
} }
pub async fn read_by_date( pub async fn read_by_date_and_area_including_user(
pool: &PgPool,
date: NaiveDate,
) -> anyhow::Result<Vec<Availabillity>> {
let records = query!("SELECT * FROM availabillity WHERE date = $1", date)
.fetch_all(pool)
.await?;
let availabillities = records
.iter()
.map(|a| Availabillity {
id: a.id,
user_id: a.userid,
user: None,
date: a.date,
start_time: a.starttime,
end_time: a.endtime,
comment: a.comment.clone(),
})
.collect();
Ok(availabillities)
}
pub async fn read_by_date_including_user(
pool: &PgPool, pool: &PgPool,
date: NaiveDate, date: NaiveDate,
area_id: i32
) -> anyhow::Result<Vec<Availabillity>> { ) -> anyhow::Result<Vec<Availabillity>> {
let records = query!( let records = query!(
r##" r##"
@ -69,7 +46,7 @@ impl Availabillity {
availabillity.date, availabillity.date,
availabillity.startTime, availabillity.startTime,
availabillity.endTime, availabillity.endTime,
availabillity.comment, availabillity.comment,
user_.name, user_.name,
user_.email, user_.email,
user_.password, user_.password,
@ -82,9 +59,11 @@ impl Availabillity {
user_.receiveNotifications user_.receiveNotifications
FROM availabillity FROM availabillity
JOIN user_ ON availabillity.userId = user_.id JOIN user_ ON availabillity.userId = user_.id
WHERE availabillity.date = $1; WHERE availabillity.date = $1
AND user_.areaId = $2;
"##, "##,
date date,
area_id
) )
.fetch_all(pool) .fetch_all(pool)
.await?; .await?;
@ -130,7 +109,7 @@ impl Availabillity {
availabillity.date, availabillity.date,
availabillity.startTime, availabillity.startTime,
availabillity.endTime, availabillity.endTime,
availabillity.comment, availabillity.comment,
user_.name, user_.name,
user_.email, user_.email,
user_.password, user_.password,
@ -211,7 +190,7 @@ impl Availabillity {
availabillity.date, availabillity.date,
availabillity.startTime, availabillity.startTime,
availabillity.endTime, availabillity.endTime,
availabillity.comment, availabillity.comment,
user_.name, user_.name,
user_.email, user_.email,
user_.password, user_.password,

View File

@ -34,34 +34,10 @@ impl Event {
Ok(result.id) Ok(result.id)
} }
pub async fn read_by_date(pool: &PgPool, date: NaiveDate) -> anyhow::Result<Vec<Event>> { pub async fn read_by_date_and_area_including_location(
let records = query!("SELECT * FROM event WHERE date = $1;", date)
.fetch_all(pool)
.await?;
let events = records
.iter()
.map(|record| Event {
id: record.id,
date: record.date,
start_time: record.starttime,
end_time: record.endtime,
name: record.name.to_string(),
location_id: record.locationid,
location: None,
voluntary_wachhabender: record.voluntarywachhabender,
amount_of_posten: record.amountofposten,
clothing: record.clothing.to_string(),
canceled: record.canceled,
})
.collect();
Ok(events)
}
pub async fn read_by_date_including_location(
pool: &PgPool, pool: &PgPool,
date: NaiveDate, date: NaiveDate,
area_id: i32
) -> anyhow::Result<Vec<Event>> { ) -> anyhow::Result<Vec<Event>> {
let records = query!( let records = query!(
r#" r#"
@ -81,9 +57,11 @@ impl Event {
location.areaId AS locationAreaId location.areaId AS locationAreaId
FROM event FROM event
JOIN location ON event.locationId = location.id JOIN location ON event.locationId = location.id
WHERE date = $1; WHERE date = $1
AND location.areaId = $2;
"#, "#,
date date,
area_id
) )
.fetch_all(pool) .fetch_all(pool)
.await?; .await?;

View File

@ -5,14 +5,45 @@
<div class="container"> <div class="container">
<div class="level"> <div class="level">
<div class="level-left"> <div class="level-left">
<a hx-boost="true" class="button is-link level-item" href="/?date={{ date.pred() }}">&larr;</a> <a hx-boost="true" class="button is-link level-item"
href="/?date={{ date.pred() }}{{ selected_area|show_area_query }}">
<span class="icon">
<svg class="feather">
<use href="/static/feather-sprite.svg#arrow-left" />
</svg>
</span>
</a>
</div> </div>
<div class="control level-item is-flex-grow-0"> <div class="control level-item is-flex-grow-0">
<input id="date-selector" class="input" type="date" value="{{ date }}"> <input id="date-selector" class="input" type="date" value="{{ date }}">
{% if user.role == Role::Admin %}
<div class="select ml-2">
<select hx-get="/?date={{ date }}" hx-target="closest body" hx-push-url="true" name="area">
{% for area in areas %}
{% if (user.area_id == area.id && selected_area.is_none()) || selected_area.is_some() &&
selected_area.unwrap() == area.id %}
<option selected value="{{ area.id }}">{{ area.name }}</option>
{% else %}
<option value="{{ area.id }}">{{ area.name }}</option>
{% endif %}
{% endfor %}
</select>
</div>
{% endif %}
</div> </div>
<div class="level-right"> <div class="level-right">
<a hx-boost="true" class="button is-link level-item" href="/?date={{ date.succ() }}">&rarr;</a> <a hx-boost="true" class="button is-link level-item"
href="/?date={{ date.succ() }}{{ selected_area|show_area_query }}">
<span class="icon">
<svg class="feather">
<use href="/static/feather-sprite.svg#arrow-right" />
</svg>
</span>
</a>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
@ -25,14 +56,17 @@
Events am {{ date.format("%d.%m.%Y") }} Events am {{ date.format("%d.%m.%Y") }}
</h3> </h3>
</div> </div>
{% if (user.role == Role::Admin || user.role == Role::AreaManager) && (selected_area.is_none() ||
selected_area.unwrap() == user.area_id) %}
<div class="level-right"> <div class="level-right">
<a class="button" href="/events/new?date={{ date }}">Neues Event für diesen Tag</a> <a class="button" href="/events/new?date={{ date }}">Neues Event für diesen Tag</a>
</div> </div>
{% endif %}
</div> </div>
{% if events.len() == 0 %} {% if events.len() == 0 %}
<div class="box"> <div class="box">
<h5 class="title is-5">keine Events geplant</h5> <h5 class="subtitle is-5">keine Events geplant</h5>
</div> </div>
{% else %} {% else %}
{% for event in events %} {% for event in events %}
@ -67,14 +101,17 @@
Verfügbarkeiten am {{ date.format("%d.%m.%Y") }} Verfügbarkeiten am {{ date.format("%d.%m.%Y") }}
</h3> </h3>
</div> </div>
{% if (user.role == Role::Admin || user.role == Role::AreaManager) && selected_area.is_some() &&
selected_area.unwrap() == user.area_id %}
<div class="level-right"> <div class="level-right">
<a class="button" href="/availabillity/new?date={{ date }}">Neue Verfügbarkeit für diesen Tag</a> <a class="button" href="/availabillity/new?date={{ date }}">Neue Verfügbarkeit für diesen Tag</a>
</div> </div>
{% endif %}
</div> </div>
{% if availabillities.len() == 0 %} {% if availabillities.len() == 0 %}
<div class="box"> <div class="box">
<h5 class="title is-5">keine Verfügbarkeiten eingetragen</h5> <h5 class="subtitle is-5">keine Verfügbarkeiten eingetragen</h5>
</div> </div>
{% else %} {% else %}
<div class="box"> <div class="box">