feat(table,runs,sessions): add server-side sorting and pagination
- add sortable column support to Table with asc/desc/unsorted icons - active sort icon uses --color-primary; no header background change - Table supports server-side mode via total/page/onPageChange props - wire server-side sort+pagination in ScenariosPage, AllRunsPage, RunsPage, SessionsPage - remove steps count column from run tables - fix server: RunsQueryDto now extends PaginationQueryDto with orderBy/orderDir - fix findAllRuns to use QueryBuilder; sort by scenario.name via JOIN - add per-resource typed query DTOs with @IsIn allowlist on orderBy - prevents SQL injection and returns 400 for unknown orderBy values
This commit is contained in:
@@ -162,8 +162,8 @@ export const environments = {
|
||||
// ── Sessions ──────────────────────────────────────────────────────────────────
|
||||
|
||||
export const sessions = {
|
||||
list(page = 1, limit = 50): Promise<PaginatedResponse<Session>> {
|
||||
return request(`/sessions?page=${page}&limit=${limit}`);
|
||||
list(page = 1, limit = 50, orderBy = 'id', orderDir: 'ASC' | 'DESC' = 'DESC'): Promise<PaginatedResponse<Session>> {
|
||||
return request(`/sessions?page=${page}&limit=${limit}&orderBy=${orderBy}&orderDir=${orderDir}`);
|
||||
},
|
||||
get(id: string): Promise<Session> {
|
||||
return request(`/sessions/${id}`);
|
||||
@@ -176,8 +176,13 @@ export const sessions = {
|
||||
// ── Scenarios ─────────────────────────────────────────────────────────────────
|
||||
|
||||
export const scenarios = {
|
||||
list(page = 1, limit = 50): Promise<PaginatedResponse<Scenario>> {
|
||||
return request(`/scenarios?page=${page}&limit=${limit}&orderBy=updatedAt&orderDir=DESC`);
|
||||
list(
|
||||
page = 1,
|
||||
limit = 50,
|
||||
orderBy = 'updatedAt',
|
||||
orderDir: 'ASC' | 'DESC' = 'DESC',
|
||||
): Promise<PaginatedResponse<Scenario>> {
|
||||
return request(`/scenarios?page=${page}&limit=${limit}&orderBy=${orderBy}&orderDir=${orderDir}`);
|
||||
},
|
||||
get(id: string): Promise<Scenario & { steps: ScenarioStep[] }> {
|
||||
return request(`/scenarios/${id}`);
|
||||
@@ -245,12 +250,14 @@ export const runs = {
|
||||
page = 1,
|
||||
limit = 20,
|
||||
status?: string,
|
||||
orderBy = 'createdAt',
|
||||
orderDir: 'ASC' | 'DESC' = 'DESC',
|
||||
): Promise<
|
||||
PaginatedResponse<
|
||||
ScenarioRun & { stepRuns: ScenarioRunStep[]; scenario: { id: string; name: string } }
|
||||
>
|
||||
> {
|
||||
const q = new URLSearchParams({ page: String(page), limit: String(limit) });
|
||||
const q = new URLSearchParams({ page: String(page), limit: String(limit), orderBy, orderDir });
|
||||
if (status) q.set('status', status);
|
||||
return request(`/scenarios/runs?${q}`);
|
||||
},
|
||||
@@ -258,8 +265,10 @@ export const runs = {
|
||||
scenarioId: string,
|
||||
page = 1,
|
||||
limit = 20,
|
||||
orderBy = 'createdAt',
|
||||
orderDir: 'ASC' | 'DESC' = 'DESC',
|
||||
): Promise<PaginatedResponse<ScenarioRun & { stepRuns: ScenarioRunStep[] }>> {
|
||||
return request(`/scenarios/${scenarioId}/runs?page=${page}&limit=${limit}`);
|
||||
return request(`/scenarios/${scenarioId}/runs?page=${page}&limit=${limit}&orderBy=${orderBy}&orderDir=${orderDir}`);
|
||||
},
|
||||
get(scenarioId: string, runId: string, q?: string): Promise<ScenarioRunDetail> {
|
||||
const qs = q?.trim() ? `?q=${encodeURIComponent(q.trim())}` : '';
|
||||
|
||||
Reference in New Issue
Block a user