Skip to content

Commit 40ba7bb

Browse files
authored
Persist table column sizes (#45)
1 parent 9040c04 commit 40ba7bb

File tree

3 files changed

+84
-22
lines changed

3 files changed

+84
-22
lines changed

.changeset/three-doors-tell.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@hyperdx/app': patch
3+
---
4+
5+
enhancement - Persist log table column sizes to local storage

packages/app/src/LogTable.tsx

Lines changed: 78 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import {
22
ColumnDef,
3+
ColumnResizeMode,
34
flexRender,
45
getCoreRowModel,
6+
TableOptions,
57
Row as TableRow,
68
useReactTable,
79
} from '@tanstack/react-table';
@@ -20,7 +22,7 @@ import FieldMultiSelect from './FieldMultiSelect';
2022
import InstallInstructionsModal from './InstallInstructionsModal';
2123
import LogLevel from './LogLevel';
2224
import api from './api';
23-
import { usePrevious, useWindowSize } from './utils';
25+
import { useLocalStorage, usePrevious, useWindowSize } from './utils';
2426
import { useSearchEventStream } from './search';
2527
import { useHotkeys } from 'react-hotkeys-hook';
2628

@@ -211,6 +213,7 @@ function LogTableSettingsModal({
211213

212214
export const RawLogTable = memo(
213215
({
216+
tableId,
214217
displayedColumns,
215218
fetchNextPage,
216219
formatUTC,
@@ -252,6 +255,7 @@ export const RawLogTable = memo(
252255
onScroll: (scrollTop: number) => void;
253256
isLive: boolean;
254257
onShowPatternsClick?: () => void;
258+
tableId?: string;
255259
}) => {
256260
const dedupLogs = useMemo(() => {
257261
const lIds = new Set();
@@ -267,6 +271,10 @@ export const RawLogTable = memo(
267271
const { width } = useWindowSize();
268272
const isSmallScreen = (width ?? 1000) < 900;
269273

274+
const [columnSizeStorage, setColumnSizeStorage] = useLocalStorage<
275+
Record<string, number>
276+
>(`${tableId}-column-sizes`, {});
277+
270278
const tsFormat = 'MMM d HH:mm:ss.SSS';
271279
const tsShortFormat = 'HH:mm:ss';
272280
// https://github.com/TanStack/table/discussions/3192#discussioncomment-3873093
@@ -336,7 +344,7 @@ export const RawLogTable = memo(
336344
</span>
337345
);
338346
},
339-
size: isSmallScreen ? 75 : 180,
347+
size: columnSizeStorage.timestamp ?? (isSmallScreen ? 75 : 180),
340348
},
341349
{
342350
accessorKey: 'severity_text',
@@ -351,7 +359,7 @@ export const RawLogTable = memo(
351359
<LogLevel level={info.getValue<string>()} />
352360
</span>
353361
),
354-
size: isSmallScreen ? 50 : 100,
362+
size: columnSizeStorage.severity_text ?? (isSmallScreen ? 50 : 100),
355363
},
356364
{
357365
accessorKey: '_service',
@@ -366,7 +374,7 @@ export const RawLogTable = memo(
366374
{info.getValue<string>()}
367375
</span>
368376
),
369-
size: isSmallScreen ? 70 : 100,
377+
size: columnSizeStorage._service ?? (isSmallScreen ? 70 : 100),
370378
},
371379
...(displayedColumns.map(column => ({
372380
accessorFn: curry(retrieveColumnValue)(column), // Columns can contain '.' and will not work with accessorKey
@@ -383,7 +391,7 @@ export const RawLogTable = memo(
383391
</span>
384392
);
385393
},
386-
size: 150,
394+
size: columnSizeStorage[column] ?? 150,
387395
})) as ColumnDef<any>[]),
388396
{
389397
accessorKey: 'body',
@@ -416,6 +424,7 @@ export const RawLogTable = memo(
416424
displayedColumns,
417425
onShowPatternsClick,
418426
isSmallScreen,
427+
columnSizeStorage,
419428
],
420429
);
421430

@@ -441,14 +450,38 @@ export const RawLogTable = memo(
441450
fetchMoreOnBottomReached(tableContainerRef.current);
442451
}, [fetchMoreOnBottomReached]);
443452

444-
const table = useReactTable({
445-
data: dedupLogs,
446-
columns,
447-
getCoreRowModel: getCoreRowModel(),
448-
// debugTable: true,
449-
enableColumnResizing: true,
450-
columnResizeMode: 'onChange',
451-
});
453+
const reactTableProps = useMemo((): TableOptions<any> => {
454+
//TODO: fix any
455+
const onColumnSizingChange = (updaterOrValue: any) => {
456+
const state =
457+
updaterOrValue instanceof Function
458+
? updaterOrValue()
459+
: updaterOrValue;
460+
setColumnSizeStorage({ ...columnSizeStorage, ...state });
461+
};
462+
463+
const initReactTableProps = {
464+
data: dedupLogs,
465+
columns,
466+
getCoreRowModel: getCoreRowModel(),
467+
// debugTable: true,
468+
enableColumnResizing: true,
469+
columnResizeMode: 'onChange' as ColumnResizeMode,
470+
};
471+
472+
const columnSizeProps = {
473+
state: {
474+
columnSizing: columnSizeStorage,
475+
},
476+
onColumnSizingChange: onColumnSizingChange,
477+
};
478+
479+
return tableId
480+
? { ...initReactTableProps, ...columnSizeProps }
481+
: initReactTableProps;
482+
}, [columns, dedupLogs, tableId, columnSizeStorage, setColumnSizeStorage]);
483+
484+
const table = useReactTable(reactTableProps);
452485

453486
const { rows } = table.getRowModel();
454487

@@ -531,7 +564,7 @@ export const RawLogTable = memo(
531564

532565
return (
533566
<div
534-
className="overflow-auto h-100 fs-8 bg-inherit"
567+
className="overflow-auto h-100 fs-8 bg-inherit py-2"
535568
onScroll={e => {
536569
fetchMoreOnBottomReached(e.target as HTMLDivElement);
537570

@@ -544,7 +577,11 @@ export const RawLogTable = memo(
544577
// Fixes flickering scroll bar: https://github.com/TanStack/virtual/issues/426#issuecomment-1403438040
545578
// style={{ overflowAnchor: 'none' }}
546579
>
547-
<table className="w-100 bg-inherit" style={{ tableLayout: 'fixed' }}>
580+
<table
581+
className="w-100 bg-inherit"
582+
id={tableId}
583+
style={{ tableLayout: 'fixed' }}
584+
>
548585
<thead
549586
className="bg-inherit"
550587
style={{
@@ -600,22 +637,38 @@ export const RawLogTable = memo(
600637
<i className="bi bi-three-dots-vertical" />
601638
</div>
602639
)}
603-
{headerIndex === headerGroup.headers.length - 1 &&
604-
onSettingsClick != null ? (
640+
{headerIndex === headerGroup.headers.length - 1 && (
605641
<div
606-
className="fs-8 text-muted-hover"
642+
className="d-flex align-items-center"
607643
style={{
608644
position: 'absolute',
609645
right: 8,
610646
top: 0,
611647
bottom: 0,
612648
}}
613-
role="button"
614-
onClick={() => onSettingsClick()}
615649
>
616-
<i className="bi bi-gear-fill" />
650+
{tableId != null &&
651+
Object.keys(columnSizeStorage).length > 0 && (
652+
<div
653+
className="fs-8 text-muted-hover disabled"
654+
role="button"
655+
onClick={() => setColumnSizeStorage({})}
656+
title="Reset Column Widths"
657+
>
658+
<i className="bi bi-arrow-clockwise" />
659+
</div>
660+
)}
661+
{onSettingsClick != null && (
662+
<div
663+
className="fs-8 text-muted-hover ms-2"
664+
role="button"
665+
onClick={() => onSettingsClick()}
666+
>
667+
<i className="bi bi-gear-fill" />
668+
</div>
669+
)}
617670
</div>
618-
) : null}
671+
)}
619672
</th>
620673
);
621674
})}
@@ -730,6 +783,7 @@ export default function LogTable({
730783
setIsUTC,
731784
onEnd,
732785
onShowPatternsClick,
786+
tableId,
733787
}: {
734788
config: {
735789
where: string;
@@ -747,6 +801,7 @@ export default function LogTable({
747801
setIsUTC: (isUTC: boolean) => void;
748802
onEnd?: () => void;
749803
onShowPatternsClick?: () => void;
804+
tableId?: string;
750805
}) {
751806
const [instructionsOpen, setInstructionsOpen] = useState(false);
752807
const [settingsOpen, setSettingsOpen] = useState(false);
@@ -833,6 +888,7 @@ export default function LogTable({
833888
}
834889
/>
835890
<RawLogTable
891+
tableId={tableId}
836892
isLive={isLive}
837893
wrapLines={wrapLines}
838894
displayedColumns={displayedColumns}

packages/app/src/SearchPage.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ const LogViewerContainer = memo(function LogViewerContainer({
349349
/>
350350
</ErrorBoundary>
351351
<LogTable
352+
tableId="search-table"
352353
isLive={isLive}
353354
setIsUTC={setIsUTC}
354355
onScroll={useCallback(

0 commit comments

Comments
 (0)