Compare commits
2 Commits
main
...
a241b9f1d8
| Author | SHA1 | Date | |
|---|---|---|---|
| a241b9f1d8 | |||
| 1de7a6fb33 |
@@ -17,9 +17,6 @@ jobs:
|
|||||||
- name: Run Test DB Script
|
- name: Run Test DB Script
|
||||||
run: ./test_db.sh
|
run: ./test_db.sh
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: npm --version
|
|
||||||
|
|
||||||
- name: Cache Cargo dependencies
|
- name: Cache Cargo dependencies
|
||||||
uses: Swatinem/rust-cache@v2
|
uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
|
|||||||
@@ -425,8 +425,10 @@ function initNewChoice(select: HTMLInputElement) {
|
|||||||
maxItemText: (maxItemCount) => {
|
maxItemText: (maxItemCount) => {
|
||||||
return `Nur ${maxItemCount} Ruderer können hinzugefügt werden`;
|
return `Nur ${maxItemCount} Ruderer können hinzugefügt werden`;
|
||||||
},
|
},
|
||||||
callbackOnInit: function () {
|
callbackOnInit: function (this: Choices) {
|
||||||
this._currentState.items.forEach(function (obj) {
|
const items = this.getValue(true); // Get all selected items
|
||||||
|
const itemsArray = Array.isArray(items) ? items : [items];
|
||||||
|
itemsArray.forEach((obj: any) => {
|
||||||
if (boat_in_ottensheim && obj.customProperties) {
|
if (boat_in_ottensheim && obj.customProperties) {
|
||||||
if (obj.customProperties.is_racing) {
|
if (obj.customProperties.is_racing) {
|
||||||
const coxSelect = <HTMLSelectElement>(
|
const coxSelect = <HTMLSelectElement>(
|
||||||
|
|||||||
@@ -9,20 +9,20 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.40.1",
|
"@playwright/test": "^1.55.1",
|
||||||
"@types/d3": "^7.4.1",
|
"@types/d3": "^7.4.3",
|
||||||
"@types/node": "^20.11.4",
|
"@types/node": "^24.6.1",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.21",
|
||||||
"postcss": "^8.4.21",
|
"postcss": "^8.5.6",
|
||||||
"sass": "^1.60.0",
|
"sass": "^1.93.2",
|
||||||
"tailwindcss": "^3.3.1",
|
"tailwindcss": "^3.4.18",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"vite": "^4.2.0",
|
"vite": "^7.1.7",
|
||||||
"vite-plugin-static-copy": "^0.13.1"
|
"vite-plugin-static-copy": "^3.1.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"choices.js": "^10.2.0",
|
"choices.js": "^11.1.0",
|
||||||
"d3": "^7.8.5",
|
"d3": "^7.9.0",
|
||||||
"terser": "^5.21.0"
|
"terser": "^5.44.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,16 +18,20 @@ test("Cox can start and cancel trip", async ({ page }, testInfo) => {
|
|||||||
await page.getByText('2x', { exact: true }).click();
|
await page.getByText('2x', { exact: true }).click();
|
||||||
await page.getByText("Joe", { exact: true }).click();
|
await page.getByText("Joe", { exact: true }).click();
|
||||||
}
|
}
|
||||||
await page.getByLabel('Remove item: \'6\'').click(); // remove pre-filled cox2
|
await page.getByRole('button', { name: 'Remove item:' }).click(); // remove pre-filled cox2
|
||||||
await page.getByPlaceholder("Ruderer auswählen").click();
|
await page.getByPlaceholder("Ruderer auswählen").click();
|
||||||
await page.getByRole("option", { name: "rower2" }).click();
|
await page.getByRole("option", { name: "rower2" }).click();
|
||||||
await page.getByRole("option", { name: "cox2" }).click();
|
await page.getByRole("option", { name: "cox2" }).click();
|
||||||
await expect(page.getByRole("listbox")).toContainText(
|
await expect(page.locator("#form")).toContainText(
|
||||||
"Nur 2 Ruderer können hinzugefügt werden",
|
"Nur 2 Ruderer können hinzugefügt werden",
|
||||||
);
|
);
|
||||||
|
|
||||||
await expect(page.locator("#shipmaster-newrowerjs")).toContainText("cox");
|
await expect(page.locator("#shipmaster-newrowerjs")).toContainText("cox");
|
||||||
await expect(page.locator("#steering_person-newrowerjs")).toContainText(
|
await expect(page.locator("#steering_person-newrowerjs")).toContainText(
|
||||||
"rower2 cox",
|
"rower2",
|
||||||
|
);
|
||||||
|
await expect(page.locator("#steering_person-newrowerjs")).toContainText(
|
||||||
|
"cox2",
|
||||||
);
|
);
|
||||||
await page.getByRole("button", { name: "Ausfahrt eintragen" }).click();
|
await page.getByRole("button", { name: "Ausfahrt eintragen" }).click();
|
||||||
await expect(page.locator("body")).toContainText(
|
await expect(page.locator("body")).toContainText(
|
||||||
@@ -60,11 +64,11 @@ test("Cox can start and finish trip", async ({ page }, testInfo) => {
|
|||||||
await page.getByText('2x', { exact: true }).click();
|
await page.getByText('2x', { exact: true }).click();
|
||||||
await page.getByText("Joe", { exact: true }).click();
|
await page.getByText("Joe", { exact: true }).click();
|
||||||
}
|
}
|
||||||
await page.getByLabel('Remove item: \'6\'').click(); // remove pre-filled cox2
|
await page.getByRole('button', { name: 'Remove item:' }).click(); // remove pre-filled cox2
|
||||||
await page.getByPlaceholder("Ruderer auswählen").click();
|
await page.getByPlaceholder("Ruderer auswählen").click();
|
||||||
await page.getByRole("option", { name: "rower2" }).click();
|
await page.getByRole("option", { name: "rower2" }).click();
|
||||||
await page.getByRole("option", { name: "cox2" }).click();
|
await page.getByRole("option", { name: "cox2" }).click();
|
||||||
await expect(page.getByRole("listbox")).toContainText(
|
await expect(page.locator("#form")).toContainText(
|
||||||
"Nur 2 Ruderer können hinzugefügt werden",
|
"Nur 2 Ruderer können hinzugefügt werden",
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -79,8 +83,12 @@ test("Cox can start and finish trip", async ({ page }, testInfo) => {
|
|||||||
|
|
||||||
await expect(page.locator("#shipmaster-newrowerjs")).toContainText("cox");
|
await expect(page.locator("#shipmaster-newrowerjs")).toContainText("cox");
|
||||||
await expect(page.locator("#steering_person-newrowerjs")).toContainText(
|
await expect(page.locator("#steering_person-newrowerjs")).toContainText(
|
||||||
"rower2 cox",
|
"rower2",
|
||||||
);
|
);
|
||||||
|
await expect(page.locator("#steering_person-newrowerjs")).toContainText(
|
||||||
|
"cox",
|
||||||
|
);
|
||||||
|
|
||||||
await page.getByRole("button", { name: "Ausfahrt eintragen" }).click();
|
await page.getByRole("button", { name: "Ausfahrt eintragen" }).click();
|
||||||
await expect(page.locator("body")).toContainText(
|
await expect(page.locator("body")).toContainText(
|
||||||
"Ausfahrt erfolgreich hinzugefügt",
|
"Ausfahrt erfolgreich hinzugefügt",
|
||||||
|
|||||||
@@ -860,7 +860,6 @@ special_user!(AllowedForPlannedTripsUser, +"Donau Linz", +"scheckbuch", +"Förde
|
|||||||
special_user!(DonauLinzUser, +"Donau Linz", +"Förderndes Mitglied", -"Unterstützend"); // TODO:
|
special_user!(DonauLinzUser, +"Donau Linz", +"Förderndes Mitglied", -"Unterstützend"); // TODO:
|
||||||
// remove ->
|
// remove ->
|
||||||
// RegularUser
|
// RegularUser
|
||||||
special_user!(ErgoAdminUser, +"ergo-admin", +"admin");
|
|
||||||
special_user!(SchnupperBetreuerUser, +"schnupper-betreuer");
|
special_user!(SchnupperBetreuerUser, +"schnupper-betreuer");
|
||||||
special_user!(VorstandUser, +"admin", +"Vorstand");
|
special_user!(VorstandUser, +"admin", +"Vorstand");
|
||||||
special_user!(EventUser, +"manage_events");
|
special_user!(EventUser, +"manage_events");
|
||||||
|
|||||||
115
src/tera/ergo.rs
115
src/tera/ergo.rs
@@ -1,7 +1,8 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
use chrono::{Datelike, Utc};
|
use chrono::Utc;
|
||||||
use rocket::{
|
use rocket::{
|
||||||
|
FromForm, Route, State,
|
||||||
form::Form,
|
form::Form,
|
||||||
fs::TempFile,
|
fs::TempFile,
|
||||||
get,
|
get,
|
||||||
@@ -9,19 +10,18 @@ use rocket::{
|
|||||||
post,
|
post,
|
||||||
request::FlashMessage,
|
request::FlashMessage,
|
||||||
response::{Flash, Redirect},
|
response::{Flash, Redirect},
|
||||||
routes, FromForm, Route, State,
|
routes,
|
||||||
};
|
};
|
||||||
use rocket_dyn_templates::{context, Template};
|
use rocket_dyn_templates::{Template, context};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
use tera::Context;
|
use tera::Context;
|
||||||
|
|
||||||
use crate::model::{
|
use crate::model::{
|
||||||
activity::ActivityBuilder,
|
|
||||||
log::Log,
|
log::Log,
|
||||||
notification::Notification,
|
notification::Notification,
|
||||||
role::Role,
|
role::Role,
|
||||||
user::{AdminUser, ErgoAdminUser, User, UserWithDetails},
|
user::{AdminUser, User, UserWithDetails},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
@@ -59,7 +59,7 @@ async fn send(db: &State<SqlitePool>, _user: AdminUser) -> Template {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[get("/reset")]
|
#[get("/reset")]
|
||||||
async fn reset(db: &State<SqlitePool>, _user: ErgoAdminUser) -> Flash<Redirect> {
|
async fn reset(db: &State<SqlitePool>, _user: AdminUser) -> Flash<Redirect> {
|
||||||
sqlx::query!("UPDATE user SET dirty_thirty = NULL, dirty_dozen = NULL;")
|
sqlx::query!("UPDATE user SET dirty_thirty = NULL, dirty_dozen = NULL;")
|
||||||
.execute(db.inner())
|
.execute(db.inner())
|
||||||
.await
|
.await
|
||||||
@@ -74,7 +74,7 @@ async fn reset(db: &State<SqlitePool>, _user: ErgoAdminUser) -> Flash<Redirect>
|
|||||||
#[get("/<challenge>/user/<user_id>/new?<new>")]
|
#[get("/<challenge>/user/<user_id>/new?<new>")]
|
||||||
async fn update(
|
async fn update(
|
||||||
db: &State<SqlitePool>,
|
db: &State<SqlitePool>,
|
||||||
_admin: ErgoAdminUser,
|
_admin: AdminUser,
|
||||||
challenge: &str,
|
challenge: &str,
|
||||||
user_id: i64,
|
user_id: i64,
|
||||||
new: &str,
|
new: &str,
|
||||||
@@ -146,61 +146,47 @@ pub struct UserAdd {
|
|||||||
sex: String,
|
sex: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/set-data", data = "<data>")]
|
//#[post("/set-data", data = "<data>")]
|
||||||
async fn new_user(db: &State<SqlitePool>, data: Form<UserAdd>, user: User) -> Flash<Redirect> {
|
//async fn new_user(db: &State<SqlitePool>, data: Form<UserAdd>, user: User) -> Flash<Redirect> {
|
||||||
if user.has_role(db, "ergo").await {
|
// if user.has_role(db, "ergo").await {
|
||||||
return Flash::error(Redirect::to("/ergo"), "Du hast deine Daten schon eingegeben. Wenn du sie updaten willst, melde dich bitte bei info@rudernlinz.at");
|
// return Flash::error(Redirect::to("/ergo"), "Du hast deine Daten schon eingegeben. Wenn du sie updaten willst, melde dich bitte bei it@rudernlinz.at");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// check data
|
// // check data
|
||||||
if data.birthyear < 1900 || data.birthyear > chrono::Utc::now().year() - 5 {
|
// if data.birthyear < 1900 || data.birthyear > chrono::Utc::now().year() - 5 {
|
||||||
return Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Geburtsjahr...");
|
// return Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Geburtsjahr...");
|
||||||
}
|
// }
|
||||||
if data.weight < 20 || data.weight > 200 {
|
// if data.weight < 20 || data.weight > 200 {
|
||||||
return Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Gewicht...");
|
// return Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Gewicht...");
|
||||||
}
|
// }
|
||||||
if &data.sex != "f" && &data.sex != "m" {
|
// if &data.sex != "f" && &data.sex != "m" {
|
||||||
return Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Geschlecht...");
|
// return Flash::error(Redirect::to("/ergo"), "Bitte überprüfe dein Geschlecht...");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// set data
|
// // set data
|
||||||
user.update_ergo(db, data.birthyear, data.weight, &data.sex)
|
// user.update_ergo(db, data.birthyear, data.weight, &data.sex)
|
||||||
.await;
|
// .await;
|
||||||
|
//
|
||||||
// inform all other `ergo` users
|
// // inform all other `ergo` users
|
||||||
let ergo = Role::find_by_name(db, "ergo").await.unwrap();
|
// let ergo = Role::find_by_name(db, "ergo").await.unwrap();
|
||||||
Notification::create_for_role(
|
// Notification::create_for_role(
|
||||||
db,
|
// db,
|
||||||
&ergo,
|
// &ergo,
|
||||||
&format!("{} nimmt heuer an der Ergochallenge teil 💪", user.name),
|
// &format!("{} nimmt heuer an der Ergochallenge teil 💪", user.name),
|
||||||
"Ergo Challenge",
|
// "Ergo Challenge",
|
||||||
None,
|
// None,
|
||||||
None,
|
// None,
|
||||||
)
|
// )
|
||||||
.await;
|
// .await;
|
||||||
|
//
|
||||||
// add to `ergo` group
|
// // add to `ergo` group
|
||||||
sqlx::query!(
|
// user.add_role(db, &ergo).await.unwrap();
|
||||||
"INSERT INTO user_role(user_id, role_id) VALUES (?, ?)",
|
//
|
||||||
user.id,
|
// Flash::success(
|
||||||
ergo.id
|
// Redirect::to("/ergo"),
|
||||||
)
|
// "Du hast deine Daten erfolgreich eingegeben. Viel Spaß beim Schwitzen :-)",
|
||||||
.execute(db.inner())
|
// )
|
||||||
.await
|
//}
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
ActivityBuilder::new(&format!(
|
|
||||||
"{user} nimmt an der Ergo-Challenge teil und hat gerade die Daten eingegeben."
|
|
||||||
))
|
|
||||||
.user(&user)
|
|
||||||
.save(db)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
Flash::success(
|
|
||||||
Redirect::to("/ergo"),
|
|
||||||
"Du hast deine Daten erfolgreich eingegeben. Viel Spaß beim Schwitzen :-)",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(FromForm, Debug)]
|
#[derive(FromForm, Debug)]
|
||||||
pub struct ErgoToAdd<'a> {
|
pub struct ErgoToAdd<'a> {
|
||||||
@@ -373,7 +359,10 @@ async fn new_dozen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
routes![index, new_thirty, new_dozen, send, reset, update, new_user]
|
routes![
|
||||||
|
index, new_thirty, new_dozen, send, reset, update,
|
||||||
|
// new_user
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ async fn index(db: &State<SqlitePool>, user: User, flash: Option<FlashMessage<'_
|
|||||||
|
|
||||||
let date = chrono::Utc::now();
|
let date = chrono::Utc::now();
|
||||||
if date.month() <= 3 || date.month() >= 10 {
|
if date.month() <= 3 || date.month() >= 10 {
|
||||||
context.insert("show_quick_ergo_button", "yes");
|
//context.insert("show_quick_ergo_button", "yes");
|
||||||
}
|
}
|
||||||
|
|
||||||
context.insert("achievements", &Achievements::for_user(db, &user).await);
|
context.insert("achievements", &Achievements::for_user(db, &user).await);
|
||||||
|
|||||||
@@ -15,7 +15,10 @@
|
|||||||
class="link-primary">Überblick der Challenges</a>
|
class="link-primary">Überblick der Challenges</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="py-1">
|
<li class="py-1">
|
||||||
Eintragung ist jederzeit möglich, wenn du sie auch an die offizielle Liste schicken willst, kannst du das <a href="https://data.ergochallenge.at/" target="_blank" style="text-decoration: underline">hier</a> machen
|
Eintragung ist jederzeit möglich, alle Daten die bis Sonntag 23:59 hier hochgeladen wurden, werden gesammelt an die Ister Ergo Challenge geschickt
|
||||||
|
<li class="py-1">
|
||||||
|
Montag → gemeinsames Training; bitte um <a href="/planned" class="link-primary">Anmeldung</a>, damit jeder einen Ergo hat
|
||||||
|
</li>
|
||||||
<li class="py-1">
|
<li class="py-1">
|
||||||
<a href="https://data.ergochallenge.at"
|
<a href="https://data.ergochallenge.at"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -191,7 +194,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
</div>
|
</div>
|
||||||
{% if "admin" in loggedin_user.roles or "ergo-admin" in loggedin_user.roles %}
|
{% if "admin" in loggedin_user.roles %}
|
||||||
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow grid gap-3">
|
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow grid gap-3">
|
||||||
<h2 class="h2">Update</h2>
|
<h2 class="h2">Update</h2>
|
||||||
<details class="p-2">
|
<details class="p-2">
|
||||||
@@ -230,14 +233,6 @@
|
|||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
<div class="mt-3 text-right">
|
|
||||||
<a href="/ergo/reset"
|
|
||||||
class="w-28 btn btn-alert"
|
|
||||||
onclick="return confirm('Willst du wirklich alle Ergo-Eingaben löschen?');">
|
|
||||||
{% include "includes/delete-icon" %}
|
|
||||||
Einträge löschen
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
Reference in New Issue
Block a user