53 Commits

Author SHA1 Message Date
a682d1e6ce Merge pull request 'ext person can also be shipmaster (and not cox)' (#656) from fix into main
Some checks failed
CI/CD Pipeline / test (push) Failing after 1m48s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
Reviewed-on: #656
2024-07-28 07:38:06 +02:00
cd1bf12e68 ext person can also be shipmaster (and not cox)
Some checks failed
CI/CD Pipeline / test (push) Failing after 1m41s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
2024-07-28 07:36:57 +02:00
5f7591f52a Merge pull request 'allow external cox; Fix #650' (#654) from external-cox into main
Some checks are pending
CI/CD Pipeline / test (push) Waiting to run
CI/CD Pipeline / deploy-staging (push) Blocked by required conditions
CI/CD Pipeline / deploy-main (push) Blocked by required conditions
Reviewed-on: #654
2024-07-28 07:31:02 +02:00
bf4ea502d3 allow external cox; Fix #650
Some checks failed
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
2024-07-28 07:29:44 +02:00
c13dfdaa77 Merge pull request 'fix spacing in roles' (#652) from fix-spacing into main
Some checks failed
CI/CD Pipeline / deploy-staging (push) Blocked by required conditions
CI/CD Pipeline / deploy-main (push) Blocked by required conditions
CI/CD Pipeline / test (push) Has been cancelled
Reviewed-on: #652
2024-07-28 07:14:29 +02:00
0bc9e11b9a fix spacing in roles
Some checks failed
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
2024-07-28 07:13:21 +02:00
2fdcab9030 Merge pull request 'allow instand logbook add' (#649) from fix-instand-add into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 10m28s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 19m49s
Reviewed-on: #649
2024-07-27 20:49:30 +02:00
b43682ac39 allow instand logbook add
Some checks failed
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
2024-07-27 20:48:32 +02:00
958dda9f52 Merge pull request 'don't allow to finalize a logbook entry more than once' (#644) from only-allow-finalizing-logbook-once into main
Some checks failed
CI/CD Pipeline / deploy-staging (push) Blocked by required conditions
CI/CD Pipeline / deploy-main (push) Blocked by required conditions
CI/CD Pipeline / test (push) Has been cancelled
Reviewed-on: #644
2024-07-26 10:34:57 +02:00
b4b922222c don't allow to finalize a logbook entry more than once
Some checks failed
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
2024-07-26 10:34:14 +02:00
84e76e8d65 Merge pull request 'one more error fix :-)' (#642) from fix into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 10m26s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 6m31s
Reviewed-on: #642
2024-07-24 09:25:19 +02:00
afa88b9529 one more error fix :-)
Some checks failed
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
2024-07-24 09:24:26 +02:00
4229a4e021 Merge pull request 'use proper role name' (#640) from fix into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 9m30s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 6m4s
Reviewed-on: #640
2024-07-24 08:46:40 +02:00
f6207e2994 use proper role name
Some checks failed
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
2024-07-24 08:45:52 +02:00
4da996251a Merge pull request 'better logs' (#637) from update-logbook-entries into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 9m43s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 6m13s
Reviewed-on: #637
2024-07-23 15:15:16 +02:00
aa9568f326 better logs
Some checks failed
CI/CD Pipeline / test (push) Has been cancelled
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
2024-07-23 15:13:36 +02:00
1db09cd8ac Merge pull request 'update logbook entries' (#634) from update-logbook-entries into main
Some checks failed
CI/CD Pipeline / deploy-staging (push) Blocked by required conditions
CI/CD Pipeline / deploy-main (push) Blocked by required conditions
CI/CD Pipeline / test (push) Has been cancelled
Reviewed-on: #634
2024-07-23 15:04:52 +02:00
4a3ee5b551 update logbook entries
Some checks failed
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
2024-07-23 14:57:09 +02:00
c73b3e94c3 Merge pull request 'new text to make clear who's responsible for fee payment' (#632) from new-text into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 9m44s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 5m56s
Reviewed-on: #632
2024-07-23 08:59:05 +02:00
3efcd99bbc new text to make clear who's responsible for fee payment
Some checks failed
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
2024-07-23 08:57:43 +02:00
4f0f509ad6 Merge pull request 'show halfprice for member fees if entry_year == current_year && start_date >= 1.7. Fixes #616' (#629) from halfprice-fee into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 10m16s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 6m33s
Reviewed-on: #629
2024-07-22 21:59:36 +02:00
b1252e8d5c fix empty but non-null date entries
Some checks failed
CI/CD Pipeline / deploy-main (push) Blocked by required conditions
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
2024-07-22 21:56:47 +02:00
a62fd116ea show halfprice for member fees if entry_year == current_year && start_date >= 1.7. Fixes #616
Some checks failed
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
2024-07-22 21:35:07 +02:00
622bc700f3 Merge pull request '[TASK] quick restructure of user screen' (#607) from restructure-user into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 9m57s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 6m59s
Reviewed-on: #607
2024-07-16 17:39:05 +02:00
0e5fd25e61 format tera files
All checks were successful
CI/CD Pipeline / test (push) Successful in 9m42s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
2024-07-16 16:38:12 +01:00
16fbeea81b [BUGFIX] only-event.png
All checks were successful
CI/CD Pipeline / test (push) Successful in 9m25s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
2024-07-16 14:38:27 +02:00
bd6fbe772e [BUGFIX] vorstand-no-admin.png
Some checks failed
CI/CD Pipeline / deploy-staging (push) Blocked by required conditions
CI/CD Pipeline / deploy-main (push) Blocked by required conditions
CI/CD Pipeline / test (push) Has been cancelled
2024-07-16 14:32:40 +02:00
647970e1fc Merge pull request 'fix-steering-only-boat-logentry' (#624) from fix-steering-only-boat-logentry into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 10m18s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 6m33s
Reviewed-on: #624
2024-07-13 21:16:05 +02:00
088fe98995 fix test
All checks were successful
CI/CD Pipeline / test (push) Successful in 10m1s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
2024-07-13 20:03:10 +01:00
4237fafdff fix error, where log entries can't be added with boats with only steering
Some checks failed
CI/CD Pipeline / deploy-staging (push) Blocked by required conditions
CI/CD Pipeline / deploy-main (push) Blocked by required conditions
CI/CD Pipeline / test (push) Has been cancelled
2024-07-13 19:58:13 +01:00
6b24008c17 Merge pull request 'more robust data fetching' (#618) from more-robust-data-fetching into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 9m40s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 6m10s
Reviewed-on: #618
2024-07-10 09:45:15 +02:00
ce8a095b31 more robust data fetching
All checks were successful
CI/CD Pipeline / test (push) Successful in 18m28s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
2024-07-10 09:44:38 +02:00
6c191cf59e Merge pull request 'fix term' (#615) from fix-term into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 9m54s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 6m36s
Reviewed-on: #615
2024-06-27 17:11:15 +02:00
6f7283f754 fix term
All checks were successful
CI/CD Pipeline / test (push) Successful in 10m17s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
2024-06-27 17:10:15 +02:00
323f721fc0 Merge pull request 'order logbook by arrival' (#612) from order-logbook-by-arrival into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 10m21s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 17m57s
Reviewed-on: #612
2024-06-27 08:52:22 +02:00
bd7cd0020e order logbook by arrival
Some checks failed
CI/CD Pipeline / test (push) Has been cancelled
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
2024-06-27 08:51:44 +02:00
22bfe48d18 Merge pull request 'update deps' (#610) from update-deps into main
Some checks failed
CI/CD Pipeline / deploy-staging (push) Blocked by required conditions
CI/CD Pipeline / deploy-main (push) Blocked by required conditions
CI/CD Pipeline / test (push) Has been cancelled
Reviewed-on: #610
2024-06-27 07:59:27 +02:00
3543ffe9e1 update deps
Some checks failed
CI/CD Pipeline / test (push) Has been cancelled
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
2024-06-27 07:58:30 +02:00
1ad6509568 minor visual improvements
All checks were successful
CI/CD Pipeline / test (push) Successful in 10m6s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
2024-06-24 19:56:35 +02:00
dba1e08c5d [TASK] quick restructure of user screen
All checks were successful
CI/CD Pipeline / test (push) Successful in 10m26s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
2024-06-24 16:58:19 +02:00
1dc0c9c0e1 Merge pull request 'update iban' (#605) from update-iban into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 9m52s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 8m28s
Reviewed-on: #605
2024-06-24 15:03:54 +02:00
3dff956544 update iban
Some checks failed
CI/CD Pipeline / test (push) Has been cancelled
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
2024-06-24 15:02:55 +02:00
79f8efc34b Merge pull request 'allow vorstand to send mail + notifications' (#603) from allow-vorstand-to-send-things into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 10m5s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 6m27s
Reviewed-on: #603
2024-06-21 11:25:27 +02:00
3e983e05f9 allow vorstand to send mail + notifications
Some checks failed
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
2024-06-21 11:24:14 +02:00
8f91cc4e88 Merge pull request 'allow vorstand to send mail + notifications' (#601) from allow-vorstand-to-send-things into main
Some checks failed
CI/CD Pipeline / test (push) Failing after 1m36s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
Reviewed-on: #601
2024-06-21 11:15:37 +02:00
76290a64ae allow vorstand to send mail + notifications
Some checks failed
CI/CD Pipeline / test (push) Failing after 1m50s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
2024-06-21 11:14:48 +02:00
4b48fbaa82 Merge pull request 'update deps' (#599) from update-deps into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 9m39s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 18m11s
Reviewed-on: #599
2024-06-19 13:44:08 +02:00
def8affb5f update deps
Some checks failed
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
2024-06-19 13:43:04 +02:00
dfa7be9928 Merge pull request 'fix migration' (#597) from fix-migration into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 9m13s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 6m26s
Reviewed-on: #597
2024-06-16 20:15:58 +02:00
1c04462c30 Merge pull request 'add more life to the mails :-)' (#595) from more-sympatic-welcome-mail into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 10m11s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Successful in 6m40s
Reviewed-on: #595
2024-06-15 18:28:24 +02:00
b2393eb6ec mb is too serious
Some checks failed
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
2024-06-15 18:27:09 +02:00
a5e82851ba fix missing word
All checks were successful
CI/CD Pipeline / test (push) Successful in 9m41s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
2024-06-10 22:23:26 +02:00
80725e223b add more life to the mails :-)
Some checks are pending
CI/CD Pipeline / test (push) Waiting to run
CI/CD Pipeline / deploy-staging (push) Blocked by required conditions
CI/CD Pipeline / deploy-main (push) Blocked by required conditions
2024-06-10 22:17:41 +02:00
19 changed files with 546 additions and 259 deletions

194
Cargo.lock generated
View File

@ -175,7 +175,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
] ]
[[package]] [[package]]
@ -186,7 +186,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
] ]
[[package]] [[package]]
@ -221,9 +221,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]] [[package]]
name = "backtrace" name = "backtrace"
version = "0.3.72" version = "0.3.73"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
dependencies = [ dependencies = [
"addr2line", "addr2line",
"cc", "cc",
@ -266,9 +266,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.5.0" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@ -309,9 +309,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.16.0" version = "1.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@ -327,9 +327,9 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.98" version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" checksum = "ac367972e516d45567c7eafc73d24e1c193dcf200a8d94e9db7b3d38b349572d"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -620,11 +620,11 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a" checksum = "35b50dba0afdca80b187392b24f2499a88c336d5a8493e4b4ccfb608708be56a"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags 2.6.0",
"proc-macro2", "proc-macro2",
"proc-macro2-diagnostics", "proc-macro2-diagnostics",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
] ]
[[package]] [[package]]
@ -647,9 +647,9 @@ checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
[[package]] [[package]]
name = "either" name = "either"
version = "1.12.0" version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@ -785,7 +785,7 @@ checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"spin 0.9.8", "spin",
] ]
[[package]] [[package]]
@ -894,7 +894,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
] ]
[[package]] [[package]]
@ -992,8 +992,8 @@ dependencies = [
"aho-corasick", "aho-corasick",
"bstr", "bstr",
"log", "log",
"regex-automata 0.4.6", "regex-automata 0.4.7",
"regex-syntax 0.8.3", "regex-syntax 0.8.4",
] ]
[[package]] [[package]]
@ -1002,7 +1002,7 @@ version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags 2.6.0",
"ignore", "ignore",
"walkdir", "walkdir",
] ]
@ -1139,9 +1139,9 @@ dependencies = [
[[package]] [[package]]
name = "httparse" name = "httparse"
version = "1.8.0" version = "1.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9"
[[package]] [[package]]
name = "httpdate" name = "httpdate"
@ -1237,7 +1237,7 @@ dependencies = [
"globset", "globset",
"log", "log",
"memchr", "memchr",
"regex-automata 0.4.6", "regex-automata 0.4.7",
"same-file", "same-file",
"walkdir", "walkdir",
"winapi-util", "winapi-util",
@ -1306,15 +1306,6 @@ version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
[[package]]
name = "itertools"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
dependencies = [
"either",
]
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.13.0" version = "0.13.0"
@ -1372,11 +1363,11 @@ dependencies = [
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
dependencies = [ dependencies = [
"spin 0.5.2", "spin",
] ]
[[package]] [[package]]
@ -1485,9 +1476,9 @@ dependencies = [
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.2" version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]] [[package]]
name = "mime" name = "mime"
@ -1503,9 +1494,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.7.3" version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
dependencies = [ dependencies = [
"adler", "adler",
] ]
@ -1535,7 +1526,7 @@ dependencies = [
"httparse", "httparse",
"memchr", "memchr",
"mime", "mime",
"spin 0.9.8", "spin",
"tokio", "tokio",
"tokio-util", "tokio-util",
"version_check", "version_check",
@ -1583,7 +1574,7 @@ version = "6.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags 2.6.0",
"crossbeam-channel", "crossbeam-channel",
"filetime", "filetime",
"fsevent-sys", "fsevent-sys",
@ -1671,9 +1662,9 @@ dependencies = [
[[package]] [[package]]
name = "object" name = "object"
version = "0.35.0" version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -1696,7 +1687,7 @@ version = "0.10.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags 2.6.0",
"cfg-if", "cfg-if",
"foreign-types", "foreign-types",
"libc", "libc",
@ -1713,7 +1704,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
] ]
[[package]] [[package]]
@ -1768,7 +1759,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"redox_syscall 0.5.1", "redox_syscall 0.5.2",
"smallvec", "smallvec",
"windows-targets 0.52.5", "windows-targets 0.52.5",
] ]
@ -1819,7 +1810,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"proc-macro2-diagnostics", "proc-macro2-diagnostics",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
] ]
[[package]] [[package]]
@ -1868,7 +1859,7 @@ dependencies = [
"pest_meta", "pest_meta",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
] ]
[[package]] [[package]]
@ -1985,9 +1976,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.85" version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -2000,7 +1991,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
"version_check", "version_check",
"yansi", "yansi",
] ]
@ -2076,11 +2067,11 @@ dependencies = [
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.5.1" version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags 2.6.0",
] ]
[[package]] [[package]]
@ -2100,19 +2091,19 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
] ]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.10.4" version = "1.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
"regex-automata 0.4.6", "regex-automata 0.4.7",
"regex-syntax 0.8.3", "regex-syntax 0.8.4",
] ]
[[package]] [[package]]
@ -2126,13 +2117,13 @@ dependencies = [
[[package]] [[package]]
name = "regex-automata" name = "regex-automata"
version = "0.4.6" version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
"regex-syntax 0.8.3", "regex-syntax 0.8.4",
] ]
[[package]] [[package]]
@ -2143,9 +2134,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.8.3" version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]] [[package]]
name = "ring" name = "ring"
@ -2157,7 +2148,7 @@ dependencies = [
"cfg-if", "cfg-if",
"getrandom", "getrandom",
"libc", "libc",
"spin 0.9.8", "spin",
"untrusted", "untrusted",
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
@ -2211,7 +2202,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"rocket_http", "rocket_http",
"syn 2.0.66", "syn 2.0.68",
"unicode-xid", "unicode-xid",
"version_check", "version_check",
] ]
@ -2267,7 +2258,7 @@ dependencies = [
"env_logger", "env_logger",
"futures", "futures",
"ics", "ics",
"itertools 0.13.0", "itertools",
"job_scheduler_ng", "job_scheduler_ng",
"lettre", "lettre",
"log", "log",
@ -2314,7 +2305,7 @@ version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags 2.6.0",
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
@ -2440,7 +2431,7 @@ version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags 2.6.0",
"core-foundation", "core-foundation",
"core-foundation-sys", "core-foundation-sys",
"libc", "libc",
@ -2474,14 +2465,14 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.117" version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -2588,12 +2579,6 @@ dependencies = [
"windows-sys 0.52.0", "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]] [[package]]
name = "spin" name = "spin"
version = "0.9.8" version = "0.9.8"
@ -2615,11 +2600,10 @@ dependencies = [
[[package]] [[package]]
name = "sqlformat" name = "sqlformat"
version = "0.2.3" version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f"
dependencies = [ dependencies = [
"itertools 0.12.1",
"nom", "nom",
"unicode_categories", "unicode_categories",
] ]
@ -2728,7 +2712,7 @@ checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418"
dependencies = [ dependencies = [
"atoi", "atoi",
"base64 0.21.7", "base64 0.21.7",
"bitflags 2.5.0", "bitflags 2.6.0",
"byteorder", "byteorder",
"bytes", "bytes",
"chrono", "chrono",
@ -2772,7 +2756,7 @@ checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e"
dependencies = [ dependencies = [
"atoi", "atoi",
"base64 0.21.7", "base64 0.21.7",
"bitflags 2.5.0", "bitflags 2.6.0",
"byteorder", "byteorder",
"chrono", "chrono",
"crc", "crc",
@ -2873,9 +2857,9 @@ dependencies = [
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.5.0" version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]] [[package]]
name = "syn" name = "syn"
@ -2890,9 +2874,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.66" version = "2.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2950,7 +2934,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
] ]
[[package]] [[package]]
@ -2996,9 +2980,9 @@ dependencies = [
[[package]] [[package]]
name = "tinyvec" name = "tinyvec"
version = "1.6.0" version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82"
dependencies = [ dependencies = [
"tinyvec_macros", "tinyvec_macros",
] ]
@ -3035,7 +3019,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
] ]
[[package]] [[package]]
@ -3122,7 +3106,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
] ]
[[package]] [[package]]
@ -3328,14 +3312,14 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"url", "url",
"webpki-roots 0.26.2", "webpki-roots 0.26.3",
] ]
[[package]] [[package]]
name = "url" name = "url"
version = "2.5.0" version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
dependencies = [ dependencies = [
"form_urlencoded", "form_urlencoded",
"idna", "idna",
@ -3350,15 +3334,15 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]] [[package]]
name = "utf8parse" name = "utf8parse"
version = "0.2.1" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.8.0" version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439"
dependencies = [ dependencies = [
"getrandom", "getrandom",
] ]
@ -3433,7 +3417,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3455,7 +3439,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -3474,9 +3458,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
[[package]] [[package]]
name = "webpki-roots" name = "webpki-roots"
version = "0.26.2" version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c452ad30530b54a4d8e71952716a212b08efd0f3562baa66c29a618b07da7c3" checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd"
dependencies = [ dependencies = [
"rustls-pki-types", "rustls-pki-types",
] ]
@ -3691,9 +3675,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.6.11" version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c52728401e1dc672a56e81e593e912aa54c78f40246869f78359a2bf24d29d" checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -3724,7 +3708,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.66", "syn 2.0.68",
] ]
[[package]] [[package]]

