Compare commits
	
		
			109 Commits
		
	
	
		
			test
			...
			127d9784ad
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 127d9784ad | |||
| bf4ea502d3 | |||
| c13dfdaa77 | |||
| 26aa222bc6 | |||
| 0bc9e11b9a | |||
| 2fdcab9030 | |||
| 7689a39ac5 | |||
| b43682ac39 | |||
| 8d7a1c707d | |||
| 958dda9f52 | |||
| 1eea8c9662 | |||
| b4b922222c | |||
| 84e76e8d65 | |||
| bdfcc6bc0a | |||
| afa88b9529 | |||
| 4229a4e021 | |||
| 6cd555298d | |||
| f6207e2994 | |||
| 4da996251a | |||
| c44c0d8505 | |||
| aa9568f326 | |||
| 1db09cd8ac | |||
| 59ef93d6fa | |||
| 4a3ee5b551 | |||
| c73b3e94c3 | |||
| 4969a0d90a | |||
| 3efcd99bbc | |||
| 4f0f509ad6 | |||
| 8112f1ed2a | |||
| b1252e8d5c | |||
| 9cb9cfe2a1 | |||
| a62fd116ea | |||
| 622bc700f3 | |||
| 2540a3dc7c | |||
| 0e5fd25e61 | |||
| 72b86d4dad | |||
|   | 16fbeea81b | ||
|   | bd6fbe772e | ||
| 647970e1fc | |||
| 1e1c1bb6d9 | |||
| 088fe98995 | |||
| 4237fafdff | |||
| 6b24008c17 | |||
| 4fbd3c7717 | |||
| ce8a095b31 | |||
| 6c191cf59e | |||
| b0698e70a4 | |||
| 6f7283f754 | |||
| 323f721fc0 | |||
| d0bcf1f384 | |||
| bd7cd0020e | |||
| 22bfe48d18 | |||
| c379a6ca79 | |||
| 3543ffe9e1 | |||
| 1d6770f11b | |||
| 1ad6509568 | |||
| 705f2ddc52 | |||
|   | dba1e08c5d | ||
| 1dc0c9c0e1 | |||
| 45004567ed | |||
| 3dff956544 | |||
| 79f8efc34b | |||
| 5c31fac230 | |||
| 3e983e05f9 | |||
| 8f91cc4e88 | |||
| c55f9743aa | |||
| 76290a64ae | |||
| 4b48fbaa82 | |||
| d25cd491d0 | |||
| def8affb5f | |||
| dfa7be9928 | |||
| 03a467270d | |||
| 1c04462c30 | |||
| 7af53203f8 | |||
| b2393eb6ec | |||
| a5e82851ba | |||
| 80725e223b | |||
| 70be6726db | |||
| 08fc324cc6 | |||
| df007524ed | |||
| 5720767af3 | |||
| 1215bdbd84 | |||
| 734490efe7 | |||
| 980fcc0c0c | |||
| 84f23e6e55 | |||
| 36193e3a64 | |||
| c6e3458588 | |||
| a0528c1c65 | |||
| 5e4d708884 | |||
| 6e41758104 | |||
| c916381fb0 | |||
| 7d44204533 | |||
| 145892104b | |||
| 6c0f0e6b04 | |||
| e004d81ca1 | |||
| 41b5aff329 | |||
| 76c8456380 | |||
| 95f43a73cf | |||
| 3d340bf803 | |||
| ae096ad602 | |||
| 25d8b1ea7c | |||
| 410cd05acc | |||
| 972811c2cf | |||
| e22d2d718e | |||
| b55f122f1d | |||
| d27489d714 | |||
| c340d1a916 | |||
| e7732b9e96 | |||
| 97dc9308bc | 
							
								
								
									
										194
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										194
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -175,7 +175,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -186,7 +186,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -221,9 +221,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" | ||||
|  | ||||
| [[package]] | ||||
| name = "backtrace" | ||||
| version = "0.3.72" | ||||
| version = "0.3.73" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" | ||||
| checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" | ||||
| dependencies = [ | ||||
|  "addr2line", | ||||
|  "cc", | ||||
| @@ -266,9 +266,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | ||||
|  | ||||
| [[package]] | ||||
| name = "bitflags" | ||||
| version = "2.5.0" | ||||
| version = "2.6.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" | ||||
| checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" | ||||
| dependencies = [ | ||||
|  "serde", | ||||
| ] | ||||
| @@ -309,9 +309,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" | ||||
|  | ||||
| [[package]] | ||||
| name = "bytemuck" | ||||
| version = "1.16.0" | ||||
| version = "1.16.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" | ||||
| checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" | ||||
|  | ||||
| [[package]] | ||||
| name = "byteorder" | ||||
| @@ -327,9 +327,9 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" | ||||
|  | ||||
| [[package]] | ||||
| name = "cc" | ||||
| version = "1.0.98" | ||||
| version = "1.0.101" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" | ||||
| checksum = "ac367972e516d45567c7eafc73d24e1c193dcf200a8d94e9db7b3d38b349572d" | ||||
|  | ||||
| [[package]] | ||||
| name = "cfg-if" | ||||
| @@ -620,11 +620,11 @@ version = "0.4.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a" | ||||
| dependencies = [ | ||||
|  "bitflags 2.5.0", | ||||
|  "bitflags 2.6.0", | ||||
|  "proc-macro2", | ||||
|  "proc-macro2-diagnostics", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -647,9 +647,9 @@ checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" | ||||
|  | ||||
| [[package]] | ||||
| name = "either" | ||||
| version = "1.12.0" | ||||
| version = "1.13.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" | ||||
| checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" | ||||
| dependencies = [ | ||||
|  "serde", | ||||
| ] | ||||
| @@ -785,7 +785,7 @@ checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" | ||||
| dependencies = [ | ||||
|  "futures-core", | ||||
|  "futures-sink", | ||||
|  "spin 0.9.8", | ||||
|  "spin", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -894,7 +894,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -992,8 +992,8 @@ dependencies = [ | ||||
|  "aho-corasick", | ||||
|  "bstr", | ||||
|  "log", | ||||
|  "regex-automata 0.4.6", | ||||
|  "regex-syntax 0.8.3", | ||||
|  "regex-automata 0.4.7", | ||||
|  "regex-syntax 0.8.4", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -1002,7 +1002,7 @@ version = "0.9.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" | ||||
| dependencies = [ | ||||
|  "bitflags 2.5.0", | ||||
|  "bitflags 2.6.0", | ||||
|  "ignore", | ||||
|  "walkdir", | ||||
| ] | ||||
| @@ -1139,9 +1139,9 @@ dependencies = [ | ||||
|  | ||||
| [[package]] | ||||
| name = "httparse" | ||||
| version = "1.8.0" | ||||
| version = "1.9.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" | ||||
| checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" | ||||
|  | ||||
| [[package]] | ||||
| name = "httpdate" | ||||
| @@ -1237,7 +1237,7 @@ dependencies = [ | ||||
|  "globset", | ||||
|  "log", | ||||
|  "memchr", | ||||
|  "regex-automata 0.4.6", | ||||
|  "regex-automata 0.4.7", | ||||
|  "same-file", | ||||
|  "walkdir", | ||||
|  "winapi-util", | ||||
| @@ -1306,15 +1306,6 @@ version = "1.70.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" | ||||
|  | ||||
| [[package]] | ||||
| name = "itertools" | ||||
| version = "0.12.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" | ||||
| dependencies = [ | ||||
|  "either", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "itertools" | ||||
| version = "0.13.0" | ||||
| @@ -1372,11 +1363,11 @@ dependencies = [ | ||||
|  | ||||
| [[package]] | ||||
| name = "lazy_static" | ||||
| version = "1.4.0" | ||||
| version = "1.5.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | ||||
| checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" | ||||
| dependencies = [ | ||||
|  "spin 0.5.2", | ||||
|  "spin", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -1485,9 +1476,9 @@ dependencies = [ | ||||
|  | ||||
| [[package]] | ||||
| name = "memchr" | ||||
| version = "2.7.2" | ||||
| version = "2.7.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" | ||||
| checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" | ||||
|  | ||||
| [[package]] | ||||
| name = "mime" | ||||
| @@ -1503,9 +1494,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" | ||||
|  | ||||
| [[package]] | ||||
| name = "miniz_oxide" | ||||
| version = "0.7.3" | ||||
| version = "0.7.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" | ||||
| checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" | ||||
| dependencies = [ | ||||
|  "adler", | ||||
| ] | ||||
| @@ -1535,7 +1526,7 @@ dependencies = [ | ||||
|  "httparse", | ||||
|  "memchr", | ||||
|  "mime", | ||||
|  "spin 0.9.8", | ||||
|  "spin", | ||||
|  "tokio", | ||||
|  "tokio-util", | ||||
|  "version_check", | ||||
| @@ -1583,7 +1574,7 @@ version = "6.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" | ||||
| dependencies = [ | ||||
|  "bitflags 2.5.0", | ||||
|  "bitflags 2.6.0", | ||||
|  "crossbeam-channel", | ||||
|  "filetime", | ||||
|  "fsevent-sys", | ||||
| @@ -1671,9 +1662,9 @@ dependencies = [ | ||||
|  | ||||
| [[package]] | ||||
| name = "object" | ||||
| version = "0.35.0" | ||||
| version = "0.36.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" | ||||
| checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" | ||||
| dependencies = [ | ||||
|  "memchr", | ||||
| ] | ||||
| @@ -1696,7 +1687,7 @@ version = "0.10.64" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" | ||||
| dependencies = [ | ||||
|  "bitflags 2.5.0", | ||||
|  "bitflags 2.6.0", | ||||
|  "cfg-if", | ||||
|  "foreign-types", | ||||
|  "libc", | ||||
| @@ -1713,7 +1704,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -1768,7 +1759,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "libc", | ||||
|  "redox_syscall 0.5.1", | ||||
|  "redox_syscall 0.5.2", | ||||
|  "smallvec", | ||||
|  "windows-targets 0.52.5", | ||||
| ] | ||||
| @@ -1819,7 +1810,7 @@ dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "proc-macro2-diagnostics", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -1868,7 +1859,7 @@ dependencies = [ | ||||
|  "pest_meta", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -1985,9 +1976,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" | ||||
|  | ||||
| [[package]] | ||||
| name = "proc-macro2" | ||||
| version = "1.0.85" | ||||
| version = "1.0.86" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" | ||||
| checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" | ||||
| dependencies = [ | ||||
|  "unicode-ident", | ||||
| ] | ||||
| @@ -2000,7 +1991,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
|  "version_check", | ||||
|  "yansi", | ||||
| ] | ||||
| @@ -2076,11 +2067,11 @@ dependencies = [ | ||||
|  | ||||
| [[package]] | ||||
| name = "redox_syscall" | ||||
| version = "0.5.1" | ||||
| version = "0.5.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" | ||||
| checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" | ||||
| dependencies = [ | ||||
|  "bitflags 2.5.0", | ||||
|  "bitflags 2.6.0", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -2100,19 +2091,19 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "regex" | ||||
| version = "1.10.4" | ||||
| version = "1.10.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" | ||||
| checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" | ||||
| dependencies = [ | ||||
|  "aho-corasick", | ||||
|  "memchr", | ||||
|  "regex-automata 0.4.6", | ||||
|  "regex-syntax 0.8.3", | ||||
|  "regex-automata 0.4.7", | ||||
|  "regex-syntax 0.8.4", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -2126,13 +2117,13 @@ dependencies = [ | ||||
|  | ||||
| [[package]] | ||||
| name = "regex-automata" | ||||
| version = "0.4.6" | ||||
| version = "0.4.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" | ||||
| checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" | ||||
| dependencies = [ | ||||
|  "aho-corasick", | ||||
|  "memchr", | ||||
|  "regex-syntax 0.8.3", | ||||
|  "regex-syntax 0.8.4", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -2143,9 +2134,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" | ||||
|  | ||||
| [[package]] | ||||
| name = "regex-syntax" | ||||
| version = "0.8.3" | ||||
| version = "0.8.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" | ||||
| checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" | ||||
|  | ||||
| [[package]] | ||||
| name = "ring" | ||||
| @@ -2157,7 +2148,7 @@ dependencies = [ | ||||
|  "cfg-if", | ||||
|  "getrandom", | ||||
|  "libc", | ||||
|  "spin 0.9.8", | ||||
|  "spin", | ||||
|  "untrusted", | ||||
|  "windows-sys 0.52.0", | ||||
| ] | ||||
| @@ -2211,7 +2202,7 @@ dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "rocket_http", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
|  "unicode-xid", | ||||
|  "version_check", | ||||
| ] | ||||
| @@ -2267,7 +2258,7 @@ dependencies = [ | ||||
|  "env_logger", | ||||
|  "futures", | ||||
|  "ics", | ||||
|  "itertools 0.13.0", | ||||
|  "itertools", | ||||
|  "job_scheduler_ng", | ||||
|  "lettre", | ||||
|  "log", | ||||
| @@ -2314,7 +2305,7 @@ version = "0.38.34" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" | ||||
| dependencies = [ | ||||
|  "bitflags 2.5.0", | ||||
|  "bitflags 2.6.0", | ||||
|  "errno", | ||||
|  "libc", | ||||
|  "linux-raw-sys", | ||||
| @@ -2440,7 +2431,7 @@ version = "2.11.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" | ||||
| dependencies = [ | ||||
|  "bitflags 2.5.0", | ||||
|  "bitflags 2.6.0", | ||||
|  "core-foundation", | ||||
|  "core-foundation-sys", | ||||
|  "libc", | ||||
| @@ -2474,14 +2465,14 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "serde_json" | ||||
| version = "1.0.117" | ||||
| version = "1.0.118" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" | ||||
| checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" | ||||
| dependencies = [ | ||||
|  "itoa", | ||||
|  "ryu", | ||||
| @@ -2588,12 +2579,6 @@ dependencies = [ | ||||
|  "windows-sys 0.52.0", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "spin" | ||||
| version = "0.5.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" | ||||
|  | ||||
| [[package]] | ||||
| name = "spin" | ||||
| version = "0.9.8" | ||||
| @@ -2615,11 +2600,10 @@ dependencies = [ | ||||
|  | ||||
| [[package]] | ||||
| name = "sqlformat" | ||||
| version = "0.2.3" | ||||
| version = "0.2.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" | ||||
| checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f" | ||||
| dependencies = [ | ||||
|  "itertools 0.12.1", | ||||
|  "nom", | ||||
|  "unicode_categories", | ||||
| ] | ||||
| @@ -2728,7 +2712,7 @@ checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" | ||||
| dependencies = [ | ||||
|  "atoi", | ||||
|  "base64 0.21.7", | ||||
|  "bitflags 2.5.0", | ||||
|  "bitflags 2.6.0", | ||||
|  "byteorder", | ||||
|  "bytes", | ||||
|  "chrono", | ||||
| @@ -2772,7 +2756,7 @@ checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" | ||||
| dependencies = [ | ||||
|  "atoi", | ||||
|  "base64 0.21.7", | ||||
|  "bitflags 2.5.0", | ||||
|  "bitflags 2.6.0", | ||||
|  "byteorder", | ||||
|  "chrono", | ||||
|  "crc", | ||||
| @@ -2873,9 +2857,9 @@ dependencies = [ | ||||
|  | ||||
| [[package]] | ||||
| name = "subtle" | ||||
| version = "2.5.0" | ||||
| version = "2.6.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" | ||||
| checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" | ||||
|  | ||||
| [[package]] | ||||
| name = "syn" | ||||
| @@ -2890,9 +2874,9 @@ dependencies = [ | ||||
|  | ||||
| [[package]] | ||||
| name = "syn" | ||||
| version = "2.0.66" | ||||
| version = "2.0.68" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" | ||||
| checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
| @@ -2950,7 +2934,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -2996,9 +2980,9 @@ dependencies = [ | ||||
|  | ||||
| [[package]] | ||||
| name = "tinyvec" | ||||
| version = "1.6.0" | ||||
| version = "1.6.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" | ||||
| checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" | ||||
| dependencies = [ | ||||
|  "tinyvec_macros", | ||||
| ] | ||||
| @@ -3035,7 +3019,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -3122,7 +3106,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -3328,14 +3312,14 @@ dependencies = [ | ||||
|  "serde", | ||||
|  "serde_json", | ||||
|  "url", | ||||
|  "webpki-roots 0.26.2", | ||||
|  "webpki-roots 0.26.3", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "url" | ||||
| version = "2.5.0" | ||||
| version = "2.5.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" | ||||
| checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" | ||||
| dependencies = [ | ||||
|  "form_urlencoded", | ||||
|  "idna", | ||||
| @@ -3350,15 +3334,15 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" | ||||
|  | ||||
| [[package]] | ||||
| name = "utf8parse" | ||||
| version = "0.2.1" | ||||
| version = "0.2.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" | ||||
| checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" | ||||
|  | ||||
| [[package]] | ||||
| name = "uuid" | ||||
| version = "1.8.0" | ||||
| version = "1.9.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" | ||||
| checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" | ||||
| dependencies = [ | ||||
|  "getrandom", | ||||
| ] | ||||
| @@ -3433,7 +3417,7 @@ dependencies = [ | ||||
|  "once_cell", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
|  "wasm-bindgen-shared", | ||||
| ] | ||||
|  | ||||
| @@ -3455,7 +3439,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
|  "wasm-bindgen-backend", | ||||
|  "wasm-bindgen-shared", | ||||
| ] | ||||
| @@ -3474,9 +3458,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" | ||||
|  | ||||
| [[package]] | ||||
| name = "webpki-roots" | ||||
| version = "0.26.2" | ||||
| version = "0.26.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3c452ad30530b54a4d8e71952716a212b08efd0f3562baa66c29a618b07da7c3" | ||||
| checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" | ||||
| dependencies = [ | ||||
|  "rustls-pki-types", | ||||
| ] | ||||
| @@ -3691,9 +3675,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" | ||||
|  | ||||
| [[package]] | ||||
| name = "winnow" | ||||
| version = "0.6.11" | ||||
| version = "0.6.13" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "56c52728401e1dc672a56e81e593e912aa54c78f40246869f78359a2bf24d29d" | ||||
| checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" | ||||
| dependencies = [ | ||||
|  "memchr", | ||||
| ] | ||||
| @@ -3724,7 +3708,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.66", | ||||
|  "syn 2.0.68", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
|   | ||||
| @@ -158,9 +158,9 @@ function selectBoatChange() { | ||||
| 	} | ||||
|  | ||||
| 	if (event.detail.customProperties.convert_handoperated_possible) { | ||||
| 		only_steering.removeAttribute('disabled'); | ||||
| 		only_steering.removeAttribute('readonly'); | ||||
| 	}else { | ||||
| 		only_steering.setAttribute('disabled', 'disabled'); | ||||
| 		only_steering.setAttribute('readonly', 'readonly'); | ||||
| 	} | ||||
|  | ||||
|         const destination = <HTMLSelectElement>( | ||||
|   | ||||
| @@ -190,3 +190,103 @@ test("Kiosk can start and finish trip", async ({ page }, testInfo) => { | ||||
|   await expect(page.locator('body')).toContainText('Ottensheim (25 km)'); | ||||
|   await expect(page.locator('body')).toContainText('Ruderer: cox2, rower2'); | ||||
| }); | ||||
|  | ||||
| test("Cox can start and finish trip with cox steering only", async ({ page }, testInfo) => { | ||||
|   await page.goto("/auth"); | ||||
|   await page.getByPlaceholder("Name").click(); | ||||
|   await page.getByPlaceholder("Name").fill("cox2"); | ||||
|   await page.getByPlaceholder("Name").press("Tab"); | ||||
|   await page.getByPlaceholder("Passwort").fill("cox"); | ||||
|   await page.getByPlaceholder("Passwort").press("Enter"); | ||||
|  | ||||
|   await page.goto("/"); | ||||
|   await page.getByRole("link", { name: "Ausfahrt eintragen" }).click(); | ||||
|   if (testInfo.project.name.includes("Mobile")) { | ||||
|     // No left boat selector on mobile views | ||||
|     await page.getByText('-- Wähle ein Boot aus ---').nth(1).click(); | ||||
|     await page.getByRole("option", { name: "cox_only_steering_boat" }).click(); | ||||
|   } else { | ||||
|     await page.getByText('2+', { exact: true }).click(); | ||||
|     await page.getByText("cox_only_steering_boat", { exact: true }).click(); | ||||
|   } | ||||
|  | ||||
|   // Trip starts 2 hours ago | ||||
|   const datetimeSelector = '#departure'; | ||||
|   const currentValue = await page.$eval(datetimeSelector, el => el.value); | ||||
|   const currentDate = new Date(currentValue); | ||||
|   currentDate.setMinutes(currentDate.getMinutes()); | ||||
|   currentDate.setHours(currentDate.getHours() - new Date().getTimezoneOffset()/60 - 2); | ||||
|   const newDatetime = currentDate.toISOString().slice(0, 16); | ||||
|   await page.$eval(datetimeSelector, (el, value) => el.value = value, newDatetime); | ||||
|  | ||||
|   await expect(page.locator("#shipmaster-newrowerjs")).toContainText("cox"); | ||||
|   await expect(page.locator("#steering_person-newrowerjs")).toContainText( | ||||
|     "cox", | ||||
|   ); | ||||
|   await page.getByRole("button", { name: "Ausfahrt eintragen" }).click(); | ||||
|   await expect(page.locator("body")).toContainText( | ||||
|     "Ausfahrt erfolgreich hinzugefügt", | ||||
|   ); | ||||
|   await expect(page.locator("body")).toContainText("cox_only_steering_boat"); | ||||
|  | ||||
|   await page.goto("/log"); | ||||
|   await page.locator("div:nth-child(2) > .border-0").click(); | ||||
|  | ||||
|   await page.getByRole("combobox", { name: "Destination" }).click(); | ||||
|   await page.getByRole("combobox", { name: "Destination" }).fill("Ottensheim"); | ||||
|   await page.getByRole("button", { name: "Ausfahrt beenden" }).click(); | ||||
|   await expect(page.locator("body")).toContainText( | ||||
|     "Ausfahrt korrekt eingetragen", | ||||
|   ); | ||||
|  | ||||
|   await page.goto('/log/show'); | ||||
|   await expect(page.locator('body')).toContainText('cox_only_steering_boat'); | ||||
|   await expect(page.locator('body')).toContainText('(cox2)'); | ||||
|   await expect(page.locator('body')).toContainText('Ottensheim (25 km)'); | ||||
| }); | ||||
|  | ||||
| test("Kiosk can start and finish trip in one stop", async ({ page }, testInfo) => { | ||||
|   await page.goto("/log/kiosk/ekrv2019/Linz"); | ||||
|  | ||||
|   if (testInfo.project.name.includes("Mobile")) { | ||||
|     // No left boat selector on mobile views | ||||
|     await page.getByText('-- Wähle ein Boot aus ---').nth(1).click(); | ||||
|     await page.getByRole("option", { name: "Joe" }).click(); | ||||
|   } else { | ||||
|     await page.getByText('2x', { exact: true }).click(); | ||||
|     await page.getByText("Joe", { exact: true }).click(); | ||||
|   } | ||||
|   await page.getByPlaceholder("Ruderer auswählen").click(); | ||||
|   await page.getByRole("option", { name: "rower2" }).click(); | ||||
|   await page.getByRole("option", { name: "cox2" }).click(); | ||||
|   await expect(page.getByRole("listbox")).toContainText( | ||||
|     "Nur 2 Ruderer können hinzugefügt werden", | ||||
|   ); | ||||
|  | ||||
|   // Trip starts 2 hours ago | ||||
|   const datetimeSelector = '#departure'; | ||||
|   const currentValue = await page.$eval(datetimeSelector, el => el.value); | ||||
|   const currentDate = new Date(currentValue); | ||||
|   currentDate.setMinutes(currentDate.getMinutes()); | ||||
|   currentDate.setHours(currentDate.getHours() - new Date().getTimezoneOffset()/60 - 2); | ||||
|   const newDatetime = currentDate.toISOString().slice(0, 16); | ||||
|   await page.$eval(datetimeSelector, (el, value) => el.value = value, newDatetime); | ||||
|  | ||||
|   await page.getByLabel('Ankunftszeit').click(); | ||||
|   await page.locator('#destination').fill('a'); | ||||
|   await page.getByLabel('Distanz').fill('1'); | ||||
|  | ||||
|   await expect(page.locator("#shipmaster-newrowerjs")).toContainText("cox"); | ||||
|   await expect(page.locator("#steering_person-newrowerjs")).toContainText( | ||||
|     "rower2 cox", | ||||
|   ); | ||||
|   await page.getByRole("button", { name: "Ausfahrt eintragen" }).click(); | ||||
|   await expect(page.locator("body")).toContainText( | ||||
|     "Ausfahrt erfolgreich hinzugefügt", | ||||
|   ); | ||||
|   await page.getByRole('link', { name: 'Logbuch' }).click(); | ||||
|   await expect(page.locator('body')).toContainText('Joe'); | ||||
|   await expect(page.locator('body')).toContainText('(cox2)'); | ||||
|   await expect(page.locator('body')).toContainText('a (1 km)'); | ||||
|   await expect(page.locator('body')).toContainText('Ruderer: cox2, rower2'); | ||||
| }); | ||||
|   | ||||
| @@ -55,6 +55,7 @@ INSERT INTO "boat" (name, amount_seats, location_id) VALUES ('Kaputtes Boot :-(' | ||||
| INSERT INTO "boat" (name, amount_seats, location_id) VALUES ('Sehr kaputtes Boot :-((', 7, 1); | ||||
| INSERT INTO "boat" (name, amount_seats, location_id) VALUES ('Ottensheim Boot', 7, 2); | ||||
| INSERT INTO "boat" (name, amount_seats, location_id, owner) VALUES ('second_private_boat_from_rower', 1, 1, 2); | ||||
| INSERT INTO "boat" (name, amount_seats, location_id, default_shipmaster_only_steering) VALUES ('cox_only_steering_boat', 3, 1, true); | ||||
| INSERT INTO "logbook_type" (name) VALUES ('Wanderfahrt'); | ||||
| INSERT INTO "logbook_type" (name) VALUES ('Regatta'); | ||||
| INSERT INTO "logbook" (boat_id, shipmaster,steering_person, shipmaster_only_steering, departure) VALUES (2, 2, 2, false, strftime('%Y', 'now') || '-12-24 10:00'); | ||||
|   | ||||
| @@ -60,6 +60,22 @@ pub struct LogToFinalize { | ||||
|     pub rowers: Vec<i64>, | ||||
| } | ||||
|  | ||||
| #[derive(FromForm, Debug, Clone)] | ||||
| pub struct LogToUpdate { | ||||
|     pub id: i64, | ||||
|     pub boat_id: i64, | ||||
|     pub shipmaster: i64, | ||||
|     pub steering_person: i64, | ||||
|     pub shipmaster_only_steering: bool, | ||||
|     pub departure: String, | ||||
|     pub arrival: Option<String>, | ||||
|     pub destination: Option<String>, | ||||
|     pub distance_in_km: Option<i64>, | ||||
|     pub comments: Option<String>, | ||||
|     pub logtype: Option<i64>, | ||||
|     pub rowers: Vec<i64>, | ||||
| } | ||||
|  | ||||
| impl TryFrom<LogToAdd> for LogToFinalize { | ||||
|     type Error = String; | ||||
|  | ||||
| @@ -94,6 +110,11 @@ pub struct LogbookWithBoatAndRowers { | ||||
|     pub rowers: Vec<User>, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, PartialEq)] | ||||
| pub enum LogbookAdminUpdateError { | ||||
|     NotAllowed, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, PartialEq)] | ||||
| pub enum LogbookUpdateError { | ||||
|     NotYourEntry, | ||||
| @@ -105,6 +126,8 @@ pub enum LogbookUpdateError { | ||||
|     UserNotAllowedToUseBoat, | ||||
|     OnlyAllowedToEndTripsEndingToday, | ||||
|     TooFast(i64, i64), | ||||
|     AlreadyFinalized, | ||||
|     ExternalSteeringPersonMustSteer, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, PartialEq)] | ||||
| @@ -129,6 +152,8 @@ pub enum LogbookCreateError { | ||||
|     OnlyAllowedToEndTripsEndingToday, | ||||
|     CantChangeHandoperatableStatusForThisBoat, | ||||
|     TooFast(i64, i64), | ||||
|     AlreadyFinalized, | ||||
|     ExternalSteeringPersonMustSteer, | ||||
| } | ||||
|  | ||||
| impl From<LogbookUpdateError> for LogbookCreateError { | ||||
| @@ -153,6 +178,10 @@ impl From<LogbookUpdateError> for LogbookCreateError { | ||||
|                 LogbookCreateError::OnlyAllowedToEndTripsEndingToday | ||||
|             } | ||||
|             LogbookUpdateError::TooFast(km, min) => LogbookCreateError::TooFast(km, min), | ||||
|             LogbookUpdateError::AlreadyFinalized => LogbookCreateError::AlreadyFinalized, | ||||
|             LogbookUpdateError::ExternalSteeringPersonMustSteer => { | ||||
|                 LogbookCreateError::ExternalSteeringPersonMustSteer | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -172,7 +201,7 @@ impl Logbook { | ||||
|         .await | ||||
|         .ok() | ||||
|     } | ||||
|     pub async fn find_by_id(db: &SqlitePool, id: i32) -> Option<Self> { | ||||
|     pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option<Self> { | ||||
|         sqlx::query_as!( | ||||
|             Self, | ||||
|             " | ||||
| @@ -242,7 +271,7 @@ ORDER BY departure DESC | ||||
|     FROM logbook | ||||
|     JOIN rower ON logbook.id = rower.logbook_id | ||||
|     WHERE arrival is not null AND rower_id = {} | ||||
|     ORDER BY departure DESC | ||||
|     ORDER BY arrival DESC | ||||
|             ",  user.id) | ||||
|             ) | ||||
|             .fetch_all(db) | ||||
| @@ -275,7 +304,7 @@ ORDER BY departure DESC | ||||
|     SELECT id, boat_id, shipmaster, steering_person, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype | ||||
|     FROM logbook | ||||
|     WHERE arrival is not null AND arrival LIKE '{}-%' | ||||
|     ORDER BY departure DESC | ||||
|     ORDER BY arrival DESC | ||||
|             ", year) | ||||
|             ) | ||||
|             .fetch_all(db) | ||||
| @@ -329,13 +358,12 @@ ORDER BY departure DESC | ||||
|             let mut tx = db.begin().await.unwrap(); | ||||
|  | ||||
|             let inserted_row = sqlx::query!( | ||||
|                 "INSERT INTO logbook(boat_id, shipmaster, steering_person, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype) VALUES (?,?,?,?,?,?,?,?,?,?) RETURNING id", | ||||
|                 "INSERT INTO logbook(boat_id, shipmaster, steering_person, shipmaster_only_steering, departure, destination, distance_in_km, comments, logtype) VALUES (?,?,?,?,?,?,?,?,?) RETURNING id", | ||||
|                 log.boat_id, | ||||
|                 log.shipmaster, | ||||
|                 log.steering_person, | ||||
|                 log.shipmaster_only_steering, | ||||
|                 log.departure, | ||||
|                 log.arrival, | ||||
|                 log.destination, | ||||
|                 log.distance_in_km, | ||||
|                 log.comments, | ||||
| @@ -391,6 +419,14 @@ ORDER BY departure DESC | ||||
|             if user.on_water(db).await { | ||||
|                 return Err(LogbookCreateError::RowerAlreadyOnWater(Box::new(user))); | ||||
|             } | ||||
|  | ||||
|             if user.name == "Externe Steuerperson" { | ||||
|                 if let Some(steering_id) = log.steering_person { | ||||
|                     if steering_id != user.id { | ||||
|                         return Err(LogbookCreateError::ExternalSteeringPersonMustSteer); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if !boat.shipmaster_allowed(db, created_by_user).await { | ||||
| @@ -437,6 +473,35 @@ ORDER BY departure DESC | ||||
|         Ok(ret) | ||||
|     } | ||||
|  | ||||
|     pub async fn update( | ||||
|         &self, | ||||
|         db: &SqlitePool, | ||||
|         data: LogToUpdate, | ||||
|         user: &User, | ||||
|     ) -> Result<(), LogbookAdminUpdateError> { | ||||
|         if !user.has_role(db, "Vorstand").await { | ||||
|             return Err(LogbookAdminUpdateError::NotAllowed); | ||||
|         } | ||||
|  | ||||
|         sqlx::query!( | ||||
|                 "UPDATE logbook SET boat_id=?, shipmaster=?, steering_person=?, shipmaster_only_steering=?, departure=?, arrival=?, destination=?, distance_in_km=?, comments=?, logtype=? WHERE id=?", | ||||
|                 data.boat_id, | ||||
|                 data.shipmaster, | ||||
|                 data.steering_person, | ||||
|                 data.shipmaster_only_steering, | ||||
|                 data.departure, | ||||
|                 data.arrival, | ||||
|                 data.destination, | ||||
|                 data.distance_in_km, | ||||
|                 data.comments, | ||||
|                 data.logtype, | ||||
|                 self.id | ||||
|             ) | ||||
|             .execute(db) | ||||
|             .await.unwrap(); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     pub async fn distances(db: &SqlitePool) -> Vec<(String, i64)> { | ||||
|         let result = sqlx::query!("SELECT destination, distance_in_km FROM logbook WHERE id IN (SELECT MIN(id) FROM logbook GROUP BY destination) AND destination IS NOT NULL AND distance_in_km IS NOT NULL;") | ||||
|         .fetch_all(db) | ||||
| @@ -496,6 +561,10 @@ ORDER BY departure DESC | ||||
|             return Err(LogbookUpdateError::NotYourEntry); | ||||
|         } | ||||
|  | ||||
|         if self.arrival.is_some() { | ||||
|             return Err(LogbookUpdateError::AlreadyFinalized); | ||||
|         } | ||||
|  | ||||
|         let boat = Boat::find_by_id_tx(db, self.boat_id as i32).await.unwrap(); //ok | ||||
|  | ||||
|         if boat.amount_seats == 1 { | ||||
| @@ -553,6 +622,13 @@ ORDER BY departure DESC | ||||
|  | ||||
|         self.remove_rowers(db).await; | ||||
|         for rower in &log.rowers { | ||||
|             if user.name == "Externe Steuerperson" { | ||||
|                 if let Some(steering_id) = log.steering_person { | ||||
|                     if steering_id != user.id { | ||||
|                         return Err(LogbookUpdateError::ExternalSteeringPersonMustSteer); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             Rower::create(db, self.id, *rower) | ||||
|                 .await | ||||
|                 .map_err(|e| LogbookUpdateError::RowerCreateError(*rower, e.to_string()))?; | ||||
|   | ||||
| @@ -182,7 +182,7 @@ dein Vereinsbeitrag für das aktuelle Jahr beträgt {}€", | ||||
|                             fees.name | ||||
|                         )) | ||||
|                     } | ||||
|                     content.push_str("\nBitte überweise diesen auf folgendes Konto: IBAN: AT13 1200 0804 1300 1200. Auf https://app.rudernlinz.at/planned findest du einen QR Code, den du mit deiner Bankapp scannen kannst um alle Eingaben bereits ausgefüllt zu haben.\n\n\ | ||||
|                     content.push_str("\nBitte überweise diesen auf folgendes Konto: IBAN: AT58 2032 0321 0072 9256. Auf https://app.rudernlinz.at/planned findest du einen QR Code, den du mit deiner Bankapp scannen kannst um alle Eingaben bereits ausgefüllt zu haben.\n\n\ | ||||
| Falls die Berechnung nicht stimmt (korrekte Preise findest du unter https://rudernlinz.at/unser-verein/gebuhren/) melde dich bitte bei it@rudernlinz.at. @Studenten: Bitte die aktuelle Studienbestätigung an it@rudernlinz.at schicken.\n\n\ | ||||
| Wenn du die Vereinsgebühren schon bezahlt hast, kannst du diese Mail einfach ignorieren.\n\n | ||||
| Beste Grüße\n\ | ||||
| @@ -293,7 +293,7 @@ Dein Vereinsbeitrag für das aktuelle Jahr beträgt {}€", | ||||
| Gemäß § 7 Abs. 3 lit. c unseres Status behalten wir uns vor, bei ausbleibender Zahlung die Mitgliedschaft zu beenden. Dies möchten wir vermeiden und hoffen auf deine Unterstützung.\n\n\ | ||||
| Bei Fragen oder Problemen stehen wir gerne zur Verfügung. | ||||
|  | ||||
| Bankverbindung: IBAN: AT13 1200 0804 1300 1200 (Unter https://app.rudernlinz.at/planned findest du einen QR Code, den du mit deiner Bankapp scannen kannst um alle Eingaben bereits ausgefüllt zu haben.) | ||||
| Bankverbindung: IBAN: AT58 2032 0321 0072 9256 (Unter https://app.rudernlinz.at/planned findest du einen QR Code, den du mit deiner Bankapp scannen kannst um alle Eingaben bereits ausgefüllt zu haben.) | ||||
|  | ||||
| Mit freundlichen Grüßen,\n\ | ||||
| Der Vorstand"); | ||||
|   | ||||
| @@ -213,7 +213,7 @@ ORDER BY day;", | ||||
|  | ||||
|     pub(crate) async fn user_allowed_to_change(&self, db: &SqlitePool, user: &User) -> bool { | ||||
|         if self.belongs_to_event(db).await { | ||||
|             user.has_role(db, "planned_event").await | ||||
|             user.has_role(db, "manage_events").await | ||||
|         } else { | ||||
|             self.user_is_cox(db, user).await != CoxAtTrip::No | ||||
|         } | ||||
|   | ||||
| @@ -273,7 +273,7 @@ ASKÖ Ruderverein Donau Linz", self.name, SCHECKBUCH/100), | ||||
|  | ||||
| herzlich willkommen im ASKÖ Ruderverein Donau Linz! Wir freuen uns sehr, dich als neues Mitglied in unserem Verein begrüßen zu dürfen.  | ||||
|  | ||||
| Um dir den Einstieg zu erleichtern, findest du in unserem Handbuch alle wichtigen Informationen über unseren Verein: https://rudernlinz.at/book. Bei weiteren Fragen stehen dir die Adressen info@rudernlinz.at und it@rudernlinz.at jederzeit zur Verfügung. | ||||
| Um dir den Einstieg zu erleichtern, findest du in unserem Handbuch alle wichtigen Informationen über unseren Verein: https://rudernlinz.at/book. Bei weiteren Fragen stehen dir die Adressen info@rudernlinz.at (für allgemeine Fragen) und it@rudernlinz.at (bei technischen Fragen) jederzeit zur Verfügung. | ||||
|  | ||||
| Du kannst auch gerne unserer Signal-Gruppe beitreten, um auf dem Laufenden zu bleiben und dich mit anderen Mitgliedern auszutauschen: https://signal.group/#CjQKICFrq6zSsRHxrucS3jEcQn6lknEXacAykwwLV3vNLKxPEhA17jxz7cpjfu3JZokLq1TH | ||||
|  | ||||
| @@ -281,7 +281,7 @@ Für die Organisation unserer Ausfahrten nutzen wir app.rudernlinz.at. Logge dic | ||||
|  | ||||
| Beim nächsten Treffen im Verein, erinnere mich (Philipp Hofer) bitte daran, deinen Fingerabdruck zu registrieren, damit du eigenständig Zugang zum Bootshaus erhältst. | ||||
|  | ||||
| Außerdem haben wir im Bootshaus ein WLAN für Vereinsmitglieder 'ASKÖ Ruderverein Donau Linz'. Das Passwort dafür lautet 'donau1921' (ohne Anführungszeichen). Bitte gib das Passwort an keine vereinsfremden Personen weiter. | ||||
| Damit du dich noch mehr verbunden fühlst (:-)), haben wir im Bootshaus ein WLAN für Vereinsmitglieder 'ASKÖ Ruderverein Donau Linz' eingerichtet. Das Passwort dafür lautet 'donau1921' (ohne Anführungszeichen). Bitte gib das Passwort an keine vereinsfremden Personen weiter. | ||||
|  | ||||
| Wir freuen uns darauf, dich bald am Wasser zu sehen und gemeinsam tolle Erfahrungen zu sammeln! | ||||
|  | ||||
| @@ -361,17 +361,38 @@ ASKÖ Ruderverein Donau Linz", self.name), | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         let halfprice = if let Some(member_since_date) = &self.member_since_date { | ||||
|             if let Ok(member_since_date) = NaiveDate::parse_from_str(member_since_date, "%Y-%m-%d") | ||||
|             { | ||||
|                 let halfprice_startdate = | ||||
|                     NaiveDate::from_ymd_opt(Local::now().year(), 7, 1).unwrap(); | ||||
|                 member_since_date >= halfprice_startdate | ||||
|             } else { | ||||
|                 false | ||||
|             } | ||||
|         } else { | ||||
|             false | ||||
|         }; | ||||
|  | ||||
|         if self.has_role(db, "Unterstützend").await { | ||||
|             fee.add("Unterstützendes Mitglied".into(), UNTERSTUETZEND); | ||||
|         } else if self.has_role(db, "Förderndes Mitglied").await { | ||||
|             fee.add("Förderndes Mitglied".into(), FOERDERND); | ||||
|         } else if Family::find_by_opt_id(db, self.family_id).await.is_none() { | ||||
|             if self.has_role(db, "Student").await || self.has_role(db, "Schüler").await { | ||||
|                 fee.add("Schüler/Student".into(), STUDENT_OR_PUPIL); | ||||
|                 if halfprice { | ||||
|                     fee.add("Schüler/Student (Halbpreis)".into(), STUDENT_OR_PUPIL / 2); | ||||
|                 } else { | ||||
|                     fee.add("Schüler/Student".into(), STUDENT_OR_PUPIL); | ||||
|                 } | ||||
|             } else if self.has_role(db, "Ehrenmitglied").await { | ||||
|                 fee.add("Ehrenmitglied".into(), 0); | ||||
|             } else { | ||||
|                 fee.add("Mitgliedsbeitrag".into(), REGULAR); | ||||
|                 if halfprice { | ||||
|                     fee.add("Mitgliedsbeitrag (Halbpreis)".into(), REGULAR / 2); | ||||
|                 } else { | ||||
|                     fee.add("Mitgliedsbeitrag".into(), REGULAR); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -14,8 +14,12 @@ pub fn schedule(db: &SqlitePool, config: &Config) { | ||||
|     let openweathermap_key = config.openweathermap_key.clone(); | ||||
|  | ||||
|     tokio::task::spawn(async { | ||||
|         waterlevel::update(&db).await.unwrap(); | ||||
|         weather::update(&db, &openweathermap_key).await.unwrap(); | ||||
|         if let Err(e) = waterlevel::update(&db).await { | ||||
|             log::error!("Water level update error: {e}, trying again next time"); | ||||
|         } | ||||
|         if let Err(e) = weather::update(&db, &openweathermap_key).await { | ||||
|             log::error!("Weather update error: {e}, trying again next time"); | ||||
|         } | ||||
|  | ||||
|         let mut sched = JobScheduler::new(); | ||||
|  | ||||
| @@ -26,10 +30,12 @@ pub fn schedule(db: &SqlitePool, config: &Config) { | ||||
|             // nicer one's rust (stable) support async closures | ||||
|             task::block_in_place(|| { | ||||
|                 tokio::runtime::Handle::current().block_on(async { | ||||
|                     waterlevel::update(&db_clone).await.unwrap(); | ||||
|                     weather::update(&db_clone, &openweathermap_key) | ||||
|                         .await | ||||
|                         .unwrap(); | ||||
|                     if let Err(e) = waterlevel::update(&db_clone).await { | ||||
|                         log::error!("Water level update error: {e}, trying again next time"); | ||||
|                     } | ||||
|                     if let Err(e) = weather::update(&db_clone, &openweathermap_key).await { | ||||
|                         log::error!("Weather update error: {e}, trying again next time"); | ||||
|                     } | ||||
|                 }); | ||||
|             }); | ||||
|         })); | ||||
|   | ||||
| @@ -9,14 +9,14 @@ use sqlx::SqlitePool; | ||||
| use crate::model::log::Log; | ||||
| use crate::model::mail::Mail; | ||||
| use crate::model::role::Role; | ||||
| use crate::model::user::AdminUser; | ||||
| use crate::model::user::UserWithDetails; | ||||
| use crate::model::user::{AdminUser, VorstandUser}; | ||||
| use crate::tera::Config; | ||||
|  | ||||
| #[get("/mail")] | ||||
| async fn index( | ||||
|     db: &State<SqlitePool>, | ||||
|     admin: AdminUser, | ||||
|     admin: VorstandUser, | ||||
|     flash: Option<FlashMessage<'_>>, | ||||
| ) -> Template { | ||||
|     let mut context = Context::new(); | ||||
| @@ -27,7 +27,7 @@ async fn index( | ||||
|  | ||||
|     context.insert( | ||||
|         "loggedin_user", | ||||
|         &UserWithDetails::from_user(admin.user, db).await, | ||||
|         &UserWithDetails::from_user(admin.0, db).await, | ||||
|     ); | ||||
|     context.insert("roles", &roles); | ||||
|  | ||||
| @@ -65,7 +65,7 @@ async fn update( | ||||
|     db: &State<SqlitePool>, | ||||
|     data: Form<MailToSend<'_>>, | ||||
|     config: &State<Config>, | ||||
|     admin: AdminUser, | ||||
|     admin: VorstandUser, | ||||
| ) -> Flash<Redirect> { | ||||
|     let d = data.into_inner(); | ||||
|     Log::create(db, format!("{admin:?} trying to send this mail: {d:?}")).await; | ||||
|   | ||||
| @@ -2,7 +2,7 @@ use crate::model::{ | ||||
|     log::Log, | ||||
|     notification::Notification, | ||||
|     role::Role, | ||||
|     user::{AdminUser, User, UserWithDetails}, | ||||
|     user::{User, UserWithDetails, VorstandUser}, | ||||
| }; | ||||
| use itertools::Itertools; | ||||
| use rocket::{ | ||||
| @@ -18,7 +18,7 @@ use sqlx::SqlitePool; | ||||
| #[get("/notification")] | ||||
| async fn index( | ||||
|     db: &State<SqlitePool>, | ||||
|     user: AdminUser, | ||||
|     user: VorstandUser, | ||||
|     flash: Option<FlashMessage<'_>>, | ||||
| ) -> Template { | ||||
|     let mut context = Context::new(); | ||||
| @@ -27,7 +27,7 @@ async fn index( | ||||
|     } | ||||
|     context.insert( | ||||
|         "loggedin_user", | ||||
|         &UserWithDetails::from_user(user.user, db).await, | ||||
|         &UserWithDetails::from_user(user.0, db).await, | ||||
|     ); | ||||
|  | ||||
|     let users: Vec<User> = User::all(db) | ||||
| @@ -62,7 +62,7 @@ pub struct NotificationToSendUser { | ||||
| async fn send_group( | ||||
|     db: &State<SqlitePool>, | ||||
|     data: Form<NotificationToSendGroup>, | ||||
|     admin: AdminUser, | ||||
|     admin: VorstandUser, | ||||
| ) -> Flash<Redirect> { | ||||
|     let d = data.into_inner(); | ||||
|     Log::create( | ||||
| @@ -89,7 +89,7 @@ async fn send_group( | ||||
| async fn send_user( | ||||
|     db: &State<SqlitePool>, | ||||
|     data: Form<NotificationToSendUser>, | ||||
|     admin: AdminUser, | ||||
|     admin: VorstandUser, | ||||
| ) -> Flash<Redirect> { | ||||
|     let d = data.into_inner(); | ||||
|     Log::create( | ||||
|   | ||||
| @@ -20,11 +20,11 @@ use crate::model::{ | ||||
|     boatreservation::BoatReservation, | ||||
|     log::Log, | ||||
|     logbook::{ | ||||
|         LogToAdd, LogToFinalize, Logbook, LogbookCreateError, LogbookDeleteError, | ||||
|         LogbookUpdateError, | ||||
|         LogToAdd, LogToFinalize, LogToUpdate, Logbook, LogbookAdminUpdateError, LogbookCreateError, | ||||
|         LogbookDeleteError, LogbookUpdateError, | ||||
|     }, | ||||
|     logtype::LogType, | ||||
|     user::{AdminUser, DonauLinzUser, User, UserWithDetails}, | ||||
|     user::{AdminUser, DonauLinzUser, User, UserWithDetails, VorstandUser}, | ||||
| }; | ||||
|  | ||||
| pub struct KioskCookie(()); | ||||
| @@ -68,7 +68,9 @@ async fn index( | ||||
|     ) | ||||
|     .await; | ||||
|     users.retain(|u| { | ||||
|         u.roles.contains(&"Donau Linz".into()) || u.roles.contains(&"scheckbuch".into()) | ||||
|         u.roles.contains(&"Donau Linz".into()) | ||||
|             || u.roles.contains(&"scheckbuch".into()) | ||||
|             || u.user.name == "Externe Steuerperson" | ||||
|     }); | ||||
|  | ||||
|     let logtypes = LogType::all(db).await; | ||||
| @@ -228,6 +230,8 @@ async fn create_logbook( | ||||
|         Err(LogbookCreateError::OnlyAllowedToEndTripsEndingToday) => Flash::error(Redirect::to("/log"), "Nur Ausfahrten, die in der letzten Woche enden dürfen eingetragen werden. Für einen Nachtrag schreibe alle Daten Philipp (Tel. nr. siehe Signal oder it@rudernlinz.at)."), | ||||
|         Err(LogbookCreateError::CantChangeHandoperatableStatusForThisBoat) => Flash::error(Redirect::to("/log"), "Handsteuer-Status dieses Boots kann nicht verändert werden."), | ||||
|         Err(LogbookCreateError::TooFast(km, min)) => Flash::error(Redirect::to("/log"), format!("KM zu groß für die eingegebene Dauer ({km} km in {min} Minuten). Bitte überprüfe deine Start- und Endzeit und versuche es erneut.")), | ||||
|         Err(LogbookCreateError::AlreadyFinalized) => Flash::error(Redirect::to("/log"), "Logbucheintrag wurde bereits abgeschlossen."), | ||||
|         Err(LogbookCreateError::ExternalSteeringPersonMustSteer) => Flash::error(Redirect::to("/log"), "Wenn du eine 'Externe Steuerperson' hinzufügst, muss diese steuern!"), | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -282,10 +286,45 @@ async fn create_kiosk( | ||||
|     create_logbook(db, data, &DonauLinzUser(creator)).await //TODO: fixme | ||||
| } | ||||
|  | ||||
| #[post("/update", data = "<data>")] | ||||
| async fn update( | ||||
|     db: &State<SqlitePool>, | ||||
|     data: Form<LogToUpdate>, | ||||
|     user: VorstandUser, | ||||
| ) -> Flash<Redirect> { | ||||
|     let data = data.into_inner(); | ||||
|  | ||||
|     let Some(logbook) = Logbook::find_by_id(db, data.id).await else { | ||||
|         return Flash::error(Redirect::to("/log"), &format!("Logbucheintrag kann nicht bearbeitet werden, da es einen Logbuch-Eintrag mit ID={} nicht gibt", data.id)); | ||||
|     }; | ||||
|  | ||||
|     match logbook.update(db, data.clone(), &user.0).await { | ||||
|         Ok(()) => { | ||||
|             Log::create( | ||||
|                 db, | ||||
|                 format!( | ||||
|                     "User {} updated log entry={:?} to {:?}", | ||||
|                     &user.name, logbook, data | ||||
|                 ), | ||||
|             ) | ||||
|             .await; | ||||
|  | ||||
|             Flash::success( | ||||
|                 Redirect::to("/log/show"), | ||||
|                 format!("Logbucheintrag erfolgreich bearbeitet"), | ||||
|             ) | ||||
|         } | ||||
|         Err(LogbookAdminUpdateError::NotAllowed) => Flash::error( | ||||
|             Redirect::to("/log/show"), | ||||
|             format!("Du hast keine Erlaubnis, diesen Logbucheintrag zu bearbeiten!"), | ||||
|         ), | ||||
|     } | ||||
| } | ||||
|  | ||||
| async fn home_logbook( | ||||
|     db: &SqlitePool, | ||||
|     data: Form<LogToFinalize>, | ||||
|     logbook_id: i32, | ||||
|     logbook_id: i64, | ||||
|     user: &DonauLinzUser, | ||||
| ) -> Flash<Redirect> { | ||||
|     let logbook: Option<Logbook> = Logbook::find_by_id(db, logbook_id).await; | ||||
| @@ -301,6 +340,8 @@ async fn home_logbook( | ||||
|         Err(LogbookUpdateError::TooManyRowers(expected, actual)) => Flash::error(Redirect::to("/log"), format!("Zu viele Ruderer (Boot fasst maximal {expected}, es wurden jedoch {actual} Ruderer ausgewählt)")), | ||||
|         Err(LogbookUpdateError::OnlyAllowedToEndTripsEndingToday) => Flash::error(Redirect::to("/log"), "Nur Ausfahrten, die heute enden dürfen eingetragen werden. Für einen Nachtrag schreibe alle Daten Philipp (Tel. nr. siehe Signal oder it@rudernlinz.at)."), | ||||
|         Err(LogbookUpdateError::TooFast(km, min)) => Flash::error(Redirect::to("/log"), format!("KM zu groß für die eingegebene Dauer ({km} km in {min} Minuten). Bitte überprüfe deine Start- und Endzeit und versuche es erneut.")), | ||||
|         Err(LogbookUpdateError::AlreadyFinalized) => Flash::error(Redirect::to("/log"), "Logbucheintrag wurde bereits abgeschlossen."), | ||||
|         Err(LogbookUpdateError::ExternalSteeringPersonMustSteer) => Flash::error(Redirect::to("/log"), "Wenn du eine 'Externe Steuerperson' hinzufügst, muss diese steuern!"), | ||||
|         Err(e) => Flash::error( | ||||
|             Redirect::to("/log"), | ||||
|             format!("Eintrag {logbook_id} konnte nicht abgesendet werden (Fehler: {e:?})!"), | ||||
| @@ -312,7 +353,7 @@ async fn home_logbook( | ||||
| async fn home_kiosk( | ||||
|     db: &State<SqlitePool>, | ||||
|     data: Form<LogToFinalize>, | ||||
|     logbook_id: i32, | ||||
|     logbook_id: i64, | ||||
|     _kiosk: KioskCookie, | ||||
| ) -> Flash<Redirect> { | ||||
|     let logbook = Logbook::find_by_id(db, logbook_id).await.unwrap(); //TODO: fixme | ||||
| @@ -340,7 +381,7 @@ async fn home_kiosk( | ||||
| async fn home( | ||||
|     db: &State<SqlitePool>, | ||||
|     data: Form<LogToFinalize>, | ||||
|     logbook_id: i32, | ||||
|     logbook_id: i64, | ||||
|     user: DonauLinzUser, | ||||
| ) -> Flash<Redirect> { | ||||
|     Log::create( | ||||
| @@ -356,7 +397,7 @@ async fn home( | ||||
| } | ||||
|  | ||||
| #[get("/<logbook_id>/delete", rank = 2)] | ||||
| async fn delete(db: &State<SqlitePool>, logbook_id: i32, user: DonauLinzUser) -> Flash<Redirect> { | ||||
| async fn delete(db: &State<SqlitePool>, logbook_id: i64, user: DonauLinzUser) -> Flash<Redirect> { | ||||
|     let logbook = Logbook::find_by_id(db, logbook_id).await; | ||||
|     if let Some(logbook) = logbook { | ||||
|         Log::create( | ||||
| @@ -385,7 +426,7 @@ async fn delete(db: &State<SqlitePool>, logbook_id: i32, user: DonauLinzUser) -> | ||||
| #[get("/<logbook_id>/delete")] | ||||
| async fn delete_kiosk( | ||||
|     db: &State<SqlitePool>, | ||||
|     logbook_id: i32, | ||||
|     logbook_id: i64, | ||||
|     _kiosk: KioskCookie, | ||||
| ) -> Flash<Redirect> { | ||||
|     let logbook = Logbook::find_by_id(db, logbook_id).await; | ||||
| @@ -425,7 +466,8 @@ pub fn routes() -> Vec<Route> { | ||||
|         show_kiosk, | ||||
|         show_for_year, | ||||
|         delete, | ||||
|         delete_kiosk | ||||
|         delete_kiosk, | ||||
|         update | ||||
|     ] | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -36,37 +36,52 @@ | ||||
|                    placeholder="Suchen nach (Name, [yes|no]-role:<name>, has-[no-]membership-pdf)" /> | ||||
|         </div> | ||||
|         <!-- END filterBar --> | ||||
|         <div class="bg-primary-100 dark:bg-primary-950 p-3 rounded-b-md grid gap-4"> | ||||
|             <div id="filter-result-js" | ||||
|                  class="text-primary-950 dark:text-white text-right"></div> | ||||
|             {% for user in users %} | ||||
|                 <div data-filterable="true" | ||||
|                      data-filter="{{ user.name }} {% for role in roles %} {% if role.name in user.roles %} yes-role:{{ role.name }} {% else %} no-role:{{ role.name }} {% endif %} role-{{ role }} {% endfor %} {% if user.membership_pdf %}has-membership-pdf{% else %}has-no-membership-pdf{% endif %} "> | ||||
|         <div id="filter-result-js" class="search-result"></div> | ||||
|         {% for user in users %} | ||||
|             <div data-filterable="true" | ||||
|                  data-filter="{{ user.name }} {% for role in roles %} {% if role.name in user.roles %} yes-role:{{ role.name }} {% else %} no-role:{{ role.name }} {% endif %} role-{{ role }} {% endfor %} {% if user.membership_pdf %}has-membership-pdf{% else %}has-no-membership-pdf{% endif %}" | ||||
|                  class="border-t bg-white dark:bg-primary-900 py-3 px-4 relative"> | ||||
|                 <details class="block dark:text-white w-full"> | ||||
|                     <summary> | ||||
|                         <span class="text-black dark:text-white cursor-pointer"> | ||||
|                             <span class="font-bold"> | ||||
|                                 {{ user.name }} | ||||
|                                 {% if not user.last_access and "admin" in loggedin_user.roles and user.mail %} | ||||
|                                     <form action="/admin/user" | ||||
|                                           method="post" | ||||
|                                           enctype="multipart/form-data" | ||||
|                                           class="inline"> | ||||
|                                         • <a class="font-normal text-primary-600 dark:text-primary-200 hover:text-primary-900 dark:hover:text-primary-300 underline" | ||||
|     href="/admin/user/{{ user.id }}/send-welcome-mail" | ||||
|     onclick="return confirm('Willst du wirklich das Willkommensmail an {{ user.name }} ausschicken?');">Willkommensmail verschicken</a> | ||||
|                                     </form> | ||||
|                                 {% endif %} | ||||
|                                 {% if user.last_access %}• ⏳ {{ user.last_access | date }}{% endif %} | ||||
|                             </span> | ||||
|                             <small class="block text-gray-600 dark:text-gray-100"> | ||||
|                                 {% for role in user.roles -%} | ||||
|                                     {{ role }} | ||||
|                                     {%- if not loop.last %}, {% endif -%} | ||||
|                                 {% endfor %} | ||||
|                             </small> | ||||
|                         </span> | ||||
|                     </summary> | ||||
|                     <form action="/admin/user" | ||||
|                           method="post" | ||||
|                           enctype="multipart/form-data" | ||||
|                           class="bg-white dark:bg-primary-900 p-3 rounded-md w-full"> | ||||
|                         <div class="w-full grid gap-3"> | ||||
|                           class="w-full mt-2"> | ||||
|                         {% if user.pw %} | ||||
|                             <a class="block my-1 font-normal text-[#f43f5e] dark:text-primary-200 hover:text-primary-900 dark:hover:text-primary-300 underline" | ||||
|                                href="/admin/user/{{ user.id }}/reset-pw" | ||||
|                                onclick="return confirm('Willst du wirklich das Passwort zurücksetzen?');">Passwort zurücksetzen</a> | ||||
|                         {% endif %} | ||||
|                         <div class="w-full grid gap-3 mt-3"> | ||||
|                             <input type="hidden" name="id" value="{{ user.id }}" /> | ||||
|                             <div class="font-bold mb-1 text-black dark:text-white"> | ||||
|                                 {{ user.name }} | ||||
|                                 {% if user.last_access %} | ||||
|                                     (last access: | ||||
|                                     {{ user.last_access | date }}) | ||||
|                                 {% endif %} | ||||
|                                 {% if user.pw %} | ||||
|                                     <a class="block mt-1 font-normal text-primary-600 dark:text-primary-200 hover:text-primary-900 dark:hover:text-primary-300 underline" | ||||
|                                        href="/admin/user/{{ user.id }}/reset-pw">Passwort zurücksetzen</a> | ||||
|                                 {% endif %} | ||||
|                                 {% if not user.last_access and "admin" in loggedin_user.roles %} | ||||
|                                     <a class="block mt-1 font-normal text-primary-600 dark:text-primary-200 hover:text-primary-900 dark:hover:text-primary-300 underline" | ||||
|                                        href="/admin/user/{{ user.id }}/send-welcome-mail">Willkommensmail verschicken</a> | ||||
|                                 {% endif %} | ||||
|                             </div> | ||||
|                             <div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-3"> | ||||
|                                 {% for role in roles %} | ||||
|                                     {{ macros::checkbox(label=role.name, name="roles[" ~ role.id ~ "]", id=loop.index , checked=role.name in user.roles, disabled=allowed_to_edit == false) }} | ||||
|                                 {% endfor %} | ||||
|                                 <hr class="sm:col-span-2 lg:col-span-4 my-3" /> | ||||
|                                 {% if user.membership_pdf %} | ||||
|                                     <a href="/admin/user/{{ user.id }}/membership" | ||||
|                                        class="text-black dark:text-white">Beitrittserklärung herunterladen</a> | ||||
| @@ -100,8 +115,8 @@ | ||||
|                             </div> | ||||
|                         {% endif %} | ||||
|                     </form> | ||||
|                 </div> | ||||
|             {% endfor %} | ||||
|         </div> | ||||
|                 </details> | ||||
|             </div> | ||||
|         {% endfor %} | ||||
|     </div> | ||||
| {% endblock content %} | ||||
|   | ||||
| @@ -36,7 +36,7 @@ | ||||
|         <div class="col-span-4 md:col-span-1"> | ||||
|             <div class="text-sm text-gray-600 dark:text-gray-100">Bootssteuerung</div> | ||||
|             <div class="h-10 flex items-center"> | ||||
|                 {{ macros::checkbox(label='handgesteuert', name='shipmaster_only_steering', disabled=true) }} | ||||
|                 {{ macros::checkbox(label='handgesteuert', name='shipmaster_only_steering', readonly=true) }} | ||||
|             </div> | ||||
|         </div> | ||||
|         {{ log::rower_select(id="newrower", selected=[], class="col-span-4", init=true) }} | ||||
| @@ -169,77 +169,101 @@ | ||||
|         </div> | ||||
|     </div> | ||||
| {% endmacro show %} | ||||
| {% macro show_old(log, state, allowed_to_close=false, index) %} | ||||
| {% macro show_old(log, state, allowed_to_close=false, allowed_to_edit=false, index) %} | ||||
|     <div class="border-t bg-white dark:bg-primary-900 py-3 px-4 relative" | ||||
|          data-filterable="true" | ||||
|          data-filter="{{ log.boat.name }} {% for rower in log.rowers %}{{ rower.name }}{% endfor %}"> | ||||
|         {% if log.logtype %} | ||||
|             <div class="absolute top-0 right-0 bg-primary-100 rounded-bl-md text-primary-950 text-xs w-32 px-2 py-1 text-center font-bold"> | ||||
|                 {% if log.logtype == 1 %} | ||||
|                     Wanderfahrt | ||||
|                 {% else %} | ||||
|                     {% if log.logtype == 2 %} | ||||
|                         Regatta | ||||
|                     {% else %} | ||||
|                         {{ log.logtype }} | ||||
|                     {% endif %} | ||||
|                 {% endif %} | ||||
|             </div> | ||||
|         {% endif %} | ||||
|         <div {% if log.logtype %}class="mt-4 sm:mt-0"{% endif %}> | ||||
|             <strong class="text-black dark:text-white">{{ log.boat.name }}</strong> | ||||
|             <small class="text-gray-600 dark:text-gray-100">({{ log.shipmaster_user.name -}} | ||||
|                 {% if log.shipmaster_only_steering %} | ||||
|                     - handgesteuert | ||||
|                 {%- endif -%} | ||||
|             )</small> | ||||
|             <small class="block text-gray-600 dark:text-gray-100"> | ||||
|                 {% if state == "completed" and log.departure | date(format='%d.%m.%Y') == log.arrival | date(format='%d.%m.%Y') %} | ||||
|                     {{ log.departure | date(format='%d.%m.%Y') }} | ||||
|                     ({{ log.departure | date(format='%H:%M') }} | ||||
|                     - | ||||
|                     {{ log.arrival | date(format='%H:%M') }}) | ||||
|                 {% else %} | ||||
|                     {{ log.departure | date(format='%d.%m.%Y (%H:%M)') }} | ||||
|                     {% if state == "completed" %} | ||||
|                         - | ||||
|                         {{ log.arrival | date(format='%d.%m.%Y (%H:%M)') }} | ||||
|                     {% endif %} | ||||
|                 {% endif %} | ||||
|             </small> | ||||
|             {% set amount_rowers = log.rowers | length %} | ||||
|             {% set amount_guests = log.boat.amount_seats - amount_rowers %} | ||||
|             {% if allowed_to_close and state == "on_water" %} | ||||
|                 {{ log::home(log=log) }} | ||||
|             {% else %} | ||||
|                 <div class="text-black dark:text-white"> | ||||
|                     {{ log.destination }} | ||||
|                     {% if state == "completed" %} | ||||
|                         <small class="text-gray-600 dark:text-gray-100">({{ log.distance_in_km }} | ||||
|                         km)</small> | ||||
|                     {% endif %} | ||||
|                     {% if log.comments %}<span class="text-sm italic">- "{{ log.comments }}"</span>{% endif %} | ||||
|                 </div> | ||||
|                 {% if amount_guests > 0 or log.rowers | length > 0 %} | ||||
|                     {% if not log.boat.amount_seats == 1 %} | ||||
|                         <div class="text-sm text-gray-600 dark:text-gray-100"> | ||||
|                             Ruderer: | ||||
|                             {% for rower in log.rowers -%} | ||||
|                                 {{ rower.name }} | ||||
|                                 {%- if rower.id == log.steering_user.id and rower.id != log.shipmaster_user.id %} | ||||
|                                     (Steuerperson){%- endif -%} | ||||
|                                     {%- if not loop.last or amount_guests > 0 and not log.boat.external %},{% endif %} | ||||
|                                 {% endfor -%} | ||||
|                                 {% if amount_guests > 0 and not log.boat.external %} | ||||
|                                     Gäste | ||||
|                                     <small class="text-gray-600 dark:text-gray-100">(ohne Account)</small>: | ||||
|                                     {{ amount_guests }} | ||||
|                                 {% endif %} | ||||
|                             </div> | ||||
|         <details> | ||||
|             <summary style="list-style: none;"> | ||||
|                 {% if log.logtype %} | ||||
|                     <div class="absolute top-0 right-0 bg-primary-100 rounded-bl-md text-primary-950 text-xs w-32 px-2 py-1 text-center font-bold"> | ||||
|                         {% if log.logtype == 1 %} | ||||
|                             Wanderfahrt | ||||
|                         {% else %} | ||||
|                             {% if log.logtype == 2 %} | ||||
|                                 Regatta | ||||
|                             {% else %} | ||||
|                                 {{ log.logtype }} | ||||
|                             {% endif %} | ||||
|                         {% endif %} | ||||
|                     {% endif %} | ||||
|                     </div> | ||||
|                 {% endif %} | ||||
|             </div> | ||||
|                 <div {% if log.logtype %}class="mt-4 sm:mt-0"{% endif %}> | ||||
|                     <strong class="text-black dark:text-white">{{ log.boat.name }}</strong> | ||||
|                     <small class="text-gray-600 dark:text-gray-100">({{ log.shipmaster_user.name -}} | ||||
|                         {% if log.shipmaster_only_steering %} | ||||
|                             - handgesteuert | ||||
|                         {%- endif -%} | ||||
|                     )</small> | ||||
|                     <small class="block text-gray-600 dark:text-gray-100"> | ||||
|                         {% if state == "completed" and log.departure | date(format='%d.%m.%Y') == log.arrival | date(format='%d.%m.%Y') %} | ||||
|                             {{ log.departure | date(format='%d.%m.%Y') }} | ||||
|                             ({{ log.departure | date(format='%H:%M') }} | ||||
|                             - | ||||
|                             {{ log.arrival | date(format='%H:%M') }}) | ||||
|                         {% else %} | ||||
|                             {{ log.departure | date(format='%d.%m.%Y (%H:%M)') }} | ||||
|                             {% if state == "completed" %} | ||||
|                                 - | ||||
|                                 {{ log.arrival | date(format='%d.%m.%Y (%H:%M)') }} | ||||
|                             {% endif %} | ||||
|                         {% endif %} | ||||
|                     </small> | ||||
|                     {% set amount_rowers = log.rowers | length %} | ||||
|                     {% set amount_guests = log.boat.amount_seats - amount_rowers %} | ||||
|                     {% if allowed_to_close and state == "on_water" %} | ||||
|                         {{ log::home(log=log) }} | ||||
|                     {% else %} | ||||
|                         <div class="text-black dark:text-white"> | ||||
|                             {{ log.destination }} | ||||
|                             {% if state == "completed" %} | ||||
|                                 <small class="text-gray-600 dark:text-gray-100">({{ log.distance_in_km }} | ||||
|                                 km)</small> | ||||
|                             {% endif %} | ||||
|                             {% if log.comments %}<span class="text-sm italic">- "{{ log.comments }}"</span>{% endif %} | ||||
|                         </div> | ||||
|                         {% if amount_guests > 0 or log.rowers | length > 0 %} | ||||
|                             {% if not log.boat.amount_seats == 1 %} | ||||
|                                 <div class="text-sm text-gray-600 dark:text-gray-100"> | ||||
|                                     Ruderer: | ||||
|                                     {% for rower in log.rowers -%} | ||||
|                                         {{ rower.name }} | ||||
|                                         {%- if rower.id == log.steering_user.id and rower.id != log.shipmaster_user.id %} | ||||
|                                             (Steuerperson){%- endif -%} | ||||
|                                             {%- if not loop.last or amount_guests > 0 and not log.boat.external %},{% endif %} | ||||
|                                         {% endfor -%} | ||||
|                                         {% if amount_guests > 0 and not log.boat.external %} | ||||
|                                             Gäste | ||||
|                                             <small class="text-gray-600 dark:text-gray-100">(ohne Account)</small>: | ||||
|                                             {{ amount_guests }} | ||||
|                                         {% endif %} | ||||
|                                     </div> | ||||
|                                 {% endif %} | ||||
|                             {% endif %} | ||||
|                         {% endif %} | ||||
|                     </div> | ||||
|                 </summary> | ||||
|                 {% if allowed_to_edit %} | ||||
|                     <form action="/log/update" method="post"> | ||||
|                         <input type="hidden" name="id" value="{{ log.id }}" /> | ||||
|                         <input type="hidden" name="boat_id" value="{{ log.boat_id }}" /> | ||||
|                         <input type="hidden" name="shipmaster" value="{{ log.shipmaster }}" /> | ||||
|                         <input type="hidden" | ||||
|                                name="steering_person" | ||||
|                                value="{{ log.steering_person }}" /> | ||||
|                         <input type="hidden" | ||||
|                                name="shipmaster_only_steering" | ||||
|                                value="{{ log.shipmaster_only_steering }}" /> | ||||
|                         <input type="datetime-local" name="departure" value="{{ log.departure }}" /> | ||||
|                         <input type="datetime-local" name="arrival" value="{{ log.arrival }}" /> | ||||
|                         <input type="hidden" name="destination" value="{{ log.destination }}" /> | ||||
|                         <input type="hidden" name="distance_in_km" value="{{ log.distance_in_km }}" /> | ||||
|                         <input type="hidden" name="comments" value="{{ log.comments }}" /> | ||||
|                         <input type="hidden" name="logtype" value="{{ log.logtype }}" /> | ||||
|                         <input type="submit" value="Updaten" /> | ||||
|                     </form> | ||||
|                 {% endif %} | ||||
|             </details> | ||||
|         </div> | ||||
|     {% endmacro show_old %} | ||||
|     {% macro home(log) %} | ||||
|   | ||||
| @@ -137,7 +137,7 @@ | ||||
|                {% if readonly %}readonly{% endif %}> | ||||
|     </div> | ||||
| {% endmacro input %} | ||||
| {% macro checkbox(label, name, id='', checked=false, class='', disabled=false) %} | ||||
| {% macro checkbox(label, name, id='', checked=false, class='', disabled=false, readonly=false) %} | ||||
|     <label for="{{ name }}{{ id }}" | ||||
|            class="flex items-center cursor-pointer text-black dark:text-white hover:text-gray-900 dark:hover:text-gray-100 {{ class }}"> | ||||
|         <input type="checkbox" | ||||
| @@ -145,6 +145,7 @@ | ||||
|                name="{{ name }}" | ||||
|                {% if checked %}checked{% endif %} | ||||
|                {% if disabled %}disabled{% endif %} | ||||
|                {% if readonly %}readonly="readonly"{% endif %} | ||||
|                class="h-4 w-4 accent-primary-600 dark:accent-primary-200 mr-2" /> | ||||
|         {{ label }} | ||||
|     </label> | ||||
|   | ||||
| @@ -155,6 +155,13 @@ | ||||
|                             <a href="/board/boathouse" | ||||
|                                class="block w-100 py-2 hover:text-primary-600">Bootshaus</a> | ||||
|                         </li> | ||||
|                         <li class="py-1"> | ||||
|                             <a href="/admin/mail" class="block w-100 py-2 hover:text-primary-600">Mail ausschicken</a> | ||||
|                         </li> | ||||
|                         <li class="py-1"> | ||||
|                             <a href="/admin/notification" | ||||
|                                class="block w-100 py-2 hover:text-primary-600">Nachricht ausschreiben</a> | ||||
|                         </li> | ||||
|                     </ul> | ||||
|                 </div> | ||||
|             {% endif %} | ||||
| @@ -169,19 +176,12 @@ | ||||
|                         <li class="py-1"> | ||||
|                             <a href="/admin/user" class="block w-100 py-2 hover:text-primary-600">User</a> | ||||
|                         </li> | ||||
|                         <li class="py-1"> | ||||
|                             <a href="/admin/mail" class="block w-100 py-2 hover:text-primary-600">Mail</a> | ||||
|                         </li> | ||||
|                         <li class="py-1"> | ||||
|                             <a href="/admin/rss" class="block w-100 py-2 hover:text-primary-600">Logs</a> | ||||
|                         </li> | ||||
|                         <li class="py-1"> | ||||
|                             <a href="/admin/list" class="block w-100 py-2 hover:text-primary-600">Fingerabdruck-Liste überprüfen</a> | ||||
|                         </li> | ||||
|                         <li class="py-1"> | ||||
|                             <a href="/admin/notification" | ||||
|                                class="block w-100 py-2 hover:text-primary-600">Nachricht ausschreiben</a> | ||||
|                         </li> | ||||
|                     </ul> | ||||
|                 </div> | ||||
|             {% endif %} | ||||
|   | ||||
| @@ -23,7 +23,15 @@ | ||||
|                        placeholder="Suchen nach Bootsname oder Ruderer..."> | ||||
|             </div> | ||||
|             <div id="filter-result-js" class="search-result"></div> | ||||
|             {% for log in logs %}{{ log::show_old(log=log, state="completed", only_ones=false, index=loop.index) }}{% endfor %} | ||||
|             {% for log in logs %} | ||||
|                 {% set_global allowed_to_edit = false %} | ||||
|                 {% if loggedin_user %} | ||||
|                     {% if "Vorstand" in loggedin_user.roles %} | ||||
|                         {% set_global allowed_to_edit = true %} | ||||
|                     {% endif %} | ||||
|                 {% endif %} | ||||
|                 {{ log::show_old(log=log, state="completed", only_ones=false, index=loop.index, allowed_to_edit=allowed_to_edit) }} | ||||
|             {% endfor %} | ||||
|         </div> | ||||
|     </div> | ||||
|     <script> | ||||
|   | ||||
| @@ -18,8 +18,8 @@ | ||||
|                         <script type="text/javascript"> | ||||
| 				var sepaqr = new sepaQR({ | ||||
| 				   benefName: 'ASKÖ Ruderverein Donau Linz', | ||||
| 				   benefBIC: 'BKAUATWWXXX', | ||||
| 				   benefAccNr: 'AT131200080413001200', | ||||
| 				   benefBIC: 'ASPKAT2LXXX', | ||||
| 				   benefAccNr: 'AT582032032100729256', | ||||
| 				   amountEuro: {{ fee.sum_in_cents/100 }}, | ||||
| 				   remittanceInf: 'Vereinsgebühren {{ fee.name }}', | ||||
| 				 }); | ||||
| @@ -44,13 +44,13 @@ | ||||
|                                 </ul> | ||||
|                             </small> | ||||
|                         {% endif %} | ||||
|                         Bitte auf folgendes Konto überweisen:  IBAN AT13 1200 0804 1300 1200. Alternativ kannst du auch mit deiner Bankapp den QR Code scannen, damit sollten alle Daten vorausgefüllt sein. | ||||
|                         Bitte auf folgendes Konto überweisen:  IBAN AT58 2032 0321 0072 9256. Alternativ kannst du auch mit deiner Bankapp den QR Code scannen, damit sollten alle Daten vorausgefüllt sein. | ||||
|                         <br /> | ||||
|                         Falls die Berechnung nicht stimmt (korrekte Preise findest du <a href="https://rudernlinz.at/unser-verein/gebuhren/" | ||||
|     target="_blank" | ||||
|     rel="noopener noreferrer">hier</a>) melde dich bitte bei it@rudernlinz.at. @Studenten: Bitte die aktuelle Studienbestätigung an it@rudernlinz.at schicken. | ||||
|                         <br /> | ||||
|                         <small>Wir aktualisieren den Ruderassistent unregelmäßig mit unserem Bankkonto. Falls du schon bezahlt hast, kannst du diese Nachricht getrost ignorieren :^)</small> | ||||
|                         <small><a href="https://rudernlinz.at/unser-verein/vorstand/" target="_blank">Unsere Kassiere</a> aktualisieren den Ruderassistent unregelmäßig mit unserem Bankkonto. Falls du schon bezahlt hast, kannst du diese Nachricht getrost ignorieren. Wenn du schon vor "einigen Wochen" bezahlt hast bitte bei kassier@rudernlinz.at nachfragen :^)</small> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
| @@ -391,15 +391,15 @@ | ||||
|         </div> | ||||
|         {# --- START Add Buttons --- #} | ||||
|         {% if "manage_events" in loggedin_user.roles or "cox" in loggedin_user.roles %} | ||||
|             <div class="grid {% if "manage_events" in loggedin_user.roles %}grid-cols-2{% endif %} text-center"> | ||||
|             <div class="grid {% if "manage_events" in loggedin_user.roles and "cox" in loggedin_user.roles %}grid-cols-2{% endif %} text-center"> | ||||
|                 {% 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 rounded-bl-md 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 "cox" in loggedin_user.roles %} | ||||
|                             rounded-bl-md | ||||
|                         {% else %} | ||||
|                             rounded-b-md | ||||
|                         {% endif %} | ||||
|                         "> | ||||
|                         <span class="absolute inset-y-0 left-0 flex items-center pl-3">{% include "includes/plus-icon" %}</span> | ||||
|                         Event | ||||
|                     </a> | ||||
|   | ||||
| @@ -51,7 +51,7 @@ | ||||
|                  data-filter="{{ reservation.user_applicant.name }} {{ reservation.trailer.name }}" | ||||
|                  class="w-full border-t bg-white dark:bg-primary-900 text-black dark:text-white p-3"> | ||||
|                 <div class="w-full"> | ||||
|                     <strong>Boot:</strong> | ||||
|                     <strong>Hänger:</strong> | ||||
|                     {{ reservation.trailer.name }} | ||||
|                     <br /> | ||||
|                     <strong>Reservierung:</strong> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user