Skip to content

Commit

Permalink
feat(QueryTracker): new columns to the list of queries [#267]
Browse files Browse the repository at this point in the history
  • Loading branch information
vitshev committed Mar 25, 2024
1 parent 7b2503d commit 2c367a0
Show file tree
Hide file tree
Showing 10 changed files with 223 additions and 45 deletions.
9 changes: 4 additions & 5 deletions packages/ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
"@gravity-ui/i18n": "^1.0.0",
"@gravity-ui/icons": "^2.4.0",
"@gravity-ui/prettier-config": "^1.1.0",
"@gravity-ui/react-data-table": "^1.2.0",
"@gravity-ui/react-data-table": "^1.3.0",
"@gravity-ui/stylelint-config": "^3.0.0",
"@gravity-ui/tsconfig": "^1.0.0",
"@gravity-ui/uikit": "^5.16.0",
Expand Down
13 changes: 9 additions & 4 deletions packages/ui/src/shared/constants/settings-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,20 @@ interface AccountsSettings {
'global::accounts::dashboardVisibilityMode': 'string';
}

type ClusterName = string;

interface QueryTrackerSettings {
'global::queryTracker::queriesListSidebarVisibilityMode': boolean;
}

type QueryTrackerHistoryColumnsSettings = {
[key in `local::${ClusterName}::queryTracker::history::Columns`]: string[];
};

interface ChytSettings {
'global::chyt::list_columns': Array<string>;
}

type ClusterName = string;

type QueryTrackerLastSelectedACOsSettings = {
[key in `local::${ClusterName}::queryTracker::lastSelectedACOs`]: string[];
};
Expand All @@ -96,7 +100,7 @@ export interface DefaultSettings {
A11Y: A11YSettings;
MENU: MenuSettings;
ACCOUNTS: AccountsSettings;
QUERY_TRACKER: QueryTrackerSettings;
QUERY_TRACKER: QueryTrackerSettings | QueryTrackerHistoryColumnsSettings;
CHYT: ChytSettings;
}

Expand All @@ -111,7 +115,8 @@ type DescribedSettings = GlobalSettings &
AccountsSettings &
QueryTrackerSettings &
ChytSettings &
QueryTrackerLastSelectedACOsSettings;
QueryTrackerLastSelectedACOsSettings &
QueryTrackerHistoryColumnsSettings;

export type Settings = DescribedSettings & OtherSettings;

Expand Down
4 changes: 4 additions & 0 deletions packages/ui/src/ui/components/common/Timeline/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ export const formatInterval = (from: MomentInput, to: MomentInput) => {
}
};

export const formatTime = (date: MomentInput) => {
return moment(date).format('HH:mm');
};

