Merge pull request 'upd' (#864) from upd into main

Reviewed-on: Ruderverein-Donau-Linz/rowt#864
This commit is contained in:
philipp 2025-02-12 07:13:13 +01:00
commit 2a37bcbec5
4 changed files with 81 additions and 27 deletions

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

@ -591,18 +591,27 @@ WHERE lower(name)=?
}
pub async fn all(db: &SqlitePool) -> Vec<Self> {
sqlx::query_as!(
Self,
"
SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id, user_token
FROM user
WHERE deleted = 0
ORDER BY last_access DESC
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!(
"
)
.fetch_all(db)
.await
.unwrap()
SELECT id, name, pw, deleted, last_access, dob, weight, sex, member_since_date, birthdate, mail, nickname, notes, phone, address, family_id, 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

@ -43,13 +43,17 @@ impl<'r> FromRequest<'r> for Referer {
}
}
#[get("/user")]
#[get("/user?<sort>&<asc>")]
async fn index(
db: &State<SqlitePool>,
user: VorstandUser,
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 { UserWithRolesAndMembershipPdf::from_user(db, u).await })

View File

@ -4,37 +4,59 @@
<div class="max-w-screen-lg w-full">
<h1 class="h1">Users</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">Neuen User hinzufügen</h2>
<div class="grid md:grid-cols-3">
<div>
<label for="name" class="sr-only">Name</label>
<input type="text"
name="name"
class="relative block rounded-md border-0 py-1.5 px-2 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-primary-600 sm:text-sm sm:leading-6 mb-2 md:mb-0"
placeholder="Name" />
</div>
<div>
<label for="name" class="sr-only">Name</label>
<input type="text"
name="name"
class="input rounded-md w-100"
placeholder="Name" />
</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>, 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>
@ -47,7 +69,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 and user.mail %}
{% if not user.last_access and allowed_to_edit and user.mail %}
<form action="/admin/user"
method="post"
enctype="multipart/form-data"