feat: add refresh functionality for bug reports and improve pagination logic
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import type { PageServerLoad } from './$types';
|
||||
import { db } from '$lib/server/db';
|
||||
import { bugReports, bugReportFiles } from '$lib/schema';
|
||||
import { eq, like, or, count, sql, desc } from 'drizzle-orm';
|
||||
import { eq, like, or, count, sql, desc, and } from 'drizzle-orm';
|
||||
|
||||
export const load: PageServerLoad = async ({ url }) => {
|
||||
const page = Math.max(1, Number(url.searchParams.get('page')) || 1);
|
||||
@@ -10,44 +10,31 @@ export const load: PageServerLoad = async ({ url }) => {
|
||||
const search = url.searchParams.get('search') || '';
|
||||
|
||||
const conditions = [];
|
||||
|
||||
if (status && ['new', 'in_review', 'resolved', 'closed'].includes(status)) {
|
||||
conditions.push(eq(bugReports.status, status as 'new' | 'in_review' | 'resolved' | 'closed'));
|
||||
}
|
||||
|
||||
if (search) {
|
||||
const pattern = `%${search}%`;
|
||||
conditions.push(
|
||||
or(
|
||||
like(bugReports.hostname, pattern),
|
||||
like(bugReports.os_user, pattern),
|
||||
like(bugReports.name, pattern),
|
||||
like(bugReports.email, pattern)
|
||||
)!
|
||||
like(bugReports.hostname, `%${search}%`),
|
||||
like(bugReports.os_user, `%${search}%`),
|
||||
like(bugReports.name, `%${search}%`),
|
||||
like(bugReports.email, `%${search}%`)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const where = conditions.length > 0
|
||||
? conditions.length === 1
|
||||
? conditions[0]
|
||||
: sql`${conditions[0]} AND ${conditions[1]}`
|
||||
: undefined;
|
||||
const where = conditions.length > 0 ? and(...conditions) : undefined;
|
||||
|
||||
const [totalResult] = await db
|
||||
.select({ count: count() })
|
||||
// Get total count
|
||||
const [{ total }] = await db
|
||||
.select({ total: count() })
|
||||
.from(bugReports)
|
||||
.where(where);
|
||||
|
||||
const total = totalResult.count;
|
||||
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
||||
|
||||
const fileCountSubquery = db
|
||||
.select({
|
||||
report_id: bugReportFiles.report_id,
|
||||
file_count: count().as('file_count')
|
||||
})
|
||||
.from(bugReportFiles)
|
||||
.groupBy(bugReportFiles.report_id)
|
||||
.as('fc');
|
||||
|
||||
// Get paginated reports with file count
|
||||
const reports = await db
|
||||
.select({
|
||||
id: bugReports.id,
|
||||
@@ -57,21 +44,27 @@ export const load: PageServerLoad = async ({ url }) => {
|
||||
os_user: bugReports.os_user,
|
||||
status: bugReports.status,
|
||||
created_at: bugReports.created_at,
|
||||
file_count: sql<number>`COALESCE(${fileCountSubquery.file_count}, 0)`.as('file_count')
|
||||
file_count: count(bugReportFiles.id)
|
||||
})
|
||||
.from(bugReports)
|
||||
.leftJoin(fileCountSubquery, eq(bugReports.id, fileCountSubquery.report_id))
|
||||
.leftJoin(bugReportFiles, eq(bugReports.id, bugReportFiles.report_id))
|
||||
.where(where)
|
||||
.groupBy(bugReports.id)
|
||||
.orderBy(desc(bugReports.created_at))
|
||||
.limit(pageSize)
|
||||
.offset((page - 1) * pageSize);
|
||||
|
||||
return {
|
||||
reports: reports.map((r) => ({
|
||||
...r,
|
||||
created_at: r.created_at.toISOString()
|
||||
})),
|
||||
pagination: { page, pageSize, total, totalPages },
|
||||
filters: { status, search }
|
||||
reports,
|
||||
pagination: {
|
||||
page,
|
||||
pageSize,
|
||||
total,
|
||||
totalPages: Math.ceil(total / pageSize)
|
||||
},
|
||||
filters: {
|
||||
status,
|
||||
search
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { goto, invalidateAll } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { statusColors, statusLabels, formatDate } from '$lib/utils';
|
||||
import { Search, ChevronLeft, ChevronRight, Filter, Paperclip } from 'lucide-svelte';
|
||||
import { Search, ChevronLeft, ChevronRight, Filter, Paperclip, RefreshCcw } from 'lucide-svelte';
|
||||
|
||||
let { data } = $props();
|
||||
|
||||
@@ -33,6 +33,14 @@
|
||||
statusFilter = '';
|
||||
goto('/');
|
||||
}
|
||||
|
||||
async function refreshReports() {
|
||||
try {
|
||||
await invalidateAll();
|
||||
} catch (err) {
|
||||
console.error('Failed to refresh reports:', err);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="space-y-4">
|
||||
@@ -66,6 +74,13 @@
|
||||
<Filter class="h-4 w-4" />
|
||||
Filter
|
||||
</button>
|
||||
<button
|
||||
onclick={refreshReports}
|
||||
class="inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90"
|
||||
>
|
||||
<RefreshCcw class="h-4 w-4" />
|
||||
Filter
|
||||
</button>
|
||||
{#if data.filters.search || data.filters.status}
|
||||
<button
|
||||
onclick={clearFilters}
|
||||
|
||||
13
dashboard/src/routes/api/reports/refresh/+server.ts
Normal file
13
dashboard/src/routes/api/reports/refresh/+server.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { RequestHandler } from './$types';
|
||||
import { json } from '@sveltejs/kit';
|
||||
import { db } from '$lib/server/db';
|
||||
import { bugReports } from '$lib/schema';
|
||||
import { count } from 'drizzle-orm';
|
||||
|
||||
export const GET: RequestHandler = async () => {
|
||||
const [{ total }] = await db
|
||||
.select({ total: count() })
|
||||
.from(bugReports);
|
||||
|
||||
return json({ total });
|
||||
};
|
||||
Reference in New Issue
Block a user