feat: differentiate area in overview
This commit is contained in:
parent
7d47b38037
commit
43169b585a
@ -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,
|
||||||
|
@ -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
7
src/filters.rs
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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?;
|
||||||
|
@ -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() }}">←</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() }}">→</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">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user