export const formatDateCompact = (date: MomentInput) => {
return moment(date).format('DD.MM.YY, HH:mm');
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,31 @@

&__name-edit {
visibility: hidden;
width: 0;
flex: 1px;
overflow: hidden;
z-index: 1;
margin: -14px 0;
}

&:hover &__name-edit {
flex: 1;
padding-left: 5px;
visibility: visible;
width: auto;
overflow: visible;
}

&_header {
padding: 8px 0;

&:hover {
background: transparent;
cursor: auto;
}
}

&__separator {
text-align: center;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
import hammer from '../../../../common/hammer';
import moment from 'moment';
import groupBy from 'lodash/groupBy';
import noop from 'lodash/noop';
import {Text} from '@gravity-ui/uikit';
import block from 'bem-cn-lite';
import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
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';
import {QueryStatusIcon} from '../../QueryStatus';
import hammer from '../../../../common/hammer';

import './index.scss';
import Pagination from '../../../../components/Pagination/Pagination';
import {noop} from 'lodash';
import {QueriesPoolingContext} from '../../hooks/QueriesPooling/context';
import {formatDateCompact} from '../../../../components/common/Timeline/util';
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 {QueriesListAuthorFilter} from '../../module/queries_list/types';
import {QueryDuration} from '../../QueryDuration';
import {useQueryNavigation} from '../../hooks/Query';
import {useQueriesPagination, useQueryList} from '../../hooks/QueriesList';
import EditQueryNameModal from '../EditQueryNameModal/EditQueryNameModal';
import {UPDATE_QUERIES_LIST} from '../../module/query-tracker-contants';
import {useQueryHistoryListColumns} from './useQueryListColumns';

import './index.scss';

const b = block('queries-history-list');

Expand Down Expand Up @@ -81,11 +84,22 @@ function useQueryHistoryList() {
return useQueryList();
}

const NameColumns: Column<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<TableItem> = {
name: 'Name',
align: 'left',
className: itemBlock('name_row'),
render: ({row}) => {
if (isHeaderTableItem(row)) {
return <div className={itemBlock('separator')}>{row.header}</div>;
}

const name = row.annotations?.title;
return (
<div className={itemBlock('name')} title={name}>
Expand All @@ -103,11 +117,15 @@ const NameColumns: Column<QueryItem> = {
},
};

const TypeColumns: Column<QueryItem> = {
const TypeColumns: Column<TableItem> = {
name: 'Type',
align: 'center',
width: 60,
render: ({row}) => {
if (isHeaderTableItem(row)) {
return null;
}

return (
<Text variant="body-1" color="secondary">
{row.engine in QueryEnginesNames ? QueryEnginesNames[row.engine] : row.engine}
Expand All @@ -116,37 +134,49 @@ const TypeColumns: Column<QueryItem> = {
},
};

const DurationColumns: Column<QueryItem> = {
const DurationColumns: Column<TableItem> = {
name: 'Duration',
align: 'left',
width: 100,
render: ({row}) => {
if (isHeaderTableItem(row)) {
return null;
}

if (row.state === QueryStatus.RUNNING) {
return hammer.format.NO_VALUE;
}
return <QueryDuration query={row} />;
},
};

const StartedColumns: Column<QueryItem> = {
const StartedColumns: Column<TableItem> = {
name: 'Started',
align: 'left',
width: 120,
width: 60,
render: ({row}) => {
if (isHeaderTableItem(row)) {
return null;
}

return (
<Text variant="body-1" color="secondary">
{formatDateCompact(row.start_time)}
{formatTime(row.start_time)}
</Text>
);
},
};

const AuthorColumns: Column<QueryItem> = {
export const AuthorColumns: Column<TableItem> = {
name: 'Author',
align: 'left',
width: 120,
className: itemBlock('author_row'),
render: ({row}) => {
if (isHeaderTableItem(row)) {
return null;
}

return (
<Text variant="body-1" ellipsis title={row.user}>
{row.user}
Expand All @@ -155,13 +185,38 @@ const AuthorColumns: Column<QueryItem> = {
},
};

const MyColumns: Column<QueryItem>[] = [NameColumns, TypeColumns, DurationColumns, StartedColumns];
const AllColumns: Column<QueryItem>[] = [
const ACOColumns: Column<TableItem> = {
name: 'ACO',
align: 'left',
width: 60,
className: itemBlock('access_control_object'),
render: ({row}) => {
if (isHeaderTableItem(row)) {
return null;
}

return (
<Text variant="body-1" ellipsis title={row.access_control_object}>
{row.access_control_object}
</Text>
);
},
};

export const MyColumns: Column<TableItem>[] = [
NameColumns,
TypeColumns,
DurationColumns,
StartedColumns,
ACOColumns,
];
export const AllColumns: Column<TableItem>[] = [
NameColumns,
TypeColumns,
DurationColumns,
AuthorColumns,
StartedColumns,
ACOColumns,
];

const tableSettings: Settings = {
Expand All @@ -173,54 +228,81 @@ const tableSettings: Settings = {

export function QueriesHistoryList() {
const [items, isLoading] = useQueryHistoryList();

const [filter] = useQuriesHistoryFilter();

const {columns} = useQueryHistoryListColumns({type: filter.user});
const timestamp = useSelector(getQueriesListTimestamp);

const {first, last, goBack, goNext, goFirst} = useQueriesPagination();

const [selectedId, goToQuery] = useQueryNavigation();

const [columns, setColumns] = useState<Column<QueryItem>[]>([]);

const scrollElemRef = useRef<HTMLDivElement | null>(null);

useEffect(() => {
if (!isLoading || !items?.length) {
setColumns(filter.user === QueriesListAuthorFilter.My ? MyColumns : AllColumns);
}
}, [items, setColumns, filter.user, isLoading]);

useEffect(() => {
if (scrollElemRef?.current) {
scrollElemRef.current.scrollTop = 0;
}
}, [scrollElemRef, timestamp]);

const setClassName = useCallback(
(item: QueryItem) => {
(item: TableItem) => {
if (isHeaderTableItem(item)) {
return itemBlock({
header: Boolean(item.header),
});
}

return itemBlock({
selected: item.id === selectedId,
});
},
[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<TableItem>),
[items],
);

return (
<div className={b()}>
<div className={b('list-wrapper')} ref={scrollElemRef}>
<DataTableYT
className={b('list')}
loading={isLoading}
columns={columns}
data={items}
data={itemsByDate}
useThemeYT={true}
rowKey={(row) => row.id}
onRowClick={goToQuery}
rowKey={(row) => {
if (isHeaderTableItem(row)) {
return row.header;
}

return row.id;
}}
onRowClick={(item) => {
if (!isHeaderTableItem(item)) {
goToQuery(item);
}
}}
disableRightGap={true}
settings={tableSettings}
rowClassName={setClassName}
getColSpansOfRow={({row}) => {
if (isHeaderTableItem(row)) {
return {
Name: columns.length,
};
}

return undefined;
}}
/>
<div className={b('pagination')}>
{(!first || !last) && (
Expand Down
Loading

0 comments on commit 2c367a0

Please # to comment.