diff --git a/Cargo.lock b/Cargo.lock index 3ec6612..dc13d37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -76,9 +76,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -174,18 +174,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] name = "async-trait" -version = "0.1.79" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -326,9 +326,9 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.92" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" +checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" [[package]] name = "cfg-if" @@ -338,9 +338,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -349,7 +349,7 @@ dependencies = [ "pure-rust-locales", "serde", "wasm-bindgen", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -591,9 +591,9 @@ dependencies = [ [[package]] name = "deunicode" -version = "1.4.3" +version = "1.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6e854126756c496b8c81dec88f9a706b15b875c5849d4097a3854476b9fdf94" +checksum = "322ef0094744e63628e6f0eb2295517f79276a5b342a4c2ff3042566ca181d4e" [[package]] name = "devise" @@ -625,7 +625,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -648,9 +648,9 @@ checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" [[package]] name = "either" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" dependencies = [ "serde", ] @@ -673,9 +673,9 @@ checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -744,9 +744,9 @@ checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "figment" -version = "0.10.15" +version = "0.10.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7270677e7067213e04f323b55084586195f18308cd7546cfac9f873344ccceb6" +checksum = "d032832d74006f99547004d49410a4b4218e4c33382d56ca3ff89df74f86b953" dependencies = [ "atomic 0.6.0", "pear", @@ -891,7 +891,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1681,7 +1681,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1787,7 +1787,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1836,7 +1836,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1953,9 +1953,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -1968,7 +1968,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "version_check", "yansi", ] @@ -1990,9 +1990,9 @@ checksum = "1190fd18ae6ce9e137184f207593877e70f39b015040156b1e05081cdfe3733a" [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -2059,7 +2059,7 @@ checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2170,7 +2170,7 @@ dependencies = [ "proc-macro2", "quote", "rocket_http", - "syn 2.0.58", + "syn 2.0.60", "unicode-xid", "version_check", ] @@ -2384,29 +2384,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", @@ -2815,9 +2815,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.58" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -2875,7 +2875,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2890,9 +2890,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -2911,9 +2911,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -2960,7 +2960,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -3011,9 +3011,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.9" +version = "0.22.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +checksum = "fb686a972ccef8537b39eead3968b0e8616cb5040dbb9bba93007c8e07c9215f" dependencies = [ "indexmap", "serde", @@ -3048,7 +3048,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -3325,7 +3325,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "wasm-bindgen-shared", ] @@ -3347,7 +3347,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3420,7 +3420,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -3438,7 +3438,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -3458,17 +3458,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -3479,9 +3480,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -3491,9 +3492,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -3503,9 +3504,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -3515,9 +3522,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -3527,9 +3534,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -3539,9 +3546,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -3551,15 +3558,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" dependencies = [ "memchr", ] @@ -3590,7 +3597,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts index e5adfb0..520a154 100644 --- a/frontend/playwright.config.ts +++ b/frontend/playwright.config.ts @@ -72,5 +72,6 @@ export default defineConfig({ webServer: { timeout: 15 * 60 * 1000, command: 'cd .. && ./test_db.sh && cargo r', + url: 'http://127.0.0.1:8000' }, }); diff --git a/frontend/scss/app.scss b/frontend/scss/app.scss index 770dc11..02e94d7 100644 --- a/frontend/scss/app.scss +++ b/frontend/scss/app.scss @@ -13,3 +13,4 @@ @import 'components/search'; @import 'components/important'; @import 'components/searchable-table'; +@import 'components/notification'; diff --git a/frontend/scss/components/_notification.scss b/frontend/scss/components/_notification.scss new file mode 100644 index 0000000..0532299 --- /dev/null +++ b/frontend/scss/components/_notification.scss @@ -0,0 +1,5 @@ +.notification { + right: -.2rem; + top: -.1rem; + font-size: .5rem; +} diff --git a/frontend/tests/cox.spec.ts b/frontend/tests/cox.spec.ts index c19ae45..d38dc96 100644 --- a/frontend/tests/cox.spec.ts +++ b/frontend/tests/cox.spec.ts @@ -8,7 +8,7 @@ test("cox can create and delete trip", async ({ page }) => { await page.getByPlaceholder("Passwort").fill("cox"); await page.getByPlaceholder("Passwort").press("Enter"); await page.locator('li').filter({ hasText: 'Geplante Ausfahrten' }).getByRole('link').click(); - await page.locator(".relative").first().click(); + await page.locator('a[href="#"]:has-text("Ausfahrt")').first().click(); await page.locator("#sidebar #planned_starting_time").click(); await page.locator("#sidebar #planned_starting_time").fill("18:00"); await page.locator("#sidebar #planned_starting_time").press("Tab"); @@ -38,8 +38,8 @@ test.describe("cox can edit trips", () => { await page.getByPlaceholder("Name").press("Tab"); await page.getByPlaceholder("Passwort").fill("cox"); await page.getByPlaceholder("Passwort").press("Enter"); - await page.locator('li').filter({ hasText: 'Geplante Ausfahrten' }).getByRole('link').click(); - await page.locator(".relative").first().click(); + await page.locator('li').filter({ hasText: 'Geplante Ausfahrten' }).getByRole('link').click(); + await page.locator('a[href="#"]:has-text("Ausfahrt")').first().click(); await page.locator("#sidebar #planned_starting_time").click(); await page.locator("#sidebar #planned_starting_time").fill("18:00"); await page.locator("#sidebar #planned_starting_time").press("Tab"); diff --git a/src/model/boatreservation.rs b/src/model/boatreservation.rs index bacddea..804d384 100644 --- a/src/model/boatreservation.rs +++ b/src/model/boatreservation.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use crate::model::{boat::Boat, user::User}; use crate::tera::boatreservation::ReservationEditForm; use chrono::NaiveDate; @@ -25,7 +27,7 @@ pub struct BoatReservation { #[derive(FromRow, Debug, Serialize, Deserialize)] pub struct BoatReservationWithDetails { #[serde(flatten)] - boat_reservation: BoatReservation, + reservation: BoatReservation, boat: Boat, user_applicant: User, user_confirmation: Option, @@ -85,7 +87,7 @@ WHERE end_date >= CURRENT_DATE ORDER BY end_date .unwrap(); res.push(BoatReservationWithDetails { - boat_reservation: reservation, + reservation, boat, user_applicant, user_confirmation, @@ -93,6 +95,31 @@ WHERE end_date >= CURRENT_DATE ORDER BY end_date } res } + pub async fn all_future_with_groups( + db: &SqlitePool, + ) -> HashMap> { + let mut grouped_reservations: HashMap> = + HashMap::new(); + + let reservations = Self::all_future(db).await; + for reservation in reservations { + let key = format!( + "{}-{}-{}-{}-{}", + reservation.reservation.start_date, + reservation.reservation.end_date, + reservation.reservation.time_desc, + reservation.reservation.usage, + reservation.user_applicant.name + ); + + grouped_reservations + .entry(key) + .or_insert_with(Vec::new) + .push(reservation); + } + + grouped_reservations + } pub async fn create( db: &SqlitePool, diff --git a/src/model/user.rs b/src/model/user.rs index 86e311a..dc9bb4a 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -26,7 +26,7 @@ const REGULAR: i32 = 22000; const UNTERSTUETZEND: i32 = 2500; const FOERDERND: i32 = 8500; -#[derive(FromRow, Serialize, Deserialize, Clone, Debug)] +#[derive(FromRow, Serialize, Deserialize, Clone, Debug, Eq, Hash)] pub struct User { pub id: i64, pub name: String, @@ -47,16 +47,18 @@ pub struct User { } #[derive(Debug, Serialize, Deserialize)] -pub struct UserWithRoles { +pub struct UserWithRolesAndNotificationCount { #[serde(flatten)] pub user: User, + pub amount_unread_notifications: i32, pub roles: Vec, } -impl UserWithRoles { +impl UserWithRolesAndNotificationCount { pub async fn from_user(user: User, db: &SqlitePool) -> Self { Self { roles: user.roles(db).await, + amount_unread_notifications: user.amount_unread_notifications(db).await, user, } } @@ -237,6 +239,17 @@ impl User { .count } + pub async fn amount_unread_notifications(&self, db: &SqlitePool) -> i32 { + sqlx::query!( + "SELECT COUNT(*) as count FROM notification WHERE user_id = ? AND read_at IS NULL", + self.id + ) + .fetch_one(db) + .await + .unwrap() + .count + } + pub async fn has_role(&self, db: &SqlitePool, role: &str) -> bool { if sqlx::query!( "SELECT * FROM user_role WHERE user_id=? AND role_id = (SELECT id FROM role WHERE name = ?)", @@ -977,8 +990,8 @@ pub struct UserWithRolesAndMembershipPdf { impl UserWithRolesAndMembershipPdf { pub(crate) async fn from_user(db: &SqlitePool, user: User) -> Self { let membership_pdf: bool = - sqlx::query_scalar!("SELECT membership_pdf FROM user WHERE id = $1", user.id) - .fetch_optional(db) + sqlx::query_scalar!("SELECT membership_pdf FROM user WHERE id = ?", user.id) + .fetch_one(db) .await .unwrap() .is_some(); diff --git a/src/tera/admin/boat.rs b/src/tera/admin/boat.rs index e23d2e4..b034a38 100644 --- a/src/tera/admin/boat.rs +++ b/src/tera/admin/boat.rs @@ -2,7 +2,7 @@ use crate::model::{ boat::{Boat, BoatToAdd, BoatToUpdate}, location::Location, log::Log, - user::{AdminUser, User, UserWithRoles}, + user::{AdminUser, User, UserWithRolesAndNotificationCount}, }; use rocket::{ form::Form, @@ -33,7 +33,7 @@ async fn index( context.insert("users", &users); context.insert( "loggedin_user", - &UserWithRoles::from_user(admin.user, db).await, + &UserWithRolesAndNotificationCount::from_user(admin.user, db).await, ); Template::render("admin/boat/index", context.into_json()) diff --git a/src/tera/admin/mail.rs b/src/tera/admin/mail.rs index 2afcd3a..1f6f11c 100644 --- a/src/tera/admin/mail.rs +++ b/src/tera/admin/mail.rs @@ -10,7 +10,7 @@ use crate::model::log::Log; use crate::model::mail::Mail; use crate::model::role::Role; use crate::model::user::AdminUser; -use crate::model::user::UserWithRoles; +use crate::model::user::UserWithRolesAndNotificationCount; use crate::tera::Config; #[get("/mail")] @@ -27,7 +27,7 @@ async fn index( context.insert( "loggedin_user", - &UserWithRoles::from_user(admin.user, db).await, + &UserWithRolesAndNotificationCount::from_user(admin.user, db).await, ); context.insert("roles", &roles); diff --git a/src/tera/admin/notification.rs b/src/tera/admin/notification.rs index 2e36c51..0e7ab9a 100644 --- a/src/tera/admin/notification.rs +++ b/src/tera/admin/notification.rs @@ -2,7 +2,7 @@ use crate::model::{ log::Log, notification::Notification, role::Role, - user::{AdminUser, User, UserWithRoles}, + user::{AdminUser, User, UserWithRolesAndNotificationCount}, }; use rocket::{ form::Form, @@ -26,7 +26,7 @@ async fn index( } context.insert( "loggedin_user", - &UserWithRoles::from_user(user.user, db).await, + &UserWithRolesAndNotificationCount::from_user(user.user, db).await, ); context.insert("roles", &Role::all(db).await); diff --git a/src/tera/admin/schnupper.rs b/src/tera/admin/schnupper.rs index 41d536d..f08abb3 100644 --- a/src/tera/admin/schnupper.rs +++ b/src/tera/admin/schnupper.rs @@ -1,6 +1,6 @@ use crate::model::{ role::Role, - user::{SchnupperBetreuerUser, User, UserWithRoles}, + user::{SchnupperBetreuerUser, User, UserWithRolesAndNotificationCount}, }; use futures::future::join_all; use rocket::{ @@ -38,9 +38,9 @@ async fn index( let user_futures: Vec<_> = User::all_with_role(db, &schnupperant) .await .into_iter() - .map(|u| async move { UserWithRoles::from_user(u, db).await }) + .map(|u| async move { UserWithRolesAndNotificationCount::from_user(u, db).await }) .collect(); - let users: Vec = join_all(user_futures).await; + let users: Vec = join_all(user_futures).await; let mut context = Context::new(); if let Some(msg) = flash { @@ -49,7 +49,7 @@ async fn index( context.insert("schnupperanten", &users); context.insert( "loggedin_user", - &UserWithRoles::from_user(user.into(), db).await, + &UserWithRolesAndNotificationCount::from_user(user.into(), db).await, ); Template::render("admin/schnupper/index", context.into_json()) diff --git a/src/tera/admin/user.rs b/src/tera/admin/user.rs index 30c63b7..e5d9781 100644 --- a/src/tera/admin/user.rs +++ b/src/tera/admin/user.rs @@ -6,8 +6,8 @@ use crate::model::{ logbook::Logbook, role::Role, user::{ - AdminUser, User, UserWithMembershipPdf, UserWithRoles, UserWithRolesAndMembershipPdf, - VorstandUser, + AdminUser, User, UserWithMembershipPdf, UserWithRolesAndMembershipPdf, + UserWithRolesAndNotificationCount, VorstandUser, }, }; use futures::future::join_all; @@ -67,7 +67,10 @@ async fn index( context.insert("users", &users); context.insert("roles", &roles); context.insert("families", &families); - context.insert("loggedin_user", &UserWithRoles::from_user(user, db).await); + context.insert( + "loggedin_user", + &UserWithRolesAndNotificationCount::from_user(user, db).await, + ); Template::render("admin/user/index", context.into_json()) } @@ -99,7 +102,10 @@ async fn index_admin( context.insert("users", &users); context.insert("roles", &roles); context.insert("families", &families); - context.insert("loggedin_user", &UserWithRoles::from_user(user, db).await); + context.insert( + "loggedin_user", + &UserWithRolesAndNotificationCount::from_user(user, db).await, + ); Template::render("admin/user/index", context.into_json()) } @@ -127,7 +133,7 @@ async fn fees( } context.insert( "loggedin_user", - &UserWithRoles::from_user(admin.into(), db).await, + &UserWithRolesAndNotificationCount::from_user(admin.into(), db).await, ); Template::render("admin/user/fees", context.into_json()) @@ -147,7 +153,7 @@ async fn scheckbuch( for s in scheckbooks { scheckbooks_with_roles.push(( Logbook::completed_with_user(db, &s).await, - UserWithRoles::from_user(s, db).await, + UserWithRolesAndNotificationCount::from_user(s, db).await, )) } @@ -158,7 +164,7 @@ async fn scheckbuch( } context.insert( "loggedin_user", - &UserWithRoles::from_user(user.into(), db).await, + &UserWithRolesAndNotificationCount::from_user(user.into(), db).await, ); Template::render("admin/user/scheckbuch", context.into_json()) diff --git a/src/tera/board/boathouse.rs b/src/tera/board/boathouse.rs index 266f81a..fbaa16c 100644 --- a/src/tera/board/boathouse.rs +++ b/src/tera/board/boathouse.rs @@ -1,7 +1,7 @@ use crate::model::{ boat::Boat, boathouse::Boathouse, - user::{AdminUser, UserWithRoles, VorstandUser}, + user::{AdminUser, UserWithRolesAndNotificationCount, VorstandUser}, }; use rocket::{ form::Form, @@ -39,7 +39,7 @@ async fn index( context.insert( "loggedin_user", - &UserWithRoles::from_user(admin.into(), db).await, + &UserWithRolesAndNotificationCount::from_user(admin.into(), db).await, ); Template::render("board/boathouse", context.into_json()) diff --git a/src/tera/boatdamage.rs b/src/tera/boatdamage.rs index 39088af..0fca62b 100644 --- a/src/tera/boatdamage.rs +++ b/src/tera/boatdamage.rs @@ -13,7 +13,7 @@ use crate::{ model::{ boat::Boat, boatdamage::{BoatDamage, BoatDamageFixed, BoatDamageToAdd, BoatDamageVerified}, - user::{CoxUser, DonauLinzUser, TechUser, User, UserWithRoles}, + user::{CoxUser, DonauLinzUser, TechUser, User, UserWithRolesAndNotificationCount}, }, tera::log::KioskCookie, }; @@ -59,7 +59,7 @@ async fn index( context.insert("boats", &boats); context.insert( "loggedin_user", - &UserWithRoles::from_user(user.into(), db).await, + &UserWithRolesAndNotificationCount::from_user(user.into(), db).await, ); Template::render("boatdamages", context.into_json()) diff --git a/src/tera/boatreservation.rs b/src/tera/boatreservation.rs index 5205fff..2aeda0a 100644 --- a/src/tera/boatreservation.rs +++ b/src/tera/boatreservation.rs @@ -75,7 +75,7 @@ async fn index( context.insert("user", &User::all(db).await); context.insert( "loggedin_user", - &UserWithRoles::from_user(user.into(), db).await, + &UserWithRolesAndNotificationCount::from_user(user.into(), db).await, ); Template::render("boatreservations", context.into_json()) diff --git a/src/tera/ergo.rs b/src/tera/ergo.rs index 8818d6b..c419781 100644 --- a/src/tera/ergo.rs +++ b/src/tera/ergo.rs @@ -18,7 +18,7 @@ use tera::Context; use crate::model::{ log::Log, - user::{AdminUser, User, UserWithRoles}, + user::{AdminUser, User, UserWithRolesAndNotificationCount}, }; #[derive(Serialize)] @@ -51,7 +51,7 @@ async fn send(db: &State, _user: AdminUser) -> Template { Template::render( "ergo.final", - context!(loggedin_user: &UserWithRoles::from_user(_user.user, db).await, thirty, dozen), + context!(loggedin_user: &UserWithRolesAndNotificationCount::from_user(_user.user, db).await, thirty, dozen), ) } @@ -120,7 +120,10 @@ async fn index(db: &State, user: User, flash: Option, user: DonauLinzUser) -> Template { Template::render( "log.completed", - context!(logs, loggedin_user: &UserWithRoles::from_user(user.into(), db).await), + context!(logs, loggedin_user: &UserWithRolesAndNotificationCount::from_user(user.into(), db).await), ) } @@ -108,7 +113,7 @@ async fn show_for_year(db: &State, user: AdminUser, year: i32) -> Te Template::render( "log.completed", - context!(logs, loggedin_user: &UserWithRoles::from_user(user.user, db).await), + context!(logs, loggedin_user: &UserWithRolesAndNotificationCount::from_user(user.user, db).await), ) } @@ -169,7 +174,10 @@ async fn kiosk( } context.insert("boats", &boats); - context.insert("reservations", &BoatReservation::all_future(db).await); + context.insert( + "reservations", + &BoatReservation::all_future_with_groups(db).await, + ); context.insert("coxes", &coxes); context.insert("users", &users); context.insert("logtypes", &logtypes); diff --git a/src/tera/mod.rs b/src/tera/mod.rs index 0ee0bf8..33bbf53 100644 --- a/src/tera/mod.rs +++ b/src/tera/mod.rs @@ -23,7 +23,7 @@ use tera::Context; use crate::model::{ notification::Notification, role::Role, - user::{User, UserWithRoles}, + user::{User, UserWithRolesAndNotificationCount}, }; pub(crate) mod admin; @@ -53,7 +53,10 @@ async fn index(db: &State, user: User, flash: Option, user: User, flash: Option, user: DonauLinzUser) -> Template { Template::render( "stat.boats", - context!(loggedin_user: &UserWithRoles::from_user(user.into(), db).await, stat, kiosk), + context!(loggedin_user: &UserWithRolesAndNotificationCount::from_user(user.into(), db).await, stat, kiosk), ) } @@ -38,7 +38,7 @@ async fn index(db: &State, user: DonauLinzUser, year: Option) - Template::render( "stat.people", - context!(loggedin_user: &UserWithRoles::from_user(user.into(), db).await, stat, personal, kiosk, guest_km, club_km), + context!(loggedin_user: &UserWithRolesAndNotificationCount::from_user(user.into(), db).await, stat, personal, kiosk, guest_km, club_km), ) } diff --git a/templates/includes/macros.html.tera b/templates/includes/macros.html.tera index e591143..f1dcdc0 100644 --- a/templates/includes/macros.html.tera +++ b/templates/includes/macros.html.tera @@ -2,7 +2,8 @@

Reservierungen ({{ reservations | length }})

- {% for reservation in reservations %} + {% for _, reservations_for_event in reservations %} + {% set reservation = reservations_for_event[0] %}
{{ reservation.start_date | date(format="%d.%m.%Y") }} @@ -13,7 +14,10 @@ ({{ reservation.time_desc }}) - {{ reservation.boat.name }} + {% for reservation in reservations_for_event %} + {{ reservation.boat.name }} + {% if not loop.last %}+{% endif %} + {% endfor %} ({{ reservation.user_applicant.name }}) {{ reservation.usage }} @@ -33,7 +37,24 @@ {{ loggedin_user.name }}
-
+
+ {% if loggedin_user.amount_unread_notifications > 0 %} + + + + {{ loggedin_user.amount_unread_notifications }} + + + {% endif %} {% if participants | length > 0 %} {% for rower in participants %} - {{ rower.name }} - {% if rower.is_guest %}(Scheckbuch){% endif %} - {% if rower.is_real_guest %} - (Gast) - {% if allow_removing %} - Abmelden +
+ {{ rower.name }} + {% if rower.is_guest %}(Scheckbuch){% endif %} + {% if rower.is_real_guest %} + (Gast) + {% if allow_removing %} + + + + + Abmelden + + {% endif %} {% endif %} - {% endif %} - -
+ +
{% endfor %} {% else %} {{ text }} diff --git a/templates/index.html.tera b/templates/index.html.tera index 8899e66..b200554 100644 --- a/templates/index.html.tera +++ b/templates/index.html.tera @@ -2,7 +2,11 @@ {% extends "base" %} {% block content %}
-

Ruderassistent

+

+ Ruder + + assistent +

-