Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 29 additions & 21 deletions static/app/views/explore/components/table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,18 @@ export function useTableStyles(
tableRef: React.RefObject<HTMLDivElement | null>,
options?: {
minimumColumnWidth?: number;
onResizeEnd?: () => void;
prefixColumnWidth?: 'min-content' | number;
staticColumnWidths?: Record<string, number | 'minmax(90px,1fr)'>;
staticColumnWidths?: Record<string, number | string>;
}
) {
const minimumColumnWidth = options?.minimumColumnWidth ?? MINIMUM_COLUMN_WIDTH;
const prefixColumnWidth =
defined(options?.prefixColumnWidth) && typeof options.prefixColumnWidth === 'number'
? `${options.prefixColumnWidth}px`
: options?.prefixColumnWidth;
const staticColumnWidths = options?.staticColumnWidths;
const onResizeEnd = options?.onResizeEnd;

const resizingColumnIndex = useRef<number | null>(null);
const columnWidthsRef = useRef<Array<number | null>>(fields.map(_ => null));
Expand All @@ -84,21 +87,33 @@ export function useTableStyles(
);
}, [fields]);

const initialTableStyles = useMemo(() => {
const gridTemplateColumns = fields.map(field => {
const staticWidth = options?.staticColumnWidths?.[field];
const getColumnTemplateWidth = useCallback(
(field: string, index: number) => {
const resizedWidth = columnWidthsRef.current[index];
if (typeof resizedWidth === 'number') {
return `${resizedWidth}px`;
}
const staticWidth = staticColumnWidths?.[field];
if (staticWidth) {
return typeof staticWidth === 'number' ? `${staticWidth}px` : staticWidth;
}
return `minmax(${minimumColumnWidth}px, auto)`;
});
},
[minimumColumnWidth, staticColumnWidths]
);

const buildGridTemplateColumns = useCallback(() => {
const tracks = fields.map(getColumnTemplateWidth);
if (defined(prefixColumnWidth)) {
gridTemplateColumns.unshift(prefixColumnWidth);
tracks.unshift(prefixColumnWidth);
}
return {
gridTemplateColumns: gridTemplateColumns.join(' '),
};
}, [fields, minimumColumnWidth, prefixColumnWidth, options?.staticColumnWidths]);
return tracks.join(' ');
}, [fields, prefixColumnWidth, getColumnTemplateWidth]);

const initialTableStyles = useMemo(
() => ({gridTemplateColumns: buildGridTemplateColumns()}),
[buildGridTemplateColumns]
);

const onResizeMouseDown = useCallback(
(event: React.MouseEvent<HTMLDivElement>, index: number) => {
Expand Down Expand Up @@ -129,16 +144,7 @@ export function useTableStyles(

columnWidthsRef.current[index] = newWidth;

// Updating the grid's `gridTemplateColumns` directly
const gridTemplateColumns = columnWidthsRef.current.map(width => {
return typeof width === 'number'
? `${width}px`
: `minmax(${minimumColumnWidth}px, auto)`;
});
if (defined(prefixColumnWidth)) {
gridTemplateColumns.unshift(prefixColumnWidth);
}
gridElement.style.gridTemplateColumns = gridTemplateColumns.join(' ');
gridElement.style.gridTemplateColumns = buildGridTemplateColumns();
}

function onMouseUp() {
Expand All @@ -147,12 +153,14 @@ export function useTableStyles(
// Cleaning up event listeners
window.removeEventListener('mousemove', onMouseMove);
window.removeEventListener('mouseup', onMouseUp);

onResizeEnd?.();
}

window.addEventListener('mousemove', onMouseMove);
window.addEventListener('mouseup', onMouseUp);
},
[tableRef, minimumColumnWidth, prefixColumnWidth]
[buildGridTemplateColumns, minimumColumnWidth, onResizeEnd, tableRef]
);

return {initialTableStyles, onResizeMouseDown};
Expand Down
31 changes: 20 additions & 11 deletions static/app/views/explore/logs/tables/logsInfiniteTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import {
import {calculateLogsTableMinWidth} from 'sentry/views/explore/logs/tables/calculateLogsTableMinWidth';
import {LogsEmptyResults} from 'sentry/views/explore/logs/tables/logsEmptyResults';
import {LogRowContent} from 'sentry/views/explore/logs/tables/logsTableRow';
import {useLogsTableColumnWidths} from 'sentry/views/explore/logs/tables/useLogsTableColumnWidths';
import {
OurLogKnownFieldKey,
type OurLogsResponseItem,
Expand Down Expand Up @@ -239,17 +240,6 @@ export function LogsInfiniteTable({
const scrollFetchDisabled = isFunctionScrolling || autorefreshEnabled;

const sharedHoverTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const {initialTableStyles, onResizeMouseDown} = useTableStyles(
fields.slice(),
tableRef,
{
minimumColumnWidth: 50,
prefixColumnWidth: 'min-content',
staticColumnWidths: {
[OurLogKnownFieldKey.MESSAGE]: 'minmax(90px,1fr)',
},
}
);

const estimateSize = useCallback(
(index: number) => {
Expand Down Expand Up @@ -361,6 +351,25 @@ export function LogsInfiniteTable({

const {scrollDirection, scrollOffset, isScrolling} = virtualizer;

const [staticColumnWidths, clearColumnWidths] = useLogsTableColumnWidths({
fields,
tableRef,
isPending,
isScrolling,
dataLength: data?.length ?? 0,
});

const {initialTableStyles, onResizeMouseDown} = useTableStyles(
fields.slice(),
tableRef,
{
minimumColumnWidth: 50,
prefixColumnWidth: 'min-content',
staticColumnWidths,
onResizeEnd: clearColumnWidths,
}
);
Comment thread
cursor[bot] marked this conversation as resolved.

useEffect(() => {
if (isFunctionScrolling && !isScrolling && scrollOffset === 0) {
setTimeout(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {useCallback, useEffect, useState, type RefObject} from 'react';

import {useWindowSize} from 'sentry/utils/window/useWindowSize';
import {OurLogKnownFieldKey} from 'sentry/views/explore/logs/types';

type LogsTableColumnWidthOptions = {
dataLength: number;
fields: readonly string[];
isPending: boolean;
isScrolling: boolean;
tableRef: RefObject<HTMLElement | null>;
};

type ColumnWidths = Record<string, number | string>;

export function useLogsTableColumnWidths({
fields,
tableRef,
isPending,
isScrolling,
dataLength,
}: LogsTableColumnWidthOptions) {
const [columnWidths, setColumnWidths] = useState<ColumnWidths | undefined>();
const windowSize = useWindowSize();

const clearColumnWidths = useCallback(() => setColumnWidths(undefined), []);

useEffect(() => {
setColumnWidths(undefined);
}, [fields, windowSize]);

useEffect(() => {
if (
!dataLength ||
!isScrolling ||
!tableRef.current ||
columnWidths !== undefined ||
isPending
) {
return;
}

const domWidths = getComputedStyle(tableRef.current).gridTemplateColumns.split(/\s+/);

setColumnWidths(
Object.fromEntries(
fields.map((field, i) => {
if (field === OurLogKnownFieldKey.MESSAGE) {
return [field, 'minmax(90px, 99fr)'];
}
if (i === fields.length - 1) {
return [field, 'minmax(0px, 1fr)'];
}
return [field, parseFloat(domWidths[i + 1]!)];
})
)
);
}, [isScrolling, isPending, dataLength, columnWidths, fields, tableRef]);

return [columnWidths, clearColumnWidths] as const;
}
Loading