Minor: improve the UX of profiler graph tooltip (#17892)

* Minor: improve the UX of profiler graph tooltip

* addressing comment
This commit is contained in:
Shailesh Parmar 2024-09-18 18:58:06 +05:30 committed by GitHub
parent 4b0b22af2a
commit ec6a662202
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 75 additions and 23 deletions

View File

@ -32,6 +32,11 @@ jest.mock('../../../common/ErrorWithPlaceholder/ErrorPlaceHolder', () => {
return <div>ErrorPlaceHolder</div>; return <div>ErrorPlaceHolder</div>;
}); });
}); });
jest.mock('../../../../utils/DataInsightUtils', () => {
return jest.fn().mockImplementation(() => {
return <div>CustomTooltip</div>;
});
});
describe('ProfilerDetailsCard Test', () => { describe('ProfilerDetailsCard Test', () => {
it('Component should render', async () => { it('Component should render', async () => {

View File

@ -30,6 +30,8 @@ import {
tooltipFormatter, tooltipFormatter,
updateActiveChartFilter, updateActiveChartFilter,
} from '../../../../utils/ChartUtils'; } from '../../../../utils/ChartUtils';
import { CustomTooltip } from '../../../../utils/DataInsightUtils';
import { formatDateTime } from '../../../../utils/date-time/DateTimeUtils';
import ErrorPlaceHolder from '../../../common/ErrorWithPlaceholder/ErrorPlaceHolder'; import ErrorPlaceHolder from '../../../common/ErrorWithPlaceholder/ErrorPlaceHolder';
import { ProfilerDetailsCardProps } from '../ProfilerDashboard/profilerDashboard.interface'; import { ProfilerDetailsCardProps } from '../ProfilerDashboard/profilerDashboard.interface';
import ProfilerLatestValue from '../ProfilerLatestValue/ProfilerLatestValue'; import ProfilerLatestValue from '../ProfilerLatestValue/ProfilerLatestValue';
@ -94,10 +96,16 @@ const ProfilerDetailsCard: React.FC<ProfilerDetailsCardProps> = ({
type={showYAxisCategory ? 'category' : 'number'} type={showYAxisCategory ? 'category' : 'number'}
/> />
<Tooltip <Tooltip
formatter={(value: number | string) => content={
<CustomTooltip
dateTimeFormatter={formatDateTime}
timeStampKey="timestamp"
valueFormatter={(value) =>
tooltipFormatter(value, tickFormatter) tooltipFormatter(value, tickFormatter)
} }
/> />
}
/>
{information.map((info) => ( {information.map((info) => (
<Line <Line
dataKey={info.dataKey} dataKey={info.dataKey}

View File

@ -48,7 +48,11 @@ import {
axisTickFormatter, axisTickFormatter,
tooltipFormatter, tooltipFormatter,
} from '../../../../../utils/ChartUtils'; } from '../../../../../utils/ChartUtils';
import { getRandomHexColor } from '../../../../../utils/DataInsightUtils'; import {
CustomTooltip,
getRandomHexColor,
} from '../../../../../utils/DataInsightUtils';
import { formatDateTime } from '../../../../../utils/date-time/DateTimeUtils';
import { import {
showErrorToast, showErrorToast,
showSuccessToast, showSuccessToast,
@ -260,11 +264,18 @@ const CustomMetricGraphs = ({
tickFormatter={(props) => axisTickFormatter(props)} tickFormatter={(props) => axisTickFormatter(props)}
type="number" type="number"
/> />
<Tooltip <Tooltip
formatter={(value: number | string) => content={
<CustomTooltip
dateTimeFormatter={formatDateTime}
timeStampKey="timestamp"
valueFormatter={(value) =>
tooltipFormatter(value) tooltipFormatter(value)
} }
/> />
}
/>
<Line <Line
dataKey={key} dataKey={key}

View File

@ -58,7 +58,11 @@ const mockProps = {
}, },
], ],
}; };
jest.mock('../../../../../utils/DataInsightUtils', () => {
return jest.fn().mockImplementation(() => {
return <div>CustomTooltip</div>;
});
});
jest.mock( jest.mock(
'../../../../DataQuality/CustomMetricForm/CustomMetricForm.component', '../../../../DataQuality/CustomMetricForm/CustomMetricForm.component',
() => { () => {

View File

@ -36,6 +36,11 @@ const mockCustomBarChartProp: CustomBarChartProps = {
}, },
name: 'testChart', name: 'testChart',
}; };
jest.mock('../../../utils/DataInsightUtils', () => {
return jest.fn().mockImplementation(() => {
return <div>CustomTooltip</div>;
});
});
describe('CustomBarChart component test', () => { describe('CustomBarChart component test', () => {
it('Component should render', async () => { it('Component should render', async () => {

View File

@ -30,6 +30,8 @@ import {
tooltipFormatter, tooltipFormatter,
updateActiveChartFilter, updateActiveChartFilter,
} from '../../../utils/ChartUtils'; } from '../../../utils/ChartUtils';
import { CustomTooltip } from '../../../utils/DataInsightUtils';
import { formatDateTime } from '../../../utils/date-time/DateTimeUtils';
import ErrorPlaceHolder from '../../common/ErrorWithPlaceholder/ErrorPlaceHolder'; import ErrorPlaceHolder from '../../common/ErrorWithPlaceholder/ErrorPlaceHolder';
import { CustomBarChartProps } from './Chart.interface'; import { CustomBarChartProps } from './Chart.interface';
@ -77,8 +79,12 @@ const CustomBarChart = ({
tickFormatter={(props) => axisTickFormatter(props, tickFormatter)} tickFormatter={(props) => axisTickFormatter(props, tickFormatter)}
/> />
<Tooltip <Tooltip
formatter={(value: number | string) => content={
tooltipFormatter(value, tickFormatter) <CustomTooltip
dateTimeFormatter={formatDateTime}
timeStampKey="timestamp"
valueFormatter={(value) => tooltipFormatter(value, tickFormatter)}
/>
} }
/> />
{information.map((info) => ( {information.map((info) => (

View File

@ -36,6 +36,11 @@ const mockCustomBarChartProp: CustomBarChartProps = {
}, },
name: 'testChart', name: 'testChart',
}; };
jest.mock('../../../utils/DataInsightUtils', () => {
return jest.fn().mockImplementation(() => {
return <div>CustomTooltip</div>;
});
});
describe('OperationDateBarChart component test', () => { describe('OperationDateBarChart component test', () => {
it('Component should render', async () => { it('Component should render', async () => {

View File

@ -22,12 +22,15 @@ import {
ResponsiveContainer, ResponsiveContainer,
Scatter, Scatter,
Tooltip, Tooltip,
TooltipProps,
XAxis, XAxis,
} from 'recharts'; } from 'recharts';
import { GRAPH_BACKGROUND_COLOR } from '../../../constants/constants'; import { GRAPH_BACKGROUND_COLOR } from '../../../constants/constants';
import { updateActiveChartFilter } from '../../../utils/ChartUtils'; import {
import { formatNumberWithComma } from '../../../utils/CommonUtils'; tooltipFormatter,
updateActiveChartFilter,
} from '../../../utils/ChartUtils';
import { CustomTooltip } from '../../../utils/DataInsightUtils';
import { formatDateTime } from '../../../utils/date-time/DateTimeUtils';
import ErrorPlaceHolder from '../../common/ErrorWithPlaceholder/ErrorPlaceHolder'; import ErrorPlaceHolder from '../../common/ErrorWithPlaceholder/ErrorPlaceHolder';
import { CustomBarChartProps } from './Chart.interface'; import { CustomBarChartProps } from './Chart.interface';
@ -38,14 +41,6 @@ const OperationDateBarChart = ({
const { data, information } = chartCollection; const { data, information } = chartCollection;
const [activeKeys, setActiveKeys] = useState<string[]>([]); const [activeKeys, setActiveKeys] = useState<string[]>([]);
const tooltipFormatter: TooltipProps<number | string, string>['formatter'] = (
_value,
_label,
data
) => {
return formatNumberWithComma(data.payload.data);
};
const handleClick: LegendProps['onClick'] = (event) => { const handleClick: LegendProps['onClick'] = (event) => {
setActiveKeys((prevActiveKeys) => setActiveKeys((prevActiveKeys) =>
updateActiveChartFilter(event.dataKey, prevActiveKeys) updateActiveChartFilter(event.dataKey, prevActiveKeys)
@ -75,7 +70,16 @@ const OperationDateBarChart = ({
tick={{ fontSize: 12 }} tick={{ fontSize: 12 }}
/> />
<CartesianGrid stroke={GRAPH_BACKGROUND_COLOR} /> <CartesianGrid stroke={GRAPH_BACKGROUND_COLOR} />
<Tooltip formatter={tooltipFormatter} /> <Tooltip
content={
<CustomTooltip
dateTimeFormatter={formatDateTime}
timeStampKey="timestamp"
valueFormatter={(value) => tooltipFormatter(value)}
/>
}
/>
{information.map((info) => ( {information.map((info) => (
<Bar <Bar
barSize={1} barSize={1}

View File

@ -41,7 +41,8 @@ export interface ChartFilter {
export interface DataInsightChartTooltipProps extends TooltipProps<any, any> { export interface DataInsightChartTooltipProps extends TooltipProps<any, any> {
isPercentage?: boolean; isPercentage?: boolean;
isTier?: boolean; isTier?: boolean;
valueFormatter?: (value: number | string, key?: string) => string; dateTimeFormatter?: (date?: number) => string;
valueFormatter?: (value: number | string, key?: string) => string | number;
timeStampKey?: string; timeStampKey?: string;
} }

View File

@ -26,6 +26,7 @@ import {
startCase, startCase,
sumBy, sumBy,
toNumber, toNumber,
uniqBy,
} from 'lodash'; } from 'lodash';
import moment from 'moment'; import moment from 'moment';
import React from 'react'; import React from 'react';
@ -144,19 +145,21 @@ export const CustomTooltip = (props: DataInsightChartTooltipProps) => {
active, active,
payload = [], payload = [],
valueFormatter, valueFormatter,
dateTimeFormatter = formatDate,
isPercentage, isPercentage,
timeStampKey = 'timestampValue', timeStampKey = 'timestampValue',
} = props; } = props;
if (active && payload && payload.length) { if (active && payload && payload.length) {
const timestamp = formatDate(payload[0].payload[timeStampKey] || 0); const timestamp = dateTimeFormatter(payload[0].payload[timeStampKey] || 0);
const payloadValue = uniqBy(payload, 'dataKey');
return ( return (
<Card <Card
className="custom-data-insight-tooltip" className="custom-data-insight-tooltip"
title={<Typography.Title level={5}>{timestamp}</Typography.Title>}> title={<Typography.Title level={5}>{timestamp}</Typography.Title>}>
<ul className="custom-data-insight-tooltip-container"> <ul className="custom-data-insight-tooltip-container">
{payload.map((entry, index) => ( {payloadValue.map((entry, index) => (
<li <li
className="d-flex items-center justify-between gap-6 p-b-xss text-sm" className="d-flex items-center justify-between gap-6 p-b-xss text-sm"
key={`item-${index}`}> key={`item-${index}`}>