reanme-to-event #553
@ -3,7 +3,7 @@ use std::io::Write;
|
|||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use ics::{
|
use ics::{
|
||||||
properties::{DtStart, Summary},
|
properties::{DtStart, Summary},
|
||||||
Event, ICalendar,
|
ICalendar,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use sqlx::{FromRow, Row, SqlitePool};
|
use sqlx::{FromRow, Row, SqlitePool};
|
||||||
@ -11,10 +11,10 @@ use sqlx::{FromRow, Row, SqlitePool};
|
|||||||
use super::{notification::Notification, tripdetails::TripDetails, triptype::TripType, user::User};
|
use super::{notification::Notification, tripdetails::TripDetails, triptype::TripType, user::User};
|
||||||
|
|
||||||
#[derive(Serialize, Clone, FromRow, Debug, PartialEq)]
|
#[derive(Serialize, Clone, FromRow, Debug, PartialEq)]
|
||||||
pub struct PlannedEvent {
|
pub struct Event {
|
||||||
pub id: i64,
|
pub id: i64,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
planned_amount_cox: i64,
|
pub(crate) planned_amount_cox: i64,
|
||||||
trip_details_id: i64,
|
trip_details_id: i64,
|
||||||
pub planned_starting_time: String,
|
pub planned_starting_time: String,
|
||||||
pub(crate) max_people: i64,
|
pub(crate) max_people: i64,
|
||||||
@ -22,14 +22,14 @@ pub struct PlannedEvent {
|
|||||||
pub notes: Option<String>,
|
pub notes: Option<String>,
|
||||||
pub allow_guests: bool,
|
pub allow_guests: bool,
|
||||||
trip_type_id: Option<i64>,
|
trip_type_id: Option<i64>,
|
||||||
always_show: bool,
|
pub(crate) always_show: bool,
|
||||||
is_locked: bool,
|
pub(crate) is_locked: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
pub struct PlannedEventWithUserAndTriptype {
|
pub struct EventWithUserAndTriptype {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub planned_event: PlannedEvent,
|
pub event: Event,
|
||||||
trip_type: Option<TripType>,
|
trip_type: Option<TripType>,
|
||||||
cox_needed: bool,
|
cox_needed: bool,
|
||||||
cox: Vec<Registration>,
|
cox: Vec<Registration>,
|
||||||
@ -73,7 +73,7 @@ FROM user_trip WHERE trip_details_id = {}
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn all_cox(db: &SqlitePool, trip_details_id: i64) -> Vec<Registration> {
|
pub async fn all_cox(db: &SqlitePool, event_id: i64) -> Vec<Registration> {
|
||||||
//TODO: switch to join
|
//TODO: switch to join
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"
|
"
|
||||||
@ -82,7 +82,7 @@ SELECT
|
|||||||
(SELECT created_at FROM user WHERE cox_id = id) as registered_at
|
(SELECT created_at FROM user WHERE cox_id = id) as registered_at
|
||||||
FROM trip WHERE planned_event_id = ?
|
FROM trip WHERE planned_event_id = ?
|
||||||
",
|
",
|
||||||
trip_details_id
|
event_id
|
||||||
)
|
)
|
||||||
.fetch_all(db)
|
.fetch_all(db)
|
||||||
.await
|
.await
|
||||||
@ -94,7 +94,7 @@ FROM trip WHERE planned_event_id = ?
|
|||||||
is_guest: false,
|
is_guest: false,
|
||||||
is_real_guest: false,
|
is_real_guest: false,
|
||||||
})
|
})
|
||||||
.collect() //Okay, as PlannedEvent can only be created with proper DB backing
|
.collect() //Okay, as Event can only be created with proper DB backing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ pub struct EventUpdate<'a> {
|
|||||||
pub is_locked: bool,
|
pub is_locked: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlannedEvent {
|
impl Event {
|
||||||
pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option<Self> {
|
pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option<Self> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as!(
|
||||||
Self,
|
Self,
|
||||||
@ -128,19 +128,16 @@ WHERE planned_event.id like ?
|
|||||||
pub async fn get_pinned_for_day(
|
pub async fn get_pinned_for_day(
|
||||||
db: &SqlitePool,
|
db: &SqlitePool,
|
||||||
day: NaiveDate,
|
day: NaiveDate,
|
||||||
) -> Vec<PlannedEventWithUserAndTriptype> {
|
) -> Vec<EventWithUserAndTriptype> {
|
||||||
let mut events = Self::get_for_day(db, day).await;
|
let mut events = Self::get_for_day(db, day).await;
|
||||||
events.retain(|e| e.planned_event.always_show);
|
events.retain(|e| e.event.always_show);
|
||||||
events
|
events
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_for_day(
|
pub async fn get_for_day(db: &SqlitePool, day: NaiveDate) -> Vec<EventWithUserAndTriptype> {
|
||||||
db: &SqlitePool,
|
|
||||||
day: NaiveDate,
|
|
||||||
) -> Vec<PlannedEventWithUserAndTriptype> {
|
|
||||||
let day = format!("{day}");
|
let day = format!("{day}");
|
||||||
let events = sqlx::query_as!(
|
let events = sqlx::query_as!(
|
||||||
PlannedEvent,
|
Event,
|
||||||
"SELECT planned_event.id, planned_event.name, planned_amount_cox, trip_details_id, planned_starting_time, always_show, max_people, day, notes, allow_guests, trip_type_id, is_locked
|
"SELECT planned_event.id, planned_event.name, planned_amount_cox, trip_details_id, planned_starting_time, always_show, max_people, day, notes, allow_guests, trip_type_id, is_locked
|
||||||
FROM planned_event
|
FROM planned_event
|
||||||
INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id
|
INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id
|
||||||
@ -158,20 +155,20 @@ WHERE day=?",
|
|||||||
if let Some(trip_type_id) = event.trip_type_id {
|
if let Some(trip_type_id) = event.trip_type_id {
|
||||||
trip_type = TripType::find_by_id(db, trip_type_id).await;
|
trip_type = TripType::find_by_id(db, trip_type_id).await;
|
||||||
}
|
}
|
||||||
ret.push(PlannedEventWithUserAndTriptype {
|
ret.push(EventWithUserAndTriptype {
|
||||||
cox_needed: event.planned_amount_cox > cox.len() as i64,
|
cox_needed: event.planned_amount_cox > cox.len() as i64,
|
||||||
cox,
|
cox,
|
||||||
rower: Registration::all_rower(db, event.trip_details_id).await,
|
rower: Registration::all_rower(db, event.trip_details_id).await,
|
||||||
planned_event: event,
|
event,
|
||||||
trip_type,
|
trip_type,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn all(db: &SqlitePool) -> Vec<PlannedEvent> {
|
pub async fn all(db: &SqlitePool) -> Vec<Event> {
|
||||||
sqlx::query_as!(
|
sqlx::query_as!(
|
||||||
PlannedEvent,
|
Event,
|
||||||
"SELECT planned_event.id, planned_event.name, planned_amount_cox, trip_details_id, planned_starting_time, always_show, max_people, day, notes, allow_guests, trip_type_id, is_locked
|
"SELECT planned_event.id, planned_event.name, planned_amount_cox, trip_details_id, planned_starting_time, always_show, max_people, day, notes, allow_guests, trip_type_id, is_locked
|
||||||
FROM planned_event
|
FROM planned_event
|
||||||
INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id",
|
INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id",
|
||||||
@ -198,11 +195,27 @@ INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id",
|
|||||||
is_rower.amount > 0
|
is_rower.amount > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn find_by_trip_details(db: &SqlitePool, tripdetails_id: i64) -> Option<Self> {
|
||||||
|
sqlx::query_as!(
|
||||||
|
Self,
|
||||||
|
"
|
||||||
|
SELECT planned_event.id, planned_event.name, planned_amount_cox, trip_details_id, planned_starting_time, always_show, max_people, day, notes, allow_guests, trip_type_id, is_locked
|
||||||
|
FROM planned_event
|
||||||
|
INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id
|
||||||
|
WHERE trip_details.id=?
|
||||||
|
",
|
||||||
|
tripdetails_id
|
||||||
|
)
|
||||||
|
.fetch_one(db)
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn create(
|
pub async fn create(
|
||||||
db: &SqlitePool,
|
db: &SqlitePool,
|
||||||
name: &str,
|
name: &str,
|
||||||
planned_amount_cox: i32,
|
planned_amount_cox: i32,
|
||||||
trip_details: TripDetails,
|
trip_details: &TripDetails,
|
||||||
) {
|
) {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"INSERT INTO planned_event(name, planned_amount_cox, trip_details_id) VALUES(?, ?, ?)",
|
"INSERT INTO planned_event(name, planned_amount_cox, trip_details_id) VALUES(?, ?, ?)",
|
||||||
@ -260,7 +273,7 @@ INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id",
|
|||||||
),
|
),
|
||||||
"Absage Ausfahrt",
|
"Absage Ausfahrt",
|
||||||
None,
|
None,
|
||||||
Some(&format!("remove_trip_by_planned_event:{}", self.id)),
|
Some(&format!("remove_trip_by_event:{}", self.id)),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -298,11 +311,7 @@ INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id",
|
|||||||
&format!("remove_user_trip_with_trip_details_id:{}", tripdetails.id),
|
&format!("remove_user_trip_with_trip_details_id:{}", tripdetails.id),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
Notification::delete_by_action(
|
Notification::delete_by_action(db, &format!("remove_trip_by_event:{}", self.id)).await;
|
||||||
db,
|
|
||||||
&format!("remove_trip_by_planned_event:{}", self.id),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +337,7 @@ INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id",
|
|||||||
sqlx::query!("DELETE FROM planned_event WHERE id = ?", self.id)
|
sqlx::query!("DELETE FROM planned_event WHERE id = ?", self.id)
|
||||||
.execute(db)
|
.execute(db)
|
||||||
.await
|
.await
|
||||||
.unwrap(); //Okay, as PlannedEvent can only be created with proper DB backing
|
.unwrap(); //Okay, as Event can only be created with proper DB backing
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -336,9 +345,10 @@ INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id",
|
|||||||
pub async fn get_ics_feed(db: &SqlitePool) -> String {
|
pub async fn get_ics_feed(db: &SqlitePool) -> String {
|
||||||
let mut calendar = ICalendar::new("2.0", "ics-rs");
|
let mut calendar = ICalendar::new("2.0", "ics-rs");
|
||||||
|
|
||||||
let events = PlannedEvent::all(db).await;
|
let events = Event::all(db).await;
|
||||||
for event in events {
|
for event in events {
|
||||||
let mut vevent = Event::new(format!("{}@rudernlinz.at", event.id), "19900101T180000");
|
let mut vevent =
|
||||||
|
ics::Event::new(format!("{}@rudernlinz.at", event.id), "19900101T180000");
|
||||||
vevent.push(DtStart::new(format!(
|
vevent.push(DtStart::new(format!(
|
||||||
"{}T{}00",
|
"{}T{}00",
|
||||||
event.day.replace('-', ""),
|
event.day.replace('-', ""),
|
||||||
@ -363,7 +373,7 @@ INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id",
|
|||||||
mod test {
|
mod test {
|
||||||
use crate::{model::tripdetails::TripDetails, testdb};
|
use crate::{model::tripdetails::TripDetails, testdb};
|
||||||
|
|
||||||
use super::PlannedEvent;
|
use super::Event;
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
@ -371,8 +381,7 @@ mod test {
|
|||||||
fn test_get_day() {
|
fn test_get_day() {
|
||||||
let pool = testdb!();
|
let pool = testdb!();
|
||||||
|
|
||||||
let res =
|
let res = Event::get_for_day(&pool, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).await;
|
||||||
PlannedEvent::get_for_day(&pool, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).await;
|
|
||||||
assert_eq!(res.len(), 1);
|
assert_eq!(res.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,22 +391,20 @@ mod test {
|
|||||||
|
|
||||||
let trip_details = TripDetails::find_by_id(&pool, 1).await.unwrap();
|
let trip_details = TripDetails::find_by_id(&pool, 1).await.unwrap();
|
||||||
|
|
||||||
PlannedEvent::create(&pool, "new-event".into(), 2, trip_details).await;
|
Event::create(&pool, "new-event".into(), 2, &trip_details).await;
|
||||||
|
|
||||||
let res =
|
let res = Event::get_for_day(&pool, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).await;
|
||||||
PlannedEvent::get_for_day(&pool, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).await;
|
|
||||||
assert_eq!(res.len(), 2);
|
assert_eq!(res.len(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[sqlx::test]
|
#[sqlx::test]
|
||||||
fn test_delete() {
|
fn test_delete() {
|
||||||
let pool = testdb!();
|
let pool = testdb!();
|
||||||
let planned_event = PlannedEvent::find_by_id(&pool, 1).await.unwrap();
|
let planned_event = Event::find_by_id(&pool, 1).await.unwrap();
|
||||||
|
|
||||||
planned_event.delete(&pool).await.unwrap();
|
planned_event.delete(&pool).await.unwrap();
|
||||||
|
|
||||||
let res =
|
let res = Event::get_for_day(&pool, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).await;
|
||||||
PlannedEvent::get_for_day(&pool, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).await;
|
|
||||||
assert_eq!(res.len(), 0);
|
assert_eq!(res.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,7 +412,7 @@ mod test {
|
|||||||
fn test_ics() {
|
fn test_ics() {
|
||||||
let pool = testdb!();
|
let pool = testdb!();
|
||||||
|
|
||||||
let actual = PlannedEvent::get_ics_feed(&pool).await;
|
let actual = Event::get_ics_feed(&pool).await;
|
||||||
assert_eq!("BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:ics-rs\r\nBEGIN:VEVENT\r\nUID:1@rudernlinz.at\r\nDTSTAMP:19900101T180000\r\nDTSTART:19700101T100000\r\nSUMMARY:test-planned-event\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n", actual);
|
assert_eq!("BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:ics-rs\r\nBEGIN:VEVENT\r\nUID:1@rudernlinz.at\r\nDTSTAMP:19900101T180000\r\nDTSTART:19700101T100000\r\nSUMMARY:test-planned-event\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n", actual);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,7 +3,7 @@ use serde::Serialize;
|
|||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
planned_event::{PlannedEvent, PlannedEventWithUserAndTriptype},
|
event::{Event, EventWithUserAndTriptype},
|
||||||
trip::{Trip, TripWithUserAndType},
|
trip::{Trip, TripWithUserAndType},
|
||||||
waterlevel::Waterlevel,
|
waterlevel::Waterlevel,
|
||||||
weather::Weather,
|
weather::Weather,
|
||||||
@ -13,6 +13,7 @@ pub mod boat;
|
|||||||
pub mod boatdamage;
|
pub mod boatdamage;
|
||||||
pub mod boathouse;
|
pub mod boathouse;
|
||||||
pub mod boatreservation;
|
pub mod boatreservation;
|
||||||
|
pub mod event;
|
||||||
pub mod family;
|
pub mod family;
|
||||||
pub mod location;
|
pub mod location;
|
||||||
pub mod log;
|
pub mod log;
|
||||||
@ -20,7 +21,6 @@ pub mod logbook;
|
|||||||
pub mod logtype;
|
pub mod logtype;
|
||||||
pub mod mail;
|
pub mod mail;
|
||||||
pub mod notification;
|
pub mod notification;
|
||||||
pub mod planned_event;
|
|
||||||
pub mod role;
|
pub mod role;
|
||||||
pub mod rower;
|
pub mod rower;
|
||||||
pub mod stat;
|
pub mod stat;
|
||||||
@ -35,7 +35,7 @@ pub mod weather;
|
|||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
pub struct Day {
|
pub struct Day {
|
||||||
day: NaiveDate,
|
day: NaiveDate,
|
||||||
planned_events: Vec<PlannedEventWithUserAndTriptype>,
|
events: Vec<EventWithUserAndTriptype>,
|
||||||
trips: Vec<TripWithUserAndType>,
|
trips: Vec<TripWithUserAndType>,
|
||||||
is_pinned: bool,
|
is_pinned: bool,
|
||||||
max_waterlevel: Option<i64>,
|
max_waterlevel: Option<i64>,
|
||||||
@ -47,7 +47,7 @@ impl Day {
|
|||||||
if is_pinned {
|
if is_pinned {
|
||||||
Self {
|
Self {
|
||||||
day,
|
day,
|
||||||
planned_events: PlannedEvent::get_pinned_for_day(db, day).await,
|
events: Event::get_pinned_for_day(db, day).await,
|
||||||
trips: Trip::get_pinned_for_day(db, day).await,
|
trips: Trip::get_pinned_for_day(db, day).await,
|
||||||
is_pinned,
|
is_pinned,
|
||||||
max_waterlevel: Waterlevel::max_waterlevel_for_day(db, day).await,
|
max_waterlevel: Waterlevel::max_waterlevel_for_day(db, day).await,
|
||||||
@ -56,7 +56,7 @@ impl Day {
|
|||||||
} else {
|
} else {
|
||||||
Self {
|
Self {
|
||||||
day,
|
day,
|
||||||
planned_events: PlannedEvent::get_for_day(db, day).await,
|
events: Event::get_for_day(db, day).await,
|
||||||
trips: Trip::get_for_day(db, day).await,
|
trips: Trip::get_for_day(db, day).await,
|
||||||
is_pinned,
|
is_pinned,
|
||||||
max_waterlevel: Waterlevel::max_waterlevel_for_day(db, day).await,
|
max_waterlevel: Waterlevel::max_waterlevel_for_day(db, day).await,
|
||||||
@ -67,7 +67,7 @@ impl Day {
|
|||||||
pub async fn new_guest(db: &SqlitePool, day: NaiveDate, is_pinned: bool) -> Self {
|
pub async fn new_guest(db: &SqlitePool, day: NaiveDate, is_pinned: bool) -> Self {
|
||||||
let mut day = Self::new(db, day, is_pinned).await;
|
let mut day = Self::new(db, day, is_pinned).await;
|
||||||
|
|
||||||
day.planned_events.retain(|e| e.planned_event.allow_guests);
|
day.events.retain(|e| e.event.allow_guests);
|
||||||
day.trips.retain(|t| t.trip.allow_guests);
|
day.trips.retain(|t| t.trip.allow_guests);
|
||||||
|
|
||||||
day
|
day
|
||||||
|
@ -7,7 +7,7 @@ use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
|
|||||||
|
|
||||||
use super::{role::Role, user::User};
|
use super::{role::Role, user::User};
|
||||||
|
|
||||||
#[derive(FromRow, Debug, Serialize, Deserialize)]
|
#[derive(FromRow, Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Notification {
|
pub struct Notification {
|
||||||
pub id: i64,
|
pub id: i64,
|
||||||
pub user_id: i64,
|
pub user_id: i64,
|
||||||
@ -153,7 +153,7 @@ ORDER BY read_at DESC, created_at DESC;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Cox read notification about cancelled event
|
// Cox read notification about cancelled event
|
||||||
let re = Regex::new(r"^remove_trip_by_planned_event:(\d+)$").unwrap();
|
let re = Regex::new(r"^remove_trip_by_event:(\d+)$").unwrap();
|
||||||
if let Some(caps) = re.captures(action) {
|
if let Some(caps) = re.captures(action) {
|
||||||
if let Some(matched) = caps.get(1) {
|
if let Some(matched) = caps.get(1) {
|
||||||
if let Ok(number) = matched.as_str().parse::<i32>() {
|
if let Ok(number) = matched.as_str().parse::<i32>() {
|
||||||
@ -180,3 +180,114 @@ ORDER BY read_at DESC, created_at DESC;
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::{
|
||||||
|
model::{
|
||||||
|
event::{Event, EventUpdate, Registration},
|
||||||
|
notification::Notification,
|
||||||
|
trip::Trip,
|
||||||
|
tripdetails::{TripDetails, TripDetailsToAdd},
|
||||||
|
user::{CoxUser, User},
|
||||||
|
usertrip::UserTrip,
|
||||||
|
},
|
||||||
|
testdb,
|
||||||
|
};
|
||||||
|
|
||||||
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
|
#[sqlx::test]
|
||||||
|
fn event_canceled() {
|
||||||
|
let pool = testdb!();
|
||||||
|
|
||||||
|
// Create event
|
||||||
|
let add_tripdetails = TripDetailsToAdd {
|
||||||
|
planned_starting_time: "10:00",
|
||||||
|
max_people: 4,
|
||||||
|
day: "1970-02-01".into(),
|
||||||
|
notes: None,
|
||||||
|
trip_type: None,
|
||||||
|
allow_guests: false,
|
||||||
|
always_show: false,
|
||||||
|
};
|
||||||
|
let tripdetails_id = TripDetails::create(&pool, add_tripdetails).await;
|
||||||
|
let trip_details = TripDetails::find_by_id(&pool, tripdetails_id)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
Event::create(&pool, "new-event".into(), 2, &trip_details).await;
|
||||||
|
let event = Event::find_by_trip_details(&pool, trip_details.id)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Rower + Cox joins
|
||||||
|
let rower = User::find_by_name(&pool, "rower").await.unwrap();
|
||||||
|
UserTrip::create(&pool, &rower, &trip_details, None)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let cox = CoxUser::new(&pool, User::find_by_name(&pool, "cox").await.unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
Trip::new_join(&pool, &cox, &event).await.unwrap();
|
||||||
|
|
||||||
|
// Cancel Event
|
||||||
|
let cancel_update = EventUpdate {
|
||||||
|
name: &event.name,
|
||||||
|
planned_amount_cox: event.planned_amount_cox as i32,
|
||||||
|
max_people: 0,
|
||||||
|
notes: event.notes.as_deref(),
|
||||||
|
always_show: event.always_show,
|
||||||
|
is_locked: event.is_locked,
|
||||||
|
};
|
||||||
|
event.update(&pool, &cancel_update).await;
|
||||||
|
|
||||||
|
// Rower received notification
|
||||||
|
let notifications = Notification::for_user(&pool, &rower).await;
|
||||||
|
let rower_notification = notifications[0].clone();
|
||||||
|
assert_eq!(rower_notification.category, "Absage Ausfahrt");
|
||||||
|
assert_eq!(
|
||||||
|
rower_notification.action_after_reading.as_deref(),
|
||||||
|
Some("remove_user_trip_with_trip_details_id:3")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Cox received notification
|
||||||
|
let notifications = Notification::for_user(&pool, &cox.user).await;
|
||||||
|
let cox_notification = notifications[0].clone();
|
||||||
|
assert_eq!(cox_notification.category, "Absage Ausfahrt");
|
||||||
|
assert_eq!(
|
||||||
|
cox_notification.action_after_reading.as_deref(),
|
||||||
|
Some("remove_trip_by_event:2")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Notification removed if cancellation is cancelled
|
||||||
|
let update = EventUpdate {
|
||||||
|
name: &event.name,
|
||||||
|
planned_amount_cox: event.planned_amount_cox as i32,
|
||||||
|
max_people: 3,
|
||||||
|
notes: event.notes.as_deref(),
|
||||||
|
always_show: event.always_show,
|
||||||
|
is_locked: event.is_locked,
|
||||||
|
};
|
||||||
|
event.update(&pool, &update).await;
|
||||||
|
assert!(Notification::for_user(&pool, &rower).await.is_empty());
|
||||||
|
assert!(Notification::for_user(&pool, &cox.user).await.is_empty());
|
||||||
|
|
||||||
|
// Cancel event again
|
||||||
|
event.update(&pool, &cancel_update).await;
|
||||||
|
|
||||||
|
// Rower is removed if notification is accepted
|
||||||
|
assert!(event.is_rower_registered(&pool, &rower).await);
|
||||||
|
rower_notification.mark_read(&pool).await;
|
||||||
|
assert!(!event.is_rower_registered(&pool, &rower).await);
|
||||||
|
|
||||||
|
// Cox is removed if notification is accepted
|
||||||
|
let registration = Registration::all_cox(&pool, event.id).await;
|
||||||
|
assert_eq!(registration.len(), 1);
|
||||||
|
assert_eq!(registration[0].name, "cox");
|
||||||
|
|
||||||
|
cox_notification.mark_read(&pool).await;
|
||||||
|
|
||||||
|
let registration = Registration::all_cox(&pool, event.id).await;
|
||||||
|
assert!(registration.is_empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,8 +3,8 @@ use serde::Serialize;
|
|||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
event::{Event, Registration},
|
||||||
notification::Notification,
|
notification::Notification,
|
||||||
planned_event::{PlannedEvent, Registration},
|
|
||||||
tripdetails::TripDetails,
|
tripdetails::TripDetails,
|
||||||
triptype::TripType,
|
triptype::TripType,
|
||||||
user::{CoxUser, User},
|
user::{CoxUser, User},
|
||||||
@ -133,28 +133,28 @@ WHERE trip.id=?
|
|||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cox decides to help in a planned event.
|
/// Cox decides to help in a event.
|
||||||
pub async fn new_join(
|
pub async fn new_join(
|
||||||
db: &SqlitePool,
|
db: &SqlitePool,
|
||||||
cox: &CoxUser,
|
cox: &CoxUser,
|
||||||
planned_event: &PlannedEvent,
|
event: &Event,
|
||||||
) -> Result<(), CoxHelpError> {
|
) -> Result<(), CoxHelpError> {
|
||||||
if planned_event.is_rower_registered(db, cox).await {
|
if event.is_rower_registered(db, cox).await {
|
||||||
return Err(CoxHelpError::AlreadyRegisteredAsRower);
|
return Err(CoxHelpError::AlreadyRegisteredAsRower);
|
||||||
}
|
}
|
||||||
|
|
||||||
if planned_event.trip_details(db).await.is_locked {
|
if event.trip_details(db).await.is_locked {
|
||||||
return Err(CoxHelpError::DetailsLocked);
|
return Err(CoxHelpError::DetailsLocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
if planned_event.max_people == 0 {
|
if event.max_people == 0 {
|
||||||
return Err(CoxHelpError::CanceledEvent);
|
return Err(CoxHelpError::CanceledEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
match sqlx::query!(
|
match sqlx::query!(
|
||||||
"INSERT INTO trip (cox_id, planned_event_id) VALUES(?, ?)",
|
"INSERT INTO trip (cox_id, planned_event_id) VALUES(?, ?)",
|
||||||
cox.id,
|
cox.id,
|
||||||
planned_event.id
|
event.id
|
||||||
)
|
)
|
||||||
.execute(db)
|
.execute(db)
|
||||||
.await
|
.await
|
||||||
@ -281,16 +281,16 @@ WHERE day=?
|
|||||||
pub async fn delete_by_planned_event(
|
pub async fn delete_by_planned_event(
|
||||||
db: &SqlitePool,
|
db: &SqlitePool,
|
||||||
cox: &CoxUser,
|
cox: &CoxUser,
|
||||||
planned_event: &PlannedEvent,
|
event: &Event,
|
||||||
) -> Result<(), TripHelpDeleteError> {
|
) -> Result<(), TripHelpDeleteError> {
|
||||||
if planned_event.trip_details(db).await.is_locked {
|
if event.trip_details(db).await.is_locked {
|
||||||
return Err(TripHelpDeleteError::DetailsLocked);
|
return Err(TripHelpDeleteError::DetailsLocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
let affected_rows = sqlx::query!(
|
let affected_rows = sqlx::query!(
|
||||||
"DELETE FROM trip WHERE cox_id = ? AND planned_event_id = ?",
|
"DELETE FROM trip WHERE cox_id = ? AND planned_event_id = ?",
|
||||||
cox.id,
|
cox.id,
|
||||||
planned_event.id
|
event.id
|
||||||
)
|
)
|
||||||
.execute(db)
|
.execute(db)
|
||||||
.await
|
.await
|
||||||
@ -374,7 +374,7 @@ pub enum TripUpdateError {
|
|||||||
mod test {
|
mod test {
|
||||||
use crate::{
|
use crate::{
|
||||||
model::{
|
model::{
|
||||||
planned_event::PlannedEvent,
|
event::Event,
|
||||||
trip::{self, TripDeleteError},
|
trip::{self, TripDeleteError},
|
||||||
tripdetails::TripDetails,
|
tripdetails::TripDetails,
|
||||||
user::{CoxUser, User},
|
user::{CoxUser, User},
|
||||||
@ -425,7 +425,7 @@ mod test {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let planned_event = PlannedEvent::find_by_id(&pool, 1).await.unwrap();
|
let planned_event = Event::find_by_id(&pool, 1).await.unwrap();
|
||||||
|
|
||||||
assert!(Trip::new_join(&pool, &cox, &planned_event).await.is_ok());
|
assert!(Trip::new_join(&pool, &cox, &planned_event).await.is_ok());
|
||||||
}
|
}
|
||||||
@ -441,7 +441,7 @@ mod test {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let planned_event = PlannedEvent::find_by_id(&pool, 1).await.unwrap();
|
let planned_event = Event::find_by_id(&pool, 1).await.unwrap();
|
||||||
|
|
||||||
Trip::new_join(&pool, &cox, &planned_event).await.unwrap();
|
Trip::new_join(&pool, &cox, &planned_event).await.unwrap();
|
||||||
assert!(Trip::new_join(&pool, &cox, &planned_event).await.is_err());
|
assert!(Trip::new_join(&pool, &cox, &planned_event).await.is_err());
|
||||||
@ -542,7 +542,7 @@ mod test {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let planned_event = PlannedEvent::find_by_id(&pool, 1).await.unwrap();
|
let planned_event = Event::find_by_id(&pool, 1).await.unwrap();
|
||||||
|
|
||||||
Trip::new_join(&pool, &cox, &planned_event).await.unwrap();
|
Trip::new_join(&pool, &cox, &planned_event).await.unwrap();
|
||||||
|
|
||||||
|
@ -823,7 +823,7 @@ ORDER BY last_access DESC
|
|||||||
for date in TripDetails::pinned_days(db, self.amount_days_to_show(db).await - 1).await {
|
for date in TripDetails::pinned_days(db, self.amount_days_to_show(db).await - 1).await {
|
||||||
if self.has_role(db, "scheckbuch").await {
|
if self.has_role(db, "scheckbuch").await {
|
||||||
let day = Day::new_guest(db, date, true).await;
|
let day = Day::new_guest(db, date, true).await;
|
||||||
if !day.planned_events.is_empty() {
|
if !day.events.is_empty() {
|
||||||
days.push(day);
|
days.push(day);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1124,15 +1124,15 @@ impl<'r> FromRequest<'r> for VorstandUser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct PlannedEventUser(pub(crate) User);
|
pub struct EventUser(pub(crate) User);
|
||||||
|
|
||||||
impl From<PlannedEventUser> for User {
|
impl From<EventUser> for User {
|
||||||
fn from(val: PlannedEventUser) -> Self {
|
fn from(val: EventUser) -> Self {
|
||||||
val.0
|
val.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for PlannedEventUser {
|
impl Deref for EventUser {
|
||||||
type Target = User;
|
type Target = User;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@ -1183,7 +1183,7 @@ impl UserWithMembershipPdf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<'r> FromRequest<'r> for PlannedEventUser {
|
impl<'r> FromRequest<'r> for EventUser {
|
||||||
type Error = LoginError;
|
type Error = LoginError;
|
||||||
|
|
||||||
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
|
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
|
||||||
@ -1191,7 +1191,7 @@ impl<'r> FromRequest<'r> for PlannedEventUser {
|
|||||||
match User::from_request(req).await {
|
match User::from_request(req).await {
|
||||||
Outcome::Success(user) => {
|
Outcome::Success(user) => {
|
||||||
if user.has_role(db, "planned_event").await {
|
if user.has_role(db, "planned_event").await {
|
||||||
Outcome::Success(PlannedEventUser(user))
|
Outcome::Success(EventUser(user))
|
||||||
} else {
|
} else {
|
||||||
Outcome::Error((Status::Forbidden, LoginError::NotACox))
|
Outcome::Error((Status::Forbidden, LoginError::NotACox))
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ pub enum UserTripDeleteError {
|
|||||||
mod test {
|
mod test {
|
||||||
use crate::{
|
use crate::{
|
||||||
model::{
|
model::{
|
||||||
planned_event::PlannedEvent, trip::Trip, tripdetails::TripDetails, user::CoxUser,
|
event::Event, trip::Trip, tripdetails::TripDetails, user::CoxUser,
|
||||||
usertrip::UserTripError,
|
usertrip::UserTripError,
|
||||||
},
|
},
|
||||||
testdb,
|
testdb,
|
||||||
@ -240,8 +240,8 @@ mod test {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let planned_event = PlannedEvent::find_by_id(&pool, 1).await.unwrap();
|
let event = Event::find_by_id(&pool, 1).await.unwrap();
|
||||||
Trip::new_join(&pool, &cox, &planned_event).await.unwrap();
|
Trip::new_join(&pool, &cox, &event).await.unwrap();
|
||||||
|
|
||||||
let trip_details = TripDetails::find_by_id(&pool, 1).await.unwrap();
|
let trip_details = TripDetails::find_by_id(&pool, 1).await.unwrap();
|
||||||
let result = UserTrip::create(&pool, &cox, &trip_details, None)
|
let result = UserTrip::create(&pool, &cox, &trip_details, None)
|
||||||
|
@ -8,14 +8,14 @@ use serde::Serialize;
|
|||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use crate::model::{
|
use crate::model::{
|
||||||
planned_event::{self, PlannedEvent},
|
event::{self, Event},
|
||||||
tripdetails::{TripDetails, TripDetailsToAdd},
|
tripdetails::{TripDetails, TripDetailsToAdd},
|
||||||
user::PlannedEventUser,
|
user::EventUser,
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: add constraints (e.g. planned_amount_cox > 0)
|
//TODO: add constraints (e.g. planned_amount_cox > 0)
|
||||||
#[derive(FromForm, Serialize)]
|
#[derive(FromForm, Serialize)]
|
||||||
struct AddPlannedEventForm<'r> {
|
struct AddEventForm<'r> {
|
||||||
name: &'r str,
|
name: &'r str,
|
||||||
planned_amount_cox: i32,
|
planned_amount_cox: i32,
|
||||||
tripdetails: TripDetailsToAdd<'r>,
|
tripdetails: TripDetailsToAdd<'r>,
|
||||||
@ -24,8 +24,8 @@ struct AddPlannedEventForm<'r> {
|
|||||||
#[post("/planned-event", data = "<data>")]
|
#[post("/planned-event", data = "<data>")]
|
||||||
async fn create(
|
async fn create(
|
||||||
db: &State<SqlitePool>,
|
db: &State<SqlitePool>,
|
||||||
data: Form<AddPlannedEventForm<'_>>,
|
data: Form<AddEventForm<'_>>,
|
||||||
_admin: PlannedEventUser,
|
_admin: EventUser,
|
||||||
) -> Flash<Redirect> {
|
) -> Flash<Redirect> {
|
||||||
let data = data.into_inner();
|
let data = data.into_inner();
|
||||||
|
|
||||||
@ -34,14 +34,14 @@ async fn create(
|
|||||||
//just created
|
//just created
|
||||||
//the object
|
//the object
|
||||||
|
|
||||||
PlannedEvent::create(db, data.name, data.planned_amount_cox, trip_details).await;
|
Event::create(db, data.name, data.planned_amount_cox, &trip_details).await;
|
||||||
|
|
||||||
Flash::success(Redirect::to("/planned"), "Event hinzugefügt")
|
Flash::success(Redirect::to("/planned"), "Event hinzugefügt")
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: add constraints (e.g. planned_amount_cox > 0)
|
//TODO: add constraints (e.g. planned_amount_cox > 0)
|
||||||
#[derive(FromForm)]
|
#[derive(FromForm)]
|
||||||
struct UpdatePlannedEventForm<'r> {
|
struct UpdateEventForm<'r> {
|
||||||
id: i64,
|
id: i64,
|
||||||
name: &'r str,
|
name: &'r str,
|
||||||
planned_amount_cox: i32,
|
planned_amount_cox: i32,
|
||||||
@ -54,10 +54,10 @@ struct UpdatePlannedEventForm<'r> {
|
|||||||
#[put("/planned-event", data = "<data>")]
|
#[put("/planned-event", data = "<data>")]
|
||||||
async fn update(
|
async fn update(
|
||||||
db: &State<SqlitePool>,
|
db: &State<SqlitePool>,
|
||||||
data: Form<UpdatePlannedEventForm<'_>>,
|
data: Form<UpdateEventForm<'_>>,
|
||||||
_admin: PlannedEventUser,
|
_admin: EventUser,
|
||||||
) -> Flash<Redirect> {
|
) -> Flash<Redirect> {
|
||||||
let update = planned_event::EventUpdate {
|
let update = event::EventUpdate {
|
||||||
name: data.name,
|
name: data.name,
|
||||||
planned_amount_cox: data.planned_amount_cox,
|
planned_amount_cox: data.planned_amount_cox,
|
||||||
max_people: data.max_people,
|
max_people: data.max_people,
|
||||||
@ -65,7 +65,7 @@ async fn update(
|
|||||||
always_show: data.always_show,
|
always_show: data.always_show,
|
||||||
is_locked: data.is_locked,
|
is_locked: data.is_locked,
|
||||||
};
|
};
|
||||||
match PlannedEvent::find_by_id(db, data.id).await {
|
match Event::find_by_id(db, data.id).await {
|
||||||
Some(planned_event) => {
|
Some(planned_event) => {
|
||||||
planned_event.update(db, &update).await;
|
planned_event.update(db, &update).await;
|
||||||
Flash::success(Redirect::to("/planned"), "Event erfolgreich bearbeitet")
|
Flash::success(Redirect::to("/planned"), "Event erfolgreich bearbeitet")
|
||||||
@ -75,9 +75,9 @@ async fn update(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get("/planned-event/<id>/delete")]
|
#[get("/planned-event/<id>/delete")]
|
||||||
async fn delete(db: &State<SqlitePool>, id: i64, _admin: PlannedEventUser) -> Flash<Redirect> {
|
async fn delete(db: &State<SqlitePool>, id: i64, _admin: EventUser) -> Flash<Redirect> {
|
||||||
let Some(event) = PlannedEvent::find_by_id(db, id).await else {
|
let Some(event) = Event::find_by_id(db, id).await else {
|
||||||
return Flash::error(Redirect::to("/planned"), "PlannedEvent does not exist");
|
return Flash::error(Redirect::to("/planned"), "Event does not exist");
|
||||||
};
|
};
|
||||||
|
|
||||||
match event.delete(db).await {
|
match event.delete(db).await {
|
||||||
@ -105,7 +105,7 @@ mod test {
|
|||||||
fn test_delete() {
|
fn test_delete() {
|
||||||
let db = testdb!();
|
let db = testdb!();
|
||||||
|
|
||||||
let _ = PlannedEvent::find_by_id(&db, 1).await.unwrap();
|
let _ = Event::find_by_id(&db, 1).await.unwrap();
|
||||||
|
|
||||||
let rocket = rocket::build().manage(db.clone());
|
let rocket = rocket::build().manage(db.clone());
|
||||||
let rocket = crate::tera::config(rocket);
|
let rocket = crate::tera::config(rocket);
|
||||||
@ -130,7 +130,7 @@ mod test {
|
|||||||
|
|
||||||
assert_eq!(flash_cookie.value(), "7:successEvent gelöscht");
|
assert_eq!(flash_cookie.value(), "7:successEvent gelöscht");
|
||||||
|
|
||||||
let event = PlannedEvent::find_by_id(&db, 1).await;
|
let event = Event::find_by_id(&db, 1).await;
|
||||||
assert_eq!(event, None);
|
assert_eq!(event, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,16 +159,16 @@ mod test {
|
|||||||
.get("_flash")
|
.get("_flash")
|
||||||
.expect("Expected flash cookie");
|
.expect("Expected flash cookie");
|
||||||
|
|
||||||
assert_eq!(flash_cookie.value(), "5:errorPlannedEvent does not exist");
|
assert_eq!(flash_cookie.value(), "5:errorEvent does not exist");
|
||||||
|
|
||||||
let _ = PlannedEvent::find_by_id(&db, 1).await.unwrap();
|
let _ = Event::find_by_id(&db, 1).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[sqlx::test]
|
#[sqlx::test]
|
||||||
fn test_update() {
|
fn test_update() {
|
||||||
let db = testdb!();
|
let db = testdb!();
|
||||||
|
|
||||||
let event = PlannedEvent::find_by_id(&db, 1).await.unwrap();
|
let event = Event::find_by_id(&db, 1).await.unwrap();
|
||||||
assert_eq!(event.notes, Some("trip_details for a planned event".into()));
|
assert_eq!(event.notes, Some("trip_details for a planned event".into()));
|
||||||
|
|
||||||
let rocket = rocket::build().manage(db.clone());
|
let rocket = rocket::build().manage(db.clone());
|
||||||
@ -200,7 +200,7 @@ mod test {
|
|||||||
"7:successEvent erfolgreich bearbeitet"
|
"7:successEvent erfolgreich bearbeitet"
|
||||||
);
|
);
|
||||||
|
|
||||||
let event = PlannedEvent::find_by_id(&db, 1).await.unwrap();
|
let event = Event::find_by_id(&db, 1).await.unwrap();
|
||||||
assert_eq!(event.notes, Some("new-planned-event-text".into()));
|
assert_eq!(event.notes, Some("new-planned-event-text".into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +267,7 @@ mod test {
|
|||||||
|
|
||||||
assert_eq!(flash_cookie.value(), "7:successEvent hinzugefügt");
|
assert_eq!(flash_cookie.value(), "7:successEvent hinzugefügt");
|
||||||
|
|
||||||
let event = PlannedEvent::find_by_id(&db, 2).await.unwrap();
|
let event = Event::find_by_id(&db, 2).await.unwrap();
|
||||||
assert_eq!(event.name, "my-cool-new-event");
|
assert_eq!(event.name, "my-cool-new-event");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ use rocket::{
|
|||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use crate::model::{
|
use crate::model::{
|
||||||
|
event::Event,
|
||||||
log::Log,
|
log::Log,
|
||||||
planned_event::PlannedEvent,
|
|
||||||
trip::{self, CoxHelpError, Trip, TripDeleteError, TripHelpDeleteError, TripUpdateError},
|
trip::{self, CoxHelpError, Trip, TripDeleteError, TripHelpDeleteError, TripUpdateError},
|
||||||
tripdetails::{TripDetails, TripDetailsToAdd},
|
tripdetails::{TripDetails, TripDetailsToAdd},
|
||||||
user::CoxUser,
|
user::CoxUser,
|
||||||
@ -82,7 +82,7 @@ async fn update(
|
|||||||
|
|
||||||
#[get("/join/<planned_event_id>")]
|
#[get("/join/<planned_event_id>")]
|
||||||
async fn join(db: &State<SqlitePool>, planned_event_id: i64, cox: CoxUser) -> Flash<Redirect> {
|
async fn join(db: &State<SqlitePool>, planned_event_id: i64, cox: CoxUser) -> Flash<Redirect> {
|
||||||
if let Some(planned_event) = PlannedEvent::find_by_id(db, planned_event_id).await {
|
if let Some(planned_event) = Event::find_by_id(db, planned_event_id).await {
|
||||||
match Trip::new_join(db, &cox, &planned_event).await {
|
match Trip::new_join(db, &cox, &planned_event).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
Log::create(
|
Log::create(
|
||||||
@ -137,7 +137,7 @@ async fn remove_trip(db: &State<SqlitePool>, trip_id: i64, cox: CoxUser) -> Flas
|
|||||||
|
|
||||||
#[get("/remove/<planned_event_id>")]
|
#[get("/remove/<planned_event_id>")]
|
||||||
async fn remove(db: &State<SqlitePool>, planned_event_id: i64, cox: CoxUser) -> Flash<Redirect> {
|
async fn remove(db: &State<SqlitePool>, planned_event_id: i64, cox: CoxUser) -> Flash<Redirect> {
|
||||||
if let Some(planned_event) = PlannedEvent::find_by_id(db, planned_event_id).await {
|
if let Some(planned_event) = Event::find_by_id(db, planned_event_id).await {
|
||||||
match Trip::delete_by_planned_event(db, &cox, &planned_event).await {
|
match Trip::delete_by_planned_event(db, &cox, &planned_event).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
Log::create(
|
Log::create(
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use rocket::{get, http::ContentType, routes, Route, State};
|
use rocket::{get, http::ContentType, routes, Route, State};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use crate::model::planned_event::PlannedEvent;
|
use crate::model::event::Event;
|
||||||
|
|
||||||
#[get("/cal")]
|
#[get("/cal")]
|
||||||
async fn cal(db: &State<SqlitePool>) -> (ContentType, String) {
|
async fn cal(db: &State<SqlitePool>) -> (ContentType, String) {
|
||||||
//TODO: add unit test once proper functionality is there
|
//TODO: add unit test once proper functionality is there
|
||||||
(ContentType::Calendar, PlannedEvent::get_ics_feed(db).await)
|
(ContentType::Calendar, Event::get_ics_feed(db).await)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
|
@ -58,11 +58,11 @@
|
|||||||
<h1 class="h1 sm:col-span-2 lg:col-span-3">Ausfahrten</h1>
|
<h1 class="h1 sm:col-span-2 lg:col-span-3">Ausfahrten</h1>
|
||||||
{% include "includes/buttons" %}
|
{% include "includes/buttons" %}
|
||||||
{% for day in days %}
|
{% for day in days %}
|
||||||
{% set amount_trips = day.planned_events | length + day.trips | length %}
|
{% set amount_trips = day.events | length + day.trips | length %}
|
||||||
{% set_global day_cox_needed = false %}
|
{% set_global day_cox_needed = false %}
|
||||||
{% if day.planned_events | length > 0 %}
|
{% if day.events | length > 0 %}
|
||||||
{% for planned_event in day.planned_events %}
|
{% for event in day.events %}
|
||||||
{% if planned_event.cox_needed %}
|
{% if event.cox_needed %}
|
||||||
{% set_global day_cox_needed = true %}
|
{% set_global day_cox_needed = true %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@ -88,82 +88,82 @@
|
|||||||
</small>
|
</small>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h2>
|
</h2>
|
||||||
{% if day.planned_events | length > 0 or day.trips | length > 0 %}
|
{% if day.events | length > 0 or day.trips | length > 0 %}
|
||||||
<div class="grid grid-cols-1 gap-3 mb-3">
|
<div class="grid grid-cols-1 gap-3 mb-3">
|
||||||
{# --- START Events --- #}
|
{# --- START Events --- #}
|
||||||
{% if day.planned_events | length > 0 %}
|
{% if day.events | length > 0 %}
|
||||||
{% for planned_event in day.planned_events | sort(attribute="planned_starting_time") %}
|
{% for event in day.events | sort(attribute="planned_starting_time") %}
|
||||||
{% set amount_cur_cox = planned_event.cox | length %}
|
{% set amount_cur_cox = event.cox | length %}
|
||||||
{% set amount_cox_missing = planned_event.planned_amount_cox - amount_cur_cox %}
|
{% set amount_cox_missing = event.planned_amount_cox - amount_cur_cox %}
|
||||||
<div class="pt-2 px-3 border-t border-gray-200"
|
<div class="pt-2 px-3 border-t border-gray-200"
|
||||||
style="order: {{ planned_event.planned_starting_time | replace(from=":", to="") }}">
|
style="order: {{ event.planned_starting_time | replace(from=":", to="") }}">
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<div class="mr-1">
|
<div class="mr-1">
|
||||||
{% if planned_event.max_people == 0 %}
|
{% if event.max_people == 0 %}
|
||||||
<strong class="text-[#f43f5e]">⚠ Absage
|
<strong class="text-[#f43f5e]">⚠ Absage
|
||||||
{{ planned_event.planned_starting_time }}
|
{{ event.planned_starting_time }}
|
||||||
Uhr
|
Uhr
|
||||||
</strong>
|
</strong>
|
||||||
<small class="text-[#f43f5e]">({{ planned_event.name }}
|
<small class="text-[#f43f5e]">({{ event.name }}
|
||||||
{%- if planned_event.trip_type %}
|
{%- if event.trip_type %}
|
||||||
- {{ planned_event.trip_type.icon | safe }} {{ planned_event.trip_type.name }}
|
- {{ event.trip_type.icon | safe }} {{ event.trip_type.name }}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
)</small>
|
)</small>
|
||||||
{% else %}
|
{% else %}
|
||||||
<strong class="text-primary-900 dark:text-white">
|
<strong class="text-primary-900 dark:text-white">
|
||||||
{{ planned_event.planned_starting_time }}
|
{{ event.planned_starting_time }}
|
||||||
Uhr
|
Uhr
|
||||||
</strong>
|
</strong>
|
||||||
<small class="text-gray-600 dark:text-gray-100">({{ planned_event.name }}
|
<small class="text-gray-600 dark:text-gray-100">({{ event.name }}
|
||||||
{%- if planned_event.trip_type %}
|
{%- if event.trip_type %}
|
||||||
- {{ planned_event.trip_type.icon | safe }} {{ planned_event.trip_type.name }}
|
- {{ event.trip_type.icon | safe }} {{ event.trip_type.name }}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
)</small>
|
)</small>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<br />
|
<br />
|
||||||
<a href="#" data-sidebar="true" data-trigger="sidebar" data-header="<strong>{{ planned_event.planned_starting_time }} Uhr</strong> ({{ planned_event.name }})
|
<a href="#" data-sidebar="true" data-trigger="sidebar" data-header="<strong>{{ event.planned_starting_time }} Uhr</strong> ({{ event.name }})
|
||||||
{% if planned_event.trip_type %}<small class='block'>{{ planned_event.trip_type.desc }}</small>{% endif %}
|
{% if event.trip_type %}<small class='block'>{{ event.trip_type.desc }}</small>{% endif %}
|
||||||
{% if planned_event.notes %}<small class='block'>{{ planned_event.notes }}</small>{% endif %}
|
{% if event.notes %}<small class='block'>{{ event.notes }}</small>{% endif %}
|
||||||
" data-body="#event{{ planned_event.trip_details_id }}" class="inline-block link-primary mr-3">
|
" data-body="#event{{ event.trip_details_id }}" class="inline-block link-primary mr-3">
|
||||||
Details
|
Details
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right grid gap-2">
|
<div class="text-right grid gap-2">
|
||||||
{# --- START Row Buttons --- #}
|
{# --- START Row Buttons --- #}
|
||||||
{% set_global cur_user_participates = false %}
|
{% set_global cur_user_participates = false %}
|
||||||
{% for rower in planned_event.rower %}
|
{% for rower in event.rower %}
|
||||||
{% if rower.name == loggedin_user.name %}
|
{% if rower.name == loggedin_user.name %}
|
||||||
{% set_global cur_user_participates = true %}
|
{% set_global cur_user_participates = true %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if cur_user_participates %}
|
{% if cur_user_participates %}
|
||||||
<a href="/planned/remove/{{ planned_event.trip_details_id }}"
|
<a href="/planned/remove/{{ event.trip_details_id }}"
|
||||||
class="btn btn-attention btn-fw">Abmelden</a>
|
class="btn btn-attention btn-fw">Abmelden</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if planned_event.max_people > planned_event.rower | length and cur_user_participates == false %}
|
{% if event.max_people > event.rower | length and cur_user_participates == false %}
|
||||||
<a href="/planned/join/{{ planned_event.trip_details_id }}"
|
<a href="/planned/join/{{ event.trip_details_id }}"
|
||||||
class="btn btn-primary btn-fw"
|
class="btn btn-primary btn-fw"
|
||||||
{% if planned_event.trip_type %}onclick="return confirm('{{ planned_event.trip_type.question }}');"{% endif %}>Mitrudern</a>
|
{% if event.trip_type %}onclick="return confirm('{{ event.trip_type.question }}');"{% endif %}>Mitrudern</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{# --- END Row Buttons --- #}
|
{# --- END Row Buttons --- #}
|
||||||
{# --- START Cox Buttons --- #}
|
{# --- START Cox Buttons --- #}
|
||||||
{% if "cox" in loggedin_user.roles %}
|
{% if "cox" in loggedin_user.roles %}
|
||||||
{% set_global cur_user_participates = false %}
|
{% set_global cur_user_participates = false %}
|
||||||
{% for cox in planned_event.cox %}
|
{% for cox in event.cox %}
|
||||||
{% if cox.name == loggedin_user.name %}
|
{% if cox.name == loggedin_user.name %}
|
||||||
{% set_global cur_user_participates = true %}
|
{% set_global cur_user_participates = true %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if cur_user_participates %}
|
{% if cur_user_participates %}
|
||||||
<a href="/cox/remove/{{ planned_event.id }}"
|
<a href="/cox/remove/{{ event.id }}"
|
||||||
class="block btn btn-attention btn-fw">
|
class="block btn btn-attention btn-fw">
|
||||||
{% include "includes/cox-icon" %}
|
{% include "includes/cox-icon" %}
|
||||||
Abmelden
|
Abmelden
|
||||||
</a>
|
</a>
|
||||||
{% elif planned_event.planned_amount_cox > 0 %}
|
{% elif event.planned_amount_cox > 0 %}
|
||||||
<a href="/cox/join/{{ planned_event.id }}"
|
<a href="/cox/join/{{ event.id }}"
|
||||||
class="block btn {% if amount_cox_missing > 0 %} btn-dark {% else %} btn-gray {% endif %} btn-fw"
|
class="block btn {% if amount_cox_missing > 0 %} btn-dark {% else %} btn-gray {% endif %} btn-fw"
|
||||||
{% if planned_event.trip_type %}onclick="return confirm('{{ planned_event.trip_type.question }}');"{% endif %}>
|
{% if event.trip_type %}onclick="return confirm('{{ event.trip_type.question }}');"{% endif %}>
|
||||||
{% include "includes/cox-icon" %}
|
{% include "includes/cox-icon" %}
|
||||||
Steuern
|
Steuern
|
||||||
</a>
|
</a>
|
||||||
@ -174,30 +174,30 @@
|
|||||||
</div>
|
</div>
|
||||||
{# --- START Sidebar Content --- #}
|
{# --- START Sidebar Content --- #}
|
||||||
<div class="hidden">
|
<div class="hidden">
|
||||||
<div id="event{{ planned_event.trip_details_id }}">
|
<div id="event{{ event.trip_details_id }}">
|
||||||
{# --- START List Coxes --- #}
|
{# --- START List Coxes --- #}
|
||||||
{% if planned_event.planned_amount_cox > 0 %}
|
{% if event.planned_amount_cox > 0 %}
|
||||||
{% if planned_event.max_people == 0 %}
|
{% if event.max_people == 0 %}
|
||||||
{{ macros::box(participants=planned_event.cox, empty_seats="", header='Absage', bg='[#f43f5e]') }}
|
{{ macros::box(participants=event.cox, empty_seats="", header='Absage', bg='[#f43f5e]') }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if amount_cox_missing > 0 %}
|
{% if amount_cox_missing > 0 %}
|
||||||
{{ macros::box(participants=planned_event.cox, empty_seats=planned_event.planned_amount_cox - amount_cur_cox, header='Noch benötigte Steuerleute:', text='Keine Steuerleute angemeldet') }}
|
{{ macros::box(participants=event.cox, empty_seats=event.planned_amount_cox - amount_cur_cox, header='Noch benötigte Steuerleute:', text='Keine Steuerleute angemeldet') }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ macros::box(participants=planned_event.cox, empty_seats="", header='Genügend Steuerleute haben sich angemeldet :-)', text='Keine Steuerleute angemeldet') }}
|
{{ macros::box(participants=event.cox, empty_seats="", header='Genügend Steuerleute haben sich angemeldet :-)', text='Keine Steuerleute angemeldet') }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{# --- END List Coxes --- #}
|
{# --- END List Coxes --- #}
|
||||||
{# --- START List Rowers --- #}
|
{# --- START List Rowers --- #}
|
||||||
{% set amount_cur_rower = planned_event.rower | length %}
|
{% set amount_cur_rower = event.rower | length %}
|
||||||
{% if planned_event.max_people == 0 %}
|
{% if event.max_people == 0 %}
|
||||||
{{ macros::box(header='Absage', bg='[#f43f5e]', participants=planned_event.rower, trip_details_id=planned_event.trip_details_id, allow_removing="planned_event" in loggedin_user.roles) }}
|
{{ macros::box(header='Absage', bg='[#f43f5e]', participants=event.rower, trip_details_id=event.trip_details_id, allow_removing="event" in loggedin_user.roles) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ macros::box(participants=planned_event.rower, empty_seats=planned_event.max_people - amount_cur_rower, bg='primary-100', color='black', trip_details_id=planned_event.trip_details_id, allow_removing="planned_event" in loggedin_user.roles) }}
|
{{ macros::box(participants=event.rower, empty_seats=event.max_people - amount_cur_rower, bg='primary-100', color='black', trip_details_id=event.trip_details_id, allow_removing="event" in loggedin_user.roles) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{# --- END List Rowers --- #}
|
{# --- END List Rowers --- #}
|
||||||
{% if "planned_event" in loggedin_user.roles %}
|
{% if "event" in loggedin_user.roles %}
|
||||||
<form action="/planned/join/{{ planned_event.trip_details_id }}"
|
<form action="/planned/join/{{ event.trip_details_id }}"
|
||||||
method="get" />
|
method="get" />
|
||||||
{{ macros::input(label='Gast', class="input rounded-t", name='user_note', type='text', required=true) }}
|
{{ macros::input(label='Gast', class="input rounded-t", name='user_note', type='text', required=true) }}
|
||||||
<input value="Gast hinzufügen"
|
<input value="Gast hinzufügen"
|
||||||
@ -205,51 +205,51 @@
|
|||||||
type="submit" />
|
type="submit" />
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if planned_event.allow_guests %}
|
{% if event.allow_guests %}
|
||||||
<div class="text-primary-900 bg-primary-50 text-center p-1 mb-4">Gäste willkommen!</div>
|
<div class="text-primary-900 bg-primary-50 text-center p-1 mb-4">Gäste willkommen!</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if "planned_event" in loggedin_user.roles %}
|
{% if "event" in loggedin_user.roles %}
|
||||||
{# --- START Edit Form --- #}
|
{# --- START Edit Form --- #}
|
||||||
<div class="bg-gray-100 dark:bg-primary-900 p-3 mt-4 rounded-md">
|
<div class="bg-gray-100 dark:bg-primary-900 p-3 mt-4 rounded-md">
|
||||||
<h3 class="text-primary-950 dark:text-white font-bold uppercase tracking-wide mb-2">Ausfahrt bearbeiten</h3>
|
<h3 class="text-primary-950 dark:text-white font-bold uppercase tracking-wide mb-2">Ausfahrt bearbeiten</h3>
|
||||||
<form action="/admin/planned-event" method="post" class="grid gap-3">
|
<form action="/admin/planned-event" method="post" class="grid gap-3">
|
||||||
<input type="hidden" name="_method" value="put" />
|
<input type="hidden" name="_method" value="put" />
|
||||||
<input type="hidden" name="id" value="{{ planned_event.id }}" />
|
<input type="hidden" name="id" value="{{ event.id }}" />
|
||||||
{{ macros::input(label='Titel', name='name', type='input', value=planned_event.name) }}
|
{{ macros::input(label='Titel', name='name', type='input', value=event.name) }}
|
||||||
{{ macros::input(label='Anzahl Ruderer', name='max_people', type='number', required=true, value=planned_event.max_people, min='1') }}
|
{{ macros::input(label='Anzahl Ruderer', name='max_people', type='number', required=true, value=event.max_people, min='1') }}
|
||||||
{{ macros::input(label='Anzahl Steuerleute', name='planned_amount_cox', type='number', value=planned_event.planned_amount_cox, required=true, min='0') }}
|
{{ macros::input(label='Anzahl Steuerleute', name='planned_amount_cox', type='number', value=event.planned_amount_cox, required=true, min='0') }}
|
||||||
{{ macros::checkbox(label='Immer anzeigen', name='always_show', id=planned_event.id,checked=planned_event.always_show) }}
|
{{ macros::checkbox(label='Immer anzeigen', name='always_show', id=event.id,checked=event.always_show) }}
|
||||||
{{ macros::checkbox(label='Gesperrt', name='is_locked', id=planned_event.id,checked=planned_event.is_locked) }}
|
{{ macros::checkbox(label='Gesperrt', name='is_locked', id=event.id,checked=event.is_locked) }}
|
||||||
{{ macros::input(label='Anmerkungen', name='notes', type='input', value=planned_event.notes) }}
|
{{ macros::input(label='Anmerkungen', name='notes', type='input', value=event.notes) }}
|
||||||
<input value="Speichern" class="btn btn-primary" type="submit" />
|
<input value="Speichern" class="btn btn-primary" type="submit" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{# --- END Edit Form --- #}
|
{# --- END Edit Form --- #}
|
||||||
{# --- START Delete Btn --- #}
|
{# --- START Delete Btn --- #}
|
||||||
{% if planned_event.rower | length == 0 and amount_cur_cox == 0 %}
|
{% if event.rower | length == 0 and amount_cur_cox == 0 %}
|
||||||
<div class="text-right mt-6">
|
<div class="text-right mt-6">
|
||||||
<a href="/admin/planned-event/{{ planned_event.id }}/delete"
|
<a href="/admin/planned-event/{{ event.id }}/delete"
|
||||||
class="inline-block btn btn-alert">
|
class="inline-block btn btn-alert">
|
||||||
{% include "includes/delete-icon" %}
|
{% include "includes/delete-icon" %}
|
||||||
Termin löschen
|
Termin löschen
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if planned_event.max_people == 0 %}
|
{% if event.max_people == 0 %}
|
||||||
Wenn du deine Absage absagen (:^)) willst, einfach entsprechende Anzahl an Ruderer oben eintragen.
|
Wenn du deine Absage absagen (:^)) willst, einfach entsprechende Anzahl an Ruderer oben eintragen.
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="bg-gray-100 dark:bg-primary-900 p-3 mt-4 rounded-md">
|
<div class="bg-gray-100 dark:bg-primary-900 p-3 mt-4 rounded-md">
|
||||||
<h3 class="text-primary-950 dark:text-white font-bold uppercase tracking-wide mb-2">Event absagen</h3>
|
<h3 class="text-primary-950 dark:text-white font-bold uppercase tracking-wide mb-2">Event absagen</h3>
|
||||||
<form action="/admin/planned-event" method="post" class="grid">
|
<form action="/admin/planned-event" method="post" class="grid">
|
||||||
<input type="hidden" name="_method" value="put" />
|
<input type="hidden" name="_method" value="put" />
|
||||||
<input type="hidden" name="id" value="{{ planned_event.id }}" />
|
<input type="hidden" name="id" value="{{ event.id }}" />
|
||||||
{{ macros::input(label='Grund der Absage', name='notes', type='input', value='') }}
|
{{ macros::input(label='Grund der Absage', name='notes', type='input', value='') }}
|
||||||
{{ macros::input(label='', name='max_people', type='hidden', value=0) }}
|
{{ macros::input(label='', name='max_people', type='hidden', value=0) }}
|
||||||
{{ macros::input(label='', name='name', type='hidden', value=planned_event.name) }}
|
{{ macros::input(label='', name='name', type='hidden', value=event.name) }}
|
||||||
{{ macros::input(label='', name='max_people', type='hidden', value=planned_event.max_people) }}
|
{{ macros::input(label='', name='max_people', type='hidden', value=event.max_people) }}
|
||||||
{{ macros::input(label='', name='planned_amount_cox', type='hidden', value=planned_event.planned_amount_cox) }}
|
{{ macros::input(label='', name='planned_amount_cox', type='hidden', value=event.planned_amount_cox) }}
|
||||||
{{ macros::input(label='', name='always_show', type='hidden', value=planned_event.always_show) }}
|
{{ macros::input(label='', name='always_show', type='hidden', value=event.always_show) }}
|
||||||
{{ macros::input(label='', name='is_locked', type='hidden', value=planned_event.is_locked) }}
|
{{ macros::input(label='', name='is_locked', type='hidden', value=event.is_locked) }}
|
||||||
<input value="Ausfahrt absagen" class="btn btn-alert" type="submit" />
|
<input value="Ausfahrt absagen" class="btn btn-alert" type="submit" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -389,9 +389,9 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{# --- START Add Buttons --- #}
|
{# --- START Add Buttons --- #}
|
||||||
{% if "planned_event" in loggedin_user.roles or "cox" in loggedin_user.roles %}
|
{% if "event" in loggedin_user.roles or "cox" in loggedin_user.roles %}
|
||||||
<div class="grid {% if "planned_event" in loggedin_user.roles %}grid-cols-2{% endif %} text-center">
|
<div class="grid {% if "event" in loggedin_user.roles %}grid-cols-2{% endif %} text-center">
|
||||||
{% if "planned_event" in loggedin_user.roles %}
|
{% if "event" in loggedin_user.roles %}
|
||||||
<a href="#"
|
<a href="#"
|
||||||
data-sidebar="true"
|
data-sidebar="true"
|
||||||
data-trigger="sidebar"
|
data-trigger="sidebar"
|
||||||
@ -405,7 +405,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if "cox" in loggedin_user.roles %}
|
{% if "cox" in loggedin_user.roles %}
|
||||||
<a href="#" data-sidebar="true" data-trigger="sidebar" data-header="<strong>Ausfahrt</strong> am {{ day.day| date(format='%d.%m.%Y') }} erstellen" data-day="{{ day.day }}" data-body="#sidebarForm" class="relative inline-block w-full py-2 text-primary-900 hover:text-primary-950 dark:bg-primary-600 dark:text-white dark:hover:bg-primary-500 dark:hover:text-white focus:text-primary-950 text-sm font-semibold bg-gray-100 hover:bg-gray-200 focus:bg-gray-200
|
<a href="#" data-sidebar="true" data-trigger="sidebar" data-header="<strong>Ausfahrt</strong> am {{ day.day| date(format='%d.%m.%Y') }} erstellen" data-day="{{ day.day }}" data-body="#sidebarForm" class="relative inline-block w-full py-2 text-primary-900 hover:text-primary-950 dark:bg-primary-600 dark:text-white dark:hover:bg-primary-500 dark:hover:text-white focus:text-primary-950 text-sm font-semibold bg-gray-100 hover:bg-gray-200 focus:bg-gray-200
|
||||||
{% if "planned_event" in loggedin_user.roles %}
|
{% if "event" in loggedin_user.roles %}
|
||||||
rounded-br-md
|
rounded-br-md
|
||||||
{% else %}
|
{% else %}
|
||||||
rounded-b-md
|
rounded-b-md
|
||||||
@ -425,7 +425,7 @@
|
|||||||
{% if "cox" in loggedin_user.roles %}
|
{% if "cox" in loggedin_user.roles %}
|
||||||
{% include "forms/trip" %}
|
{% include "forms/trip" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if "planned_event" in loggedin_user.roles %}
|
{% if "event" in loggedin_user.roles %}
|
||||||
{% include "forms/event" %}
|
{% include "forms/event" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
Loading…
Reference in New Issue
Block a user