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
All checks were successful
delpoy / build-and-deploy (push) Successful in 31s
This commit is contained in:
parent
b7177708a7
commit
b1f546ee94
@ -10,24 +10,22 @@
|
||||
};
|
||||
</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>
|
||||
</Input>
|
||||
<Input size="sm" placeholder="Alle" bind:value={reportFilter.reported}>
|
||||
<span slot="label">Reportete Spieler</span>
|
||||
</Input>
|
||||
<Select label="Bearbeitungsstatus" size="sm" bind:value={reportFilter.status}>
|
||||
<option value="none">Unbearbeitet</option>
|
||||
<option value="review">In Bearbeitung</option>
|
||||
<option value={null}>Unbearbeitet & In Bearbeitung</option>
|
||||
<option value="reviewed">Bearbeitet</option>
|
||||
</Select>
|
||||
<Select label="Reportstatus" size="sm" bind:value={reportFilter.draft}>
|
||||
<option value={false}>Erstellt</option>
|
||||
<option value={true}>Entwurf</option>
|
||||
<option value={null}>Erstellt & Entwurf</option>
|
||||
</Select>
|
||||
</form>
|
||||
</div>
|
||||
<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>
|
||||
</Input>
|
||||
<Input size="sm" placeholder="Alle" bind:value={reportFilter.reported}>
|
||||
<span slot="label">Reportete Spieler</span>
|
||||
</Input>
|
||||
<Select label="Bearbeitungsstatus" size="sm" bind:value={reportFilter.status}>
|
||||
<option value="none">Unbearbeitet</option>
|
||||
<option value="review">In Bearbeitung</option>
|
||||
<option value={null}>Unbearbeitet & In Bearbeitung</option>
|
||||
<option value="reviewed">Bearbeitet</option>
|
||||
</Select>
|
||||
<Select label="Reportstatus" size="sm" bind:value={reportFilter.draft}>
|
||||
<option value={false}>Erstellt</option>
|
||||
<option value={true}>Entwurf</option>
|
||||
<option value={null}>Erstellt & Entwurf</option>
|
||||
</Select>
|
||||
</form>
|
||||
|
@ -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>
|
||||
|
@ -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,
|
||||
|
25
src/routes/admin/users/HeaderBar.svelte
Normal file
25
src/routes/admin/users/HeaderBar.svelte
Normal 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>
|
Loading…
x
Reference in New Issue
Block a user