feat: improve report ui

This commit is contained in:
Sam 2023-05-17 13:26:23 +02:00
parent a72546658f
commit 130a1996d7
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
3 changed files with 106 additions and 8 deletions

View file

@ -59,7 +59,13 @@ func (db *DB) Reports(ctx context.Context, closed bool, before int) (rs []Report
} }
func (db *DB) ReportsByUser(ctx context.Context, userID xid.ID, before int) (rs []Report, err error) { func (db *DB) ReportsByUser(ctx context.Context, userID xid.ID, before int) (rs []Report, err error) {
builder := sq.Select("*").From("reports").Where("user_id = ?", userID).Limit(ReportPageSize).OrderBy("id DESC") builder := sq.Select("*",
"(SELECT username FROM users WHERE id = reports.user_id) AS user_name",
"(SELECT name FROM members WHERE id = reports.member_id) AS member_name").
From("reports").
Where("user_id = ?", userID).
Limit(ReportPageSize).
OrderBy("id DESC")
if before != 0 { if before != 0 {
builder = builder.Where("id < ?", before) builder = builder.Where("id < ?", before)
} }
@ -79,7 +85,13 @@ func (db *DB) ReportsByUser(ctx context.Context, userID xid.ID, before int) (rs
} }
func (db *DB) ReportsByReporter(ctx context.Context, reporterID xid.ID, before int) (rs []Report, err error) { func (db *DB) ReportsByReporter(ctx context.Context, reporterID xid.ID, before int) (rs []Report, err error) {
builder := sq.Select("*").From("reports").Where("reporter_id = ?", reporterID).Limit(ReportPageSize).OrderBy("id DESC") builder := sq.Select("*",
"(SELECT username FROM users WHERE id = reports.user_id) AS user_name",
"(SELECT name FROM members WHERE id = reports.member_id) AS member_name").
From("reports").
Where("reporter_id = ?", reporterID).
Limit(ReportPageSize).
OrderBy("id DESC")
if before != 0 { if before != 0 {
builder = builder.Where("id < ?", before) builder = builder.Where("id < ?", before)
} }

View file

@ -3,7 +3,7 @@
import { fastFetchClient } from "$lib/api/fetch"; import { fastFetchClient } from "$lib/api/fetch";
import ErrorAlert from "$lib/components/ErrorAlert.svelte"; import ErrorAlert from "$lib/components/ErrorAlert.svelte";
import { addToast } from "$lib/toast"; import { addToast } from "$lib/toast";
import { Button, FormGroup, Modal, ModalBody, ModalFooter } from "sveltestrap"; import { Button, ButtonGroup, FormGroup, Modal, ModalBody, ModalFooter } from "sveltestrap";
import type { PageData } from "./$types"; import type { PageData } from "./$types";
import ReportCard from "./ReportCard.svelte"; import ReportCard from "./ReportCard.svelte";
@ -88,6 +88,18 @@
error = e as APIError; error = e as APIError;
} }
}; };
const urlParamsWith = (name: string, value: string) => {
const params = new URLSearchParams(window.location.search);
params.set(name, value);
return params.toString();
};
const urlParamsWithout = (name: string) => {
const params = new URLSearchParams(window.location.search);
params.delete(name);
return params.toString();
};
</script> </script>
<svelte:head> <svelte:head>
@ -97,6 +109,36 @@
<div class="container"> <div class="container">
<h1>Reports</h1> <h1>Reports</h1>
<div>
<ButtonGroup>
{#if data.userId || data.reporterId}
<Button color="secondary" disabled>Showing all reports</Button>
{:else if data.isClosed}
<Button color="primary" href="/reports?{urlParamsWith('closed', 'false')}"
>Showing closed reports</Button
>
{:else}
<Button color="secondary" href="/reports?{urlParamsWith('closed', 'true')}"
>Showing open reports</Button
>
{/if}
{#if data.userId}
<Button color="secondary" href="/reports?{urlParamsWithout('user_id')}"
>Filtering on specific user</Button
>
{:else}
<Button color="secondary" disabled>Not filtering on user</Button>
{/if}
{#if data.reporterId}
<Button color="secondary" href="/reports?{urlParamsWithout('reporter_id')}"
>Filtering on specific reporter</Button
>
{:else}
<Button color="secondary" disabled>Not filtering on reporter</Button>
{/if}
</ButtonGroup>
</div>
<div> <div>
{#each data.reports as report, index} {#each data.reports as report, index}
<div class="my-2"> <div class="my-2">
@ -111,13 +153,28 @@
<Button outline color="secondary" size="sm" on:click={() => openIgnoreModalFor(index)} <Button outline color="secondary" size="sm" on:click={() => openIgnoreModalFor(index)}
>Ignore report</Button >Ignore report</Button
> >
&bull;
<a href="/reports?user_id={report.user_id}">Show all reports of this user</a>
&bull;
<a href="/reports?reporter_id={report.reporter_id}">Show all reports by this reporter</a>
</ReportCard> </ReportCard>
</div> </div>
{:else} {:else}
There are no open reports :) There are no reports matching your search!
{/each} {/each}
</div> </div>
{#if data.reports.length >= 100}
<div>
<a
href="/reports?{urlParamsWith(
'before',
data.reports[data.reports.length - 1].id.toString(),
)}">Load more reports</a
>
</div>
{/if}
<Modal header="Warn user" isOpen={warnModalOpen} toggle={toggleWarnModal}> <Modal header="Warn user" isOpen={warnModalOpen} toggle={toggleWarnModal}>
<ModalBody> <ModalBody>
{#if error} {#if error}

View file

@ -2,10 +2,39 @@ import { ErrorCode, type APIError, type Report } from "$lib/api/entities";
import { apiFetchClient } from "$lib/api/fetch"; import { apiFetchClient } from "$lib/api/fetch";
import { error } from "@sveltejs/kit"; import { error } from "@sveltejs/kit";
export const load = async () => { export const load = async ({ url }) => {
const { searchParams } = url;
const before = +(searchParams.get("before") || 0);
const userId = searchParams.get("user_id");
const reporterId = searchParams.get("reporter_id");
const isClosed = searchParams.get("closed") === "true";
try { try {
const reports = await apiFetchClient<Report[]>("/admin/reports"); let reports: Report[];
return { page: 0, isClosed: false, userId: null, reporterId: null, reports } as PageLoadData; if (userId) {
const params = new URLSearchParams();
if (before) params.append("before", before.toString());
reports = await apiFetchClient<Report[]>(
`/admin/reports/by-user/${userId}?${params.toString()}`,
);
} else if (reporterId) {
const params = new URLSearchParams();
if (before) params.append("before", before.toString());
reports = await apiFetchClient<Report[]>(
`/admin/reports/by-reporter/${reporterId}?${params.toString()}`,
);
} else {
const params = new URLSearchParams();
if (before) params.append("before", before.toString());
if (isClosed) params.append("closed", "true");
reports = await apiFetchClient<Report[]>(`/admin/reports?${params.toString()}`);
}
return { before, isClosed, userId, reporterId, reports } as PageLoadData;
} catch (e) { } catch (e) {
if ((e as APIError).code === ErrorCode.Forbidden) { if ((e as APIError).code === ErrorCode.Forbidden) {
throw error(400, "You're not an admin"); throw error(400, "You're not an admin");
@ -15,7 +44,7 @@ export const load = async () => {
}; };
interface PageLoadData { interface PageLoadData {
page: number; before: number;
isClosed: boolean; isClosed: boolean;
userId: string | null; userId: string | null;
reporterId: string | null; reporterId: string | null;