diff --git a/src/src/components/Table/Table.tsx b/src/src/components/Table/Table.tsx index 915b8dae..1dc04e77 100644 --- a/src/src/components/Table/Table.tsx +++ b/src/src/components/Table/Table.tsx @@ -2,7 +2,7 @@ /* eslint-disable react/prop-types */ import React from 'react'; -import { isEmpty, isEqual, isNil } from 'lodash-es'; +import { isEmpty, isEqual, isNil, debounce } from 'lodash-es'; import { useResizeObserver } from 'hooks'; import _ from 'lodash-es'; @@ -26,6 +26,7 @@ import ManageColumnsPopover from 'pages/Metrics/components/Table/ManageColumnsPo import HideRowsPopover from 'pages/Metrics/components/Table/HideRowsPopover/HideRowsPopover'; import RowHeightPopover from 'pages/Metrics/components/Table/RowHeightPopover/RowHeightPopover'; import CompareSelectedRunsPopover from 'pages/Metrics/components/Table/CompareSelectedRunsPopover'; +import HideColumnsPopover from 'pages/Metrics/components/Table/HideColumnsPopover/HideColumnsPopover'; import { ITableProps } from 'types/components/Table/Table'; @@ -51,6 +52,7 @@ const Table = React.forwardRef(function Table( onRowHover = () => {}, onRowClick = () => {}, onTableResizeModeChange, + onDefaultColumnsVisibilityChange, custom, data, columns, @@ -71,6 +73,7 @@ const Table = React.forwardRef(function Table( updateColumnsWidths, sortFields, hiddenRows, + unselectedColumnState, isLoading, showRowClickBehaviour = true, showResizeContainerActionBar = true, @@ -379,19 +382,21 @@ const Table = React.forwardRef(function Table( const groupRow = dataRef.current[groupKey]; if (!!groupRow && !!groupRow.data) { if (colKey === 'value') { + const { min, line, max, stdDevValue, stdErrValue } = + groupRow.data.aggregation.area; groupHeaderRowCell.children[0].children[0].children[0].textContent = - groupRow.data.aggregation.area.min; + min; groupHeaderRowCell.children[0].children[0].children[1].textContent = - groupRow.data.aggregation.line; + line; groupHeaderRowCell.children[0].children[0].children[2].textContent = - groupRow.data.aggregation.area.max; + max; if (!isNil(groupRow.data.aggregation.area.stdDevValue)) { groupHeaderRowCell.children[0].children[0].children[3].textContent = - groupRow.data.aggregation.area.stdDevValue; + stdDevValue; } if (!isNil(groupRow.data.aggregation.area.stdErrValue)) { groupHeaderRowCell.children[0].children[0].children[3].textContent = - groupRow.data.aggregation.area.stdErrValue; + stdErrValue; } } else { groupHeaderRowCell.textContent = groupRow.data[colKey]; @@ -604,22 +609,9 @@ const Table = React.forwardRef(function Table( React.useEffect(() => { if (custom && !!tableContainerRef.current) { - const windowEdges = calculateWindow({ - scrollTop: tableContainerRef.current.scrollTop, - offsetHeight: tableContainerRef.current.offsetHeight, - scrollHeight: tableContainerRef.current.scrollHeight, - itemHeight: rowHeight, - groupMargin: - ROW_CELL_SIZE_CONFIG[rowHeight]?.groupMargin ?? - ROW_CELL_SIZE_CONFIG[RowHeightSize.md].groupMargin, - }); - - startIndex.current = windowEdges.startIndex; - endIndex.current = windowEdges.endIndex; - - virtualizedUpdate(); - - tableContainerRef.current.onscroll = ({ target }) => { + // Debounce the scroll event to avoid performance issues + const handleScroll = debounce(() => { + const target = tableContainerRef.current; const windowEdges = calculateWindow({ scrollTop: target.scrollTop, offsetHeight: target.offsetHeight, @@ -651,15 +643,16 @@ const Table = React.forwardRef(function Table( } } setListWindowMeasurements(); + }, 30); + + tableContainerRef.current.addEventListener('scroll', handleScroll); + + return () => { + if (tableContainerRef.current) { + tableContainerRef.current.removeEventListener('scroll', handleScroll); + } }; } - - return () => { - if (custom && tableContainerRef.current) { - // eslint-disable-next-line react-hooks/exhaustive-deps - tableContainerRef.current.onscroll = null; - } - }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [custom, rowData]); @@ -803,6 +796,15 @@ const Table = React.forwardRef(function Table( data={dataRef.current} /> )} + {onDefaultColumnsVisibilityChange && ( + + )} {onSort && ( = { resizeMode: ResizeModeEnum.Resizable, rowHeight: RowHeightSize.md, sortFields: [], + unselectedColumnState: UnselectedColumnState.FORCE_HIDE, hideSystemMetrics: true, hiddenMetrics: [], hiddenColumns: ['hash', 'description'], @@ -58,6 +65,7 @@ export const TABLE_DEFAULT_CONFIG: Record = { resizeMode: ResizeModeEnum.Resizable, rowHeight: RowHeightSize.md, sortFields: [], + unselectedColumnState: UnselectedColumnState.FORCE_HIDE, hiddenMetrics: [], hiddenColumns: ['hash', 'description'], nonHidableColumns: new Set(['#', 'run', 'actions']), @@ -73,6 +81,7 @@ export const TABLE_DEFAULT_CONFIG: Record = { resizeMode: ResizeModeEnum.Resizable, rowHeight: RowHeightSize.md, sortFields: [], + unselectedColumnState: UnselectedColumnState.FORCE_HIDE, hiddenMetrics: [], hiddenColumns: ['hash', 'description'], nonHidableColumns: new Set(['#', 'run', 'actions']), @@ -89,6 +98,7 @@ export const TABLE_DEFAULT_CONFIG: Record = { resizeMode: ResizeModeEnum.Resizable, rowHeight: RowHeightSize.md, sortFields: [], + unselectedColumnState: UnselectedColumnState.FORCE_HIDE, hiddenMetrics: [], hiddenColumns: ['hash', 'description'], nonHidableColumns: new Set(['#', 'run', 'actions']), diff --git a/src/src/pages/Metrics/Metrics.tsx b/src/src/pages/Metrics/Metrics.tsx index 56fb2edd..035433c5 100644 --- a/src/src/pages/Metrics/Metrics.tsx +++ b/src/src/pages/Metrics/Metrics.tsx @@ -259,6 +259,7 @@ function Metrics( resizeMode={props.resizeMode} columnsWidths={props.columnsWidths} selectedRows={props.selectedRows} + unselectedColumnState={props.unselectedColumnState} hideSystemMetrics={props.hideSystemMetrics} appName={AppNameEnum.METRICS} hiddenChartRows={props.lineChartData?.length === 0} @@ -272,6 +273,9 @@ function Metrics( onColumnsVisibilityChange={ props.onColumnsVisibilityChange } + onDefaultColumnsVisibilityChange={ + props.onDefaultColumnsVisibilityChange + } onTableDiffShow={props.onTableDiffShow} onRowHeightChange={props.onRowHeightChange} onRowsChange={props.onMetricVisibilityChange} diff --git a/src/src/pages/Metrics/MetricsContainer.tsx b/src/src/pages/Metrics/MetricsContainer.tsx index 70d93f0b..5df2a791 100644 --- a/src/src/pages/Metrics/MetricsContainer.tsx +++ b/src/src/pages/Metrics/MetricsContainer.tsx @@ -159,6 +159,9 @@ function MetricsContainer(): React.FunctionComponentElement { hiddenMetrics={metricsData?.config?.table?.hiddenMetrics!} hideSystemMetrics={metricsData?.config?.table?.hideSystemMetrics!} hiddenColumns={metricsData?.config?.table?.hiddenColumns!} + unselectedColumnState={ + metricsData?.config?.table?.unselectedColumnState! + } chartPanelOffsetHeight={chartPanelOffsetHeight} selectedRows={metricsData?.selectedRows!} groupingSelectOptions={metricsData?.groupingSelectOptions!} @@ -209,6 +212,9 @@ function MetricsContainer(): React.FunctionComponentElement { onMetricVisibilityChange={metricAppModel.onMetricVisibilityChange} onColumnsOrderChange={metricAppModel.onColumnsOrderChange} onColumnsVisibilityChange={metricAppModel.onColumnsVisibilityChange} + onDefaultColumnsVisibilityChange={ + metricAppModel.onDefaultColumnsVisibilityChange + } onTableDiffShow={metricAppModel.onTableDiffShow} onTableResizeModeChange={metricAppModel.onTableResizeModeChange} onRowsVisibilityChange={metricAppModel.onRowsVisibilityChange} diff --git a/src/src/pages/Metrics/components/Table/HideColumnsPopover/HideColumnsPopover.scss b/src/src/pages/Metrics/components/Table/HideColumnsPopover/HideColumnsPopover.scss new file mode 100644 index 00000000..cb0a3cee --- /dev/null +++ b/src/src/pages/Metrics/components/Table/HideColumnsPopover/HideColumnsPopover.scss @@ -0,0 +1,27 @@ +@use 'src/styles/abstracts' as *; + +.HideColumnsPopover { + padding: 0.5rem; + width: 16.5rem; + &__item { + text-transform: capitalize; + } +} + +.HideColumnsPopover__trigger { + cursor: pointer; + display: flex; + align-items: center; + border: 0.0625rem solid transparent; + transition: all 0.18s ease-out; + border-radius: $radius-main; + padding: 0 0.375rem !important; + margin-right: 0.375rem !important; + i { + margin-right: 0.75rem; + } + &.opened { + border: $border-main-active; + background-color: $primary-color-10; + } +} diff --git a/src/src/pages/Metrics/components/Table/HideColumnsPopover/HideColumnsPopover.tsx b/src/src/pages/Metrics/components/Table/HideColumnsPopover/HideColumnsPopover.tsx new file mode 100644 index 00000000..cba7cf84 --- /dev/null +++ b/src/src/pages/Metrics/components/Table/HideColumnsPopover/HideColumnsPopover.tsx @@ -0,0 +1,131 @@ +import React from 'react'; + +import { MenuItem, Tooltip } from '@material-ui/core'; + +import { Button, Icon, Text } from 'components/kit'; +import ControlPopover from 'components/ControlPopover/ControlPopover'; +import ErrorBoundary from 'components/ErrorBoundary/ErrorBoundary'; + +import { UnselectedColumnState } from 'config/table/tableConfigs'; + +import { AppNameEnum } from 'services/models/explorer'; + +import './HideColumnsPopover.scss'; + +function HideColumnsPopover({ + unselectedColumnState, + onDefaultColumnsVisibilityChange, + appName, +}: { + unselectedColumnState: UnselectedColumnState; + onDefaultColumnsVisibilityChange: (value: UnselectedColumnState) => void; + appName: AppNameEnum; +}) { + const columnStateChanged: boolean = React.useMemo(() => { + return unselectedColumnState !== UnselectedColumnState.DEFAULT; + }, [unselectedColumnState]); + + const [unselectedColumnLocal, setUnselectedColumnLocal] = + React.useState(unselectedColumnState); + + // Triggers re-rendering on unselectedColumnState change + React.useEffect(() => { + setUnselectedColumnLocal(unselectedColumnState); + }, [unselectedColumnState]); + + function handleDefaultColumnsVisibilityChange( + value: UnselectedColumnState, + ): void { + onDefaultColumnsVisibilityChange(value); + setUnselectedColumnLocal(value); + } + + return ( + + ( + + + + + + Hide Columns by Default + + + + + )} + component={ + + + + handleDefaultColumnsVisibilityChange( + UnselectedColumnState.FORCE_HIDE, + ) + } + > + Always Hide Unselected + + + + + handleDefaultColumnsVisibilityChange( + UnselectedColumnState.FORCE_SHOW, + ) + } + > + Always Show Unselected + + + + + handleDefaultColumnsVisibilityChange( + UnselectedColumnState.DEFAULT, + ) + } + > + Default + + + + } + /> + + ); +} + +export default React.memo(HideColumnsPopover); diff --git a/src/src/pages/Params/Params.tsx b/src/src/pages/Params/Params.tsx index 7876db40..730a0364 100644 --- a/src/src/pages/Params/Params.tsx +++ b/src/src/pages/Params/Params.tsx @@ -72,6 +72,7 @@ const Params = ({ resizeMode, notifyData, hiddenColumns, + unselectedColumnState, liveUpdateConfig, selectFormData, selectedParams, @@ -97,6 +98,7 @@ const Params = ({ onTableResizeModeChange, onNotificationDelete, onColumnsVisibilityChange, + onDefaultColumnsVisibilityChange, onTableDiffShow, onSortReset, onAxisBrushExtentChange, @@ -327,6 +329,7 @@ const Params = ({ hiddenRows={hiddenMetrics} hiddenColumns={hiddenColumns} hideSystemMetrics={hideSystemMetrics} + unselectedColumnState={unselectedColumnState} resizeMode={resizeMode} columnsWidths={columnsWidths} selectedRows={selectedRows} @@ -339,6 +342,9 @@ const Params = ({ onSort={onSortFieldsChange} onExport={onExportTableData} onColumnsVisibilityChange={onColumnsVisibilityChange} + onDefaultColumnsVisibilityChange={ + onDefaultColumnsVisibilityChange + } onManageColumns={onColumnsOrderChange} onRowHeightChange={onRowHeightChange} onRowsChange={onParamVisibilityChange} diff --git a/src/src/pages/Params/ParamsContainer.tsx b/src/src/pages/Params/ParamsContainer.tsx index be30c2cb..85afa293 100644 --- a/src/src/pages/Params/ParamsContainer.tsx +++ b/src/src/pages/Params/ParamsContainer.tsx @@ -155,6 +155,7 @@ function ParamsContainer(): React.FunctionComponentElement { sortOptions={paramsData?.sortOptions!} hiddenColumns={paramsData?.config?.table?.hiddenColumns!} hideSystemMetrics={paramsData?.config?.table?.hideSystemMetrics!} + unselectedColumnState={paramsData?.config?.table?.unselectedColumnState!} columnsOrder={paramsData?.config?.table?.columnsOrder!} resizeMode={paramsData?.config?.table?.resizeMode!} hiddenMetrics={paramsData?.config?.table?.hiddenMetrics!} @@ -191,6 +192,9 @@ function ParamsContainer(): React.FunctionComponentElement { onRunsTagsChange={paramsAppModel.onRunsTagsChange} onColumnsOrderChange={paramsAppModel.onColumnsOrderChange} onColumnsVisibilityChange={paramsAppModel.onColumnsVisibilityChange} + onDefaultColumnsVisibilityChange={ + paramsAppModel.onDefaultColumnsVisibilityChange + } onTableResizeModeChange={paramsAppModel.onTableResizeModeChange} onTableDiffShow={paramsAppModel.onTableDiffShow} onSortReset={paramsAppModel.onSortReset} diff --git a/src/src/pages/Params/components/ParamsTableGrid/ParamsTableGrid.tsx b/src/src/pages/Params/components/ParamsTableGrid/ParamsTableGrid.tsx index 68c9131c..87c0023e 100644 --- a/src/src/pages/Params/components/ParamsTableGrid/ParamsTableGrid.tsx +++ b/src/src/pages/Params/components/ParamsTableGrid/ParamsTableGrid.tsx @@ -325,7 +325,7 @@ function getParamsTableColumns( ...col, isHidden: !TABLE_DEFAULT_CONFIG.params.nonHidableColumns.has(col.key) && - hiddenColumns.includes(col.key), + hiddenColumns.includes(col.label ?? col.key), })); const columnsOrder = order?.left.concat(order.middle).concat(order.right); diff --git a/src/src/pages/Scatters/Scatters.tsx b/src/src/pages/Scatters/Scatters.tsx index e586539f..3370445e 100644 --- a/src/src/pages/Scatters/Scatters.tsx +++ b/src/src/pages/Scatters/Scatters.tsx @@ -197,6 +197,7 @@ function Scatters( hiddenRows={props.hiddenMetrics} hiddenColumns={props.hiddenColumns} hideSystemMetrics={props.hideSystemMetrics} + unselectedColumnState={props.unselectedColumnState} resizeMode={props.resizeMode} columnsWidths={props.columnsWidths} selectedRows={props.selectedRows} @@ -214,6 +215,9 @@ function Scatters( onColumnsVisibilityChange={ props.onColumnsVisibilityChange } + onDefaultColumnsVisibilityChange={ + props.onDefaultColumnsVisibilityChange + } onTableDiffShow={props.onTableDiffShow} onRowHeightChange={props.onRowHeightChange} onRowsChange={props.onParamVisibilityChange} diff --git a/src/src/pages/Scatters/ScattersContainer.tsx b/src/src/pages/Scatters/ScattersContainer.tsx index a2652128..bcefb7bc 100644 --- a/src/src/pages/Scatters/ScattersContainer.tsx +++ b/src/src/pages/Scatters/ScattersContainer.tsx @@ -154,6 +154,9 @@ function ScattersContainer(): React.FunctionComponentElement { hiddenMetrics={scattersData?.config?.table?.hiddenMetrics!} hideSystemMetrics={scattersData?.config?.table?.hideSystemMetrics!} hiddenColumns={scattersData?.config?.table?.hiddenColumns!} + unselectedColumnState={ + scattersData?.config?.table?.unselectedColumnState! + } groupingSelectOptions={scattersData?.groupingSelectOptions!} sortOptions={scattersData?.sortOptions!} projectsDataMetrics={projectsData?.metrics!} @@ -196,6 +199,9 @@ function ScattersContainer(): React.FunctionComponentElement { onParamVisibilityChange={scattersAppModel.onParamVisibilityChange} onColumnsOrderChange={scattersAppModel.onColumnsOrderChange} onColumnsVisibilityChange={scattersAppModel.onColumnsVisibilityChange} + onDefaultColumnsVisibilityChange={ + scattersAppModel.onDefaultColumnsVisibilityChange + } onTableDiffShow={scattersAppModel.onTableDiffShow} onTableResizeModeChange={scattersAppModel.onTableResizeModeChange} onRunsTagsChange={scattersAppModel.onRunsTagsChange} diff --git a/src/src/services/models/explorer/createAppModel.ts b/src/src/services/models/explorer/createAppModel.ts index ce8f0144..bec82491 100644 --- a/src/src/services/models/explorer/createAppModel.ts +++ b/src/src/services/models/explorer/createAppModel.ts @@ -16,6 +16,7 @@ import { ANALYTICS_EVENT_KEYS } from 'config/analytics/analyticsKeysMap'; import { DATE_EXPORTING_FORMAT, TABLE_DATE_FORMAT } from 'config/dates/dates'; import { getSuggestionsByExplorer } from 'config/monacoConfig/monacoConfig'; import { GroupNameEnum } from 'config/grouping/GroupingPopovers'; +import { UnselectedColumnState } from 'config/table/tableConfigs'; import { IExperimentDataShort } from 'modules/core/api/experimentsApi'; @@ -115,6 +116,7 @@ import onColorIndicatorChange from 'utils/app/onColorIndicatorChange'; import onColumnsOrderChange from 'utils/app/onColumnsOrderChange'; import onColumnsVisibilityChange from 'utils/app/onColumnsVisibilityChange'; import onCurveInterpolationChange from 'utils/app/onCurveInterpolationChange'; +import onDefaultColumnsVisibilityChange from 'utils/app/onDefaultColumnsVisibilityChange'; import onGroupingApplyChange from 'utils/app/onGroupingApplyChange'; import onGroupingModeChange from 'utils/app/onGroupingModeChange'; import onGroupingPaletteChange from 'utils/app/onGroupingPaletteChange'; @@ -277,6 +279,8 @@ function createAppModel(appConfig: IAppInitialConfig) { resizeMode: TABLE_DEFAULT_CONFIG.metrics.resizeMode, rowHeight: TABLE_DEFAULT_CONFIG.metrics.rowHeight, sortFields: [...TABLE_DEFAULT_CONFIG.metrics.sortFields], + unselectedColumnState: + TABLE_DEFAULT_CONFIG.metrics.unselectedColumnState, hiddenMetrics: [...TABLE_DEFAULT_CONFIG.metrics.hiddenMetrics], hiddenColumns: [...TABLE_DEFAULT_CONFIG.metrics.hiddenColumns], columnsWidths: { tags: 300 }, @@ -397,6 +401,8 @@ function createAppModel(appConfig: IAppInitialConfig) { if (components?.table) { config.table = { rowHeight: TABLE_DEFAULT_CONFIG.runs.rowHeight, + unselectedColumnState: + TABLE_DEFAULT_CONFIG.runs.unselectedColumnState, hideSystemMetrics: TABLE_DEFAULT_CONFIG.runs.hideSystemMetrics, hiddenMetrics: TABLE_DEFAULT_CONFIG.runs.hiddenMetrics, hiddenColumns: TABLE_DEFAULT_CONFIG.runs.hiddenColumns, @@ -445,6 +451,8 @@ function createAppModel(appConfig: IAppInitialConfig) { if (components.charts.indexOf(ChartTypeEnum.ScatterPlot) !== -1) { config.table = { ...config?.table!, + unselectedColumnState: + TABLE_DEFAULT_CONFIG.scatters.unselectedColumnState, resizeMode: TABLE_DEFAULT_CONFIG.scatters.resizeMode, }; config.chart = { @@ -1307,6 +1315,39 @@ function createAppModel(appConfig: IAppInitialConfig) { groupingSelectOptions, ); + const unselectedColumnState = configData.table?.unselectedColumnState; + + if (unselectedColumnState !== UnselectedColumnState.DEFAULT) { + const selected = modelState?.config?.select?.options.map( + (option: ISelectOption) => option.label, + ); + let hiddenColumns = configData.table?.hiddenColumns; + + const defaultHiddenColumns = + TABLE_DEFAULT_CONFIG?.[AppNameEnum.METRICS]?.hiddenColumns; + + if (unselectedColumnState === UnselectedColumnState.FORCE_HIDE) { + // Push unique values to hiddenColumns + hiddenColumns = _.uniq( + hiddenColumns?.concat( + params.filter((item: string) => !selected.includes(item)), + ), + ); + } else { + // Remove unselected values from hiddenColumns + hiddenColumns = defaultHiddenColumns; + } + + configData = { + ...configData, + table: { + ...configData.table, + rowHeight: modelState?.config?.table?.rowHeight!, + hiddenColumns, + }, + }; + } + const tableColumns = getMetricsTableColumns( params, groupingSelectOptions, @@ -2126,6 +2167,14 @@ function createAppModel(appConfig: IAppInitialConfig) { updateModelData, }); }, + onDefaultColumnsVisibilityChange(state: UnselectedColumnState): void { + onDefaultColumnsVisibilityChange({ + unselectedColumnState: state, + model, + appName, + updateModelData, + }); + }, onTableDiffShow(): void { onTableDiffShow({ model, appName, updateModelData }); }, @@ -3238,6 +3287,14 @@ function createAppModel(appConfig: IAppInitialConfig) { updateModelData, }); }, + onDefaultColumnsVisibilityChange(state: UnselectedColumnState): void { + onDefaultColumnsVisibilityChange({ + unselectedColumnState: state, + model, + appName, + updateModelData, + }); + }, onTableDiffShow(): void { onTableDiffShow({ model, appName, updateModelData }); }, @@ -3900,6 +3957,53 @@ function createAppModel(appConfig: IAppInitialConfig) { ); const sortFields = modelState?.config?.table.sortFields; + const unselectedColumnState = configData.table?.unselectedColumnState; + + if (unselectedColumnState !== UnselectedColumnState.DEFAULT) { + const selected = modelState?.config?.select?.options.map( + (option: ISelectOption) => option.label, + ); + + let hiddenColumns = configData.table?.hiddenColumns; + + const defaultHiddenColumns = + TABLE_DEFAULT_CONFIG?.[AppNameEnum.PARAMS]?.hiddenColumns; + + if (unselectedColumnState === UnselectedColumnState.FORCE_HIDE) { + // Extract the combined keys from metricsColumns dictionary + const metricList = Object.keys(metricsColumns).reduce( + (acc: string[], key: string) => { + const metricKeys = Object.keys(metricsColumns[key]); + return acc.concat( + metricKeys.map((metricKey) => `${key} ${metricKey}`.trim()), + ); + }, + [], + ); + + const metricsAndParams = metricList.concat(params); + hiddenColumns = _.uniq( + defaultHiddenColumns?.concat( + metricsAndParams.filter( + (item: string) => !selected.includes(item), + ), + ), + ); + } else { + // Remove unselected values from hiddenColumns + hiddenColumns = defaultHiddenColumns; + } + + configData = { + ...configData, + table: { + ...configData.table, + rowHeight: modelState?.config?.table?.rowHeight!, + hiddenColumns, + }, + }; + } + const tableColumns = getParamsTableColumns( sortOptions, metricsColumns, @@ -4851,6 +4955,14 @@ function createAppModel(appConfig: IAppInitialConfig) { updateModelData, }); }, + onDefaultColumnsVisibilityChange(state: UnselectedColumnState): void { + onDefaultColumnsVisibilityChange({ + unselectedColumnState: state, + model, + appName, + updateModelData, + }); + }, onTableResizeModeChange(mode: ResizeModeEnum): void { onTableResizeModeChange({ mode, model, appName }); }, @@ -5018,6 +5130,54 @@ function createAppModel(appConfig: IAppInitialConfig) { ); const sortFields = modelState?.config?.table.sortFields; + const unselectedColumnState = configData.table?.unselectedColumnState; + + if (unselectedColumnState !== UnselectedColumnState.DEFAULT) { + const selected = modelState?.config?.select?.options.map( + (option: ISelectOption) => option.label, + ); + + let hiddenColumns = configData.table?.hiddenColumns; + + const defaultHiddenColumns = + TABLE_DEFAULT_CONFIG?.[AppNameEnum.PARAMS]?.hiddenColumns; + + if (unselectedColumnState === UnselectedColumnState.FORCE_HIDE) { + // Extract the combined keys from metricsColumns dictionary + const metricList = Object.keys(metricsColumns).reduce( + (acc: string[], key: string) => { + const metricKeys = Object.keys(metricsColumns[key]); + return acc.concat( + metricKeys.map((metricKey) => `${key} ${metricKey}`.trim()), + ); + }, + [], + ); + + const metricsAndParams = metricList.concat(params); + hiddenColumns = _.uniq( + defaultHiddenColumns?.concat( + metricsAndParams.filter( + (item: string) => !selected.includes(item), + ), + ), + ); + } else { + // Remove unselected values from hiddenColumns + hiddenColumns = defaultHiddenColumns; + } + + configData = { + ...configData, + table: { + ...configData.table, + rowHeight: modelState?.config?.table?.rowHeight!, + unselectedColumnState, + hiddenColumns, + }, + }; + } + const tableColumns = getParamsTableColumns( sortOptions, metricsColumns, @@ -6355,6 +6515,14 @@ function createAppModel(appConfig: IAppInitialConfig) { updateModelData, }); }, + onDefaultColumnsVisibilityChange(state: UnselectedColumnState): void { + onDefaultColumnsVisibilityChange({ + unselectedColumnState: state, + model, + appName, + updateModelData, + }); + }, onTableResizeModeChange(mode: ResizeModeEnum): void { onTableResizeModeChange({ mode, model, appName }); }, diff --git a/src/src/types/components/Table/Table.d.ts b/src/src/types/components/Table/Table.d.ts index 9e4f2473..c762ad78 100644 --- a/src/src/types/components/Table/Table.d.ts +++ b/src/src/types/components/Table/Table.d.ts @@ -1,6 +1,6 @@ import React from 'react'; -import { RowHeight, RowHeightSize } from 'config/table/tableConfigs'; +import { RowHeight, RowHeightSize, UnselectedColumnState } from 'config/table/tableConfigs'; import { ResizeModeEnum, VisualizationElementEnum, @@ -25,6 +25,7 @@ export interface ITableProps { estimatedRowHeight?: number; onManageColumns?: (order: IColumnsOrderData) => void; onColumnsVisibilityChange?: (hiddenColumns: string[] | string) => void; + onDefaultColumnsVisibilityChange?: (state: UnselectedColumnState) => void; hiddenChartRows?: boolean; onTableDiffShow?: () => void; onSort?: (field: string, value: 'asc' | 'desc' | 'none') => void; @@ -50,6 +51,7 @@ export interface ITableProps { rowHeightMode?: any; columnsOrder?: IColumnsOrder; hiddenColumns?: string[]; + unselectedColumnState?: UnselectedColumnState; hideSystemMetrics?: boolean; updateColumns?: any; columnsWidths?: any; diff --git a/src/src/types/pages/metrics/Metrics.d.ts b/src/src/types/pages/metrics/Metrics.d.ts index af10a29e..faf479c5 100644 --- a/src/src/types/pages/metrics/Metrics.d.ts +++ b/src/src/types/pages/metrics/Metrics.d.ts @@ -1,7 +1,7 @@ import React from 'react'; import { RouteChildrenProps } from 'react-router-dom'; -import { RowHeightSize } from 'config/table/tableConfigs'; +import { RowHeightSize, UnselectedColumnState } from 'config/table/tableConfigs'; import { ResizeModeEnum } from 'config/enums/tableEnums'; import { DensityOptions } from 'config/enums/densityEnum'; import { RequestStatusEnum } from 'config/enums/requestStatusEnum'; @@ -85,6 +85,7 @@ export interface IMetricProps extends Partial { hiddenMetrics: string[]; hiddenColumns: string[]; hideSystemMetrics: boolean; + unselectedColumnState: UnselectedColumnState; sameValueColumns?: string[] | []; groupingSelectOptions: IGroupingSelectOption[]; sortOptions: IGroupingSelectOption[]; @@ -142,6 +143,7 @@ export interface IMetricProps extends Partial { onMetricVisibilityChange: (metricKeys: string[]) => void; onColumnsOrderChange: (order: any) => void; onColumnsVisibilityChange: (hiddenColumns: string[] | string) => void; + onDefaultColumnsVisibilityChange: (state: UnselectedColumnState) => void; onTableDiffShow: () => void; onTableResizeModeChange: (mode: ResizeModeEnum) => void; updateColumnsWidths: (key: string, width: number, isReset: boolean) => void; diff --git a/src/src/types/pages/params/Params.d.ts b/src/src/types/pages/params/Params.d.ts index b88d0a53..41eee410 100644 --- a/src/src/types/pages/params/Params.d.ts +++ b/src/src/types/pages/params/Params.d.ts @@ -3,6 +3,7 @@ import { RouteChildrenProps } from 'react-router-dom'; import { ITableRef } from 'components/Table/Table'; +import { UnselectedColumnState } from 'config/table/tableConfigs'; import { ResizeModeEnum } from 'config/enums/tableEnums'; import { RequestStatusEnum } from 'config/enums/requestStatusEnum'; @@ -51,6 +52,7 @@ export interface IParamsProps extends Partial { sortOptions: IGroupingSelectOption[]; hiddenMetrics: string[]; hideSystemMetrics: boolean; + unselectedColumnState: UnselectedColumnState; sortFields: [string, 'asc' | 'desc' | boolean][]; focusedState: IFocusedState; isVisibleColorIndicator: boolean; @@ -107,6 +109,7 @@ export interface IParamsProps extends Partial { onChangeTooltip: (tooltip: Partial) => void; onExportTableData: (e: React.ChangeEvent) => void; onColumnsVisibilityChange: (order: any) => void; + onDefaultColumnsVisibilityChange: (state: UnselectedColumnState) => void; onTableDiffShow: () => void; onTableResizeModeChange: (mode: ResizeModeEnum) => void; onSortReset: () => void; diff --git a/src/src/types/pages/scatters/Scatters.d.ts b/src/src/types/pages/scatters/Scatters.d.ts index d85061fa..5bd5754a 100644 --- a/src/src/types/pages/scatters/Scatters.d.ts +++ b/src/src/types/pages/scatters/Scatters.d.ts @@ -1,7 +1,7 @@ import React from 'react'; import { RouteChildrenProps } from 'react-router-dom'; -import { RowHeightSize } from 'config/table/tableConfigs'; +import { RowHeightSize, UnselectedColumnState } from 'config/table/tableConfigs'; import { ResizeModeEnum } from 'config/enums/tableEnums'; import { RequestStatusEnum } from 'config/enums/requestStatusEnum'; @@ -59,6 +59,7 @@ export interface IScattersProps extends Partial { sortFields: [string, 'asc' | 'desc' | boolean][]; hiddenMetrics: string[]; hiddenColumns: string[]; + unselectedColumnState: UnselectedColumnState; hideSystemMetrics: boolean; groupingSelectOptions: IGroupingSelectOption[]; sortOptions: IGroupingSelectOption[]; @@ -105,6 +106,7 @@ export interface IScattersProps extends Partial { onParamVisibilityChange: (metricKeys: string[]) => void; onColumnsOrderChange: (order: any) => void; onColumnsVisibilityChange: (hiddenColumns: string[] | string) => void; + onDefaultColumnsVisibilityChange: (state: UnselectedColumnState) => void; onTableDiffShow: () => void; onTableResizeModeChange: (mode: ResizeModeEnum) => void; updateColumnsWidths: (key: string, width: number, isReset: boolean) => void; diff --git a/src/src/types/services/models/explorer/createAppModel.d.ts b/src/src/types/services/models/explorer/createAppModel.d.ts index 49cf4b92..7214ed92 100644 --- a/src/src/types/services/models/explorer/createAppModel.d.ts +++ b/src/src/types/services/models/explorer/createAppModel.d.ts @@ -1,5 +1,5 @@ import { ResizeModeEnum } from 'config/enums/tableEnums'; -import { RowHeightSize } from 'config/table/tableConfigs'; +import { RowHeightSize, UnselectedColumnState } from 'config/table/tableConfigs'; import { DensityOptions } from 'config/enums/densityEnum'; import { GroupNameEnum } from 'config/grouping/GroupingPopovers'; @@ -116,6 +116,7 @@ export interface ITableConfig { resizeMode?: ResizeModeEnum; rowHeight: RowHeightSize; sortFields?: SortField[]; + unselectedColumnState?: UnselectedColumnState; hiddenMetrics?: string[]; hiddenColumns?: string[]; hideSystemMetrics?: boolean; diff --git a/src/src/utils/app/onDefaultColumnsVisibilityChange.ts b/src/src/utils/app/onDefaultColumnsVisibilityChange.ts new file mode 100644 index 00000000..dcd675ae --- /dev/null +++ b/src/src/utils/app/onDefaultColumnsVisibilityChange.ts @@ -0,0 +1,46 @@ +import { UnselectedColumnState } from 'config/table/tableConfigs'; +import { ANALYTICS_EVENT_KEYS } from 'config/analytics/analyticsKeysMap'; + +import * as analytics from 'services/analytics'; + +import { IModel, State } from 'types/services/models/model'; +import { IAppModelConfig } from 'types/services/models/explorer/createAppModel'; + +import { encode } from 'utils/encoder/encoder'; +import { setItem } from 'utils/storage'; + +export default function onDefaultColumnsVisibilityChange({ + unselectedColumnState, + model, + appName, + updateModelData, +}: { + unselectedColumnState: UnselectedColumnState; + model: IModel; + appName: string; + updateModelData: ( + configData?: IAppModelConfig | any, + shouldURLUpdate?: boolean, + ) => void; +}): void { + const configData = model.getState()?.config; + if (configData?.table) { + const table = { + ...configData.table, + unselectedColumnState, + }; + const config = { + ...configData, + table, + }; + model.setState({ config }); + setItem(`${appName}Table`, encode(table)); + updateModelData(config); + } + analytics.trackEvent( + `${ + // @ts-ignore + ANALYTICS_EVENT_KEYS[appName].table.changeDefaultColumnsVisibility + } to "${unselectedColumnState.toString()}"`, + ); +}