Compare commits
2 Commits
46669d206f
...
e6d4619641
Author | SHA1 | Date | |
---|---|---|---|
e6d4619641 | |||
8b65f7dd17 |
@ -1,6 +1,6 @@
|
||||
{
|
||||
"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 ",
|
||||
"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 ORDER BY event.starttimestamp;\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -110,5 +110,5 @@
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "10b4b80f351b66ac5e778a3031288ac5dc66efd0a66b38b7e30f4c954df91bdf"
|
||||
"hash": "65367483e39e07cd0aa142f9bb76c7a5d6dd0611e6b41edd5a593c9f955b5d04"
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"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 ",
|
||||
"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 ORDER BY availability.starttimestamp;\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@ -44,5 +44,5 @@
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "f60053118df6a791d31fa258ee3737881f8f97ca41cbebd92eb22c967292d2ee"
|
||||
"hash": "66638de4a321ba610206a9f5c237cb17eb5221c1dbe4d4c5e83167b2d2807db4"
|
||||
}
|
59
db/.sqlx/query-6788747f70812d6a87833d821c9845f59b4338bc42a40050a68736ba30d937d5.json
generated
Normal file
59
db/.sqlx/query-6788747f70812d6a87833d821c9845f59b4338bc42a40050a68736ba30d937d5.json
generated
Normal file
@ -0,0 +1,59 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT\n assignment.eventId,\n assignment.availabilityId,\n assignment.function AS \"function: Function\",\n assignment.startTimestamp,\n assignment.endTimestamp\n FROM assignment\n JOIN availability ON assignment.availabilityId = availability.id\n WHERE assignment.starttimestamp::date >= $1\n AND assignment.starttimestamp::date <= $2\n AND availability.userId = $3\n ORDER BY assignment.starttimestamp;\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "eventid",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "availabilityid",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "function: Function",
|
||||
"type_info": {
|
||||
"Custom": {
|
||||
"name": "function",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"posten",
|
||||
"fuehrungsassistent",
|
||||
"wachhabender"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "starttimestamp",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "endtimestamp",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Date",
|
||||
"Date",
|
||||
"Int4"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "6788747f70812d6a87833d821c9845f59b4338bc42a40050a68736ba30d937d5"
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use chrono::NaiveDateTime;
|
||||
use chrono::{NaiveDate, NaiveDateTime};
|
||||
use sqlx::{PgPool, query};
|
||||
|
||||
use super::{AssignmentChangeset, Function, Result};
|
||||
@ -101,6 +101,47 @@ impl Assignment {
|
||||
Ok(assignemnets)
|
||||
}
|
||||
|
||||
pub async fn read_all_by_daterange_and_user(
|
||||
pool: &PgPool,
|
||||
date_range: (&NaiveDate, &NaiveDate),
|
||||
user_id: i32,
|
||||
) -> Result<Vec<Assignment>> {
|
||||
let records = query!(
|
||||
r##"
|
||||
SELECT
|
||||
assignment.eventId,
|
||||
assignment.availabilityId,
|
||||
assignment.function AS "function: Function",
|
||||
assignment.startTimestamp,
|
||||
assignment.endTimestamp
|
||||
FROM assignment
|
||||
JOIN availability ON assignment.availabilityId = availability.id
|
||||
WHERE assignment.starttimestamp::date >= $1
|
||||
AND assignment.starttimestamp::date <= $2
|
||||
AND availability.userId = $3
|
||||
ORDER BY assignment.starttimestamp;
|
||||
"##,
|
||||
date_range.0,
|
||||
date_range.1,
|
||||
user_id
|
||||
)
|
||||
.fetch_all(pool)
|
||||
.await?;
|
||||
|
||||
let assignemnets = records
|
||||
.iter()
|
||||
.map(|r| Assignment {
|
||||
event_id: r.eventid,
|
||||
availability_id: r.availabilityid,
|
||||
function: r.function,
|
||||
start: r.starttimestamp.naive_utc(),
|
||||
end: r.endtimestamp.naive_utc(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(assignemnets)
|
||||
}
|
||||
|
||||
pub async fn read(
|
||||
pool: &PgPool,
|
||||
event_id: i32,
|
||||
|
@ -357,7 +357,8 @@ impl Availability {
|
||||
FROM availability
|
||||
WHERE availability.userId = $1
|
||||
AND availability.starttimestamp::date >= $2
|
||||
AND availability.endtimestamp::date <= $3;
|
||||
AND availability.endtimestamp::date <= $3
|
||||
ORDER BY availability.starttimestamp;
|
||||
"##,
|
||||
user_id,
|
||||
date_range.0,
|
||||
|
@ -124,7 +124,8 @@ impl Event {
|
||||
JOIN clothing ON event.clothing = clothing.id
|
||||
WHERE starttimestamp::date >= $1
|
||||
AND starttimestamp::date <= $2
|
||||
AND location.areaId = $3;
|
||||
AND location.areaId = $3
|
||||
ORDER BY event.starttimestamp;
|
||||
"#,
|
||||
date_range.0,
|
||||
date_range.1,
|
||||
|
@ -7,11 +7,11 @@ use crate::{
|
||||
filters,
|
||||
utils::{
|
||||
ApplicationError,
|
||||
DateTimeFormat::{DayMonthYearHourMinute, HourMinute, WeekdayDayMonthYear},
|
||||
DateTimeFormat::{HourMinute, WeekdayDayMonthYearHourMinute},
|
||||
TemplateResponse,
|
||||
},
|
||||
};
|
||||
use brass_db::models::{Assignment, Availability, Event, Function, Role, User};
|
||||
use brass_db::models::{Assignment, Availability, Event, Role, User};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "overview.html")]
|
||||
@ -19,6 +19,7 @@ struct OverviewTemplate {
|
||||
user: User,
|
||||
events: Vec<Event>,
|
||||
availabilities: Vec<Availability>,
|
||||
assignments: Vec<(Assignment, String)>,
|
||||
}
|
||||
|
||||
#[actix_web::get("/")]
|
||||
@ -28,22 +29,36 @@ async fn get(
|
||||
) -> Result<impl Responder, ApplicationError> {
|
||||
let today = Utc::now().date_naive();
|
||||
let next_month = today.checked_add_months(Months::new(1)).unwrap();
|
||||
let date_range = (&today, &next_month);
|
||||
|
||||
let events = Event::read_all_by_daterange_and_area_including_location(
|
||||
pool.get_ref(),
|
||||
(&today, &next_month),
|
||||
date_range,
|
||||
user.area_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let availabilities =
|
||||
Availability::read_by_user_and_daterange(pool.get_ref(), user.id, (&today, &next_month))
|
||||
.await?;
|
||||
Availability::read_by_user_and_daterange(pool.get_ref(), user.id, date_range).await?;
|
||||
|
||||
let assignments =
|
||||
Assignment::read_all_by_daterange_and_user(pool.get_ref(), date_range, user.id)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|a| {
|
||||
if let Some(e) = events.iter().find(|e| e.id == a.event_id) {
|
||||
(a, e.name.clone())
|
||||
} else {
|
||||
(a, String::new())
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let template = OverviewTemplate {
|
||||
user: user.into_inner(),
|
||||
events,
|
||||
availabilities,
|
||||
assignments,
|
||||
};
|
||||
|
||||
Ok(template.to_response()?)
|
||||
|
@ -8,6 +8,7 @@ pub enum DateTimeFormat {
|
||||
HourMinute,
|
||||
WeekdayDayMonth,
|
||||
WeekdayDayMonthYear,
|
||||
WeekdayDayMonthYearHourMinute,
|
||||
}
|
||||
|
||||
impl From<DateTimeFormat> for &'static str {
|
||||
@ -21,6 +22,7 @@ impl From<DateTimeFormat> for &'static str {
|
||||
DateTimeFormat::HourMinute => "%H:%M",
|
||||
DateTimeFormat::WeekdayDayMonth => "%A, %d.%m.",
|
||||
DateTimeFormat::WeekdayDayMonthYear => "%A, %d.%m.%Y",
|
||||
DateTimeFormat::WeekdayDayMonthYearHourMinute => "%A, %d.%m.%Y %H:%M",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,5 +23,5 @@ pub fn get_return_url_for_date(date: &NaiveDate) -> String {
|
||||
return String::from("/");
|
||||
}
|
||||
|
||||
format!("/?date={}", date)
|
||||
format!("/calendar?date={}", date)
|
||||
}
|
||||
|
@ -111,7 +111,7 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<a class="button is-link is-light" hx-boost="true" href="/?date={{ date }}">
|
||||
<a class="button is-link is-light" hx-boost="true" href="/calendar?date={{ date }}">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#arrow-left" />
|
||||
</svg>
|
||||
|
@ -8,7 +8,7 @@
|
||||
<div class="level is-hidden-mobile">
|
||||
<div class="level-left">
|
||||
<a hx-boost="true" class="button is-link level-item"
|
||||
href="/?date={{ date.pred() }}{{ selected_area|show_area_query(false) }}">
|
||||
href="/calendar?date={{ date.pred() }}{{ selected_area|show_area_query(false) }}">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#arrow-left" />
|
||||
</svg>
|
||||
@ -37,7 +37,7 @@
|
||||
|
||||
<div class="level-right">
|
||||
<a hx-boost="true" class="button is-link level-item"
|
||||
href="/?date={{ date.succ() }}{{ selected_area|show_area_query(false) }}">
|
||||
href="/calendar?date={{ date.succ() }}{{ selected_area|show_area_query(false) }}">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#arrow-right" />
|
||||
</svg>
|
||||
@ -49,7 +49,7 @@
|
||||
<div class="level is-hidden-tablet is-mobile">
|
||||
<div class="level-left">
|
||||
<a hx-boost="true" class="button is-link level-item"
|
||||
href="/?date={{ date.pred() }}{{ selected_area|show_area_query(false) }}">
|
||||
href="/calendar?date={{ date.pred() }}{{ selected_area|show_area_query(false) }}">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#arrow-left" />
|
||||
</svg>
|
||||
@ -63,7 +63,7 @@
|
||||
|
||||
<div class="level-right">
|
||||
<a hx-boost="true" class="button is-link level-item"
|
||||
href="/?date={{ date.succ() }}{{ selected_area|show_area_query(false) }}">
|
||||
href="/calendar?date={{ date.succ() }}{{ selected_area|show_area_query(false) }}">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#arrow-right" />
|
||||
</svg>
|
||||
|
@ -225,7 +225,7 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<a class="button is-link is-light" hx-boost="true" href="/?date={{ date }}">
|
||||
<a class="button is-link is-light" hx-boost="true" href="/calendar?date={{ date }}">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#arrow-left" />
|
||||
</svg>
|
||||
|
@ -64,7 +64,7 @@
|
||||
</div>
|
||||
|
||||
<div class="control">
|
||||
<a class="button is-link is-light" hx-boost="true" href="/?date={{ event.start.date() }}">
|
||||
<a class="button is-link is-light" hx-boost="true" href="/calendar?date={{ event.start.date() }}">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#arrow-left" />
|
||||
</svg>
|
||||
|
@ -1,9 +1,95 @@
|
||||
{% extends "nav.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section id="progress" class="section">
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
Übersicht
|
||||
<h1 class="title is-1">Übersicht</h1>
|
||||
<h3 class="title is-3">geplante Veranstaltungen</h3>
|
||||
<p class="subtitle is-5">in den nächsten 31 Tagen</p>
|
||||
{% if events.len() == 0 %}
|
||||
<div class="notification">
|
||||
Keine Veranstaltungen für diesen Zeitraum geplant.
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="panel p-2">
|
||||
{% for e in events %}
|
||||
<div class="panel-block is-justify-content-space-between">
|
||||
<span>
|
||||
<b>{{ e.name }}</b> {{ e.start|fmt_datetime(WeekdayDayMonthYearHourMinute) }} - {{
|
||||
e.end|fmt_datetime(HourMinute) }}
|
||||
</span>
|
||||
<a class="button is-small is-link is-light" href="/calendar?date={{ e.start.date() }}">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#calendar" />
|
||||
</svg>
|
||||
<span>im Kalender anzeigen</span>
|
||||
</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h3 class="title is-3">Deine Verfügbarkeiten</h3>
|
||||
<p class="subtitle is-5">in den nächsten 31 Tagen</p>
|
||||
{% if availabilities.len() == 0 %}
|
||||
<div class="notification">
|
||||
Keine Verfügbarkeiten für diesen Zeitraum hinterlegt.
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="panel p-2">
|
||||
{% for a in availabilities %}
|
||||
<div class="panel-block is-justify-content-space-between">
|
||||
<span>
|
||||
{{ a.start|fmt_datetime(WeekdayDayMonthYearHourMinute) }} - {{
|
||||
a.end|fmt_datetime(HourMinute) }} {% if let Some(comment) = a.comment %} Kommentar: {{ comment }}
|
||||
{% endif %}
|
||||
</span>
|
||||
<div class="buttons are-small">
|
||||
<a class="button is-primary is-light" href="/availability/edit/{{ a.id }}">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#edit" />
|
||||
</svg>
|
||||
<span>Bearbeiten</span>
|
||||
</a>
|
||||
|
||||
<a class="button is-link is-light" href="/calendar?date={{ a.start.date() }}">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#calendar" />
|
||||
</svg>
|
||||
<span>im Kalender anzeigen</span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h3 class="title is-3">Deine Einteilungen</h3>
|
||||
<p class="subtitle is-5">in den nächsten 31 Tagen</p>
|
||||
{% if assignments.len() == 0 %}
|
||||
<div class="notification">
|
||||
Keine Einteilungen für diesen Zeitraum vorhanden.
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="panel p-2">
|
||||
{% for (a, event_name) in assignments %}
|
||||
<div class="panel-block is-justify-content-space-between">
|
||||
<span>
|
||||
{{ a.start|fmt_datetime(WeekdayDayMonthYearHourMinute) }} - {{
|
||||
a.end|fmt_datetime(HourMinute) }} bei {{ event_name }} als {{ a.function }}
|
||||
</span>
|
||||
<a class="button is-small is-link is-light" href="/calendar?date={{ a.start.date() }}">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#calendar" />
|
||||
</svg>
|
||||
<span>im Kalender anzeigen</span>
|
||||
</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
Loading…
x
Reference in New Issue
Block a user