new-link #805

Merged
philipp merged 4 commits from new-link into staging 2024-11-27 08:14:02 +01:00
14 changed files with 173 additions and 55 deletions
Showing only changes of commit a07ff1d993 - Show all commits

View File

@ -9,8 +9,12 @@ use serde::Serialize;
use sqlx::{FromRow, Row, SqlitePool}; use sqlx::{FromRow, Row, SqlitePool};
use super::{ use super::{
notification::Notification, role::Role, tripdetails::TripDetails, triptype::TripType, log::Log,
user::User, notification::Notification,
role::Role,
tripdetails::TripDetails,
triptype::TripType,
user::{EventUser, User},
}; };
#[derive(Serialize, Clone, FromRow, Debug, PartialEq)] #[derive(Serialize, Clone, FromRow, Debug, PartialEq)]
@ -242,6 +246,7 @@ WHERE trip_details.id=?
pub async fn create( pub async fn create(
db: &SqlitePool, db: &SqlitePool,
user: &EventUser,
name: &str, name: &str,
planned_amount_cox: i32, planned_amount_cox: i32,
always_show: bool, always_show: bool,
@ -270,6 +275,15 @@ WHERE trip_details.id=?
.execute(db) .execute(db)
.await .await
.unwrap(); //Okay, as TripDetails can only be created with proper DB backing .unwrap(); //Okay, as TripDetails can only be created with proper DB backing
Log::create(
db,
format!(
"{} created event {} on {} at {}.",
user.user.name, name, trip_details.day, trip_details.planned_starting_time
),
)
.await;
} }
//TODO: create unit test //TODO: create unit test
@ -449,7 +463,13 @@ WHERE trip_details.id=?
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::{model::tripdetails::TripDetails, testdb}; use crate::{
model::{
tripdetails::TripDetails,
user::{EventUser, User},
},
testdb,
};
use super::Event; use super::Event;
use chrono::Local; use chrono::Local;
@ -469,7 +489,10 @@ mod test {
let trip_details = TripDetails::find_by_id(&pool, 1).await.unwrap(); let trip_details = TripDetails::find_by_id(&pool, 1).await.unwrap();
Event::create(&pool, "new-event".into(), 2, false, &trip_details).await; let admin = EventUser::new(&pool, User::find_by_id(&pool, 1).await.unwrap())
.await
.unwrap();
Event::create(&pool, &admin, "new-event".into(), 2, false, &trip_details).await;
let res = Event::get_for_day(&pool, Local::now().date_naive()).await; let res = Event::get_for_day(&pool, Local::now().date_naive()).await;
assert_eq!(res.len(), 2); assert_eq!(res.len(), 2);

View File

@ -221,7 +221,7 @@ mod test {
notification::Notification, notification::Notification,
trip::Trip, trip::Trip,
tripdetails::{TripDetails, TripDetailsToAdd}, tripdetails::{TripDetails, TripDetailsToAdd},
user::{SteeringUser, User}, user::{EventUser, SteeringUser, User},
usertrip::UserTrip, usertrip::UserTrip,
}, },
testdb, testdb,
@ -247,7 +247,10 @@ mod test {
let trip_details = TripDetails::find_by_id(&pool, tripdetails_id) let trip_details = TripDetails::find_by_id(&pool, tripdetails_id)
.await .await
.unwrap(); .unwrap();
Event::create(&pool, "new-event".into(), 2, false, &trip_details).await; let user = EventUser::new(&pool, User::find_by_id(&pool, 1).await.unwrap())
.await
.unwrap();
Event::create(&pool, &user, "new-event".into(), 2, false, &trip_details).await;
let event = Event::find_by_trip_details(&pool, trip_details.id) let event = Event::find_by_trip_details(&pool, trip_details.id)
.await .await
.unwrap(); .unwrap();

View File

@ -9,7 +9,7 @@ use super::{
notification::Notification, notification::Notification,
tripdetails::TripDetails, tripdetails::TripDetails,
triptype::TripType, triptype::TripType,
user::{SteeringUser, User}, user::{ErgoUser, SteeringUser, User},
usertrip::UserTrip, usertrip::UserTrip,
}; };
@ -38,7 +38,7 @@ pub struct TripWithUserAndType {
} }
pub struct TripUpdate<'a> { pub struct TripUpdate<'a> {
pub cox: &'a SteeringUser, pub cox: &'a User,
pub trip: &'a Trip, pub trip: &'a Trip,
pub max_people: i32, pub max_people: i32,
pub notes: Option<&'a str>, pub notes: Option<&'a str>,
@ -63,9 +63,23 @@ impl TripWithUserAndType {
impl Trip { impl Trip {
/// Cox decides to create own trip. /// Cox decides to create own trip.
pub async fn new_own(db: &SqlitePool, cox: &SteeringUser, trip_details: TripDetails) { pub async fn new_own(db: &SqlitePool, cox: &SteeringUser, trip_details: TripDetails) {
Self::perform_new(db, &cox.user, trip_details).await
}
pub async fn new_own_ergo(db: &SqlitePool, ergo: &ErgoUser, trip_details: TripDetails) {
let typ = trip_details.triptype(db).await;
if let Some(typ) = typ {
let allowed_type = TripType::find_by_id(db, 4).await.unwrap();
if typ == allowed_type {
Self::perform_new(db, &ergo.user, trip_details).await;
}
}
}
async fn perform_new(db: &SqlitePool, user: &User, trip_details: TripDetails) {
let _ = sqlx::query!( let _ = sqlx::query!(
"INSERT INTO trip (cox_id, trip_details_id) VALUES(?, ?)", "INSERT INTO trip (cox_id, trip_details_id) VALUES(?, ?)",
cox.id, user.id,
trip_details.id trip_details.id
) )
.execute(db) .execute(db)
@ -96,7 +110,7 @@ impl Trip {
&user, &user,
&format!( &format!(
"{} hat eine Ausfahrt zur selben Zeit ({} um {}) wie du erstellt", "{} hat eine Ausfahrt zur selben Zeit ({} um {}) wie du erstellt",
cox.user.name, trip.day, trip.planned_starting_time user.name, trip.day, trip.planned_starting_time
), ),
"Neue Ausfahrt zur selben Zeit", "Neue Ausfahrt zur selben Zeit",
None, None,
@ -273,6 +287,12 @@ WHERE day=?
return Err(TripUpdateError::NotYourTrip); return Err(TripUpdateError::NotYourTrip);
} }
if update.trip_type != Some(4) {
if !update.cox.allowed_to_steer(db).await {
return Err(TripUpdateError::TripTypeNotAllowed);
}
}
let Some(trip_details_id) = update.trip.trip_details_id else { let Some(trip_details_id) = update.trip.trip_details_id else {
return Err(TripUpdateError::TripDetailsDoesNotExist); //TODO: Remove? return Err(TripUpdateError::TripDetailsDoesNotExist); //TODO: Remove?
}; };
@ -314,7 +334,7 @@ WHERE day=?
&user, &user,
&format!( &format!(
"Die Ausfahrt von {} am {} um {} wurde abgesagt. {} Bitte gib Bescheid, dass du die Info erhalten hast indem du auf ✓ klickst.", "Die Ausfahrt von {} am {} um {} wurde abgesagt. {} Bitte gib Bescheid, dass du die Info erhalten hast indem du auf ✓ klickst.",
update.cox.user.name, update.cox.name,
update.trip.day, update.trip.day,
update.trip.planned_starting_time, update.trip.planned_starting_time,
notes notes
@ -384,11 +404,7 @@ WHERE day=?
Ok(()) Ok(())
} }
pub(crate) async fn delete( pub(crate) async fn delete(&self, db: &SqlitePool, user: &User) -> Result<(), TripDeleteError> {
&self,
db: &SqlitePool,
user: &SteeringUser,
) -> Result<(), TripDeleteError> {
let registered_rower = Registration::all_rower(db, self.trip_details_id.unwrap()).await; let registered_rower = Registration::all_rower(db, self.trip_details_id.unwrap()).await;
if !registered_rower.is_empty() { if !registered_rower.is_empty() {
return Err(TripDeleteError::SomebodyAlreadyRegistered); return Err(TripDeleteError::SomebodyAlreadyRegistered);
@ -398,7 +414,7 @@ WHERE day=?
return Err(TripDeleteError::NotYourTrip); return Err(TripDeleteError::NotYourTrip);
} }
Log::create(db, format!("{} deleted trip: {:#?}", user.user.name, self)).await; Log::create(db, format!("{} deleted trip: {:#?}", user.name, self)).await;
sqlx::query!("DELETE FROM trip WHERE id = ?", self.id) sqlx::query!("DELETE FROM trip WHERE id = ?", self.id)
.execute(db) .execute(db)
@ -464,6 +480,7 @@ pub enum TripDeleteError {
pub enum TripUpdateError { pub enum TripUpdateError {
NotYourTrip, NotYourTrip,
TripDetailsDoesNotExist, TripDetailsDoesNotExist,
TripTypeNotAllowed,
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sqlx::{FromRow, SqlitePool}; use sqlx::{FromRow, SqlitePool};
#[derive(FromRow, Debug, Serialize, Deserialize, Clone)] #[derive(FromRow, Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct TripType { pub struct TripType {
pub id: i64, pub id: i64,
pub name: String, pub name: String,

View File

@ -1166,6 +1166,7 @@ macro_rules! special_user {
} }
special_user!(TechUser, +"tech"); special_user!(TechUser, +"tech");
special_user!(ErgoUser, +"ergo");
special_user!(SteeringUser, +"cox", +"Bootsführer"); special_user!(SteeringUser, +"cox", +"Bootsführer");
special_user!(AdminUser, +"admin"); special_user!(AdminUser, +"admin");
special_user!(AllowedForPlannedTripsUser, +"Donau Linz", +"scheckbuch"); special_user!(AllowedForPlannedTripsUser, +"Donau Linz", +"scheckbuch");

View File

@ -26,7 +26,7 @@ struct AddEventForm<'r> {
async fn create( async fn create(
db: &State<SqlitePool>, db: &State<SqlitePool>,
data: Form<AddEventForm<'_>>, data: Form<AddEventForm<'_>>,
_admin: EventUser, user: EventUser,
) -> Flash<Redirect> { ) -> Flash<Redirect> {
let data = data.into_inner(); let data = data.into_inner();
@ -37,6 +37,7 @@ async fn create(
Event::create( Event::create(
db, db,
&user,
data.name, data.name,
data.planned_amount_cox, data.planned_amount_cox,
data.always_show, data.always_show,

View File

@ -11,9 +11,32 @@ use crate::model::{
log::Log, log::Log,
trip::{self, CoxHelpError, Trip, TripDeleteError, TripHelpDeleteError, TripUpdateError}, trip::{self, CoxHelpError, Trip, TripDeleteError, TripHelpDeleteError, TripUpdateError},
tripdetails::{TripDetails, TripDetailsToAdd}, tripdetails::{TripDetails, TripDetailsToAdd},
user::{AllowedToUpdateTripToAlwaysBeShownUser, SteeringUser}, user::{AllowedToUpdateTripToAlwaysBeShownUser, ErgoUser, SteeringUser, User},
}; };
#[post("/trip", data = "<data>", rank = 2)]
async fn create_ergo(
db: &State<SqlitePool>,
data: Form<TripDetailsToAdd<'_>>,
cox: ErgoUser,
) -> Flash<Redirect> {
let trip_details_id = TripDetails::create(db, data.into_inner()).await;
let trip_details = TripDetails::find_by_id(db, trip_details_id).await.unwrap(); //Okay, bc just
//created
Trip::new_own_ergo(db, &cox, trip_details).await; //TODO: fix
//Log::create(
// db,
// format!(
// "Cox {} created trip on {} @ {} for {} rower",
// cox.name, trip_details.day, trip_details.planned_starting_time, trip_details.max_people,
// ),
//)
//.await;
Flash::success(Redirect::to("/planned"), "Ausfahrt erfolgreich erstellt.")
}
#[post("/trip", data = "<data>")] #[post("/trip", data = "<data>")]
async fn create( async fn create(
db: &State<SqlitePool>, db: &State<SqlitePool>,
@ -50,7 +73,7 @@ async fn update(
db: &State<SqlitePool>, db: &State<SqlitePool>,
data: Form<EditTripForm<'_>>, data: Form<EditTripForm<'_>>,
trip_id: i64, trip_id: i64,
cox: SteeringUser, cox: User,
) -> Flash<Redirect> { ) -> Flash<Redirect> {
if let Some(trip) = Trip::find_by_id(db, trip_id).await { if let Some(trip) = Trip::find_by_id(db, trip_id).await {
let update = trip::TripUpdate { let update = trip::TripUpdate {
@ -69,6 +92,10 @@ async fn update(
Err(TripUpdateError::NotYourTrip) => { Err(TripUpdateError::NotYourTrip) => {
Flash::error(Redirect::to("/planned"), "Nicht deine Ausfahrt!") Flash::error(Redirect::to("/planned"), "Nicht deine Ausfahrt!")
} }
Err(TripUpdateError::TripTypeNotAllowed) => Flash::error(
Redirect::to("/planned"),
"Du darfst nur Ergo-Events erstellen",
),
Err(TripUpdateError::TripDetailsDoesNotExist) => { Err(TripUpdateError::TripDetailsDoesNotExist) => {
Flash::error(Redirect::to("/planned"), "Ausfahrt gibt's nicht") Flash::error(Redirect::to("/planned"), "Ausfahrt gibt's nicht")
} }
@ -130,7 +157,7 @@ async fn join(db: &State<SqlitePool>, planned_event_id: i64, cox: SteeringUser)
} }
#[get("/remove/trip/<trip_id>")] #[get("/remove/trip/<trip_id>")]
async fn remove_trip(db: &State<SqlitePool>, trip_id: i64, cox: SteeringUser) -> Flash<Redirect> { async fn remove_trip(db: &State<SqlitePool>, trip_id: i64, cox: User) -> Flash<Redirect> {
let trip = Trip::find_by_id(db, trip_id).await; let trip = Trip::find_by_id(db, trip_id).await;
match trip { match trip {
None => Flash::error(Redirect::to("/planned"), "Trip gibt's nicht!"), None => Flash::error(Redirect::to("/planned"), "Trip gibt's nicht!"),
@ -185,6 +212,7 @@ async fn remove(
pub fn routes() -> Vec<Route> { pub fn routes() -> Vec<Route> {
routes![ routes![
create, create,
create_ergo,
join, join,
remove, remove,
remove_trip, remove_trip,

View File

@ -209,10 +209,12 @@ async fn new_thirty(
if let Err(e) = data.proof.move_copy_to(file_path).await { if let Err(e) = data.proof.move_copy_to(file_path).await {
eprintln!("Failed to persist file: {:?}", e); eprintln!("Failed to persist file: {:?}", e);
} }
let result = data.result.trim_start_matches(|c| c == '0' || c == ' ');
sqlx::query!( sqlx::query!(
"UPDATE user SET dirty_thirty = ? where id = ?", "UPDATE user SET dirty_thirty = ? where id = ?",
data.result, result,
data.user data.user
) )
.execute(db.inner()) .execute(db.inner())
@ -231,6 +233,32 @@ async fn new_thirty(
Flash::success(Redirect::to("/ergo"), "Erfolgreich eingetragen") Flash::success(Redirect::to("/ergo"), "Erfolgreich eingetragen")
} }
fn format_time(input: &str) -> String {
let mut parts: Vec<&str> = input.split(':').collect();
// If there's only seconds (e.g., "24.2"), treat it as "00:00:24.2"
if parts.len() == 1 {
parts.insert(0, "0"); // Add "0" for hours
parts.insert(0, "0"); // Add "0" for minutes
}
// If there are two parts (e.g., "4:24.2"), treat it as "00:04:24.2"
if parts.len() == 2 {
parts.insert(0, "0"); // Add "0" for hours
}
// Now parts should have [hours, minutes, seconds]
let hours = if parts[0].len() == 1 { format!("0{}", parts[0]) } else { parts[0].to_string() };
let minutes = if parts[1].len() == 1 { format!("0{}", parts[1]) } else { parts[1].to_string() };
let seconds = parts[2];
// Split seconds into whole and fractional parts
let (sec_int, sec_frac) = seconds.split_once('.').unwrap_or((seconds, "0"));
// Format the time as "hh:mm:ss.s"
format!("{}:{}:{}.{:1}", hours, minutes, sec_int, sec_frac.chars().next().unwrap_or('0'))
}
#[post("/dozen", data = "<data>", format = "multipart/form-data")] #[post("/dozen", data = "<data>", format = "multipart/form-data")]
async fn new_dozen( async fn new_dozen(
db: &State<SqlitePool>, db: &State<SqlitePool>,
@ -253,10 +281,16 @@ async fn new_dozen(
if let Err(e) = data.proof.move_copy_to(file_path).await { if let Err(e) = data.proof.move_copy_to(file_path).await {
eprintln!("Failed to persist file: {:?}", e); eprintln!("Failed to persist file: {:?}", e);
} }
let result = data.result.trim_start_matches(|c| c == '0' || c == ' ');
let result = if result.contains(":") || result.contains(".") {
format_time(result)
}else{
result.to_string()
};
sqlx::query!( sqlx::query!(
"UPDATE user SET dirty_dozen = ? where id = ?", "UPDATE user SET dirty_dozen = ? where id = ?",
data.result, result,
data.user data.user
) )
.execute(db.inner()) .execute(db.inner())

View File

@ -29,7 +29,10 @@ async fn index(
let mut context = Context::new(); let mut context = Context::new();
if user.allowed_to_steer(db).await || user.has_role(db, "manage_events").await { if user.allowed_to_steer(db).await
|| user.has_role(db, "manage_events").await
|| user.has_role(db, "ergo").await
{
let triptypes = TripType::all(db).await; let triptypes = TripType::all(db).await;
context.insert("trip_types", &triptypes); context.insert("trip_types", &triptypes);
} }

View File

@ -7,13 +7,15 @@
<summary>Dirty Thirty</summary> <summary>Dirty Thirty</summary>
<p> <p>
<div class="border-r border-l"> <div class="border-r border-l">
{% for stat in thirty %} <textarea style="width: 100%; height: 300px;">
{% set names = stat.name | split(pat=" ") %}{% set lastname_index = names | length - 1 %}{% set lastname = names[lastname_index] %}{{ lastname }}&#9; {%- for stat in thirty %}
{% for name in names %} {%- set names = stat.name | split(pat=" ") %}{% set lastname_index = names | length - 1 %}{% set lastname = names[lastname_index] %}{{ lastname }}&#9;
{%- for name in names -%}
{% if loop.index != lastname_index +1 %}{{ name }}{% endif %} {% if loop.index != lastname_index +1 %}{{ name }}{% endif %}
{% endfor %} {%- endfor -%}
&#9;{{ stat.dob }}&#9;{{ stat.weight }}&#9;{{ stat.sex }}&#9;&#9;DLI&#9;{{ stat.result }} &#9;{{ stat.dob }}&#9;{{ stat.weight }}&#9;{{ stat.sex }}&#9;&#9;DLI&#9;{{ stat.result }}&#13;&#10;
{% endfor %} {%- endfor -%}
</textarea>
</div> </div>
</p> </p>
</details> </details>
@ -21,17 +23,15 @@
<summary>Dirty Dozen</summary> <summary>Dirty Dozen</summary>
<p> <p>
<div class="border-r border-l"> <div class="border-r border-l">
{% for stat in dozen %} <textarea style="width: 100%; height: 300px;">
{% set names = stat.name | split(pat=" ") %} {%- for stat in dozen -%}
{% set lastname_index = names | length - 1 %} {%- set names = stat.name | split(pat=" ") %}{% set lastname_index = names | length - 1 %}{% set lastname = names[lastname_index] %}{{ lastname }}&#9;
{% set lastname = names[lastname_index] %} {%- for name in names -%}
{{ lastname }};
{% for name in names %}
{% if loop.index != lastname_index +1 %}{{ name }}{% endif %} {% if loop.index != lastname_index +1 %}{{ name }}{% endif %}
{% endfor %} {%- endfor -%}
;{{ stat.dob }};{{ stat.weight }};{{ stat.sex }};DLI;{{ stat.result }} &#9;{{ stat.dob }}&#9;{{ stat.weight }}&#9;{{ stat.sex }}&#9;&#9;DLI&#9;{{ stat.result }}&#13;&#10;
<br /> {%- endfor -%}
{% endfor %} </textarea>
</div> </div>
</p> </p>
</details> </details>

View File

@ -20,11 +20,9 @@
Montag &rarr; gemeinsames Training; bitte um <a href="/planned" class="link-primary">Anmeldung</a>, damit jeder einen Ergo hat Montag &rarr; gemeinsames Training; bitte um <a href="/planned" class="link-primary">Anmeldung</a>, damit jeder einen Ergo hat
</li> </li>
<li class="py-1"> <li class="py-1">
Offizielle Ergebnisse: <a href="https://rudernlinz.at/dt" <a href="https://data.ergochallenge.at"
target="_blank" target="_blank"
style="text-decoration: underline">Dirty Thirty (rudernlinz.at/dt)</a> / <a href="https://rudernlinz.at/dd" style="text-decoration: underline">Offizielle Ergebnisse</a>, bei Fehlern direkt mit <a href="mailto:office@ergochallenge.at"
target="_blank"
style="text-decoration: underline">Dirty Dozen (rudernlinz.at/dd)</a>, bei Fehlern direkt mit <a href="mailto:office@ergochallenge.at"
style="text-decoration: underline">Christian (Ister)</a> Kontakt aufnehmen style="text-decoration: underline">Christian (Ister)</a> Kontakt aufnehmen
</li> </li>
</ul> </ul>

View File

@ -6,7 +6,11 @@
{{ macros::input(label='Anzahl Ruderer (ohne Steuerperson)', name='max_people', type='number', required=true, min='0') }} {{ macros::input(label='Anzahl Ruderer (ohne Steuerperson)', name='max_people', type='number', required=true, min='0') }}
{{ macros::checkbox(label='Scheckbuch-Anmeldungen erlauben', name='allow_guests') }} {{ macros::checkbox(label='Scheckbuch-Anmeldungen erlauben', name='allow_guests') }}
{{ macros::input(label='Anmerkungen', name='notes', type='input') }} {{ macros::input(label='Anmerkungen', name='notes', type='input') }}
{{ macros::select(label='Typ', data=trip_types, name='trip_type', default='Reguläre Ausfahrt') }} {% if loggedin_user.allowed_to_steer %}
{{ macros::select(label='Typ', data=trip_types, name='trip_type', default='Reguläre Ausfahrt') }}
{% else %}
{{ macros::select(label='Typ', data=trip_types, name='trip_type', only_ergo=true) }}
{% endif %}
<input value="Erstellen" class="w-full btn btn-primary" type="submit" /> <input value="Erstellen" class="w-full btn btn-primary" type="submit" />
</form> </form>
</div> </div>

View File

@ -190,7 +190,7 @@ function setChoiceByLabel(choicesInstance, label) {
{{ label }} {{ label }}
</label> </label>
{% endmacro checkbox %} {% endmacro checkbox %}
{% macro select(label, data, name='trip_type', default='', id='', selected_id='', display='', extras='', class='', wrapper_class='', required=false, show_seats=false, new_last_entry='', nonSelectableDefault=false) %} {% macro select(label, data, name='trip_type', default='', id='', selected_id='', display='', extras='', class='', wrapper_class='', required=false, show_seats=false, new_last_entry='', nonSelectableDefault=false, only_ergo=false) %}
<div class="{{ wrapper_class }}"> <div class="{{ wrapper_class }}">
<label for="{{ name }}" class="text-sm text-gray-600 dark:text-gray-100">{{ label }}</label> <label for="{{ name }}" class="text-sm text-gray-600 dark:text-gray-100">{{ label }}</label>
{% if display == '' %} {% if display == '' %}
@ -203,7 +203,7 @@ function setChoiceByLabel(choicesInstance, label) {
{% if default %}<option selected value>{{ default }}</option>{% endif %} {% if default %}<option selected value>{{ default }}</option>{% endif %}
{% if nonSelectableDefault %}<option disabled selected value>{{ nonSelectableDefault }}</option>{% endif %} {% if nonSelectableDefault %}<option disabled selected value>{{ nonSelectableDefault }}</option>{% endif %}
{% for d in data %} {% for d in data %}
<option value="{{ d.id }}" {% if d.id == selected_id %}selected{% endif %} {% if extras != '' %} {% for extra in extras %} {% if extra != 'on_water' and d[extra] %} data- {{ extra }}={{ d[extra] }} {% else %} {% if d[extra] %}disabled{% endif %} {% endif %} {% endfor %} {% endif %} {% if show_seats %} data-custom-properties='{"amount_seats": {{ d["amount_seats"] }}, "owner": "{{ d["owner"] }}", "default_destination": "{{ d["default_destination"] }}", "boat_in_ottensheim": {{ d["location_id"] == 2 }}, "boat_reserved_today": {{ d["reserved_today"] }}, "convert_handoperated_possible": {{ d["convert_handoperated_possible"] }}, "default_handoperated": {{ d["default_shipmaster_only_steering"] }}}' {% endif %}> <option value="{{ d.id }}" {% if only_ergo and d.id!=4 %} disabled {% endif %}{% if d.id == selected_id %}selected{% endif %} {% if extras != '' %} {% for extra in extras %} {% if extra != 'on_water' and d[extra] %} data- {{ extra }}={{ d[extra] }} {% else %} {% if d[extra] %}disabled{% endif %} {% endif %} {% endfor %} {% endif %} {% if show_seats %} data-custom-properties='{"amount_seats": {{ d["amount_seats"] }}, "owner": "{{ d["owner"] }}", "default_destination": "{{ d["default_destination"] }}", "boat_in_ottensheim": {{ d["location_id"] == 2 }}, "boat_reserved_today": {{ d["reserved_today"] }}, "convert_handoperated_possible": {{ d["convert_handoperated_possible"] }}, "default_handoperated": {{ d["default_shipmaster_only_steering"] }}}' {% endif %}>
{% for displa in display -%} {% for displa in display -%}
{%- if d[displa] -%} {%- if d[displa] -%}
{{- d[displa] -}} {{- d[displa] -}}

View File

@ -354,7 +354,11 @@
{{ macros::input(label='Anzahl Ruderer', name='max_people', type='number', required=true, value=trip.max_people, min=trip.rower | length) }} {{ macros::input(label='Anzahl Ruderer', name='max_people', type='number', required=true, value=trip.max_people, min=trip.rower | length) }}
{{ macros::input(label='Anmerkungen', name='notes', type='input', value=trip.notes) }} {{ macros::input(label='Anmerkungen', name='notes', type='input', value=trip.notes) }}
{{ macros::checkbox(label='Gesperrt', name='is_locked', id=trip.id,checked=trip.is_locked) }} {{ macros::checkbox(label='Gesperrt', name='is_locked', id=trip.id,checked=trip.is_locked) }}
{{ macros::select(label='Typ', name='trip_type', data=trip_types, default='Reguläre Ausfahrt', selected_id=trip.trip_type_id) }} {% if loggedin_user.allowed_to_steer %}
{{ macros::select(label='Typ', name='trip_type', data=trip_types, default='Reguläre Ausfahrt', selected_id=trip.trip_type_id, only_ergo=not loggedin_user.allowed_to_steer) }}
{% else %}
{{ macros::select(label='Typ', name='trip_type', data=trip_types, selected_id=trip.trip_type_id, only_ergo=not loggedin_user.allowed_to_steer, only_ergos=true) }}
{% endif %}
<input value="Speichern" class="btn btn-primary" type="submit" /> <input value="Speichern" class="btn btn-primary" type="submit" />
</form> </form>
</div> </div>
@ -421,11 +425,11 @@
{% endif %} {% endif %}
</div> </div>
{# --- START Add Buttons --- #} {# --- START Add Buttons --- #}
{% if "manage_events" in loggedin_user.roles or loggedin_user.allowed_to_steer %} {% if "manage_events" in loggedin_user.roles or loggedin_user.allowed_to_steer or "ergo" in loggedin_user.roles %}
<div class="grid {% if "manage_events" in loggedin_user.roles and loggedin_user.allowed_to_steer %}grid-cols-2{% endif %} text-center"> <div class="grid {% if "manage_events" in loggedin_user.roles and (loggedin_user.allowed_to_steer or "ergo" in loggedin_user.roles) %}grid-cols-2{% endif %} text-center">
{% if "manage_events" in loggedin_user.roles %} {% if "manage_events" in loggedin_user.roles %}
<a href="#" data-sidebar="true" data-trigger="sidebar" data-header="<strong>Event</strong> am {{ day.day| date(format='%d.%m.%Y') }} erstellen" data-day="{{ day.day }}" data-body="#addEventForm" class="relative inline-block w-full bg-primary-900 hover:bg-primary-950 focus:bg-primary-950 dark:bg-primary-950 text-white py-2 text-sm font-semibold <a href="#" data-sidebar="true" data-trigger="sidebar" data-header="<strong>Event</strong> am {{ day.day| date(format='%d.%m.%Y') }} erstellen" data-day="{{ day.day }}" data-body="#addEventForm" class="relative inline-block w-full bg-primary-900 hover:bg-primary-950 focus:bg-primary-950 dark:bg-primary-950 text-white py-2 text-sm font-semibold
{% if loggedin_user.allowed_to_steer %} {% if loggedin_user.allowed_to_steer or "ergo" in loggedin_user.roles %}
rounded-bl-md rounded-bl-md
{% else %} {% else %}
rounded-b-md rounded-b-md
@ -435,7 +439,7 @@
Event Event
</a> </a>
{% endif %} {% endif %}
{% if loggedin_user.allowed_to_steer %} {% if loggedin_user.allowed_to_steer or "ergo" 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 "manage_events" in loggedin_user.roles %} {% if "manage_events" in loggedin_user.roles %}
rounded-br-md rounded-br-md
@ -444,7 +448,9 @@
{% endif %} {% endif %}
"> ">
<span class="absolute inset-y-0 left-0 flex items-center pl-3">{% include "includes/plus-icon" %}</span> <span class="absolute inset-y-0 left-0 flex items-center pl-3">{% include "includes/plus-icon" %}</span>
Ausfahrt {% if not loggedin_user.allowed_to_steer %}Ergo-Session
{%- else -%}
Ausfahrt{%endif%}
</a> </a>
{% endif %} {% endif %}
</div> </div>
@ -454,7 +460,7 @@
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
{% if loggedin_user.allowed_to_steer %} {% if loggedin_user.allowed_to_steer or "ergo" in loggedin_user.roles %}
{% include "forms/trip" %} {% include "forms/trip" %}
{% endif %} {% endif %}
{% if "manage_events" in loggedin_user.roles %} {% if "manage_events" in loggedin_user.roles %}