From 6fde852473d9dcf53be6456a484847a69314cff2 Mon Sep 17 00:00:00 2001 From: Thiago Dallacqua Date: Tue, 22 Oct 2024 13:01:21 -0300 Subject: [PATCH] refactor: Update column definition keys and handle columns order change. --- .../react/src/components/ColumnPickerMenu.tsx | 77 ++++++------------- webui/react/src/pages/FlatRuns/FlatRuns.tsx | 26 +++---- 2 files changed, 34 insertions(+), 69 deletions(-) diff --git a/webui/react/src/components/ColumnPickerMenu.tsx b/webui/react/src/components/ColumnPickerMenu.tsx index f3bdccbfd398..a5f56e0a110a 100644 --- a/webui/react/src/components/ColumnPickerMenu.tsx +++ b/webui/react/src/components/ColumnPickerMenu.tsx @@ -8,7 +8,7 @@ import Message from 'hew/Message'; import Pivot from 'hew/Pivot'; import Spinner from 'hew/Spinner'; import { Loadable } from 'hew/utils/loadable'; -import React, { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react'; +import React, { ChangeEvent, useCallback, useMemo, useState } from 'react'; import { FixedSizeList as List } from 'react-window'; import { V1LocationType } from 'services/api-ts-sdk'; @@ -22,6 +22,8 @@ const BANNED_COLUMNS: Set = new Set([]); const removeBannedColumns = (columns: ProjectColumn[]) => columns.filter((col) => !BANNED_COLUMNS.has(col.column)); +export const METADATA_SEPARATOR = '\u241F' as const; + export const LOCATION_LABEL_MAP: Record = { [V1LocationType.EXPERIMENT]: 'General', [V1LocationType.RUN]: 'General', @@ -64,6 +66,11 @@ interface ColumnTabProps { onHeatmapSelectionRemove?: (id: string) => void; } +export const formatColumnKey = (col: ProjectColumn): string => { + if (col.location === 'LOCATION_TYPE_RUN_METADATA') return `${col.type}${METADATA_SEPARATOR}${col.column}`; + return col.column; +}; + const ColumnPickerTab: React.FC = ({ columnState, compare, @@ -96,27 +103,12 @@ const ColumnPickerTab: React.FC = ({ }, [searchString, totalColumns, tab]); const allFilteredColumnsChecked = useMemo(() => { - return filteredColumns.every((col) => { - const colType = col.type.replace('COLUMN_TYPE_', ''); - - if (col.column.includes('metadata')) - return columnState.includes(col.column.concat(`_${colType}`)); - return columnState.includes(col.column); - }); + return filteredColumns.every((col) => columnState.includes(formatColumnKey(col))); }, [columnState, filteredColumns]); - const [metadataColumns, setMetadataColumns] = useState(() => new Map()); // a map of metadata columns and found indexes const handleShowHideAll = useCallback(() => { const filteredColumnMap: Record = filteredColumns.reduce((acc, col) => { - const colType = col.type.replace('COLUMN_TYPE_', ''); - - if (col.column.includes('metadata')) - return { - ...acc, - [col.column.concat(`_${colType}`)]: columnState.includes( - col.column.concat(`_${colType}`), - ), - }; + if (col.column.includes('metadata')) return { ...acc, [formatColumnKey(col)]: columnState.includes(formatColumnKey(col)) }; return { ...acc, [col.column]: columnState.includes(col.column) }; }, {}); @@ -127,9 +119,7 @@ const ColumnPickerTab: React.FC = ({ ...new Set([ ...columnState, ...filteredColumns.map((col) => { - const colType = col.type.replace('COLUMN_TYPE_', ''); - - if (col.column.includes('metadata')) return col.column.concat(`_${colType}`); + if (col.column.includes('metadata')) formatColumnKey(col); return col.column; }), ]), @@ -154,8 +144,7 @@ const ColumnPickerTab: React.FC = ({ if (id === undefined) return; - const [col] = id.split('_'); - const targetCol = col.includes('metadata') ? id : col; + const targetCol = id; if (compare) { // pin or unpin column @@ -199,61 +188,43 @@ const ColumnPickerTab: React.FC = ({ const col = filteredColumns[index]; const colType = col.type.replace('COLUMN_TYPE_', ''); const getColDisplayName = (col: ProjectColumn) => { - const metCol = metadataColumns.get(col.column); - - if (metCol !== undefined && metCol.length > 1) { - return ( - <> - {col.column} - - ); - } - return ( <> {col.displayName || col.column} ); }; + const getId = () => { + if (col.column.includes('metadata')) return formatColumnKey(col); + + return col.column; + }; const getChecked = () => { - if (col.column.includes('metadata')) - return checkedColumnNames.has(`${col.column}_${colType}`); + if (col.column.includes('metadata')) return checkedColumnNames.has(formatColumnKey(col)); + return checkedColumnNames.has(col.column); }; + return (
{getColDisplayName(col)}
); }, - [filteredColumns, checkedColumnNames, metadataColumns, handleColumnChange], + [filteredColumns, checkedColumnNames, handleColumnChange], ); - useEffect(() => { - for (const [index, { column }] of totalColumns.entries()) { - if (column.includes('metadata')) { - const columnEntry = metadataColumns.get(column) ?? []; - if (!columnEntry.includes(index)) { - setMetadataColumns((prev) => { - prev.set(column, [...columnEntry, index]); - return prev; - }); - } - } - } - }, [totalColumns, metadataColumns]); - return (
= ({ projectId, workspaceId, searchId }) => { const projectColumnsMap: Loadable> = Loadable.map( projectColumns, (columns) => { - return columns.reduce((acc, col) => { - const colType = col.type.replace('COLUMN_TYPE_', ''); - - if (col.column.includes('metadata')) - return { ...acc, [col.column.concat(`_${colType}`)]: col }; - - return { ...acc, [col.column]: col }; - }, {}); + return columns.reduce((acc, col) => ({ ...acc, [`${col.type}${METADATA_SEPARATOR}${col.column}`]: col }), {}); }, ); const columnDefs = getColumnDefs({ @@ -365,6 +358,7 @@ const FlatRuns: React.FC = ({ projectId, workspaceId, searchId }) => { }; let dataPath: string | undefined = undefined; + const columnDefKey = formatColumnKey(currentColumn); switch (currentColumn.location) { case V1LocationType.EXPERIMENT: dataPath = `experiment.${currentColumn.column}`; @@ -405,7 +399,7 @@ const FlatRuns: React.FC = ({ projectId, workspaceId, searchId }) => { settings.heatmapOn && !settings.heatmapSkipped.includes(currentColumn.column) ) { - columnDefs[currentColumn.column] = defaultNumberColumn( + columnDefs[columnDefKey] = defaultNumberColumn( currentColumn.column, currentColumn.displayName || currentColumn.column, settings.columnWidths[currentColumn.column] ?? @@ -418,7 +412,7 @@ const FlatRuns: React.FC = ({ projectId, workspaceId, searchId }) => { }, ); } else { - columnDefs[currentColumn.column] = defaultNumberColumn( + columnDefs[columnDefKey] = defaultNumberColumn( currentColumn.column, currentColumn.displayName || currentColumn.column, settings.columnWidths[currentColumn.column] ?? @@ -431,7 +425,7 @@ const FlatRuns: React.FC = ({ projectId, workspaceId, searchId }) => { break; } case V1ColumnType.DATE: - columnDefs[currentColumn.column] = defaultDateColumn( + columnDefs[columnDefKey] = defaultDateColumn( currentColumn.column, currentColumn.displayName || currentColumn.column, settings.columnWidths[currentColumn.column] ?? @@ -441,7 +435,7 @@ const FlatRuns: React.FC = ({ projectId, workspaceId, searchId }) => { ); break; case V1ColumnType.ARRAY: - columnDefs[currentColumn.column] = defaultArrayColumn( + columnDefs[columnDefKey] = defaultArrayColumn( currentColumn.column, currentColumn.displayName || currentColumn.column, settings.columnWidths[currentColumn.column] ?? @@ -453,7 +447,7 @@ const FlatRuns: React.FC = ({ projectId, workspaceId, searchId }) => { case V1ColumnType.TEXT: case V1ColumnType.UNSPECIFIED: default: - columnDefs[currentColumn.column] = defaultTextColumn( + columnDefs[columnDefKey] = defaultTextColumn( currentColumn.column, currentColumn.displayName || currentColumn.column, settings.columnWidths[currentColumn.column] ?? @@ -467,7 +461,7 @@ const FlatRuns: React.FC = ({ projectId, workspaceId, searchId }) => { .getOrElse([]) .find((h) => h.metricsName === currentColumn.column); - columnDefs[currentColumn.column] = searcherMetricsValColumn( + columnDefs[columnDefKey] = searcherMetricsValColumn( settings.columnWidths[currentColumn.column], heatmap && settings.heatmapOn && !settings.heatmapSkipped.includes(currentColumn.column) ? { @@ -477,7 +471,7 @@ const FlatRuns: React.FC = ({ projectId, workspaceId, searchId }) => { : undefined, ); } - return columnDefs[currentColumn.column]; + return columnDefs[columnDefKey]; }) .flatMap((col) => (col ? [col] : [])); return gridColumns;