View File

@ -158,9 +158,9 @@ function selectBoatChange() {
} }
if (event.detail.customProperties.convert_handoperated_possible) { if (event.detail.customProperties.convert_handoperated_possible) {
only_steering.removeAttribute('disabled'); only_steering.removeAttribute('readonly');
}else { }else {
only_steering.setAttribute('disabled', 'disabled'); only_steering.setAttribute('readonly', 'readonly');
} }
const destination = <HTMLSelectElement>( const destination = <HTMLSelectElement>(

View File

@ -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('Ottensheim (25 km)');
await expect(page.locator('body')).toContainText('Ruderer: cox2, rower2'); 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');
});

View File

@ -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 ('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) 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, 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 ('Wanderfahrt');
INSERT INTO "logbook_type" (name) VALUES ('Regatta'); 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'); INSERT INTO "logbook" (boat_id, shipmaster,steering_person, shipmaster_only_steering, departure) VALUES (2, 2, 2, false, strftime('%Y', 'now') || '-12-24 10:00');

View File

@ -60,6 +60,22 @@ pub struct LogToFinalize {
pub rowers: Vec<i64>, 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 { impl TryFrom<LogToAdd> for LogToFinalize {
type Error = String; type Error = String;
@ -94,6 +110,11 @@ pub struct LogbookWithBoatAndRowers {
pub rowers: Vec<User>, pub rowers: Vec<User>,
} }
#[derive(Debug, PartialEq)]
pub enum LogbookAdminUpdateError {
NotAllowed,
}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum LogbookUpdateError { pub enum LogbookUpdateError {
NotYourEntry, NotYourEntry,
@ -105,6 +126,8 @@ pub enum LogbookUpdateError {
UserNotAllowedToUseBoat, UserNotAllowedToUseBoat,
OnlyAllowedToEndTripsEndingToday, OnlyAllowedToEndTripsEndingToday,
TooFast(i64, i64), TooFast(i64, i64),
AlreadyFinalized,
ExternalSteeringPersonMustSteerOrShipmaster,
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -129,6 +152,8 @@ pub enum LogbookCreateError {
OnlyAllowedToEndTripsEndingToday, OnlyAllowedToEndTripsEndingToday,
CantChangeHandoperatableStatusForThisBoat, CantChangeHandoperatableStatusForThisBoat,
TooFast(i64, i64), TooFast(i64, i64),
AlreadyFinalized,
ExternalSteeringPersonMustSteerOrShipmaster,
} }
impl From<LogbookUpdateError> for LogbookCreateError { impl From<LogbookUpdateError> for LogbookCreateError {
@ -153,6 +178,10 @@ impl From<LogbookUpdateError> for LogbookCreateError {
LogbookCreateError::OnlyAllowedToEndTripsEndingToday LogbookCreateError::OnlyAllowedToEndTripsEndingToday
} }
LogbookUpdateError::TooFast(km, min) => LogbookCreateError::TooFast(km, min), LogbookUpdateError::TooFast(km, min) => LogbookCreateError::TooFast(km, min),
LogbookUpdateError::AlreadyFinalized => LogbookCreateError::AlreadyFinalized,
LogbookUpdateError::ExternalSteeringPersonMustSteer => {
LogbookCreateError::ExternalSteeringPersonMustSteer
}
} }
} }
} }
@ -172,7 +201,7 @@ impl Logbook {
.await .await
.ok() .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!( sqlx::query_as!(
Self, Self,
" "
@ -242,7 +271,7 @@ ORDER BY departure DESC
FROM logbook FROM logbook
JOIN rower ON logbook.id = rower.logbook_id JOIN rower ON logbook.id = rower.logbook_id
WHERE arrival is not null AND rower_id = {} WHERE arrival is not null AND rower_id = {}
ORDER BY departure DESC ORDER BY arrival DESC
", user.id) ", user.id)
) )
.fetch_all(db) .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 SELECT id, boat_id, shipmaster, steering_person, shipmaster_only_steering, departure, arrival, destination, distance_in_km, comments, logtype
FROM logbook FROM logbook
WHERE arrival is not null AND arrival LIKE '{}-%' WHERE arrival is not null AND arrival LIKE '{}-%'
ORDER BY departure DESC ORDER BY arrival DESC
", year) ", year)
) )
.fetch_all(db) .fetch_all(db)
@ -329,13 +358,12 @@ ORDER BY departure DESC
let mut tx = db.begin().await.unwrap(); let mut tx = db.begin().await.unwrap();
let inserted_row = sqlx::query!( 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.boat_id,
log.shipmaster, log.shipmaster,
log.steering_person, log.steering_person,
log.shipmaster_only_steering, log.shipmaster_only_steering,
log.departure, log.departure,
log.arrival,
log.destination, log.destination,
log.distance_in_km, log.distance_in_km,
log.comments, log.comments,
@ -391,6 +419,18 @@ ORDER BY departure DESC
if user.on_water(db).await { if user.on_water(db).await {
return Err(LogbookCreateError::RowerAlreadyOnWater(Box::new(user))); return Err(LogbookCreateError::RowerAlreadyOnWater(Box::new(user)));
} }
if user.name == "Externe Steuerperson" {
if let (Some(steering_id), Some(shipmaster_id)) =
(log.steering_person, log.shipmaster)
{
if steering_id != user.id && shipmaster_id != user.id {
return Err(
LogbookCreateError::ExternalSteeringPersonMustSteerOrShipmaster,
);
}
}
}
} }
if !boat.shipmaster_allowed(db, created_by_user).await { if !boat.shipmaster_allowed(db, created_by_user).await {
@ -437,6 +477,35 @@ ORDER BY departure DESC
Ok(ret) 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)> { 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;") 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) .fetch_all(db)
@ -496,6 +565,10 @@ ORDER BY departure DESC
return Err(LogbookUpdateError::NotYourEntry); 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 let boat = Boat::find_by_id_tx(db, self.boat_id as i32).await.unwrap(); //ok
if boat.amount_seats == 1 { if boat.amount_seats == 1 {
@ -553,6 +626,18 @@ ORDER BY departure DESC
self.remove_rowers(db).await; self.remove_rowers(db).await;
for rower in &log.rowers { for rower in &log.rowers {
if user.name == "Externe Steuerperson" {
if let (Some(steering_id), Some(shipmaster_id)) =
(log.steering_person, log.shipmaster)
{
if steering_id != user.id && shipmaster_id != user.id {
return Err(
LogbookUpdateError::ExternalSteeringPersonMustSteerOrShipmaster,
);
}
}
}
Rower::create(db, self.id, *rower) Rower::create(db, self.id, *rower)
.await .await
.map_err(|e| LogbookUpdateError::RowerCreateError(*rower, e.to_string()))?; .map_err(|e| LogbookUpdateError::RowerCreateError(*rower, e.to_string()))?;

View File

@ -182,7 +182,7 @@ dein Vereinsbeitrag für das aktuelle Jahr beträgt {}€",
fees.name 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\ 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 Wenn du die Vereinsgebühren schon bezahlt hast, kannst du diese Mail einfach ignorieren.\n\n
Beste Grüße\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\ 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. 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\ Mit freundlichen Grüßen,\n\
Der Vorstand"); Der Vorstand");

View File

@ -213,7 +213,7 @@ ORDER BY day;",
pub(crate) async fn user_allowed_to_change(&self, db: &SqlitePool, user: &User) -> bool { pub(crate) async fn user_allowed_to_change(&self, db: &SqlitePool, user: &User) -> bool {
if self.belongs_to_event(db).await { if self.belongs_to_event(db).await {
user.has_role(db, "planned_event").await user.has_role(db, "manage_events").await
} else { } else {
self.user_is_cox(db, user).await != CoxAtTrip::No self.user_is_cox(db, user).await != CoxAtTrip::No
} }

View File

@ -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. 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 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. 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! 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 { if self.has_role(db, "Unterstützend").await {
fee.add("Unterstützendes Mitglied".into(), UNTERSTUETZEND); fee.add("Unterstützendes Mitglied".into(), UNTERSTUETZEND);
} else if self.has_role(db, "Förderndes Mitglied").await { } else if self.has_role(db, "Förderndes Mitglied").await {
fee.add("Förderndes Mitglied".into(), FOERDERND); fee.add("Förderndes Mitglied".into(), FOERDERND);
} else if Family::find_by_opt_id(db, self.family_id).await.is_none() { } 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 { 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 { } else if self.has_role(db, "Ehrenmitglied").await {
fee.add("Ehrenmitglied".into(), 0); fee.add("Ehrenmitglied".into(), 0);
} else { } else {
fee.add("Mitgliedsbeitrag".into(), REGULAR); if halfprice {
fee.add("Mitgliedsbeitrag (Halbpreis)".into(), REGULAR / 2);
} else {
fee.add("Mitgliedsbeitrag".into(), REGULAR);
}
} }
} }

View File

@ -14,8 +14,12 @@ pub fn schedule(db: &SqlitePool, config: &Config) {
let openweathermap_key = config.openweathermap_key.clone(); let openweathermap_key = config.openweathermap_key.clone();
tokio::task::spawn(async { tokio::task::spawn(async {
waterlevel::update(&db).await.unwrap(); if let Err(e) = waterlevel::update(&db).await {
weather::update(&db, &openweathermap_key).await.unwrap(); 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(); let mut sched = JobScheduler::new();
@ -26,10 +30,12 @@ pub fn schedule(db: &SqlitePool, config: &Config) {
// nicer one's rust (stable) support async closures // nicer one's rust (stable) support async closures
task::block_in_place(|| { task::block_in_place(|| {
tokio::runtime::Handle::current().block_on(async { tokio::runtime::Handle::current().block_on(async {
waterlevel::update(&db_clone).await.unwrap(); if let Err(e) = waterlevel::update(&db_clone).await {
weather::update(&db_clone, &openweathermap_key) log::error!("Water level update error: {e}, trying again next time");
.await }
.unwrap(); if let Err(e) = weather::update(&db_clone, &openweathermap_key).await {
log::error!("Weather update error: {e}, trying again next time");
}
}); });
}); });
})); }));

View File

@ -9,14 +9,14 @@ use sqlx::SqlitePool;
use crate::model::log::Log; use crate::model::log::Log;
use crate::model::mail::Mail; use crate::model::mail::Mail;
use crate::model::role::Role; use crate::model::role::Role;
use crate::model::user::AdminUser;
use crate::model::user::UserWithDetails; use crate::model::user::UserWithDetails;
use crate::model::user::{AdminUser, VorstandUser};
use crate::tera::Config; use crate::tera::Config;
#[get("/mail")] #[get("/mail")]
async fn index( async fn index(
db: &State<SqlitePool>, db: &State<SqlitePool>,
admin: AdminUser, admin: VorstandUser,
flash: Option<FlashMessage<'_>>, flash: Option<FlashMessage<'_>>,
) -> Template { ) -> Template {
let mut context = Context::new(); let mut context = Context::new();
@ -27,7 +27,7 @@ async fn index(
context.insert( context.insert(
"loggedin_user", "loggedin_user",
&UserWithDetails::from_user(admin.user, db).await, &UserWithDetails::from_user(admin.0, db).await,
); );
context.insert("roles", &roles); context.insert("roles", &roles);
@ -65,7 +65,7 @@ async fn update(
db: &State<SqlitePool>, db: &State<SqlitePool>,
data: Form<MailToSend<'_>>, data: Form<MailToSend<'_>>,
config: &State<Config>, config: &State<Config>,
admin: AdminUser, admin: VorstandUser,
) -> Flash<Redirect> { ) -> Flash<Redirect> {
let d = data.into_inner(); let d = data.into_inner();
Log::create(db, format!("{admin:?} trying to send this mail: {d:?}")).await; Log::create(db, format!("{admin:?} trying to send this mail: {d:?}")).await;

View File

@ -2,7 +2,7 @@ use crate::model::{
log::Log, log::Log,
notification::Notification, notification::Notification,
role::Role, role::Role,
user::{AdminUser, User, UserWithDetails}, user::{User, UserWithDetails, VorstandUser},
}; };
use itertools::Itertools; use itertools::Itertools;
use rocket::{ use rocket::{
@ -18,7 +18,7 @@ use sqlx::SqlitePool;
#[get("/notification")] #[get("/notification")]
async fn index( async fn index(
db: &State<SqlitePool>, db: &State<SqlitePool>,
user: AdminUser, user: VorstandUser,
flash: Option<FlashMessage<'_>>, flash: Option<FlashMessage<'_>>,
) -> Template { ) -> Template {
let mut context = Context::new(); let mut context = Context::new();
@ -27,7 +27,7 @@ async fn index(
} }
context.insert( context.insert(
"loggedin_user", "loggedin_user",
&UserWithDetails::from_user(user.user, db).await, &UserWithDetails::from_user(user.0, db).await,
); );
let users: Vec<User> = User::all(db) let users: Vec<User> = User::all(db)
@ -62,7 +62,7 @@ pub struct NotificationToSendUser {
async fn send_group( async fn send_group(
db: &State<SqlitePool>, db: &State<SqlitePool>,
data: Form<NotificationToSendGroup>, data: Form<NotificationToSendGroup>,
admin: AdminUser, admin: VorstandUser,
) -> Flash<Redirect> { ) -> Flash<Redirect> {
let d = data.into_inner(); let d = data.into_inner();
Log::create( Log::create(
@ -89,7 +89,7 @@ async fn send_group(
async fn send_user( async fn send_user(
db: &State<SqlitePool>, db: &State<SqlitePool>,
data: Form<NotificationToSendUser>, data: Form<NotificationToSendUser>,
admin: AdminUser, admin: VorstandUser,
) -> Flash<Redirect> { ) -> Flash<Redirect> {
let d = data.into_inner(); let d = data.into_inner();
Log::create( Log::create(

View File

@ -20,11 +20,11 @@ use crate::model::{
boatreservation::BoatReservation, boatreservation::BoatReservation,
log::Log, log::Log,
logbook::{ logbook::{
LogToAdd, LogToFinalize, Logbook, LogbookCreateError, LogbookDeleteError, LogToAdd, LogToFinalize, LogToUpdate, Logbook, LogbookAdminUpdateError, LogbookCreateError,
LogbookUpdateError, LogbookDeleteError, LogbookUpdateError,
}, },
logtype::LogType, logtype::LogType,
user::{AdminUser, DonauLinzUser, User, UserWithDetails}, user::{AdminUser, DonauLinzUser, User, UserWithDetails, VorstandUser},
}; };
pub struct KioskCookie(()); pub struct KioskCookie(());
@ -68,7 +68,9 @@ async fn index(
) )
.await; .await;
users.retain(|u| { 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; 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::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::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::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::ExternalSteeringPersonMustSteerOrShipmaster) => Flash::error(Redirect::to("/log"), "Wenn du eine 'Externe Steuerperson' hinzufügst, muss diese steuern oder Schiffsführer sein!"),
} }
} }
@ -282,10 +286,45 @@ async fn create_kiosk(
create_logbook(db, data, &DonauLinzUser(creator)).await //TODO: fixme 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( async fn home_logbook(
db: &SqlitePool, db: &SqlitePool,
data: Form<LogToFinalize>, data: Form<LogToFinalize>,
logbook_id: i32, logbook_id: i64,
user: &DonauLinzUser, user: &DonauLinzUser,
) -> Flash<Redirect> { ) -> Flash<Redirect> {
let logbook: Option<Logbook> = Logbook::find_by_id(db, logbook_id).await; 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::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::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::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::ExternalSteeringPersonMustSteerOrShipmaster) => Flash::error(Redirect::to("/log"), "Wenn du eine 'Externe Steuerperson' hinzufügst, muss diese steuern oder Schiffsführer sein!"),
Err(e) => Flash::error( Err(e) => Flash::error(
Redirect::to("/log"), Redirect::to("/log"),
format!("Eintrag {logbook_id} konnte nicht abgesendet werden (Fehler: {e:?})!"), format!("Eintrag {logbook_id} konnte nicht abgesendet werden (Fehler: {e:?})!"),
@ -312,7 +353,7 @@ async fn home_logbook(
async fn home_kiosk( async fn home_kiosk(
db: &State<SqlitePool>, db: &State<SqlitePool>,
data: Form<LogToFinalize>, data: Form<LogToFinalize>,
logbook_id: i32, logbook_id: i64,
_kiosk: KioskCookie, _kiosk: KioskCookie,
) -> Flash<Redirect> { ) -> Flash<Redirect> {
let logbook = Logbook::find_by_id(db, logbook_id).await.unwrap(); //TODO: fixme let logbook = Logbook::find_by_id(db, logbook_id).await.unwrap(); //TODO: fixme
@ -340,7 +381,7 @@ async fn home_kiosk(
async fn home( async fn home(
db: &State<SqlitePool>, db: &State<SqlitePool>,
data: Form<LogToFinalize>, data: Form<LogToFinalize>,
logbook_id: i32, logbook_id: i64,
user: DonauLinzUser, user: DonauLinzUser,
) -> Flash<Redirect> { ) -> Flash<Redirect> {
Log::create( Log::create(
@ -356,7 +397,7 @@ async fn home(
} }
#[get("/<logbook_id>/delete", rank = 2)] #[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; let logbook = Logbook::find_by_id(db, logbook_id).await;
if let Some(logbook) = logbook { if let Some(logbook) = logbook {
Log::create( Log::create(
@ -385,7 +426,7 @@ async fn delete(db: &State<SqlitePool>, logbook_id: i32, user: DonauLinzUser) ->
#[get("/<logbook_id>/delete")] #[get("/<logbook_id>/delete")]
async fn delete_kiosk( async fn delete_kiosk(
db: &State<SqlitePool>, db: &State<SqlitePool>,
logbook_id: i32, logbook_id: i64,
_kiosk: KioskCookie, _kiosk: KioskCookie,
) -> Flash<Redirect> { ) -> Flash<Redirect> {
let logbook = Logbook::find_by_id(db, logbook_id).await; let logbook = Logbook::find_by_id(db, logbook_id).await;
@ -425,7 +466,8 @@ pub fn routes() -> Vec<Route> {
show_kiosk, show_kiosk,
show_for_year, show_for_year,
delete, delete,
delete_kiosk delete_kiosk,
update
] ]
} }

View File

@ -36,37 +36,52 @@
placeholder="Suchen nach (Name, [yes|no]-role:<name>, has-[no-]membership-pdf)" /> placeholder="Suchen nach (Name, [yes|no]-role:<name>, has-[no-]membership-pdf)" />
</div> </div>
<!-- END filterBar --> <!-- 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="search-result"></div>
<div id="filter-result-js" {% for user in users %}
class="text-primary-950 dark:text-white text-right"></div> <div data-filterable="true"
{% for user in users %} 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 data-filterable="true" class="border-t bg-white dark:bg-primary-900 py-3 px-4 relative">
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 %} "> <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">
&bullet; <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 %}&bullet; ⏳&nbsp;{{ 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" <form action="/admin/user"
method="post" method="post"
enctype="multipart/form-data" enctype="multipart/form-data"
class="bg-white dark:bg-primary-900 p-3 rounded-md w-full"> class="w-full mt-2">
<div class="w-full grid gap-3"> {% 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 }}" /> <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"> <div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-3">
{% for role in roles %} {% 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) }} {{ macros::checkbox(label=role.name, name="roles[" ~ role.id ~ "]", id=loop.index , checked=role.name in user.roles, disabled=allowed_to_edit == false) }}
{% endfor %} {% endfor %}
<hr class="sm:col-span-2 lg:col-span-4 my-3" />
{% if user.membership_pdf %} {% if user.membership_pdf %}
<a href="/admin/user/{{ user.id }}/membership" <a href="/admin/user/{{ user.id }}/membership"
class="text-black dark:text-white">Beitrittserklärung herunterladen</a> class="text-black dark:text-white">Beitrittserklärung herunterladen</a>
@ -100,8 +115,8 @@
</div> </div>
{% endif %} {% endif %}
</form> </form>
</div> </details>
{% endfor %} </div>
</div> {% endfor %}
</div> </div>
{% endblock content %} {% endblock content %}

View File

@ -36,7 +36,7 @@
<div class="col-span-4 md:col-span-1"> <div class="col-span-4 md:col-span-1">
<div class="text-sm text-gray-600 dark:text-gray-100">Bootssteuerung</div> <div class="text-sm text-gray-600 dark:text-gray-100">Bootssteuerung</div>
<div class="h-10 flex items-center"> <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>
</div> </div>
{{ log::rower_select(id="newrower", selected=[], class="col-span-4", init=true) }} {{ log::rower_select(id="newrower", selected=[], class="col-span-4", init=true) }}
@ -169,77 +169,101 @@
</div> </div>
</div> </div>
{% endmacro show %} {% 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" <div class="border-t bg-white dark:bg-primary-900 py-3 px-4 relative"
data-filterable="true" data-filterable="true"
data-filter="{{ log.boat.name }} {% for rower in log.rowers %}{{ rower.name }}{% endfor %}"> data-filter="{{ log.boat.name }} {% for rower in log.rowers %}{{ rower.name }}{% endfor %}">
{% if log.logtype %} <details>
<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"> <summary style="list-style: none;">
{% if log.logtype == 1 %} {% if log.logtype %}
Wanderfahrt <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">
{% else %} {% if log.logtype == 1 %}
{% if log.logtype == 2 %} Wanderfahrt
Regatta {% else %}
{% else %} {% if log.logtype == 2 %}
{{ log.logtype }} Regatta
{% endif %} {% else %}
{% endif %} {{ log.logtype }}
</div> {% endif %}
{% 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>
{% endif %} {% endif %}
{% endif %} </div>
{% endif %} {% 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> </div>
{% endmacro show_old %} {% endmacro show_old %}
{% macro home(log) %} {% macro home(log) %}

View File

@ -137,7 +137,7 @@
{% if readonly %}readonly{% endif %}> {% if readonly %}readonly{% endif %}>
</div> </div>
{% endmacro input %} {% 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 }}" <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 }}"> class="flex items-center cursor-pointer text-black dark:text-white hover:text-gray-900 dark:hover:text-gray-100 {{ class }}">
<input type="checkbox" <input type="checkbox"
@ -145,6 +145,7 @@
name="{{ name }}" name="{{ name }}"
{% if checked %}checked{% endif %} {% if checked %}checked{% endif %}
{% if disabled %}disabled{% endif %} {% if disabled %}disabled{% endif %}
{% if readonly %}readonly="readonly"{% endif %}
class="h-4 w-4 accent-primary-600 dark:accent-primary-200 mr-2" /> class="h-4 w-4 accent-primary-600 dark:accent-primary-200 mr-2" />
{{ label }} {{ label }}
</label> </label>

View File

@ -155,6 +155,13 @@
<a href="/board/boathouse" <a href="/board/boathouse"
class="block w-100 py-2 hover:text-primary-600">Bootshaus</a> class="block w-100 py-2 hover:text-primary-600">Bootshaus</a>
</li> </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> </ul>
</div> </div>
{% endif %} {% endif %}
@ -169,19 +176,12 @@
<li class="py-1"> <li class="py-1">
<a href="/admin/user" class="block w-100 py-2 hover:text-primary-600">User</a> <a href="/admin/user" class="block w-100 py-2 hover:text-primary-600">User</a>
</li> </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"> <li class="py-1">
<a href="/admin/rss" class="block w-100 py-2 hover:text-primary-600">Logs</a> <a href="/admin/rss" class="block w-100 py-2 hover:text-primary-600">Logs</a>
</li> </li>
<li class="py-1"> <li class="py-1">
<a href="/admin/list" class="block w-100 py-2 hover:text-primary-600">Fingerabdruck-Liste überprüfen</a> <a href="/admin/list" class="block w-100 py-2 hover:text-primary-600">Fingerabdruck-Liste überprüfen</a>
</li> </li>
<li class="py-1">
<a href="/admin/notification"
class="block w-100 py-2 hover:text-primary-600">Nachricht ausschreiben</a>
</li>
</ul> </ul>
</div> </div>
{% endif %} {% endif %}

View File

@ -23,7 +23,15 @@
placeholder="Suchen nach Bootsname oder Ruderer..."> placeholder="Suchen nach Bootsname oder Ruderer...">
</div> </div>
<div id="filter-result-js" class="search-result"></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>
</div> </div>
<script> <script>

View File

@ -18,8 +18,8 @@
<script type="text/javascript"> <script type="text/javascript">
var sepaqr = new sepaQR({ var sepaqr = new sepaQR({
benefName: 'ASKÖ Ruderverein Donau Linz', benefName: 'ASKÖ Ruderverein Donau Linz',
benefBIC: 'BKAUATWWXXX', benefBIC: 'ASPKAT2LXXX',
benefAccNr: 'AT131200080413001200', benefAccNr: 'AT582032032100729256',
amountEuro: {{ fee.sum_in_cents/100 }}, amountEuro: {{ fee.sum_in_cents/100 }},
remittanceInf: 'Vereinsgebühren {{ fee.name }}', remittanceInf: 'Vereinsgebühren {{ fee.name }}',
}); });
@ -44,13 +44,13 @@
</ul> </ul>
</small> </small>
{% endif %} {% 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 /> <br />
Falls die Berechnung nicht stimmt (korrekte Preise findest du <a href="https://rudernlinz.at/unser-verein/gebuhren/" Falls die Berechnung nicht stimmt (korrekte Preise findest du <a href="https://rudernlinz.at/unser-verein/gebuhren/"
target="_blank" 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. rel="noopener noreferrer">hier</a>) melde dich bitte bei it@rudernlinz.at. @Studenten: Bitte die aktuelle Studienbestätigung an it@rudernlinz.at schicken.
<br /> <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> </div>
</div> </div>
@ -391,15 +391,15 @@
</div> </div>
{# --- START Add Buttons --- #} {# --- START Add Buttons --- #}
{% if "manage_events" in loggedin_user.roles or "cox" in loggedin_user.roles %} {% 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 %} {% if "manage_events" in loggedin_user.roles %}
<a href="#" <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
data-sidebar="true" {% if "cox" in loggedin_user.roles %}
data-trigger="sidebar" rounded-bl-md
data-header="<strong>Event</strong> am {{ day.day| date(format='%d.%m.%Y') }} erstellen" {% else %}
data-day="{{ day.day }}" rounded-b-md
data-body="#addEventForm" {% endif %}
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"> ">
<span class="absolute inset-y-0 left-0 flex items-center pl-3">{% include "includes/plus-icon" %}</span> <span class="absolute inset-y-0 left-0 flex items-center pl-3">{% include "includes/plus-icon" %}</span>
Event Event
</a> </a>

View File

@ -51,7 +51,7 @@
data-filter="{{ reservation.user_applicant.name }} {{ reservation.trailer.name }}" 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"> class="w-full border-t bg-white dark:bg-primary-900 text-black dark:text-white p-3">
<div class="w-full"> <div class="w-full">
<strong>Boot:</strong> <strong>Hänger:</strong>
{{ reservation.trailer.name }} {{ reservation.trailer.name }}
<br /> <br />
<strong>Reservierung:</strong> <strong>Reservierung:</strong>