From 8dd8d11011cbe0891afb0075038aadbcc0e44c88 Mon Sep 17 00:00:00 2001 From: Maksim Efremov Date: Thu, 16 Nov 2023 19:04:30 +0300 Subject: [PATCH] chore(Chyt): add ability to select columns [YTFRONT-3863] --- .../ui/src/shared/constants/settings-types.ts | 13 +- packages/ui/src/shared/constants/settings.ts | 5 + .../chyt/ChytPageList/ChytPageListTable.tsx | 235 ++++++++++++------ .../chyt/ChytPageList/ChytPageListToolbar.tsx | 48 +++- .../ui/pages/chyt/components/CliqueState.tsx | 16 +- packages/ui/src/ui/store/actions/chyt/api.ts | 25 +- packages/ui/src/ui/store/actions/chyt/list.ts | 27 +- .../ui/src/ui/store/actions/settings/index.ts | 17 +- .../ui/store/reducers/chyt/list-filters.ts | 3 +- .../ui/src/ui/store/selectors/chyt/index.ts | 46 ++++ .../src/ui/store/selectors/settings-base.ts | 4 + 11 files changed, 324 insertions(+), 115 deletions(-) create mode 100644 packages/ui/src/ui/store/selectors/settings-base.ts diff --git a/packages/ui/src/shared/constants/settings-types.ts b/packages/ui/src/shared/constants/settings-types.ts index 2523ac494..d960f57bc 100644 --- a/packages/ui/src/shared/constants/settings-types.ts +++ b/packages/ui/src/shared/constants/settings-types.ts @@ -68,6 +68,10 @@ interface AccountsSettings { 'global::accounts::dashboardVisibilityMode': 'string'; } +interface ChytSettings { + 'global::chyt::list_columns': Array; +} + interface OtherSettings { [key: string]: any; } @@ -82,9 +86,10 @@ export interface DefaultSettings { A11Y: A11YSettings; MENU: MenuSettings; ACCOUNTS: AccountsSettings; + CHYT: ChytSettings; } -export type Settings = GlobalSettings & +type DescribedSettings = GlobalSettings & YsonSettings & DevelopmentSettings & SystemSettings & @@ -93,4 +98,8 @@ export type Settings = GlobalSettings & A11YSettings & MenuSettings & AccountsSettings & - OtherSettings; + ChytSettings; + +export type Settings = DescribedSettings & OtherSettings; + +export type SettingKey = keyof DescribedSettings; diff --git a/packages/ui/src/shared/constants/settings.ts b/packages/ui/src/shared/constants/settings.ts index 92ff66f75..7a9ee7d82 100644 --- a/packages/ui/src/shared/constants/settings.ts +++ b/packages/ui/src/shared/constants/settings.ts @@ -113,6 +113,9 @@ export const SettingName = { STAGE: 'queryTrackerStage', YQL_AGENT_STAGE: 'yqlAgentStage', }, + CHYT: { + LIST_COLUMNS: 'list_columns', + }, } as const; const GLOBAL = createNS('global'); @@ -132,6 +135,7 @@ const OPERATION_PRESETS = createNestedNS('presets', OPERATION); const ACCOUNTS = createNestedNS('accounts', GLOBAL); const SCHEDULING = createNestedNS('scheduling', GLOBAL); const QUERY_TRACKER = createNestedNS('query-tracker', GLOBAL); +const CHYT = createNestedNS('chyt', GLOBAL); export const NAMESPACES = { GLOBAL, @@ -151,6 +155,7 @@ export const NAMESPACES = { ACCOUNTS, SCHEDULING, QUERY_TRACKER, + CHYT, }; export const FAVOURITES = 'favourites'; diff --git a/packages/ui/src/ui/pages/chyt/ChytPageList/ChytPageListTable.tsx b/packages/ui/src/ui/pages/chyt/ChytPageList/ChytPageListTable.tsx index fdfe75306..922e6202b 100644 --- a/packages/ui/src/ui/pages/chyt/ChytPageList/ChytPageListTable.tsx +++ b/packages/ui/src/ui/pages/chyt/ChytPageList/ChytPageListTable.tsx @@ -15,16 +15,19 @@ import Icon from '../../../components/Icon/Icon'; import Link from '../../../components/Link/Link'; import {OperationId} from '../../../components/OperationId/OperationId'; import {UserCard} from '../../../components/UserLink/UserLink'; +import Label from '../../../components/Label/Label'; import {chytToggleSortState} from '../../../store/actions/chyt/list-fitlers'; import {getCluster} from '../../../store/selectors/global'; import { + getChytListColumns, getChytListTableItems, getChytListTableSortStateByName, } from '../../../store/selectors/chyt'; import {ChytInfo} from '../../../store/reducers/chyt/list'; import {chytListAction} from '../../../store/actions/chyt/list'; import {Page} from '../../../../shared/constants/settings'; +import {showErrorPopup} from '../../../utils/utils'; import {CliqueState} from '../components/CliqueState'; @@ -33,44 +36,11 @@ import './ChytPageListTable.scss'; const block = cn('chyt-page-list-table'); function useChytListColumns(cluster: string) { + const checkedColumns = useSelector(getChytListColumns).filter((i) => i.checked); + const columns: Array> = React.useMemo(() => { - return [ - { - name: 'name', - header: , - render({row}) { - return ( -
- - {row.alias} - -
- -
-
- ); - }, - }, - { - name: 'creator', - header: , - render({row}) { - return ( - - {!row.creator ? format.NO_VALUE : } - - ); - }, - }, - { + const columnsByName = { + instance_count: { name: 'instance_count', header: , render({row}) { @@ -84,8 +54,8 @@ function useChytListColumns(cluster: string) { }, align: 'right', width: 120, - }, - { + } as Column, + total_cpu: { name: 'cores', header: , render({row}) { @@ -99,8 +69,8 @@ function useChytListColumns(cluster: string) { }, align: 'right', width: 100, - }, - { + } as Column, + total_memory: { name: 'memory', header: , render({row}) { @@ -114,48 +84,164 @@ function useChytListColumns(cluster: string) { }, align: 'right', width: 120, - }, - { - name: 'State', - header: , + } as Column, + health: { + name: 'health', + header: , render({row}) { return ( - + ); }, align: 'center', width: 100, - }, - { - name: 'Health', - header: , + } as Column, + creation_time: { + name: 'creation_time', + header: , render({row}) { + const {creation_time} = row; return ( - + {creation_time ? format.DateTime(creation_time) : format.NO_VALUE} ); }, - align: 'center', - width: 100, - }, - { - name: 'creation_time', + width: 180, + } as Column, + speclet_modification_time: { + name: 'speclet_modification_time', header: ( - + ), render({row}) { - const {creation_time} = row; + const {speclet_modification_time: value} = row; return ( - {creation_time ? format.DateTime(creation_time) : format.NO_VALUE} + {value ? format.DateTime(value) : format.NO_VALUE} + + ); + }, + } as Column, + stage: { + name: 'stage', + header: , + render({row}) { + return ( + { + ); + }, + } as Column, + strawberry_state_modification_time: { + name: 'strawberry_state_modification_time', + header: ( + + ), + render({row}) { + const {strawberry_state_modification_time: value} = row; + return ( + + {value ? format.DateTime(value) : format.NO_VALUE} + + ); + }, + } as Column, + yt_operation_finish_time: { + name: 'yt_operation_finish_time', + header: ( + + ), + render({row}) { + const {yt_operation_finish_time: value} = row; + return ( + + {value ? format.DateTime(value) : format.NO_VALUE} ); }, width: 180, - }, + } as Column, + yt_operation_start_time: { + name: 'yt_operation_start_time', + header: ( + + ), + render({row}) { + const {yt_operation_start_time: value} = row; + return ( + + {value ? format.DateTime(value) : format.NO_VALUE} + + ); + }, + width: 180, + } as Column, + }; + + const res = checkedColumns.map((i) => columnsByName[i.column]); + return [ + { + name: 'alias', + header: , + render({row}) { + return ( +
+ + {row.alias} + +
+ +
+
+ ); + }, + } as Column, + { + name: 'creator', + header: , + render({row}) { + return ( + + {!row.creator ? format.NO_VALUE : } + + ); + }, + } as Column, + { + name: 'state', + header: , + render({row}) { + return ( + + + + ); + }, + align: 'center', + width: 100, + } as Column, + ...res, { name: 'actions', header: '', @@ -168,9 +254,9 @@ function useChytListColumns(cluster: string) { }, align: 'center', width: 60, - }, + } as Column, ]; - }, [cluster]); + }, [cluster, checkedColumns]); return columns; } @@ -181,7 +267,7 @@ function ChytListHeader({ withUndefined, }: { column: keyof ChytInfo; - title: string; + title?: string; withUndefined?: boolean; }) { const dispatch = useDispatch(); @@ -191,7 +277,7 @@ function ChytListHeader({ allowUnordered withUndefined={withUndefined} column={column} - title={title} + title={title ?? format.ReadableField(column)} sortable {...sortState[column]} toggleSort={(col, nextOrder, options) => { @@ -233,14 +319,19 @@ function ChytCliqueActions({alias}: {alias: string}) { ]; return ( - - - - } - items={menuItems} - /> + + + + + + } + items={menuItems} + /> + ); } diff --git a/packages/ui/src/ui/pages/chyt/ChytPageList/ChytPageListToolbar.tsx b/packages/ui/src/ui/pages/chyt/ChytPageList/ChytPageListToolbar.tsx index 0a750083f..4fe8618b9 100644 --- a/packages/ui/src/ui/pages/chyt/ChytPageList/ChytPageListToolbar.tsx +++ b/packages/ui/src/ui/pages/chyt/ChytPageList/ChytPageListToolbar.tsx @@ -2,10 +2,13 @@ import React from 'react'; import {useDispatch, useSelector} from 'react-redux'; import cn from 'bem-cn-lite'; -import {TextInput} from '@gravity-ui/uikit'; +import {Button, TextInput} from '@gravity-ui/uikit'; + +import format from '../../../common/hammer/format'; import {Toolbar} from '../../../components/WithStickyToolbar/Toolbar/Toolbar'; import {SelectSingle} from '../../../components/Select/Select'; +import ColumnSelectorModal from '../../../components/ColumnSelectorModal/ColumnSelectorModal'; import {chytUpdateListFilters} from '../../../store/actions/chyt/list-fitlers'; import { @@ -14,8 +17,10 @@ import { getChytListFilterAlias, getChytListFilterCreator, getChytListFilterState, + getChytListColumns, } from '../../../store/selectors/chyt'; import {ChytListFilters} from '../../../store/reducers/chyt/list-filters'; +import {chytSetVisibleColumns} from '../../../store/actions/chyt/list'; import './ChytPageListToolbar.scss'; @@ -48,6 +53,10 @@ function ChytPageListToolbar() { name: 'state', node: , }, + { + name: 'columns', + node: , + }, ]} /> ); @@ -118,4 +127,41 @@ function StateFilter({onUpdate}: {onUpdate: (value: {state?: string}) => void}) ); } +function ChytListColumnsButton() { + const dispatch = useDispatch(); + + const [visible, setVisible] = React.useState(false); + const columns = useSelector(getChytListColumns); + + const dialog = ( + { + return { + name: format.ReadableField(i.column), + checked: i.checked, + data: { + column: i.column, + }, + }; + })} + onConfirm={(value) => { + const newColumns = value.filter((i) => i.checked).map((i) => i.data.column); + dispatch(chytSetVisibleColumns(newColumns)); + setVisible(false); + }} + onCancel={() => setVisible(false)} + /> + ); + + return ( + + {visible && dialog} + + + ); +} + export default React.memo(ChytPageListToolbar); diff --git a/packages/ui/src/ui/pages/chyt/components/CliqueState.tsx b/packages/ui/src/ui/pages/chyt/components/CliqueState.tsx index d9acb1ce6..2fe646203 100644 --- a/packages/ui/src/ui/pages/chyt/components/CliqueState.tsx +++ b/packages/ui/src/ui/pages/chyt/components/CliqueState.tsx @@ -4,13 +4,15 @@ import format from '../../../common/hammer/format'; import Label from '../../../components/Label/Label'; import {ChytCliqueHealthType, ChytCliqueStateType} from '../../../store/actions/chyt/api'; -const THEME_MAP: Partial> = - { - good: 'success', - failed: 'danger', - active: 'success', - inactive: 'danger', - }; +const THEME_MAP: Partial< + Record +> = { + good: 'success', + failed: 'danger', + active: 'success', + inactive: 'danger', + pending: 'info', +}; export function CliqueState({state}: {state?: ChytCliqueStateType | ChytCliqueHealthType}) { return !state ? format.NO_VALUE :