membership-pdf-new #284
| @@ -140,3 +140,13 @@ CREATE TABLE IF NOT EXISTS "boat_damage" ( | ||||
| 	"verified_at" datetime, | ||||
| 	"lock_boat" boolean not null default false -- if true: noone can use the boat  | ||||
| ); | ||||
|  | ||||
| CREATE TABLE IF NOT EXISTS "boathouse" ( | ||||
|     "id" INTEGER PRIMARY KEY AUTOINCREMENT, | ||||
|     "boat_id" INTEGER NOT NULL REFERENCES boat(id), | ||||
|     "aisle" TEXT NOT NULL CHECK (aisle in ('water', 'middle', 'mountain')), | ||||
|     "side" TEXT NOT NULL CHECK(side IN ('mountain', 'water')), | ||||
|     "level" INTEGER NOT NULL CHECK(level BETWEEN 0 AND 3), | ||||
|     CONSTRAINT unq UNIQUE (aisle, side, level) -- only 1 boat allowed to rest at each space  | ||||
| ); | ||||
|  | ||||
|   | ||||
| @@ -181,6 +181,41 @@ ORDER BY amount_seats DESC | ||||
|         Self::boats_to_details(db, boats).await | ||||
|     } | ||||
|  | ||||
|     pub async fn all_for_boatshouse(db: &SqlitePool) -> Vec<BoatWithDetails> { | ||||
|         let boats = sqlx::query_as!( | ||||
|             Boat, | ||||
|             " | ||||
| SELECT  | ||||
|     b.id,  | ||||
|     b.name,  | ||||
|     b.amount_seats,  | ||||
|     b.location_id,  | ||||
|     b.owner,  | ||||
|     b.year_built,  | ||||
|     b.boatbuilder,  | ||||
|     b.default_shipmaster_only_steering,  | ||||
|     b.default_destination,  | ||||
|     b.skull,  | ||||
|     b.external | ||||
| FROM  | ||||
|     boat AS b | ||||
| LEFT JOIN  | ||||
|     boathouse AS bh ON b.id = bh.boat_id | ||||
| WHERE  | ||||
|     b.external = false  | ||||
|     AND b.location_id = (SELECT id FROM location WHERE name = 'Linz') | ||||
|     AND bh.id IS NULL -- This ensures the boat does not have an entry in the boathouse table | ||||
| ORDER BY  | ||||
|     b.name DESC; | ||||
|         " | ||||
|         ) | ||||
|         .fetch_all(db) | ||||
|         .await | ||||
|         .unwrap(); //TODO: fixme | ||||
|  | ||||
|         Self::boats_to_details(db, boats).await | ||||
|     } | ||||
|  | ||||
|     pub async fn for_user(db: &SqlitePool, user: &User) -> Vec<BoatWithDetails> { | ||||
|         if user.has_role(db, "admin").await { | ||||
|             return Self::all(db).await; | ||||
|   | ||||
							
								
								
									
										90
									
								
								src/model/boathouse.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/model/boathouse.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| use std::collections::HashMap; | ||||
|  | ||||
| use rocket::serde::{Deserialize, Serialize}; | ||||
| use sqlx::{FromRow, SqlitePool}; | ||||
|  | ||||
| use crate::tera::board::boathouse::FormBoathouseToAdd; | ||||
|  | ||||
| use super::boat::Boat; | ||||
|  | ||||
| #[derive(FromRow, Debug, Serialize, Deserialize)] | ||||
| pub struct Boathouse { | ||||
|     pub id: i64, | ||||
|     pub boat_id: i64, | ||||
|     pub aisle: String, | ||||
|     pub side: String, | ||||
|     pub level: i64, | ||||
| } | ||||
|  | ||||
| impl Boathouse { | ||||
|     pub async fn get(db: &SqlitePool) -> HashMap<&str, HashMap<&str, [Option<(i64, Boat)>; 4]>> { | ||||
|         let mut ret: HashMap<&str, HashMap<&str, [Option<(i64, Boat)>; 4]>> = HashMap::new(); | ||||
|  | ||||
|         let mut mountain = HashMap::new(); | ||||
|         mountain.insert("mountain", [None, None, None, None]); | ||||
|         mountain.insert("water", [None, None, None, None]); | ||||
|         ret.insert("mountain-aisle", mountain); | ||||
|  | ||||
|         let mut middle = HashMap::new(); | ||||
|         middle.insert("mountain", [None, None, None, None]); | ||||
|         middle.insert("water", [None, None, None, None]); | ||||
|         ret.insert("middle-aisle", middle); | ||||
|  | ||||
|         let mut water = HashMap::new(); | ||||
|         water.insert("mountain", [None, None, None, None]); | ||||
|         water.insert("water", [None, None, None, None]); | ||||
|         ret.insert("water-aisle", water); | ||||
|  | ||||
|         let boathouses = sqlx::query_as!( | ||||
|             Boathouse, | ||||
|             "SELECT id, boat_id, aisle, side, level FROM boathouse" | ||||
|         ) | ||||
|         .fetch_all(db) | ||||
|         .await | ||||
|         .unwrap(); //TODO: fixme | ||||
|  | ||||
|         for boathouse in boathouses { | ||||
|             let aisle = ret | ||||
|                 .get_mut(format!("{}-aisle", boathouse.aisle).as_str()) | ||||
|                 .unwrap(); | ||||
|             let side = aisle.get_mut(boathouse.side.as_str()).unwrap(); | ||||
|  | ||||
|             side[boathouse.level as usize] = Some(( | ||||
|                 boathouse.id, | ||||
|                 Boat::find_by_id(db, boathouse.boat_id as i32) | ||||
|                     .await | ||||
|                     .unwrap(), | ||||
|             )); | ||||
|         } | ||||
|  | ||||
|         ret | ||||
|     } | ||||
|  | ||||
|     pub async fn create(db: &SqlitePool, data: FormBoathouseToAdd) -> Result<(), String> { | ||||
|         sqlx::query!( | ||||
|             "INSERT INTO boathouse(boat_id, aisle, side, level) VALUES (?,?,?,?)", | ||||
|             data.boat_id, | ||||
|             data.aisle, | ||||
|             data.side, | ||||
|             data.level | ||||
|         ) | ||||
|         .execute(db) | ||||
|         .await | ||||
|         .map_err(|e| e.to_string())?; | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     pub async fn find_by_id(db: &SqlitePool, id: i32) -> Option<Self> { | ||||
|         sqlx::query_as!(Self, "SELECT * FROM boathouse WHERE id like ?", id) | ||||
|             .fetch_one(db) | ||||
|             .await | ||||
|             .ok() | ||||
|     } | ||||
|  | ||||
|     pub async fn delete(&self, db: &SqlitePool) { | ||||
|         sqlx::query!("DELETE FROM boathouse WHERE id=?", self.id) | ||||
|             .execute(db) | ||||
|             .await | ||||
|             .unwrap(); //Okay, because we can only create a Boat of a valid id | ||||
|     } | ||||
| } | ||||
| @@ -9,6 +9,7 @@ use self::{ | ||||
|  | ||||
| pub mod boat; | ||||
| pub mod boatdamage; | ||||
| pub mod boathouse; | ||||
| pub mod family; | ||||
| pub mod location; | ||||
| pub mod log; | ||||
|   | ||||
							
								
								
									
										85
									
								
								src/tera/board/boathouse.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								src/tera/board/boathouse.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| use crate::model::{ | ||||
|     boat::Boat, | ||||
|     boathouse::Boathouse, | ||||
|     user::{AdminUser, UserWithRoles, VorstandUser}, | ||||
| }; | ||||
| use rocket::{ | ||||
|     form::Form, | ||||
|     get, post, | ||||
|     request::FlashMessage, | ||||
|     response::{Flash, Redirect}, | ||||
|     routes, FromForm, Route, State, | ||||
| }; | ||||
| use rocket_dyn_templates::{tera::Context, Template}; | ||||
| use sqlx::SqlitePool; | ||||
|  | ||||
| #[get("/boathouse")] | ||||
| async fn index( | ||||
|     db: &State<SqlitePool>, | ||||
|     admin: VorstandUser, | ||||
|     flash: Option<FlashMessage<'_>>, | ||||
| ) -> Template { | ||||
|     let mut context = Context::new(); | ||||
|     if let Some(msg) = flash { | ||||
|         context.insert("flash", &msg.into_inner()); | ||||
|     } | ||||
|  | ||||
|     let boats = Boat::all_for_boatshouse(db).await; | ||||
|     context.insert("boats", &boats); | ||||
|  | ||||
|     let boathouse = Boathouse::get(db).await; | ||||
|     context.insert("boathouse", &boathouse); | ||||
|  | ||||
|     context.insert( | ||||
|         "loggedin_user", | ||||
|         &UserWithRoles::from_user(admin.into(), db).await, | ||||
|     ); | ||||
|  | ||||
|     Template::render("board/boathouse", context.into_json()) | ||||
| } | ||||
|  | ||||
| #[derive(FromForm)] | ||||
| pub struct FormBoathouseToAdd { | ||||
|     pub boat_id: i32, | ||||
|     pub aisle: String, | ||||
|     pub side: String, | ||||
|     pub level: i32, | ||||
| } | ||||
| #[post("/boathouse", data = "<data>")] | ||||
| async fn new<'r>( | ||||
|     db: &State<SqlitePool>, | ||||
|     data: Form<FormBoathouseToAdd>, | ||||
|     _admin: AdminUser, | ||||
| ) -> Flash<Redirect> { | ||||
|     match Boathouse::create(db, data.into_inner()).await { | ||||
|         Ok(_) => Flash::success(Redirect::to("/board/boathouse"), "Boot hinzugefügt"), | ||||
|         Err(e) => Flash::error(Redirect::to("/board/boathouse"), e), | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[get("/boathouse/<boathouse_id>/delete")] | ||||
| async fn delete(db: &State<SqlitePool>, _admin: AdminUser, boathouse_id: i32) -> Flash<Redirect> { | ||||
|     let boat = Boathouse::find_by_id(db, boathouse_id).await; | ||||
|     match boat { | ||||
|         Some(boat) => { | ||||
|             boat.delete(db).await; | ||||
|             Flash::success(Redirect::to("/board/boathouse"), "Bootsplatz gelöscht") | ||||
|         } | ||||
|         None => Flash::error(Redirect::to("/board/boathouse"), "Boatplace does not exist"), | ||||
|     } | ||||
| } | ||||
| //#[post("/boat/new", data = "<data>")] | ||||
| //async fn create( | ||||
| //    db: &State<SqlitePool>, | ||||
| //    data: Form<BoatToAdd<'_>>, | ||||
| //    _admin: AdminUser, | ||||
| //) -> Flash<Redirect> { | ||||
| //    match Boat::create(db, data.into_inner()).await { | ||||
| //        Ok(_) => Flash::success(Redirect::to("/admin/boat"), "Boot hinzugefügt"), | ||||
| //        Err(e) => Flash::error(Redirect::to("/admin/boat"), e), | ||||
| //    } | ||||
| //} | ||||
|  | ||||
| pub fn routes() -> Vec<Route> { | ||||
|     routes![index, new, delete] | ||||
| } | ||||
							
								
								
									
										9
									
								
								src/tera/board/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/tera/board/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| use rocket::Route; | ||||
|  | ||||
| pub mod boathouse; | ||||
|  | ||||
| pub fn routes() -> Vec<Route> { | ||||
|     let mut ret = Vec::new(); | ||||
|     ret.append(&mut boathouse::routes()); | ||||
|     ret | ||||
| } | ||||
| @@ -21,6 +21,7 @@ use crate::model::user::{User, UserWithRoles}; | ||||
|  | ||||
| pub(crate) mod admin; | ||||
| mod auth; | ||||
| pub(crate) mod board; | ||||
| mod boatdamage; | ||||
| mod cox; | ||||
| mod ergo; | ||||
| @@ -89,6 +90,7 @@ pub fn config(rocket: Rocket<Build>) -> Rocket<Build> { | ||||
|         .mount("/boatdamage", boatdamage::routes()) | ||||
|         .mount("/cox", cox::routes()) | ||||
|         .mount("/admin", admin::routes()) | ||||
|         .mount("/board", board::routes()) | ||||
|         .mount("/", misc::routes()) | ||||
|         .mount("/public", FileServer::from("static/")) | ||||
|         .register("/", catchers![unauthorized_error, forbidden_error]) | ||||
|   | ||||
| @@ -0,0 +1,9 @@ | ||||
| CREATE TABLE IF NOT EXISTS "boathouse" ( | ||||
|     "id" INTEGER PRIMARY KEY AUTOINCREMENT, | ||||
|     "boat_id" INTEGER NOT NULL REFERENCES boat(id), | ||||
|     "aisle" TEXT NOT NULL CHECK (aisle in ('water', 'middle', 'mountain')), | ||||
|     "side" TEXT NOT NULL CHECK(side IN ('mountain', 'water')), | ||||
|     "level" INTEGER NOT NULL CHECK(level BETWEEN 0 AND 3), | ||||
|     CONSTRAINT unq UNIQUE (aisle, side, level) -- only 1 boat allowed to rest at each space  | ||||
| ); | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,6 @@ | ||||
| {% import "includes/forms/boat" as boat %} | ||||
| {% extends "base" %} | ||||
| {% block content %} | ||||
|     {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}{% endif %} | ||||
|     <div class="max-w-screen-lg w-full"> | ||||
|         <h1 class="h1">Boats</h1> | ||||
|         {{ boat::new() }} | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| {% import "includes/macros" as macros %} | ||||
| {% extends "base" %} | ||||
| {% block content %} | ||||
|     {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}{% endif %} | ||||
|     <div class="max-w-screen-lg w-full"> | ||||
|         <h1 class="h1">List</h1> | ||||
|         <form action="/admin/list" method="post"> | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| {% import "includes/macros" as macros %} | ||||
| {% extends "base" %} | ||||
| {% block content %} | ||||
|     {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}{% endif %} | ||||
|     <div class="max-w-screen-lg w-full"> | ||||
|         <h1 class="h1">List - Result</h1> | ||||
|         <ol> | ||||
|   | ||||
| @@ -2,7 +2,6 @@ | ||||
| {% import "includes/forms/boat" as boat %} | ||||
| {% extends "base" %} | ||||
| {% block content %} | ||||
|     {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}{% endif %} | ||||
|     <div class="max-w-screen-lg w-full"> | ||||
|         <h1 class="h1">Mail</h1> | ||||
|         <form action="/admin/mail" method="post" enctype="multipart/form-data"> | ||||
|   | ||||
| @@ -2,7 +2,6 @@ | ||||
| {% extends "base" %} | ||||
| {% block content %} | ||||
|     <div class="max-w-screen-lg w-full"> | ||||
|         {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}{% endif %} | ||||
|         <h1 class="h1">Schnupper Verwaltung</h1> | ||||
|         <div class="grid gap-3"> | ||||
|             <div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5" | ||||
|   | ||||
| @@ -2,7 +2,6 @@ | ||||
| {% extends "base" %} | ||||
| {% block content %} | ||||
|     <div class="max-w-screen-lg w-full bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"> | ||||
|         {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}{% endif %} | ||||
|         <h1 class="h1">Gebühren</h1> | ||||
|         <!-- START filterBar --> | ||||
|         <div class="search-wrapper"> | ||||
|   | ||||
| @@ -2,7 +2,6 @@ | ||||
| {% extends "base" %} | ||||
| {% block content %} | ||||
|     <div class="max-w-screen-lg w-full"> | ||||
|         {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}{% endif %} | ||||
|         <h1 class="h1">Users</h1> | ||||
|         {% if allowed_to_edit %} | ||||
|             <form action="/admin/user/new" | ||||
|   | ||||
| @@ -3,7 +3,6 @@ | ||||
| {% extends "base" %} | ||||
| {% block content %} | ||||
|     <div class="max-w-screen-lg w-full bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"> | ||||
|         {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}{% endif %} | ||||
|         <h1 class="h1">Scheckbücher</h1> | ||||
|         <!-- START filterBar --> | ||||
|         <div class="search-wrapper"> | ||||
|   | ||||
| @@ -25,7 +25,12 @@ | ||||
|                 </div> | ||||
|             </header> | ||||
|         {% endif %} | ||||
|         <div class="flex min-h-screen {% if not loggedin_user and not show_kiosk_header %} items-center dark:bg-primary-900 {% else %} items-start {% endif %} justify-center px-4 py-12 sm:px-6 lg:px-8"> | ||||
|         <div class="flex flex-wrap min-h-screen {% if not loggedin_user and not show_kiosk_header %} items-center dark:bg-primary-900 {% else %} items-start {% endif %} justify-center px-4 py-12 sm:px-6 lg:px-8"> | ||||
|             {% if flash and loggedin_user %} | ||||
|                 <div class="max-w-screen-lg w-full mb-3"> | ||||
|                     {{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }} | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|             {% block content %} | ||||
|             {% endblock content %} | ||||
|         </div> | ||||
|   | ||||
							
								
								
									
										54
									
								
								templates/board/boathouse.html.tera
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								templates/board/boathouse.html.tera
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| {% import "includes/macros" as macros %} | ||||
| {% import "includes/forms/log" as log %} | ||||
| {% import "includes/forms/boat" as boat %} | ||||
| {% extends "base" %} | ||||
| {% macro show_place(aisle_name, side_name, level) %} | ||||
|     <li class="truncate p-2 flex relative w-full"> | ||||
|         {% set aisle = aisle_name ~ "-aisle" %} | ||||
|         {% set place = boathouse[aisle][side_name] %} | ||||
|         {% if place[level] %} | ||||
|             {{ place[level].1.name }} <a class="btn btn-primary absolute end-0" href="/board/boathouse/{{ place[level].0 }}/delete">X</a> | ||||
|         {% elif boats | length > 0 %} | ||||
|             <details> | ||||
|                 <summary>Kein Boot</summary> | ||||
|                 <form action="/board/boathouse" method="post" class="grid gap-3"> | ||||
|                     {{ macros::select(label="Boot", data=boats, name="boat_id", id="boat_id", display=["name", " (","amount_seats", " x)"], wrapper_class="col-span-4") }} | ||||
|                     <input type="hidden" name="aisle" value="{{ aisle_name }}" /> | ||||
|                     <input type="hidden" name="side" value="{{ side_name }}" /> | ||||
|                     <input type="hidden" name="level" value="{{ level }}" /> | ||||
|                     <input type="submit" | ||||
|                            class="btn btn-primary w-full col-span-4" | ||||
|                            value="Boot eintragen" /> | ||||
|                 </form> | ||||
|             </details> | ||||
|         {% else %} | ||||
|             Kein Boot | ||||
|         {% endif %} | ||||
|     </li> | ||||
| {% endmacro show_place %} | ||||
| {% macro show_side(aisle_name, side_name) %} | ||||
|     <div class="{{ side_name }}-side"> | ||||
|         <ol> | ||||
|             {{ self::show_place(aisle_name = aisle_name, side_name = side_name, level = 0) }} | ||||
|             {{ self::show_place(aisle_name = aisle_name, side_name = side_name, level = 1) }} | ||||
|             {{ self::show_place(aisle_name = aisle_name, side_name = side_name, level = 2) }} | ||||
|             {{ self::show_place(aisle_name = aisle_name, side_name = side_name, level = 3) }} | ||||
|         </ol> | ||||
|     </div> | ||||
| {% endmacro show_side %} | ||||
| {% macro show_aisle(name, last=false) %} | ||||
|     <div id="{{ name }}-aisle" class="grid grid-cols-2 gap-4 {% if not last %}md:border-r{% endif %}"> | ||||
|         {{ self::show_side(aisle_name = name, side_name = "mountain") }} | ||||
|         {{ self::show_side(aisle_name = name, side_name = "water") }} | ||||
|     </div> | ||||
| {% endmacro show_aisle %} | ||||
| {% block content %} | ||||
|     <div class="max-w-screen-lg w-full dark:text-white"> | ||||
|         <h1 class="h1">Bootshaus</h1> | ||||
|         <div class="grid md:grid-cols-3 gap-4"> | ||||
|             {{ self::show_aisle(name = "mountain") }} | ||||
|             {{ self::show_aisle(name = "middle") }} | ||||
|             {{ self::show_aisle(name = "water", last = true) }} | ||||
|         </div> | ||||
|     </div> | ||||
| {% endblock content %} | ||||
| @@ -4,7 +4,6 @@ | ||||
| {% block content %} | ||||
|     <div class="max-w-screen-lg w-full"> | ||||
|         <h1 class="h1">Bootschäden</h1> | ||||
|         {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3 mt-3") }}{% endif %} | ||||
|         <h2 class="text-md font-bold tracking-wide bg-primary-900 mt-3 p-3 text-white flex justify-between items-center rounded-md"> | ||||
|             Neuen Schaden | ||||
|             <a href="#" | ||||
|   | ||||
| @@ -2,7 +2,6 @@ | ||||
| {% extends "base" %} | ||||
| {% block content %} | ||||
|     <div class="max-w-screen-lg w-full"> | ||||
|         {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}{% endif %} | ||||
|         <h1 class="h1">Aktuelle Woche</h1> | ||||
|         <details> | ||||
|             <summary>Dirty Thirty</summary> | ||||
|   | ||||
| @@ -3,7 +3,6 @@ | ||||
| {% block content %} | ||||
|     <div class="max-w-screen-lg w-full"> | ||||
|         <h1 class="h1">Ergo Challenges</h1> | ||||
|         {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="my-3") }}{% endif %} | ||||
|         <div class="grid gap-3"> | ||||
|             <div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5" | ||||
|                  role="alert"> | ||||
|   | ||||
| @@ -2,7 +2,6 @@ | ||||
| {% extends "base" %} | ||||
| {% block content %} | ||||
|     <div class="max-w-screen-lg w-full"> | ||||
|         {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}{% endif %} | ||||
|         <h1 class="h1">Ruderassistent</h1> | ||||
|         <div class="grid gap-3"> | ||||
|             <div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5" | ||||
| @@ -110,6 +109,9 @@ | ||||
|                             <li class="py-1"> | ||||
|                                 <a href="/admin/user" class="link-primary">User</a> | ||||
|                             </li> | ||||
|                             <li class="py-1"> | ||||
|                                 <a href="/board/boathouse" class="link-primary">Bootshaus</a> | ||||
|                             </li> | ||||
|                         </ul> | ||||
|                     </div> | ||||
|                 </div> | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
| {% block content %} | ||||
|     <div class="w-full"> | ||||
|         <h1 class="h1">Logbuch</h1> | ||||
|         {% if flash %} | ||||
|         {% if flash and not loggedin_user %} | ||||
|             <div class="pt-3 max-w-lg m-auto"> | ||||
|                 {{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }} | ||||
|             </div> | ||||
|   | ||||
| @@ -4,9 +4,6 @@ | ||||
| {% block content %} | ||||
|     <div class="w-full"> | ||||
|         <h1 class="h1">Logbuch</h1> | ||||
|         {% if flash %} | ||||
|             <div class="w-full">{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}</div> | ||||
|         {% endif %} | ||||
|         <div class="w-full grid md:grid-cols-5 gap-3 mt-5"> | ||||
|             <div class="bg-white dark:bg-primary-900 rounded-md hidden md:block shadow"> | ||||
|                 <h2 class="h2">Boote</h2> | ||||
|   | ||||
| @@ -3,7 +3,6 @@ | ||||
| {% extends "base" %} | ||||
| {% block content %} | ||||
|     <div class="max-w-screen-xl w-full grid sm:grid-cols-2 lg:grid-cols-3 gap-4"> | ||||
|         {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}{% endif %} | ||||
|         {% if "scheckbuch" in loggedin_user.roles %} | ||||
|             <div class="grid gap-3 sm:col-span-2 lg:col-span-3"> | ||||
|                 <div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user