forked from mirrors/pronouns.cc
feat: improve report ui
This commit is contained in:
parent
a72546658f
commit
130a1996d7
3 changed files with 106 additions and 8 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
>
|
>
|
||||||
|
•
|
||||||
|
<a href="/reports?user_id={report.user_id}">Show all reports of this user</a>
|
||||||
|
•
|
||||||
|
<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}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue