From f57926cb1af406a74fee8a683ea7f627bb08e553 Mon Sep 17 00:00:00 2001 From: vitshev Date: Tue, 27 Feb 2024 14:29:08 +0100 Subject: [PATCH] feat(queryTracker): dividing the query tracker history by day [#267] --- .../QueriesList/QueriesHistoryList/index.scss | 13 ++++ .../QueriesList/QueriesHistoryList/index.tsx | 68 ++++++++++++++++++- 2 files changed, 78 insertions(+), 3 deletions(-) diff --git a/packages/ui/src/ui/pages/query-tracker/QueriesList/QueriesHistoryList/index.scss b/packages/ui/src/ui/pages/query-tracker/QueriesList/QueriesHistoryList/index.scss index 5bded8014..2c26d707e 100644 --- a/packages/ui/src/ui/pages/query-tracker/QueriesList/QueriesHistoryList/index.scss +++ b/packages/ui/src/ui/pages/query-tracker/QueriesList/QueriesHistoryList/index.scss @@ -45,6 +45,19 @@ width: auto; overflow: visible; } + + &_header { + padding: 8px 0; + + &:hover { + background: transparent; + cursor: auto; + } + } + + &__separator { + text-align: center; + } } .queries-history-list { diff --git a/packages/ui/src/ui/pages/query-tracker/QueriesList/QueriesHistoryList/index.tsx b/packages/ui/src/ui/pages/query-tracker/QueriesList/QueriesHistoryList/index.tsx index aa56013aa..9bde8d560 100644 --- a/packages/ui/src/ui/pages/query-tracker/QueriesList/QueriesHistoryList/index.tsx +++ b/packages/ui/src/ui/pages/query-tracker/QueriesList/QueriesHistoryList/index.tsx @@ -1,8 +1,11 @@ import noop from 'lodash/noop'; +import moment from 'moment'; +import groupBy from 'lodash/groupBy'; import {Text} from '@gravity-ui/uikit'; import block from 'bem-cn-lite'; import React, {useCallback, useContext, useEffect, useMemo, useRef} from 'react'; import {useDispatch, useSelector} from 'react-redux'; +import DataTable, {Column, Settings} from '@gravity-ui/react-data-table'; import {QueryItem, QueryStatus} from '../../module/api'; import {refreshQueriesListIfNeeded} from '../../module/queries_list/actions'; import {getQueriesListTimestamp, getUncompletedItems} from '../../module/queries_list/selectors'; @@ -14,7 +17,6 @@ import {QueriesPoolingContext} from '../../hooks/QueriesPooling/context'; import {formatTime} from '../../../../components/common/Timeline/util'; import {QueryEnginesNames} from '../../utils/query'; import DataTableYT from '../../../../components/DataTableYT/DataTableYT'; -import DataTable, {Column, Settings} from '@gravity-ui/react-data-table'; import {useQuriesHistoryFilter} from '../../hooks/QueryListFilter'; import {QueryDuration} from '../../QueryDuration'; import {useQueryNavigation} from '../../hooks/Query'; @@ -82,13 +84,22 @@ function useQueryHistoryList() { return useQueryList(); } -type TableItem = QueryItem; +type HeaderTableItem = {header: string}; +type TableItem = QueryItem | HeaderTableItem; + +const isHeaderTableItem = (b: TableItem): b is HeaderTableItem => { + return (b as HeaderTableItem).header !== undefined; +}; export const NameColumns: Column = { name: 'Name', align: 'left', className: itemBlock('name_row'), render: ({row}) => { + if (isHeaderTableItem(row)) { + return
{row.header}
; + } + const name = row.annotations?.title; return (
@@ -111,6 +122,10 @@ const TypeColumns: Column = { align: 'center', width: 60, render: ({row}) => { + if (isHeaderTableItem(row)) { + return null; + } + return ( {row.engine in QueryEnginesNames ? QueryEnginesNames[row.engine] : row.engine} @@ -124,6 +139,10 @@ const DurationColumns: Column = { align: 'left', width: 100, render: ({row}) => { + if (isHeaderTableItem(row)) { + return null; + } + if (row.state === QueryStatus.RUNNING) { return hammer.format.NO_VALUE; } @@ -136,6 +155,10 @@ const StartedColumns: Column = { align: 'left', width: 60, render: ({row}) => { + if (isHeaderTableItem(row)) { + return null; + } + return ( {formatTime(row.start_time)} @@ -150,6 +173,10 @@ const AuthorColumns: Column = { width: 120, className: itemBlock('author_row'), render: ({row}) => { + if (isHeaderTableItem(row)) { + return null; + } + return ( {row.user} @@ -164,6 +191,10 @@ const ACOColumns: Column = { width: 60, className: itemBlock('access_control_object'), render: ({row}) => { + if (isHeaderTableItem(row)) { + return null; + } + return ( {row.access_control_object} @@ -212,6 +243,12 @@ export function QueriesHistoryList() { const setClassName = useCallback( (item: TableItem) => { + if (isHeaderTableItem(item)) { + return itemBlock({ + header: Boolean(item.header), + }); + } + return itemBlock({ selected: item.id === selectedId, }); @@ -219,6 +256,20 @@ export function QueriesHistoryList() { [selectedId], ); + const itemsByDate = useMemo( + () => + Object.entries( + groupBy(items, (item) => moment(item.start_time).format('DD MMMM YYYY')), + ).reduce((ret, [header, items]) => { + ret.push({ + header, + }); + + return ret.concat(items.map((item) => item)); + }, [] as Array), + [items], + ); + return (
@@ -226,13 +277,24 @@ export function QueriesHistoryList() { className={b('list')} loading={isLoading} columns={columns} - data={items} + data={itemsByDate} useThemeYT={true} rowKey={(row) => (row as QueryItem).id} onRowClick={(item) => goToQuery(item as QueryItem)} disableRightGap={true} settings={tableSettings} rowClassName={setClassName} + getColSpansOfRow={({row}) => { + if (isHeaderTableItem(row)) { + return columns.reduce((ret, item) => { + ret[item.name] = item.name === 'Name' ? columns.length : 0; + + return ret; + }, {} as Record); + } + + return undefined; + }} />
{(!first || !last) && (