forked from Ruderverein-Donau-Linz/rowt
		
	Merge pull request 'upd' (#864) from upd into main
Reviewed-on: Ruderverein-Donau-Linz/rowt#864
This commit is contained in:
		@@ -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');
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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> {
 | 
			
		||||
 
 | 
			
		||||
@@ -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 })
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user