Skip to content

Commit 91b62ac

Browse files
committed
Improve sorting
1 parent 19694c2 commit 91b62ac

4 files changed

Lines changed: 39 additions & 23 deletions

File tree

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
import { Table } from '@mantine/core';
22

3-
import { SortColumn } from '../types';
3+
import { SortColumn, SortDirection } from '../types';
44

55
interface Props {
66
sortKey: SortColumn;
77
label: string;
88
onSort: (col: SortColumn) => void;
9+
activeColumn?: SortColumn;
10+
direction?: SortDirection;
911
}
1012

11-
export function SortableHeader({ sortKey, label, onSort }: Props) {
13+
export function SortableHeader({ sortKey, label, onSort, activeColumn, direction }: Props) {
14+
const isActive = activeColumn === sortKey;
15+
const indicator = isActive ? (direction === 'asc' ? ' ↑' : ' ↓') : '';
1216
return (
13-
<Table.Th style={{ cursor: 'pointer' }} onClick={() => onSort(sortKey)}>
14-
{label}
17+
<Table.Th style={{ cursor: 'pointer', whiteSpace: 'nowrap' }} onClick={() => onSort(sortKey)}>
18+
{label}{indicator}
1519
</Table.Th>
1620
);
1721
}

backend/frontend/src/pages/Home.tsx

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from 'react';
1+
import { useMemo, useEffect, useState } from 'react';
22
import { Link } from 'react-router-dom';
33
import {
44
Anchor,
@@ -17,7 +17,7 @@ import {
1717
import { SortableHeader } from '../components/SortableHeader';
1818
import { TestHistory } from '../components/TestHistory';
1919
import { TestRow } from '../components/TestRow';
20-
import { SortColumn, TestRecord } from '../types';
20+
import { SortColumn, SortDirection, TestRecord } from '../types';
2121
import { sortRecords } from '../utils';
2222

2323
export default function Home() {
@@ -26,6 +26,8 @@ export default function Home() {
2626
const [selectedHardware, setSelectedHardware] = useState<Set<string>>(new Set());
2727
const [adminToken, setAdminToken] = useState('');
2828
const [selectedRecord, setSelectedRecord] = useState<TestRecord | null>(null);
29+
const [sortCol, setSortCol] = useState<SortColumn>('pixelError');
30+
const [sortDir, setSortDir] = useState<SortDirection>('desc');
2931

3032
useEffect(() => {
3133
fetch('/api/test-records')
@@ -34,12 +36,13 @@ export default function Home() {
3436
const hardwares = [...new Set(data.map((r) => r.hardware))].sort();
3537
setAllHardware(hardwares);
3638
setSelectedHardware(new Set(hardwares));
37-
setRecords(sortRecords(data, 'pixelError'));
39+
setRecords(data);
3840
});
3941
}, []);
4042

4143
function handleSort(column: SortColumn) {
42-
setRecords((prev) => sortRecords(prev, column));
44+
setSortDir((prev) => (column === sortCol ? (prev === 'asc' ? 'desc' : 'asc') : 'asc'));
45+
setSortCol(column);
4346
}
4447

4548
function toggleHardware(hw: string) {
@@ -74,7 +77,10 @@ export default function Home() {
7477
}
7578
}
7679

77-
const visibleRecords = records.filter((r) => selectedHardware.has(r.hardware));
80+
const visibleRecords = useMemo(
81+
() => sortRecords(records, sortCol, sortDir).filter((r) => selectedHardware.has(r.hardware)),
82+
[records, sortCol, sortDir, selectedHardware]
83+
);
7884

7985
return (
8086
<Box>
@@ -142,16 +148,18 @@ export default function Home() {
142148
<Table striped highlightOnHover withColumnBorders stickyHeader>
143149
<Table.Thead>
144150
<Table.Tr>
145-
<SortableHeader sortKey={'pixelError'} label={'Error'} onSort={handleSort} />
146-
<SortableHeader sortKey={'group'} label={'Group'} onSort={handleSort} />
147-
<SortableHeader sortKey={'name'} label={'Name'} onSort={handleSort} />
148-
<SortableHeader sortKey={'hardware'} label={'Hardware'} onSort={handleSort} />
149-
<SortableHeader sortKey={'timing'} label={'Timing'} onSort={handleSort} />
150-
<SortableHeader sortKey={'commitHash'} label={'Commit'} onSort={handleSort} />
151+
<SortableHeader sortKey={'pixelError'} label={'Error'} onSort={handleSort} activeColumn={sortCol} direction={sortDir} />
152+
<SortableHeader sortKey={'group'} label={'Group'} onSort={handleSort} activeColumn={sortCol} direction={sortDir} />
153+
<SortableHeader sortKey={'name'} label={'Name'} onSort={handleSort} activeColumn={sortCol} direction={sortDir} />
154+
<SortableHeader sortKey={'hardware'} label={'Hardware'} onSort={handleSort} activeColumn={sortCol} direction={sortDir} />
155+
<SortableHeader sortKey={'timing'} label={'Timing'} onSort={handleSort} activeColumn={sortCol} direction={sortDir} />
156+
<SortableHeader sortKey={'commitHash'} label={'Commit'} onSort={handleSort} activeColumn={sortCol} direction={sortDir} />
151157
<SortableHeader
152158
sortKey={'timeStamp'}
153159
label={'Timestamp'}
154160
onSort={handleSort}
161+
activeColumn={sortCol}
162+
direction={sortDir}
155163
/>
156164
<Table.Th>Candidate</Table.Th>
157165
<Table.Th>Reference</Table.Th>

backend/frontend/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ export type SortColumn =
2121
| 'group'
2222
| 'name'
2323
| 'hardware';
24+
25+
export type SortDirection = 'asc' | 'desc';

backend/frontend/src/utils.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { SortColumn, TestRecord } from './types';
1+
import { SortColumn, SortDirection, TestRecord } from './types';
22

33
export function diffDisplay(diff: number): string {
44
return `${Math.round(diff * 100000) / 1000}%`;
@@ -34,20 +34,22 @@ export function diffStyle(diff: number): { backgroundColor: string; color: strin
3434
else return { backgroundColor: '#cc0000', color: '#ffffff' };
3535
}
3636

37-
export function sortRecords(records: TestRecord[], column: SortColumn): TestRecord[] {
37+
export function sortRecords(
38+
records: TestRecord[],
39+
column: SortColumn,
40+
direction: SortDirection = 'asc'
41+
): TestRecord[] {
42+
const sign = direction === 'asc' ? 1 : -1;
3843
return [...records].sort((a, b) => {
3944
if (column === 'group' || column === 'name' || column === 'hardware') {
40-
return a[column] > b[column] ? 1 : -1;
45+
return (a[column] > b[column] ? 1 : -1) * sign;
4146
}
4247
const aData = a.data[a.data.length - 1];
4348
const bData = b.data[b.data.length - 1];
4449
if (!aData || !bData) return 0;
4550
if (column === 'timeStamp') {
46-
return new Date(aData.timeStamp) > new Date(bData.timeStamp) ? 1 : -1;
51+
return (new Date(aData.timeStamp) > new Date(bData.timeStamp) ? 1 : -1) * sign;
4752
}
48-
if (column === 'pixelError') {
49-
return aData.pixelError < bData.pixelError ? 1 : -1;
50-
}
51-
return aData[column] > bData[column] ? 1 : -1;
53+
return (aData[column] > bData[column] ? 1 : -1) * sign;
5254
});
5355
}

0 commit comments

Comments
 (0)