Skip to content

Commit

Permalink
feat(Job/Statistics): use operation_statistics_descriptions from supp…
Browse files Browse the repository at this point in the history
…orted_features [YTFRONT-3522]
  • Loading branch information
ma-efremoff committed Dec 25, 2024
1 parent 9a012e0 commit 8f76825
Show file tree
Hide file tree
Showing 13 changed files with 150 additions and 104 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.job-statistics {
.yt-statistics-table {
.elements-toolbar {
margin-top: -10px;
margin-bottom: 10px;
Expand Down Expand Up @@ -52,4 +52,10 @@
& &__filter {
margin-right: 8px;
}

&__description {
width: 100%;
text-overflow: unset;
white-space: unset;
}
}
95 changes: 79 additions & 16 deletions packages/ui/src/ui/components/StatisticTable/StatisticTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,32 @@ import {useSelector} from 'react-redux';
import cn from 'bem-cn-lite';

import Icon from '../Icon/Icon';
import hammer from '../../common/hammer';
import format from '../../common/hammer/format';
import ErrorBoundary from '../ErrorBoundary/ErrorBoundary';
import ElementsTableRow from '../ElementsTable/ElementsTable';
import {ExpandButton} from '../ExpandButton';
import {getFontFamilies} from '../../store/selectors/global/fonts';
import {Tooltip} from '../../components/Tooltip/Tooltip';
import MetaTable from '../../components/MetaTable/MetaTable';
import {Secondary} from '../../components/Text/Text';

import Toolbar from './Toolbar';
import {getMinWidth} from './get-min-width';
import {filterStatisticTree, prepareStatisticTs} from './prepare-statistic.ts';
import {Statistic, StatisticTree, TreeState} from './types';
import {ExpandButton} from '../ExpandButton';

import './Statistics.scss';
import {formatByUnit} from './utils';
import './StatisticTable.scss';

const block = cn('job-statistics');
const block = cn('yt-statistics-table');

export const LEVEL_OFFSET = 40;

export type StatisticInfo = {
description?: string;
unit?: string;
};

interface TreeItem {
name: string;
level: number;
Expand All @@ -34,39 +43,43 @@ interface TreeItem {

interface AvgProps {
item: TreeItem;
unit?: string;
}

function Avg({item}: AvgProps) {
function Avg({item, unit}: AvgProps) {
const statistic: Statistic = item.attributes.value as Statistic;

if (statistic && statistic.count && statistic.sum) {
const result: number = statistic.sum / statistic.count;

if (result < 1) {
return hammer.format['Number'](result, {significantDigits: 6});
return formatByUnit(result, unit, {significantDigits: 6});
} else {
return hammer.format.Number(result);
return formatByUnit(result, unit);
}
}

return hammer.format.NO_VALUE;
return format.NO_VALUE;
}

interface StatisticProps {
item: TreeItem;
aggregation: 'avg' | 'min' | 'max' | 'sum' | 'count' | 'last';
unit?: string;
}

function StatisticTableStaticCell({item, aggregation}: StatisticProps) {
function StatisticTableStaticCell({item, aggregation, unit}: StatisticProps) {
if (item.isLeafNode && Boolean(item.attributes.value)) {
if (aggregation === 'avg') {
return <Avg item={item} />;
return <Avg item={item} unit={unit} />;
} else if (aggregation === 'count') {
return format['Number'](item.attributes?.value?.[aggregation]);
} else {
return hammer.format['Number'](item.attributes?.value?.[aggregation]);
return formatByUnit(item.attributes?.value?.[aggregation], unit);
}
}

return hammer.format.NO_VALUE;
return format.NO_VALUE;
}

interface ItemState {
Expand All @@ -81,6 +94,42 @@ interface MetricProps {
toggleItemState: Function;
renderValue: (item: TreeItem) => React.ReactChild;
minWidth?: number;
info?: StatisticInfo;
}

export function StatisticName({title, info}: {title: React.ReactNode; info?: StatisticInfo}) {
const emptyInfo = !info?.description && !info?.unit;

return (
<Tooltip
content={
emptyInfo ? null : (
<MetaTable
items={[
{
key: 'Description',
value: info.description,
visible: Boolean(info.description),
className: block('description'),
},
{
key: 'Unit',
value: info.unit,
visible: Boolean(info.unit),
},
]}
/>
)
}
>
{title}{' '}
{!emptyInfo && (
<Secondary>
<Icon awesome={'question-circle'} />
</Secondary>
)}
</Tooltip>
);
}

export function ExpandedCell({
Expand All @@ -89,6 +138,7 @@ export function ExpandedCell({
toggleItemState,
minWidth = undefined,
renderValue,
info,
}: MetricProps) {
const offsetStyle = React.useMemo(() => {
return {minWidth, paddingLeft: (item?.level || 0) * LEVEL_OFFSET};
Expand All @@ -105,7 +155,7 @@ export function ExpandedCell({
<span className={block('metric')} style={offsetStyle}>
<Icon awesome="chart-line" className={block('metric-icon')} />

<span>{renderValue(item)}</span>
<StatisticName title={renderValue(item)} info={info} />
</span>
);
} else {
Expand Down Expand Up @@ -200,17 +250,21 @@ const useJobStatisticTable = ({
};

export function StatisticTable({
className,
helpUrl,
virtual,
visibleColumns,
fixedHeader,
statistic,
getStatisticInfo,
}: {
className?: string;
helpUrl?: string;
virtual?: boolean;
fixedHeader?: boolean;
statistic: StatisticTree;
visibleColumns: Array<'avg' | 'min' | 'max' | 'sum' | 'count' | 'last'>;
getStatisticInfo?: (name: string) => StatisticInfo | undefined;
}) {
const fontFamilies = useSelector(getFontFamilies);
const {items, minWidth, treeState, setTreeState, onFilterChange} = useJobStatisticTable({
Expand All @@ -222,25 +276,34 @@ export function StatisticTable({
() =>
({
name(item, _, toggleItemState, itemState) {
const info = getStatisticInfo?.(item.name) ?? {};
return (
<ExpandedCell
item={item}
minWidth={minWidth}
toggleItemState={toggleItemState}
itemState={itemState}
renderValue={(item) => item?.attributes?.name}
info={info}
/>
);
},
__default__(item, columnName: ColumnName) {
if (item.isLeafNode) {
return <StatisticTableStaticCell item={item} aggregation={columnName} />;
const {unit} = getStatisticInfo?.(item.name) ?? {};
return (
<StatisticTableStaticCell
item={item}
aggregation={columnName}
unit={unit}
/>
);
}

return null;
},
}) as StatisticTableTemplate<TreeItem>,
[minWidth],
[minWidth, getStatisticInfo],
);
const tableProps = React.useMemo(() => {
return prepareTableProps({
Expand All @@ -250,7 +313,7 @@ export function StatisticTable({

return (
<ErrorBoundary>
<div className={block()}>
<div className={block(null, className)}>
<Toolbar
helpUrl={helpUrl}
onFilterChange={onFilterChange}
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/ui/components/StatisticTable/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {TreeState} from './types';

const toolbarBlock = cn('elements-toolbar');

const block = cn('job-statistics');
const block = cn('yt-statistics-table');

export default function Toolbar(props: {
helpUrl?: string;
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/ui/components/StatisticTable/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './StatisticTable';
export type {StatisticTree} from './types';
export * from './utils';
19 changes: 19 additions & 0 deletions packages/ui/src/ui/components/StatisticTable/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import format from '../../common/hammer/format';

const UNIT_TO_FORMATTER: Record<string, undefined | ((v?: number, settings?: object) => string)> = {
['ms']: (v, settings) =>
format.TimeDuration(Math.round(v!), {format: 'milliseconds', ...settings}),
['bytes']: (v, settings) => formatBytes(v, settings),
['bytes * sec']: (v, settings) => formatBytes(v, settings, ' * sec'),
['ms * bytes']: (v, settings) => formatBytes(v, settings, ' * ms'),
['Mb*sec']: (v, settings) => formatBytes(v! * 1024 * 1024, settings, ' * sec'),
};

function formatBytes(v?: number, settings?: object, suffix = '') {
return isNaN(v!) ? format.NO_VALUE : format.Bytes(Math.round(v!), settings) + suffix;
}

export function formatByUnit(v?: number, unit?: string, settings?: object) {
const formatFn = UNIT_TO_FORMATTER[unit!] ?? format.Number;
return formatFn?.(v, settings);
}
3 changes: 3 additions & 0 deletions packages/ui/src/ui/pages/job/tabs/Statistics/Statistics.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.yt-job-statistics {
margin-bottom: 50px;
}
3 changes: 3 additions & 0 deletions packages/ui/src/ui/pages/job/tabs/Statistics/Statistics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {useSelector} from 'react-redux';
import cn from 'bem-cn-lite';

import {getRawStatistic} from '../../../../store/selectors/job/statistics';
import {getOperationStatisticsDescription} from '../../../../store/selectors/global/supported-features';
import {StatisticTable, StatisticTree} from '../../../../components/StatisticTable';
import {isDocsAllowed} from '../../../../config';
import UIFactory from '../../../../UIFactory';
Expand All @@ -13,12 +14,14 @@ const block = cn('yt-job-statistics');

export default function Statistics() {
const statistic = useSelector(getRawStatistic);
const {getStatisticInfo} = useSelector(getOperationStatisticsDescription);
return (
<StatisticTable
className={block()}
helpUrl={isDocsAllowed() ? UIFactory.docsUrls['problems:jobstatistics'] : undefined}
statistic={statistic as unknown as StatisticTree}
visibleColumns={['min', 'max', 'last', 'sum', 'count']}
getStatisticInfo={getStatisticInfo}
/>
);
}

This file was deleted.

Loading

0 comments on commit 8f76825

Please sign in to comment.