add user search in admin panel and remove user skeleton while loading data
All checks were successful
delpoy / build-and-deploy (push) Successful in 31s

This commit is contained in:
bytedream 2023-09-30 01:42:59 +02:00
parent b7177708a7
commit b1f546ee94
4 changed files with 69 additions and 76 deletions

View File

@ -10,7 +10,6 @@
};
</script>
<div class="flex flex-row justify-center items-end">
<form class="flex flex-row justify-center space-x-4 mx-4 my-2">
<Input size="sm" placeholder="Alle" bind:value={reportFilter.reporter}>
<span slot="label">Report Ersteller</span>
@ -30,4 +29,3 @@
<option value={null}>Erstellt & Entwurf</option>
</Select>
</form>
</div>

View File

@ -7,6 +7,7 @@
import type { User } from '$lib/server/database';
import { buttonTriggeredRequest, resizeTableColumn } from '$lib/components/utils';
import { browser } from '$app/environment';
import HeaderBar from './HeaderBar.svelte';
export let data: PageData;
@ -44,33 +45,24 @@
let currentPageUsers: (typeof User.prototype.dataValues)[] = [];
let currentPageUsersRequest: Promise<void> = new Promise((resolve) => resolve());
let usersCache: (typeof User.prototype.dataValues)[][] = [];
let usersPerPage = 50;
let userPage = 0;
let userFilter = { name: null, edition: null };
let userTableContainerElement: HTMLDivElement;
function fetchPageUsers(page: number) {
function fetchPageUsers(page: number, filter: any) {
if (!browser) return;
if (userTableContainerElement) userTableContainerElement.scrollTop = 0;
if (usersCache[page]) {
currentPageUsers = usersCache[page];
return;
}
// eslint-disable-next-line no-async-promise-executor
currentPageUsersRequest = new Promise(async (resolve, reject) => {
const response = await fetch(`${env.PUBLIC_BASE_PATH}/admin/users`, {
method: 'POST',
body: JSON.stringify({
limit: usersPerPage,
from: usersPerPage * page
})
body: JSON.stringify({ ...filter, limit: usersPerPage, from: usersPerPage * page })
});
if (response.ok) {
const pageUsers = await response.json();
currentPageUsers = usersCache[page] = pageUsers;
currentPageUsers = await response.json();
resolve();
} else {
reject(Error());
@ -97,7 +89,7 @@
currentPageUsers = currentPageUsers;
}
$: fetchPageUsers(userPage);
$: fetchPageUsers(userPage, userFilter);
async function updateUser(user: typeof User.prototype.dataValues) {
const response = await fetch(`${env.PUBLIC_BASE_PATH}/admin/users`, {
@ -129,6 +121,8 @@
</script>
<div>
<HeaderBar bind:userFilter />
<hr class="divider my-1 mx-8 border-none" />
<div class="h-[90vh] overflow-scroll" bind:this={userTableContainerElement}>
<table class="table relative">
<thead>
@ -158,46 +152,7 @@
</thead>
<tbody>
{#key currentPageUsersRequest}
{#await currentPageUsersRequest}
{#each Array(usersPerPage) as _, i}
<tr class="animate-pulse text-transparent">
<td on:mousedown={(e) => resizeTableColumn(e, 5)}>{i + 1}</td>
<td on:mousedown={(e) => resizeTableColumn(e, 5)}
><Input type="text" disabled={true} size="sm" /></td
>
<td on:mousedown={(e) => resizeTableColumn(e, 5)}
><Input type="text" disabled={true} size="sm" /></td
>
<td on:mousedown={(e) => resizeTableColumn(e, 5)}
><Input type="date" disabled={true} size="sm" /></td
>
<td on:mousedown={(e) => resizeTableColumn(e, 5)}
><Input type="tel" disabled={true} size="sm" /></td
>
<td on:mousedown={(e) => resizeTableColumn(e, 5)}
><Input type="text" disabled={true} size="sm" /></td
>
<td on:mousedown={(e) => resizeTableColumn(e, 5)}
><Select id="edition" disabled={true} size="sm">
<option value="java">Java Edition</option>
<option value="bedrock">Bedrock Edition</option>
<option value="cracked">Java cracked</option>
</Select></td
>
<td on:mousedown={(e) => resizeTableColumn(e, 5)}
><Input type="text" disabled={true} size="sm" /></td
>
<td on:mousedown={(e) => resizeTableColumn(e, 5)}
><Input type="text" disabled={true} size="sm" /></td
>
<td on:mousedown={(e) => resizeTableColumn(e, 5)}
><div class="flex gap-1">
<button class="btn btn-sm btn-square" disabled />
</div></td
>
</tr>
{/each}
{:then _}
{#await currentPageUsersRequest then _}
{#each currentPageUsers as user, i}
<tr>
<td on:mousedown={(e) => resizeTableColumn(e, 5)}>{i + 1}</td>

View File

@ -14,12 +14,24 @@ export const POST = (async ({ request, cookies }) => {
const data: {
limit: number | null;
from: number | null;
name: string | null;
edition: 'java' | 'bedrock' | 'cracked' | null;
search: string | null;
slim: boolean | null;
} = await request.json();
const usersFindOptions: Attributes<User> = {};
if (data.search) {
if (data.name) {
Object.assign(usersFindOptions, {
[Op.or]: {
firstname: { [Op.like]: `%${data.name}%` },
lastname: { [Op.like]: `%${data.name}%` },
username: { [Op.like]: `%${data.name}%` }
}
});
} else if (data.search) {
Object.assign(usersFindOptions, {
[Op.or]: {
username: { [Op.like]: `%${data.search}%` },
@ -27,6 +39,9 @@ export const POST = (async ({ request, cookies }) => {
}
});
}
if (data.edition) {
usersFindOptions.edition = data.edition;
}
const users = await User.findAll({
where: usersFindOptions,
attributes: data.slim ? ['username', 'uuid'] : undefined,

View File

@ -0,0 +1,25 @@
<script lang="ts">
import Select from '$lib/components/Input/Select.svelte';
import Input from '$lib/components/Input/Input.svelte';
export let userFilter = {
name: null,
edition: null
};
</script>
<form class="flex flex-row justify-center items-center space-x-4 mx-4 my-2 w-full">
<div class="w-1/6">
<Input size="sm" placeholder="..." bind:value={userFilter.name}>
<span slot="label">Suche</span>
</Input>
</div>
<div class="w-1/6">
<Select label="Edition" size="sm" bind:value={userFilter.edition}>
<option value={null}>Alle</option>
<option value="java">Java</option>
<option value="beckdrock">Bedrock</option>
<option value="cracked">Cracked</option>
</Select>
</div>
</form>