130 Commits

Author SHA1 Message Date
2520108fba Merge pull request 'Rebase from rowt' (#6) from upd into main
All checks were successful
CI/CD Pipeline / test (push) Successful in 21m39s
CI/CD Pipeline / deploy-main (push) Successful in 23m24s
Reviewed-on: #6
2025-04-03 17:11:46 +02:00
1e70e798af have new 'read all notifications' button
Some checks failed
CI/CD Pipeline / deploy-main (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
2025-04-03 17:06:18 +02:00
ecf73f72e5 fix minor mistakes during merge
Some checks failed
CI/CD Pipeline / deploy-main (push) Has been cancelled
CI/CD Pipeline / test (push) Has been cancelled
2025-04-03 17:03:11 +02:00
ab7ec637ab Merge remote-tracking branch 'upstream/main' into upd 2025-04-03 16:58:43 +02:00
f0a86a7186 Merge pull request 'fix kiosk error' (#886) from fix-kiosk-error into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#886
2025-03-26 20:58:15 +01:00
18d9f51354 fix kiosk error 2025-03-26 20:56:39 +01:00
dfe39cdd13 Merge pull request 'update deps' (#884) from upd into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#884
2025-03-26 14:52:08 +01:00
3a1ff3189d update deps 2025-03-26 14:51:10 +01:00
a89d78160d Merge pull request 'update id's' (#882) from add-unit-test into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#882
2025-03-09 19:21:41 +01:00
86e5482c6f update id's 2025-03-09 19:20:56 +01:00
08283dd392 Merge pull request 'add unit test for previous bug' (#880) from add-unit-test into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#880
2025-03-09 19:18:44 +01:00
2003ff0e59 add unit test for previous bug 2025-03-09 19:17:34 +01:00
1471ccad2c Merge pull request 'correct-name-in-notification' (#877) from correct-name-in-notification into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#877
2025-03-09 13:34:42 +01:00
d1102a7b04 show proper name in notification 2025-03-09 13:31:12 +01:00
faa8b4e767 Merge branch 'main' of ssh://git.hofer.link:2222/Ruderverein-Donau-Linz/rowt 2025-03-06 10:25:55 +01:00
bed4b4eb44 Merge pull request 'update deps' (#873) from update-deps into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#873
2025-03-06 10:25:03 +01:00
1ca0de1dd3 push 2025-03-06 10:18:34 +01:00
40bc866b3e push 2025-03-06 10:15:49 +01:00
13c9c5a708 push 2025-03-06 10:14:36 +01:00
d4b99f67ac push 2025-03-06 10:11:34 +01:00
b189c4f203 push 2025-03-06 10:10:33 +01:00
4820f8c798 push 2025-03-06 10:09:51 +01:00
7b2c47613c try 2025-03-06 10:07:35 +01:00
0a81489fa3 more updates 2025-03-06 10:06:54 +01:00
31a7643d96 update deps 2025-03-06 10:04:11 +01:00
83796a9824 test 2025-02-21 10:59:54 +01:00
227c751f60 test 2025-02-21 10:55:41 +01:00
ee5a1202fd test 2025-02-21 10:42:39 +01:00
7f824ccd2f test 2025-02-21 10:42:09 +01:00
e3d8a47af0 test 2025-02-21 10:40:46 +01:00
9f35920f3c test 2025-02-21 10:39:03 +01:00
58e3140376 fetch new ci image 2025-02-21 10:33:36 +01:00
b86043bba5 update deps 2025-02-20 18:18:48 +01:00
e141bcfc37 Merge pull request 'name proper mail addresses' (#871) from remove-philipp-mentioning into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#871
2025-02-17 22:59:01 +01:00
eaa35fb46c name proper mail addresses 2025-02-17 22:55:48 +01:00
86470da184 Merge pull request 'update deps' (#869) from update-deps into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#869
2025-02-13 10:07:01 +01:00
82a54bdea1 update deps 2025-02-13 10:06:04 +01:00
2a37bcbec5 Merge pull request 'upd' (#864) from upd into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#864
2025-02-12 07:13:13 +01:00
c96cc4b38f Merge branch 'upd' of ssh://git.hofer.link:2222/Ruderverein-Donau-Linz/rowt into upd 2025-02-11 21:39:28 +01:00
3008264261 fix default sort 2025-02-11 21:39:06 +01:00
Marie Birner
11025738bb [TASK] improve user management ux 2025-02-11 21:29:54 +01:00
Marie Birner
31fc0605d9 [TASK] improve user management ux 2025-02-11 21:28:28 +01:00
Marie Birner
1fdec59f77 [TASK] add sort element user management 2025-02-11 21:12:30 +01:00
da793fec2d allow sorting of user 2025-02-11 20:23:18 +01:00
8917629613 use proper permissions 2025-02-11 19:30:09 +01:00
2a2c2ce9dc Merge pull request 'fix ci' (#863) from allow-secretary-to-edit-boats into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#863
2025-02-11 09:37:24 +01:00
10f6268e56 fix ci 2025-02-11 09:36:44 +01:00
f0ea5823ba Merge pull request 'allow vorstand to edit boats' (#861) from allow-secretary-to-edit-boats into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#861
2025-02-11 09:23:56 +01:00
3406b66f41 allow vorstand to edit boats 2025-02-11 09:22:22 +01:00
2ffddda960 Merge pull request 'staging' (#858) from staging into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#858
2025-02-10 18:48:54 +01:00
c7c92c83fb Merge pull request 'fix ci' (#856) from allow-secretary-to-edit-boats into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#856
2025-02-10 18:48:22 +01:00
5cc77c39ff Merge branch 'staging' into allow-secretary-to-edit-boats 2025-02-10 18:47:59 +01:00
80d8857c6b Merge pull request 'fix ci' (#857) from allow-secretary-to-edit-boats into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#857
2025-02-10 18:47:28 +01:00
78403e4ec5 Merge branch 'main' into allow-secretary-to-edit-boats 2025-02-10 18:46:04 +01:00
4dd656f566 fix ci 2025-02-10 18:44:01 +01:00
23a1a118a3 Merge pull request 'allow 'schriftführer' to edit boats' (#854) from allow-secretary-to-edit-boats into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#854
2025-02-10 18:17:31 +01:00
b281201906 Merge pull request 'allow-secretary-to-edit-boats' (#855) from allow-secretary-to-edit-boats into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#855
2025-02-10 18:17:25 +01:00
4d58bd3cae allow 'schriftführer' to edit boats 2025-02-10 18:16:31 +01:00
67e790a82e Merge pull request 'fix-new-npm' (#853) from fix-new-npm into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#853
2025-01-10 14:35:40 +01:00
63bf1015cc Merge pull request 'Update frontend/tests/cox.spec.ts' (#852) from fix-new-npm into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#852
2025-01-10 14:34:34 +01:00
352dad8e6c Update frontend/tests/cox.spec.ts 2025-01-10 14:16:05 +01:00
4f42e7cb8c Merge pull request 'use new rust in ci' (#851) from update-rust into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#851
2025-01-10 12:47:30 +01:00
c6aa25fe0e Merge pull request 'use new rust in ci' (#850) from update-rust into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#850
2025-01-10 12:47:23 +01:00
9ba848cbab use new rust in ci 2025-01-10 12:46:43 +01:00
9047459d6c Merge pull request 'vorstand-show-old-logs' (#849) from vorstand-show-old-logs into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#849
2025-01-10 10:23:30 +01:00
87de3859a2 Merge pull request 'allow vorstand to see all old logs' (#848) from vorstand-show-old-logs into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#848
2025-01-10 09:52:56 +01:00
b8aaf5ba2e allow vorstand to see all old logs 2025-01-10 09:51:43 +01:00
de9ea9405e Merge pull request 'update-deps' (#847) from update-deps into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#847
2025-01-09 17:23:53 +01:00
3bd229554b Merge pull request 'update-deps' (#846) from update-deps into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#846
2025-01-09 17:04:02 +01:00
f9c9f7c523 update to sqlx 0.8 2025-01-09 16:31:53 +01:00
0dfceec737 update deps 2025-01-09 16:22:08 +01:00
e5fec411f3 Merge pull request 'notfiication-on-new-personal-stat' (#843) from notfiication-on-new-personal-stat into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#843
2025-01-09 16:19:37 +01:00
ac67c6cfdb Merge pull request 'ped clippy' (#845) from notfiication-on-new-personal-stat into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#845
2025-01-09 15:36:34 +01:00
a90c4fc07e ped clippy 2025-01-09 15:35:57 +01:00
52b960cec7 Merge pull request 'cargo clippy' (#844) from notfiication-on-new-personal-stat into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#844
2025-01-09 15:32:26 +01:00
f7d109f1b2 cargo clippy 2025-01-09 15:31:05 +01:00
63505722f9 Merge pull request 'notfiication-on-new-personal-stat' (#842) from notfiication-on-new-personal-stat into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#842
2025-01-09 11:58:10 +01:00
d21272d4bb send notifiation to user + vorstand if user completes 'äquatorpreis' or 'fahrtenabzeichen'; Fixes #746 2025-01-09 11:45:24 +01:00
97dd7794fb split to separate fee file 2025-01-09 10:37:15 +01:00
cfe99c2f2a Merge pull request 'add confirm dialog before creating a new user' (#841) from confirm-user-creation into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#841
2025-01-09 10:22:58 +01:00
2a3f846c5c Merge pull request 'confirm-user-creation' (#840) from confirm-user-creation into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#840
2025-01-09 10:22:56 +01:00
af4163a065 add confirm dialog before creating a new user 2025-01-09 10:21:44 +01:00
8a9047b3c3 Merge pull request 'reservation-styling' (#839) from reservation-styling into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#839
2025-01-08 14:50:27 +01:00
ebc7c32351 Merge pull request 'reservation-styling' (#838) from reservation-styling into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#838
2025-01-08 14:50:20 +01:00
1a850535ed switch from date to time icon + add 'Reservierung' 2025-01-08 14:46:11 +01:00
99bbb2b088 Merge pull request 'stats' (#836) from stats into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#836
2025-01-07 14:51:16 +01:00
b31209a97a Merge pull request '[TASK] make stats more beautiful' (#837) from stats into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#837
2025-01-07 14:27:59 +01:00
Marie Birner
be4f302a4c [TASK] make stats more beautiful 2025-01-07 14:07:52 +01:00
e5c2bec145 Merge pull request 'stats' (#835) from stats into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#835
2025-01-07 12:58:37 +01:00
0ebcd5a284 allow changing the year in stats again 2025-01-07 11:44:56 +01:00
6237340f72 fix ci 2025-01-07 11:39:36 +01:00
Marie Birner
5b013fe389 [TASK] rm unnecessary personal stat 2025-01-07 10:54:15 +01:00
Marie Birner
022ec6bd5b [TASK] make stats more beautiful 2025-01-07 10:52:46 +01:00
09d4c0abe4 Merge pull request 'show amount of trips in stat' (#834) from show-amount-trips into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#834
2025-01-06 13:15:05 +01:00
5448558085 Merge pull request 'show-amount-trips' (#833) from show-amount-trips into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#833
2025-01-06 13:14:55 +01:00
3232a03d75 show amount of trips in stat 2025-01-06 13:14:19 +01:00
dceb57e370 Merge pull request 'fix count in statistic' (#832) from fix-count into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#832
2025-01-04 10:57:34 +01:00
f68928df00 Merge pull request 'fix-count' (#831) from fix-count into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#831
2025-01-04 10:57:05 +01:00
d3bb050534 fix count in statistic 2025-01-04 10:56:32 +01:00
32b4131aae Merge pull request 'nicer mail text' (#830) from nicer-mail-text into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#830
2025-01-03 12:38:28 +01:00
1d34cb5794 Merge pull request 'nicer-mail-text' (#829) from nicer-mail-text into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#829
2025-01-03 12:38:09 +01:00
8a4d98a90f nicer mail text 2025-01-03 12:36:29 +01:00
Marie Birner
213e9faad4 [TASK] idea reservation styling in planned events view 2025-01-02 11:22:41 +01:00
a9a8207813 Merge pull request 'show boatreservations in planned' (#828) from show-boatreservations-in-planned into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#828
2025-01-01 19:30:58 +01:00
b7b2385264 Merge pull request 'Merge pull request 'fix no 'donau linz' group' (#825) from fix-no-group into main' (#826) from show-boatreservations-in-planned into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#826
2025-01-01 19:29:58 +01:00
b560233acf show boatreservations in planned 2025-01-01 19:05:20 +01:00
d7187a7589 Merge pull request 'fix no 'donau linz' group' (#825) from fix-no-group into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#825
2025-01-01 17:46:26 +01:00
e61b16c389 Merge pull request 'fix-no-group' (#824) from fix-no-group into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#824
2025-01-01 17:45:52 +01:00
2ac8a3155c fix no 'donau linz' group 2025-01-01 17:44:48 +01:00
d01e6ea30b Merge pull request 'allow lazy people to mark all notifcations as read' (#822) from mark-all-notifications-read into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#822
2024-12-19 21:16:40 +01:00
f38ca09eb7 Merge pull request 'allow lazy people to mark all notifcations as read' (#823) from mark-all-notifications-read into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#823
2024-12-19 21:16:31 +01:00
1ad4c31979 allow lazy people to mark all notifcations as read 2024-12-19 21:15:27 +01:00
5e413d2d72 Merge pull request 'add-renntrainer' (#820) from add-renntrainer into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#820
2024-12-17 09:14:18 +01:00
0f8e1158b9 Merge pull request 'add renntrainer role' (#821) from add-renntrainer into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#821
2024-12-17 08:57:29 +01:00
af10399797 add renntrainer role 2024-12-17 08:56:48 +01:00
6344ba720d Merge pull request 'fix-mobile-link' (#818) from fix-mobile-link into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#818
2024-12-06 18:28:49 +01:00
4b1dceb08a Merge pull request 'format' (#816) from format into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#816
2024-12-05 23:40:07 +01:00
cb819c16a3 Merge pull request 'links; Fixes #755' (#815) from links into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#815
2024-12-05 11:16:34 +01:00
08a48cb4d2 Merge pull request 'update ci' (#812) from update-ci into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#812
2024-12-05 10:23:43 +01:00
9c36da32bd Merge pull request 'demo' (#810) from demo into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#810
2024-11-30 22:33:12 +01:00
77444d25ae Merge pull request 'fix' (#808) from fix into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#808
2024-11-27 08:21:48 +01:00
a683af00d0 Merge pull request 'new-link' (#805) from new-link into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#805
2024-11-27 08:14:00 +01:00
766886d857 Merge pull request 'nicer-label' (#803) from nicer-label into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#803
2024-11-25 21:01:38 +01:00
38703321e8 Merge pull request 'ergo-trips' (#801) from ergo-trips into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#801
2024-11-25 12:31:50 +01:00
ec1c717341 Merge pull request 'allow for smaller m' (#799) from trim-ergo into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#799
2024-11-11 23:12:23 +01:00
22bb79bfbd Merge pull request 'allow m in dd' (#797) from trim-ergo into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#797
2024-11-11 23:07:28 +01:00
eba4b77983 Merge pull request 'trim-ergo' (#795) from trim-ergo into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#795
2024-11-11 23:00:08 +01:00
83d266b3e0 Merge pull request 'update data' (#793) from formating-ergo into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#793
2024-11-11 18:03:43 +01:00
980bcff1d9 Merge pull request 'fix tests' (#791) from formating-ergo into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#791
2024-11-11 15:27:15 +01:00
c15ed6e9a9 Merge pull request 'formating-ergo' (#789) from formating-ergo into staging
Reviewed-on: Ruderverein-Donau-Linz/rowt#789
2024-11-11 13:34:31 +01:00
18 changed files with 1158 additions and 625 deletions

1481
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
[package]
name = "rot"
version = "0.1.0"
edition = "2021"
edition = "2024"
[features]
default = ["rest", "rowing-tera" ]
@@ -13,20 +13,20 @@ rocket = { version = "0.5.0", features = ["secrets"]}
rocket_dyn_templates = {version = "0.2", features = [ "tera" ], optional = true }
log = "0.4"
env_logger = "0.11"
sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio-rustls", "macros", "chrono", "time"] }
sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio-rustls", "macros", "chrono"] }
argon2 = "0.5"
serde = { version = "1.0", features = [ "derive" ]}
serde_json = "1.0"
chrono = { version = "0.4", features = ["serde"]}
chrono-tz = "0.9"
chrono-tz = "0.10"
tera = { version = "1.18", features = ["date-locale"], optional = true}
ics = "0.5"
futures = "0.3"
lettre = "0.11"
csv = "1.3"
itertools = "0.13"
itertools = "0.14"
job_scheduler_ng = "2.0"
ureq = { version = "2.9", features = ["json"] }
ureq = { version = "3.0", features = ["json"] }
regex = "1.10"
urlencoding = "2.1"

View File

@@ -23,6 +23,7 @@ document.addEventListener("DOMContentLoaded", function () {
addRelationMagic(<HTMLElement>document.querySelector("body"));
reloadPage();
setCurrentdate(<HTMLInputElement>document.querySelector("#departure"));
initDropdown();
});
function changeTheme() {
@@ -795,3 +796,21 @@ function replaceStrings() {
weekday.innerHTML = weekday.innerHTML.replace("Freitag", "Markttag");
});
}
function initDropdown() {
const popoverTriggerList = document.querySelectorAll('[data-dropdown]');
popoverTriggerList.forEach((popoverTriggerEl: Element) => {
const id = popoverTriggerEl.getAttribute('data-dropdown');
if (id) {
const element = document.getElementById(id);
if (element) {
// Toggle visibility of the dropdown when clicked
popoverTriggerEl.addEventListener('click', () => {
element.classList.toggle('hidden');
});
}
}
});
}

View File

@@ -53,6 +53,7 @@ INSERT INTO "planned_event" (name, planned_amount_cox, trip_details_id) VALUES('
INSERT INTO "trip_details" (planned_starting_time, max_people, day, notes) VALUES('11:00', 1, date('now', '+1 day'), 'trip_details for trip from cox');
INSERT INTO "trip" (cox_id, trip_details_id) VALUES(4, 2);
INSERT INTO "trip_details" (planned_starting_time, max_people, day, notes) VALUES('10:00', 2, date('now'), 'same trip_details as id=1');
INSERT INTO "trip_type" (name, desc, question, icon) VALUES ('Regatta', 'Regatta!', 'Kein normales Event. Das ist eine Regatta! Willst du wirklich teilnehmen?', '&#127941;');
INSERT INTO "trip_type" (name, desc, question, icon) VALUES ('Lange Ausfahrt', 'Lange Ausfahrt!', 'Das ist eine lange Ausfahrt! Willst du wirklich teilnehmen?', '&#128170;');
INSERT INTO "trip_type" (name, desc, question, icon) VALUES ('Wanderfahrt', 'Wanderfahrt!', 'Kein normales Event. Das ist eine Wanderfahrt! Bitte überprüfe ob du alle Anforderungen erfüllst. Willst du wirklich teilnehmen?', '&#9969;');

View File

@@ -96,8 +96,8 @@ FROM trip WHERE planned_event_id = ?
.unwrap()
.into_iter()
.map(|r| Registration {
name: r.name,
registered_at: r.registered_at,
name: r.name.unwrap(),
registered_at: r.registered_at.unwrap(),
is_guest: false,
is_real_guest: false,
})

View File

@@ -208,6 +208,15 @@ ORDER BY read_at DESC, created_at DESC;
}
}
}
pub(crate) async fn mark_all_read(db: &SqlitePool, user: &User) {
let notifications = Self::for_user(db, user).await;
for notification in notifications {
notification.mark_read(db).await;
}
}
pub(crate) async fn delete_by_action(db: &sqlx::Pool<Sqlite>, action: &str) {
sqlx::query!(
"DELETE FROM notification WHERE action_after_reading=? and read_at is null",
@@ -289,7 +298,7 @@ mod test {
assert_eq!(rower_notification.category, "Absage Ausfahrt");
assert_eq!(
rower_notification.action_after_reading.as_deref(),
Some("remove_user_trip_with_trip_details_id:3")
Some("remove_user_trip_with_trip_details_id:4")
);
// Cox received notification

View File

@@ -81,33 +81,31 @@ impl Trip {
trip_details.planned_starting_time,
)
.await;
if same_starting_datetime.len() > 1 {
for notify in same_starting_datetime {
// don't notify oneself
if notify.id == trip_details.id {
continue;
}
for notify in same_starting_datetime {
// don't notify oneself
if notify.id == trip_details.id {
continue;
}
// don't notify people who have cancelled their trip
if notify.cancelled() {
continue;
}
// don't notify people who have cancelled their trip
if notify.cancelled() {
continue;
}
if let Some(trip) = Trip::find_by_trip_details(db, notify.id).await {
let user = User::find_by_id(db, trip.cox_id as i32).await.unwrap();
Notification::create(
db,
&user,
&format!(
"{} hat eine Ausfahrt zur selben Zeit ({} um {}) wie du erstellt",
user.name, trip.day, trip.planned_starting_time
),
"Neue Ausfahrt zur selben Zeit",
None,
None,
)
.await;
}
if let Some(trip) = Trip::find_by_trip_details(db, notify.id).await {
let user_earlier_trip = User::find_by_id(db, trip.cox_id as i32).await.unwrap();
Notification::create(
db,
&user_earlier_trip,
&format!(
"{} hat eine Ausfahrt zur selben Zeit ({} um {}) wie du erstellt",
user.name, trip.day, trip.planned_starting_time
),
"Neue Ausfahrt zur selben Zeit",
None,
None,
)
.await;
}
}
}
@@ -277,10 +275,8 @@ WHERE day=?
return Err(TripUpdateError::NotYourTrip);
}
if update.trip_type != Some(4) {
if !update.cox.allowed_to_steer(db).await {
return Err(TripUpdateError::TripTypeNotAllowed);
}
if update.trip_type != Some(4) && !update.cox.allowed_to_steer(db).await {
return Err(TripUpdateError::TripTypeNotAllowed);
}
let Some(trip_details_id) = update.trip.trip_details_id else {
@@ -478,6 +474,7 @@ mod test {
use crate::{
model::{
event::Event,
notification::Notification,
trip::{self, TripDeleteError},
tripdetails::TripDetails,
user::{SteeringUser, User},
@@ -509,6 +506,34 @@ mod test {
assert!(Trip::find_by_id(&pool, 1).await.is_some());
}
#[sqlx::test]
fn test_notification_cox_if_same_datetime() {
let pool = testdb!();
let cox = SteeringUser::new(
&pool,
User::find_by_name(&pool, "cox".into()).await.unwrap(),
)
.await
.unwrap();
let trip_details = TripDetails::find_by_id(&pool, 1).await.unwrap();
Trip::new_own(&pool, &cox, trip_details).await;
let cox2 = SteeringUser::new(
&pool,
User::find_by_name(&pool, "cox2".into()).await.unwrap(),
)
.await
.unwrap();
let trip_details = TripDetails::find_by_id(&pool, 3).await.unwrap();
Trip::new_own(&pool, &cox2, trip_details).await;
let last_notification = &Notification::for_user(&pool, &cox).await[0];
assert!(last_notification
.message
.starts_with("cox2 hat eine Ausfahrt zur selben Zeit"));
}
#[sqlx::test]
fn test_get_day_cox_trip() {
let pool = testdb!();

View File

@@ -339,7 +339,7 @@ mod test {
}
)
.await,
3,
4,
);
assert_eq!(
TripDetails::create(
@@ -354,7 +354,7 @@ mod test {
}
)
.await,
4,
5,
);
}

58
src/model/user/fee.rs Normal file
View File

@@ -0,0 +1,58 @@
use super::User;
use serde::Serialize;
#[derive(Debug, Serialize)]
pub struct Fee {
pub sum_in_cents: i64,
pub parts: Vec<(String, i64)>,
pub name: String,
pub user_ids: String,
pub paid: bool,
pub users: Vec<User>,
}
impl Default for Fee {
fn default() -> Self {
Self::new()
}
}
impl Fee {
pub fn new() -> Self {
Self {
sum_in_cents: 0,
name: "".into(),
parts: Vec::new(),
user_ids: "".into(),
users: Vec::new(),
paid: false,
}
}
pub fn add(&mut self, desc: String, price_in_cents: i64) {
self.sum_in_cents += price_in_cents;
self.parts.push((desc, price_in_cents));
}
pub fn add_person(&mut self, user: &User) {
if !self.name.is_empty() {
self.name.push_str(" + ");
self.user_ids.push('&');
}
self.name.push_str(&user.name);
self.user_ids.push_str(&format!("user_ids[]={}", user.id));
self.users.push(user.clone());
}
pub fn paid(&mut self) {
self.paid = true;
}
pub fn merge(&mut self, fee: Fee) {
for (desc, price_in_cents) in fee.parts {
self.add(desc, price_in_cents);
}
}
}

View File

@@ -31,7 +31,7 @@ pub struct User {
pub struct UserWithDetails {
#[serde(flatten)]
pub user: User,
pub amount_unread_notifications: i32,
pub amount_unread_notifications: i64,
pub allowed_to_steer: bool,
pub roles: Vec<String>,
}
@@ -72,7 +72,7 @@ impl User {
self.has_role_tx(db, "cox").await || self.has_role_tx(db, "Bootsführer").await
}
pub async fn amount_unread_notifications(&self, db: &SqlitePool) -> i32 {
pub async fn amount_unread_notifications(&self, db: &SqlitePool) -> i64 {
sqlx::query!(
"SELECT COUNT(*) as count FROM notification WHERE user_id = ? AND read_at IS NULL",
self.id
@@ -197,18 +197,27 @@ WHERE lower(name)=?
}
pub async fn all(db: &SqlitePool) -> Vec<Self> {
sqlx::query_as!(
Self,
Self::all_with_order(db, "last_access", false).await
}
pub async fn all_with_order(db: &SqlitePool, sort: &str, asc: bool) -> Vec<Self> {
let mut query = format!(
"
SELECT id, name, pw, deleted, last_access, user_token
FROM user
WHERE deleted = 0
ORDER BY last_access DESC
"
)
.fetch_all(db)
.await
.unwrap()
SELECT id, name, pw, deleted, last_access, user_token
FROM user
WHERE deleted = 0
ORDER BY {}
",
sort
);
if !asc {
query.push_str(" DESC");
}
sqlx::query_as::<_, User>(&query)
.fetch_all(db)
.await
.unwrap()
}
pub async fn all_with_role(db: &SqlitePool, role: &Role) -> Vec<Self> {

View File

@@ -80,8 +80,8 @@ fn fetch() -> Result<Station, String> {
let url = "https://hydro.ooe.gv.at/daten/internet/stations/OG/207068/S/forecast.json";
match ureq::get(url).call() {
Ok(response) => {
let forecast: Result<Vec<Station>, _> = response.into_json();
Ok(mut response) => {
let forecast: Result<Vec<Station>, _> = response.body_mut().read_json();
if let Ok(data) = forecast {
if data.len() == 1 {

View File

@@ -99,8 +99,8 @@ fn fetch(api_key: &str) -> Result<Data, String> {
let url = format!("https://api.openweathermap.org/data/3.0/onecall?lat=47.766249&lon=13.367683&units=metric&exclude=current,minutely,hourly,alert&appid={api_key}");
match ureq::get(&url).call() {
Ok(response) => {
let data: Result<Data, _> = response.into_json();
Ok(mut response) => {
let data: Result<Data, _> = response.body_mut().read_json();
if let Ok(data) = data {
Ok(data)

View File

@@ -33,13 +33,17 @@ impl<'r> FromRequest<'r> for Referer {
}
}
#[get("/user")]
#[get("/user?<sort>&<asc>")]
async fn index(
db: &State<SqlitePool>,
user: ManageUserUser,
flash: Option<FlashMessage<'_>>,
sort: Option<String>,
asc: bool,
) -> Template {
let user_futures: Vec<_> = User::all(db)
let sort_column = sort.unwrap_or_else(|| "last_access".to_string());
let user_futures: Vec<_> = User::all_with_order(db, &sort_column, asc)
.await
.into_iter()
.map(|u| async move { UserWithDetails::from_user(u, db).await })

View File

@@ -38,7 +38,7 @@ async fn cal_registered(
return Err("Invalid".into());
};
if &user.user_token != uuid {
if user.user_token != uuid {
return Err("Invalid".into());
}

View File

@@ -30,6 +30,12 @@ async fn mark_read(db: &State<SqlitePool>, user: User, notification_id: i64) ->
}
}
pub fn routes() -> Vec<Route> {
routes![mark_read]
#[get("/read/all")]
async fn mark_all_read(db: &State<SqlitePool>, user: User) -> Flash<Redirect> {
Notification::mark_all_read(db, &user).await;
Flash::success(Redirect::to("/"), "Alle Nachrichten als gelesen markiert")
}
pub fn routes() -> Vec<Route> {
routes![mark_read, mark_all_read]
}

View File

@@ -4,11 +4,13 @@
<div class="max-w-screen-lg w-full">
<h1 class="h1">Mitglieder</h1>
{% if allowed_to_edit %}
<form action="/admin/user/new"
<details class="mt-5 bg-gray-200 dark:bg-primary-600 p-3 rounded-md">
<summary class="px-3 cursor-pointer text-md font-bold text-primary-950 dark:text-white">Neue Person hinzufügen</summary>
<form action="/admin/user/new"
onsubmit="return confirm('Willst du wirklich einen neuen Benutzer anlegen?');"
method="post"
class="mt-4 bg-primary-900 rounded-md text-white px-3 pb-3 pt-2 sm:flex items-end justify-between">
class="flex mt-4 rounded-md sm:flex items-end justify-between">
<div class="w-full">
<h2 class="text-md font-bold mb-2 uppercase tracking-wide">Neues Mitglied hinzufügen</h2>
<div class="grid md:grid-cols-3">
<div>
<label for="name" class="sr-only">Name</label>
@@ -19,21 +21,44 @@
</div>
</div>
</div>
<div class="text-right">
<div class="text-right ml-3">
<input value="Hinzufügen"
type="submit"
class="w-28 mt-2 sm:mt-0 rounded-md bg-primary-500 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer" />
</div>
</form>
</details>
{% endif %}
<!-- START filterBar -->
<div class="search-wrapper">
<div class="search-wrapper flex">
<label for="name" class="sr-only">Suche</label>
<input type="search"
name="name"
id="filter-js"
class="search-bar"
placeholder="Suchen nach (Name, [yes|no]-role:<name>" />
placeholder="Suchen nach (Name, [yes|no]-role:<name>, has-[no-]membership-pdf)" />
<div class="relative">
<button id="dropdownbtn" data-dropdown="dropdown" class="btn btn-dark ml-3" type="button">
Sortieren
</button>
<!-- Dropdown menu -->
<div id="dropdown" class="z-10 hidden bg-white divide-y divide-gray-100 text-secondary-900 rounded-lg shadow-sm w-44 absolute right-0">
<ul class="py-2 text-sm" aria-labelledby="dropdownbtn">
<li>
<a href="./user" class="block px-4 py-2 hover:bg-gray-100 hover:text-secondary-950">Zuletzt eingeloggt</a>
</li>
<li>
<a href="?sort=name&asc" class="block px-4 py-2 hover:bg-gray-100 hover:text-secondary-950">Name A-Z</a>
</li>
<li>
<a href="?sort=name" class="block px-4 py-2 hover:bg-gray-100 hover:text-secondary-950">Name Z-A</a>
</li>
</ul>
</div>
</div>
</div>
<!-- END filterBar -->
<div id="filter-result-js" class="search-result"></div>
@@ -46,7 +71,7 @@
<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 %}
{% if not user.last_access and allowed_to_edit and user.mail %}
<form action="/admin/user"
method="post"
enctype="multipart/form-data"

View File

@@ -4,13 +4,12 @@
{% extends "base" %}
{% macro show_place(aisle_name, side_name, level) %}
<li class="truncate p-2 flex relative w-full">
{% set aisle = aisle_name ~ "-aisle" %}
{% set place = boathouse[aisle][side_name] %}
{% set place = boathouse[aisle_name][side_name].boats %}
{% if place[level] %}
{{ place[level].1.name }}
{{ place[level].boat.name }}
{% if "admin" in loggedin_user.roles %}
<a class="btn btn-primary absolute end-0"
href="/board/boathouse/{{ place[level].0 }}/delete">X</a>
href="/board/boathouse/{{ place[level].boathouse_id }}/delete">X</a>
{% endif %}
{% elif boats | length > 0 %}
{% if "admin" in loggedin_user.roles %}

View File

@@ -9,7 +9,8 @@
{% if notifications %}
{% if loggedin_user.amount_unread_notifications > 10 %}
<div class="text-primary-950 dark:text-white bg-gray-200 dark:bg-primary-950 bg-opacity-80 text-center pb-3 px-3">
Du hast viele ungelesene Benachrichtigungen. Um deine Oberfläche übersichtlich zu halten und wichtige Updates nicht zu verpassen, nimm dir bitte einen Moment Zeit sie zu überprüfen und als gelesen zu markieren (&#10003;).
Du hast viele ungelesene Benachrichtigungen. Um deine Oberfläche übersichtlich zu halten und wichtige Updates nicht zu verpassen, nimm dir bitte in Zukunft einen kurzen Moment Zeit sie zu überprüfen und als gelesen zu markieren (&#10003;).<br /><a href="/notification/read/all" class="underline">Du kannst hier ausnahmsweise alle als gelesen markieren.</a>
</div>
{% endif %}
<div class="divide-y">