feat: WIP overview for user
This commit is contained in:
parent
2ec200831f
commit
38a30e1898
114
db/.sqlx/query-10b4b80f351b66ac5e778a3031288ac5dc66efd0a66b38b7e30f4c954df91bdf.json
generated
Normal file
114
db/.sqlx/query-10b4b80f351b66ac5e778a3031288ac5dc66efd0a66b38b7e30f4c954df91bdf.json
generated
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n SELECT\n event.id AS eventId,\n event.startTimestamp,\n event.endTimestamp,\n event.name,\n event.locationId,\n event.voluntaryWachhabender,\n event.voluntaryFuehrungsassistent,\n event.amountOfPosten,\n event.clothing,\n event.canceled,\n event.note,\n location.id,\n location.name AS locationName,\n location.areaId AS locationAreaId,\n clothing.id AS clothingId,\n clothing.name AS clothingName\n FROM event\n JOIN location ON event.locationId = location.id\n JOIN clothing ON event.clothing = clothing.id\n WHERE starttimestamp::date >= $1\n AND starttimestamp::date <= $2\n AND location.areaId = $3;\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "eventid",
|
||||||
|
"type_info": "Int4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "starttimestamp",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 2,
|
||||||
|
"name": "endtimestamp",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 3,
|
||||||
|
"name": "name",
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "locationid",
|
||||||
|
"type_info": "Int4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 5,
|
||||||
|
"name": "voluntarywachhabender",
|
||||||
|
"type_info": "Bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 6,
|
||||||
|
"name": "voluntaryfuehrungsassistent",
|
||||||
|
"type_info": "Bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 7,
|
||||||
|
"name": "amountofposten",
|
||||||
|
"type_info": "Int2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 8,
|
||||||
|
"name": "clothing",
|
||||||
|
"type_info": "Int4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 9,
|
||||||
|
"name": "canceled",
|
||||||
|
"type_info": "Bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 10,
|
||||||
|
"name": "note",
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 11,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Int4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 12,
|
||||||
|
"name": "locationname",
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 13,
|
||||||
|
"name": "locationareaid",
|
||||||
|
"type_info": "Int4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 14,
|
||||||
|
"name": "clothingid",
|
||||||
|
"type_info": "Int4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 15,
|
||||||
|
"name": "clothingname",
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Date",
|
||||||
|
"Date",
|
||||||
|
"Int4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "10b4b80f351b66ac5e778a3031288ac5dc66efd0a66b38b7e30f4c954df91bdf"
|
||||||
|
}
|
48
db/.sqlx/query-f60053118df6a791d31fa258ee3737881f8f97ca41cbebd92eb22c967292d2ee.json
generated
Normal file
48
db/.sqlx/query-f60053118df6a791d31fa258ee3737881f8f97ca41cbebd92eb22c967292d2ee.json
generated
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n SELECT\n availability.id,\n availability.userId,\n availability.startTimestamp,\n availability.endTimestamp,\n availability.comment\n FROM availability\n WHERE availability.userId = $1\n AND availability.starttimestamp::date >= $2\n AND availability.endtimestamp::date <= $3;\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "id",
|
||||||
|
"type_info": "Int4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "userid",
|
||||||
|
"type_info": "Int4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 2,
|
||||||
|
"name": "starttimestamp",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 3,
|
||||||
|
"name": "endtimestamp",
|
||||||
|
"type_info": "Timestamptz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 4,
|
||||||
|
"name": "comment",
|
||||||
|
"type_info": "Text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Int4",
|
||||||
|
"Date",
|
||||||
|
"Date"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "f60053118df6a791d31fa258ee3737881f8f97ca41cbebd92eb22c967292d2ee"
|
||||||
|
}
|
@ -341,6 +341,46 @@ impl Availability {
|
|||||||
Ok(availabilities)
|
Ok(availabilities)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn read_by_user_and_daterange(
|
||||||
|
pool: &PgPool,
|
||||||
|
user_id: i32,
|
||||||
|
date_range: (&NaiveDate, &NaiveDate),
|
||||||
|
) -> Result<Vec<Availability>> {
|
||||||
|
let records = query!(
|
||||||
|
r##"
|
||||||
|
SELECT
|
||||||
|
availability.id,
|
||||||
|
availability.userId,
|
||||||
|
availability.startTimestamp,
|
||||||
|
availability.endTimestamp,
|
||||||
|
availability.comment
|
||||||
|
FROM availability
|
||||||
|
WHERE availability.userId = $1
|
||||||
|
AND availability.starttimestamp::date >= $2
|
||||||
|
AND availability.endtimestamp::date <= $3;
|
||||||
|
"##,
|
||||||
|
user_id,
|
||||||
|
date_range.0,
|
||||||
|
date_range.1
|
||||||
|
)
|
||||||
|
.fetch_all(pool)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let availabilities = records
|
||||||
|
.iter()
|
||||||
|
.map(|r| Availability {
|
||||||
|
id: r.id,
|
||||||
|
user_id: r.userid,
|
||||||
|
user: None,
|
||||||
|
start: r.starttimestamp.naive_utc(),
|
||||||
|
end: r.endtimestamp.naive_utc(),
|
||||||
|
comment: r.comment.clone(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(availabilities)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn find_adjacent_by_time_for_user(
|
pub async fn find_adjacent_by_time_for_user(
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
start: &NaiveDateTime,
|
start: &NaiveDateTime,
|
||||||
|
@ -95,6 +95,73 @@ impl Event {
|
|||||||
Ok(events)
|
Ok(events)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn read_all_by_daterange_and_area_including_location(
|
||||||
|
pool: &PgPool,
|
||||||
|
date_range: (&NaiveDate, &NaiveDate),
|
||||||
|
area_id: i32,
|
||||||
|
) -> Result<Vec<Event>> {
|
||||||
|
let records = query!(
|
||||||
|
r#"
|
||||||
|
SELECT
|
||||||
|
event.id AS eventId,
|
||||||
|
event.startTimestamp,
|
||||||
|
event.endTimestamp,
|
||||||
|
event.name,
|
||||||
|
event.locationId,
|
||||||
|
event.voluntaryWachhabender,
|
||||||
|
event.voluntaryFuehrungsassistent,
|
||||||
|
event.amountOfPosten,
|
||||||
|
event.clothing,
|
||||||
|
event.canceled,
|
||||||
|
event.note,
|
||||||
|
location.id,
|
||||||
|
location.name AS locationName,
|
||||||
|
location.areaId AS locationAreaId,
|
||||||
|
clothing.id AS clothingId,
|
||||||
|
clothing.name AS clothingName
|
||||||
|
FROM event
|
||||||
|
JOIN location ON event.locationId = location.id
|
||||||
|
JOIN clothing ON event.clothing = clothing.id
|
||||||
|
WHERE starttimestamp::date >= $1
|
||||||
|
AND starttimestamp::date <= $2
|
||||||
|
AND location.areaId = $3;
|
||||||
|
"#,
|
||||||
|
date_range.0,
|
||||||
|
date_range.1,
|
||||||
|
area_id
|
||||||
|
)
|
||||||
|
.fetch_all(pool)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let events = records
|
||||||
|
.into_iter()
|
||||||
|
.map(|record| Event {
|
||||||
|
id: record.eventid,
|
||||||
|
start: record.starttimestamp.naive_utc(),
|
||||||
|
end: record.endtimestamp.naive_utc(),
|
||||||
|
name: record.name.to_string(),
|
||||||
|
location_id: record.locationid,
|
||||||
|
location: Some(Location {
|
||||||
|
id: record.locationid,
|
||||||
|
name: record.locationname.to_string(),
|
||||||
|
area_id: record.locationareaid,
|
||||||
|
area: None,
|
||||||
|
}),
|
||||||
|
voluntary_wachhabender: record.voluntarywachhabender,
|
||||||
|
voluntary_fuehrungsassistent: record.voluntaryfuehrungsassistent,
|
||||||
|
amount_of_posten: record.amountofposten,
|
||||||
|
clothing: Clothing {
|
||||||
|
id: record.clothingid,
|
||||||
|
name: record.clothingname,
|
||||||
|
},
|
||||||
|
canceled: record.canceled,
|
||||||
|
note: record.note,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(events)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn read_by_id_including_location(pool: &PgPool, id: i32) -> Result<Option<Event>> {
|
pub async fn read_by_id_including_location(pool: &PgPool, id: i32) -> Result<Option<Event>> {
|
||||||
let record = query!(
|
let record = query!(
|
||||||
r#"
|
r#"
|
||||||
|
50
web/src/endpoints/availability/get_overview.rs
Normal file
50
web/src/endpoints/availability/get_overview.rs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
use actix_web::{web, Responder};
|
||||||
|
use askama::Template;
|
||||||
|
use chrono::{Months, Utc};
|
||||||
|
use sqlx::PgPool;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
filters,
|
||||||
|
utils::{
|
||||||
|
ApplicationError,
|
||||||
|
DateTimeFormat::{DayMonthYearHourMinute, HourMinute, WeekdayDayMonthYear},
|
||||||
|
TemplateResponse,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use brass_db::models::{Assignment, Availability, Event, Function, Role, User};
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "overview.html")]
|
||||||
|
struct OverviewTemplate {
|
||||||
|
user: User,
|
||||||
|
events: Vec<Event>,
|
||||||
|
availabilities: Vec<Availability>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_web::get("/")]
|
||||||
|
async fn get(
|
||||||
|
user: web::ReqData<User>,
|
||||||
|
pool: web::Data<PgPool>,
|
||||||
|
) -> Result<impl Responder, ApplicationError> {
|
||||||
|
let today = Utc::now().date_naive();
|
||||||
|
let next_month = today.checked_add_months(Months::new(1)).unwrap();
|
||||||
|
|
||||||
|
let events = Event::read_all_by_daterange_and_area_including_location(
|
||||||
|
pool.get_ref(),
|
||||||
|
(&today, &next_month),
|
||||||
|
user.area_id,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let availabilities =
|
||||||
|
Availability::read_by_user_and_daterange(pool.get_ref(), user.id, (&today, &next_month))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let template = OverviewTemplate {
|
||||||
|
user: user.into_inner(),
|
||||||
|
events,
|
||||||
|
availabilities,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(template.to_response()?)
|
||||||
|
}
|
@ -11,6 +11,7 @@ use brass_db::models::{Role, User};
|
|||||||
pub mod delete;
|
pub mod delete;
|
||||||
pub mod get_calendar;
|
pub mod get_calendar;
|
||||||
pub mod get_new;
|
pub mod get_new;
|
||||||
|
pub mod get_overview;
|
||||||
pub mod get_update;
|
pub mod get_update;
|
||||||
pub mod post_new;
|
pub mod post_new;
|
||||||
pub mod post_update;
|
pub mod post_update;
|
||||||
|
@ -60,6 +60,7 @@ pub fn init(cfg: &mut ServiceConfig) {
|
|||||||
cfg.service(availability::get_update::get);
|
cfg.service(availability::get_update::get);
|
||||||
cfg.service(availability::post_new::post);
|
cfg.service(availability::post_new::post);
|
||||||
cfg.service(availability::post_update::post);
|
cfg.service(availability::post_update::post);
|
||||||
|
cfg.service(availability::get_overview::get);
|
||||||
|
|
||||||
cfg.service(events::put_cancelation::put_cancel);
|
cfg.service(events::put_cancelation::put_cancel);
|
||||||
cfg.service(events::put_cancelation::put_uncancel);
|
cfg.service(events::put_cancelation::put_uncancel);
|
||||||
|
9
web/templates/overview.html
Normal file
9
web/templates/overview.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{% extends "nav.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<section id="progress" class="section">
|
||||||
|
<div class="container">
|
||||||
|
Übersicht
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user