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,7 +10,6 @@
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-row justify-center items-end">
|
|
||||||
<form class="flex flex-row justify-center space-x-4 mx-4 my-2">
|
<form class="flex flex-row justify-center space-x-4 mx-4 my-2">
|
||||||
<Input size="sm" placeholder="Alle" bind:value={reportFilter.reporter}>
|
<Input size="sm" placeholder="Alle" bind:value={reportFilter.reporter}>
|
||||||
<span slot="label">Report Ersteller</span>
|
<span slot="label">Report Ersteller</span>
|
||||||
@ -30,4 +29,3 @@
|
|||||||
<option value={null}>Erstellt & Entwurf</option>
|
<option value={null}>Erstellt & Entwurf</option>
|
||||||
</Select>
|
</Select>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
import type { User } from '$lib/server/database';
|
import type { User } from '$lib/server/database';
|
||||||
import { buttonTriggeredRequest, resizeTableColumn } from '$lib/components/utils';
|
import { buttonTriggeredRequest, resizeTableColumn } from '$lib/components/utils';
|
||||||
import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
|
import HeaderBar from './HeaderBar.svelte';
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
|
||||||
@ -44,33 +45,24 @@
|
|||||||
|
|
||||||
let currentPageUsers: (typeof User.prototype.dataValues)[] = [];
|
let currentPageUsers: (typeof User.prototype.dataValues)[] = [];
|
||||||
let currentPageUsersRequest: Promise<void> = new Promise((resolve) => resolve());
|
let currentPageUsersRequest: Promise<void> = new Promise((resolve) => resolve());
|
||||||
let usersCache: (typeof User.prototype.dataValues)[][] = [];
|
|
||||||
let usersPerPage = 50;
|
let usersPerPage = 50;
|
||||||
let userPage = 0;
|
let userPage = 0;
|
||||||
|
let userFilter = { name: null, edition: null };
|
||||||
let userTableContainerElement: HTMLDivElement;
|
let userTableContainerElement: HTMLDivElement;
|
||||||
|
|
||||||
function fetchPageUsers(page: number) {
|
function fetchPageUsers(page: number, filter: any) {
|
||||||
if (!browser) return;
|
if (!browser) return;
|
||||||
|
|
||||||
if (userTableContainerElement) userTableContainerElement.scrollTop = 0;
|
if (userTableContainerElement) userTableContainerElement.scrollTop = 0;
|
||||||
|
|
||||||
if (usersCache[page]) {
|
|
||||||
currentPageUsers = usersCache[page];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-async-promise-executor
|
// eslint-disable-next-line no-async-promise-executor
|
||||||
currentPageUsersRequest = new Promise(async (resolve, reject) => {
|
currentPageUsersRequest = new Promise(async (resolve, reject) => {
|
||||||
const response = await fetch(`${env.PUBLIC_BASE_PATH}/admin/users`, {
|
const response = await fetch(`${env.PUBLIC_BASE_PATH}/admin/users`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({ ...filter, limit: usersPerPage, from: usersPerPage * page })
|
||||||
limit: usersPerPage,
|
|
||||||
from: usersPerPage * page
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const pageUsers = await response.json();
|
currentPageUsers = await response.json();
|
||||||
currentPageUsers = usersCache[page] = pageUsers;
|
|
||||||
resolve();
|
resolve();
|
||||||
} else {
|
} else {
|
||||||
reject(Error());
|
reject(Error());
|
||||||
@ -97,7 +89,7 @@
|
|||||||
currentPageUsers = currentPageUsers;
|
currentPageUsers = currentPageUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
$: fetchPageUsers(userPage);
|
$: fetchPageUsers(userPage, userFilter);
|
||||||
|
|
||||||
async function updateUser(user: typeof User.prototype.dataValues) {
|
async function updateUser(user: typeof User.prototype.dataValues) {
|
||||||
const response = await fetch(`${env.PUBLIC_BASE_PATH}/admin/users`, {
|
const response = await fetch(`${env.PUBLIC_BASE_PATH}/admin/users`, {
|
||||||
@ -129,6 +121,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
<HeaderBar bind:userFilter />
|
||||||
|
<hr class="divider my-1 mx-8 border-none" />
|
||||||
<div class="h-[90vh] overflow-scroll" bind:this={userTableContainerElement}>
|
<div class="h-[90vh] overflow-scroll" bind:this={userTableContainerElement}>
|
||||||
<table class="table relative">
|
<table class="table relative">
|
||||||
<thead>
|
<thead>
|
||||||
@ -158,46 +152,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#key currentPageUsersRequest}
|
{#key currentPageUsersRequest}
|
||||||
{#await currentPageUsersRequest}
|
{#await currentPageUsersRequest then _}
|
||||||
{#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 _}
|
|
||||||
{#each currentPageUsers as user, i}
|
{#each currentPageUsers as user, i}
|
||||||
<tr>
|
<tr>
|
||||||
<td on:mousedown={(e) => resizeTableColumn(e, 5)}>{i + 1}</td>
|
<td on:mousedown={(e) => resizeTableColumn(e, 5)}>{i + 1}</td>
|
||||||
|
@ -14,12 +14,24 @@ export const POST = (async ({ request, cookies }) => {
|
|||||||
const data: {
|
const data: {
|
||||||
limit: number | null;
|
limit: number | null;
|
||||||
from: number | null;
|
from: number | null;
|
||||||
|
|
||||||
|
name: string | null;
|
||||||
|
edition: 'java' | 'bedrock' | 'cracked' | null;
|
||||||
|
|
||||||
search: string | null;
|
search: string | null;
|
||||||
slim: boolean | null;
|
slim: boolean | null;
|
||||||
} = await request.json();
|
} = await request.json();
|
||||||
|
|
||||||
const usersFindOptions: Attributes<User> = {};
|
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, {
|
Object.assign(usersFindOptions, {
|
||||||
[Op.or]: {
|
[Op.or]: {
|
||||||
username: { [Op.like]: `%${data.search}%` },
|
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({
|
const users = await User.findAll({
|
||||||
where: usersFindOptions,
|
where: usersFindOptions,
|
||||||
attributes: data.slim ? ['username', 'uuid'] : undefined,
|
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