Skip to content

Commit

Permalink
ADM-944: [frontend] feat: show thumbUp and thumDown Icon in tooltip a… (
Browse files Browse the repository at this point in the history
#1473)

* ADM-944: [frontend] feat: show thumbUp and thumDown Icon in tooltip and always show positive data

* ADM-944: [frontend] feat: fix test

* ADM-944: [frontend] feat: add TrendTypeIcon test

* ADM-944: [frontend] feat: rename test]
  • Loading branch information
Mandy-Tang authored May 30, 2024
1 parent b9c052d commit 9d8af33
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import ChartAndTitleWrapper from '@src/containers/ReportStep/ChartAndTitleWrapper';
import { CHART_TYPE, TREND_ICON } from '@src/constants/resources';
import { CHART_TYPE, TREND_ICON, TREND_TYPE } from '@src/constants/resources';
import { render, screen } from '@testing-library/react';

describe('ChartAndTitleWrapper', () => {
it('should render green up icon when icon is set to up and green', () => {
it('should render green up icon given icon is set to up and better', () => {
const testedTrendInfo = {
color: 'green',
trendType: TREND_TYPE.BETTER,
icon: TREND_ICON.UP,
trendNumber: 83.72,
trendNumber: 0.83,
type: CHART_TYPE.VELOCITY,
};
render(<ChartAndTitleWrapper trendInfo={testedTrendInfo} />);
Expand All @@ -17,11 +17,11 @@ describe('ChartAndTitleWrapper', () => {
expect(icon.parentElement?.parentElement).toHaveStyle({ color: 'green' });
});

it('should render down icon when icon is set to down', () => {
it('should render down icon given icon is set to down and worse', () => {
const testedTrendInfo = {
color: 'red',
trendType: TREND_TYPE.WORSE,
icon: TREND_ICON.DOWN,
trendNumber: -83.72,
trendNumber: -0.83,
type: CHART_TYPE.VELOCITY,
};
render(<ChartAndTitleWrapper trendInfo={testedTrendInfo} />);
Expand All @@ -30,4 +30,16 @@ describe('ChartAndTitleWrapper', () => {
expect(screen.getByTestId('TrendingDownSharpIcon')).toBeInTheDocument();
expect(icon.parentElement?.parentElement).toHaveStyle({ color: 'red' });
});

it('should show positive trend number even if the tend number is negative', () => {
const testedTrendInfo = {
trendType: TREND_TYPE.WORSE,
icon: TREND_ICON.DOWN,
trendNumber: -0.8372,
type: CHART_TYPE.VELOCITY,
};
render(<ChartAndTitleWrapper trendInfo={testedTrendInfo} />);

expect(screen.getByLabelText('trend number')).toHaveTextContent('83.72%');
});
});
14 changes: 14 additions & 0 deletions frontend/__tests__/containers/ReportStep/style.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { TrendTypeIcon } from '@src/containers/ReportStep/ChartAndTitleWrapper/style';
import { StyledCalendarWrapper } from '@src/containers/ReportStep/style';
import { render, screen } from '@testing-library/react';
import ThumbUpIcon from '@mui/icons-material/ThumbUp';

describe('Report step styled components', () => {
it('should render the bottom margin depend on whether StyledCalendarWrapper in summary page', () => {
Expand All @@ -22,3 +24,15 @@ describe('Report step styled components', () => {
expect(component2).toHaveStyle({ 'margin-bottom': '2rem' });
});
});

describe('ChartAndTitleWrapper styled component', () => {
it('should render the TrendTypeIcon with the given color', () => {
render(
<TrendTypeIcon aria-label='test component 1' color='red'>
<ThumbUpIcon />
</TrendTypeIcon>,
);
console.log(screen.getByLabelText('test component 1'));
expect(screen.getByLabelText('test component 1').children[0]).toHaveStyle({ color: 'red' });
});
});
11 changes: 6 additions & 5 deletions frontend/__tests__/utils/Util.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
DOWN_TREND_IS_BETTER,
METRICS_CONSTANTS,
TREND_ICON,
TREND_TYPE,
UP_TREND_IS_BETTER,
} from '@src/constants/resources';
import { CleanedBuildKiteEmoji, OriginBuildKiteEmoji } from '@src/constants/emojis/emoji';
Expand Down Expand Up @@ -639,7 +640,7 @@ describe('calculateTrendInfo function', () => {

expect(result.dateRangeList).toEqual(undefined);
expect(result.trendNumber).toEqual(undefined);
expect(result.color).toEqual(undefined);
expect(result.trendType).toEqual(undefined);
expect(result.icon).toEqual(undefined);
expect(result.type).toEqual(CHART_TYPE.VELOCITY);
});
Expand All @@ -652,7 +653,7 @@ describe('calculateTrendInfo function', () => {

expect(result.dateRangeList).toEqual(['2024/01/22-2024/01/23', '2024/01/15-2024/01/19']);
expect(result.trendNumber).toEqual(2);
expect(result.color).toEqual('green');
expect(result.trendType).toEqual(TREND_TYPE.BETTER);
expect(result.icon).toEqual(TREND_ICON.UP);
expect(result.type).toEqual(type);
},
Expand All @@ -667,7 +668,7 @@ describe('calculateTrendInfo function', () => {

expect(result.dateRangeList).toEqual(['2024/01/22-2024/01/23', '2024/01/15-2024/01/19']);
expect(Number(result.trendNumber?.toFixed(2))).toEqual(-0.67);
expect(result.color).toEqual('red');
expect(result.trendType).toEqual(TREND_TYPE.WORSE);
expect(result.icon).toEqual(TREND_ICON.DOWN);
expect(result.type).toEqual(type);
},
Expand All @@ -682,7 +683,7 @@ describe('calculateTrendInfo function', () => {

expect(result.dateRangeList).toEqual(['2024/01/22-2024/01/23', '2024/01/15-2024/01/19']);
expect(Number(result.trendNumber?.toFixed(2))).toEqual(-0.67);
expect(result.color).toEqual('green');
expect(result.trendType).toEqual(TREND_TYPE.BETTER);
expect(result.icon).toEqual(TREND_ICON.DOWN);
expect(result.type).toEqual(type);
},
Expand All @@ -697,7 +698,7 @@ describe('calculateTrendInfo function', () => {

expect(result.dateRangeList).toEqual(['2024/01/22-2024/01/23', '2024/01/15-2024/01/19']);
expect(result.trendNumber).toEqual(2);
expect(result.color).toEqual('red');
expect(result.trendType).toEqual(TREND_TYPE.WORSE);
expect(result.icon).toEqual(TREND_ICON.UP);
expect(result.type).toEqual(type);
},
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/constants/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ export enum TREND_ICON {
DOWN = 'DOWN',
}

export enum TREND_TYPE {
BETTER = 'BETTER',
WORSE = 'WORSE',
}

export const CHART_TREND_TIP = {
[CHART_TYPE.VELOCITY]: 'Velocity(Story point)',
[CHART_TYPE.AVERAGE_CYCLE_TIME]: 'Days/Story point',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import {
stackedAreaOptionMapper,
stackedBarOptionMapper,
} from '@src/containers/ReportStep/BoardMetricsChart/ChartOption';
import { CHART_TYPE, CYCLE_TIME_CHARTS_MAPPING, METRICS_CONSTANTS } from '@src/constants/resources';
import ChartAndTitleWrapper from '@src/containers/ReportStep/ChartAndTitleWrapper';
import { CHART_TYPE, CYCLE_TIME_CHARTS_MAPPING } from '@src/constants/resources';
import { calculateTrendInfo, xAxisLabelDateFormatter } from '@src/utils/util';
import { ReportResponse, Swimlane } from '@src/clients/report/dto/response';
import { ChartContainer } from '@src/containers/MetricsStep/style';
Expand Down Expand Up @@ -159,7 +159,11 @@ function extractCycleTimeData(dateRanges: string[], mappedData?: ReportResponse[
for (const [name, data] of Object.entries(cycleTimeByStatus)) {
indicators.push({ data, name: CYCLE_TIME_CHARTS_MAPPING[name], type: 'bar' });
}
const trendInfo = calculateTrendInfo(totalCycleTime, dateRanges, CHART_TYPE.CYCLE_TIME_ALLOCATION);
const developmentPercentageList = indicators.find(
({ name }) => name === CYCLE_TIME_CHARTS_MAPPING[METRICS_CONSTANTS.inDevValue],
)?.data;
const trendInfo = calculateTrendInfo(developmentPercentageList, dateRanges, CHART_TYPE.CYCLE_TIME_ALLOCATION);

return {
xAxis: dateRanges,
yAxis: {
Expand Down
38 changes: 29 additions & 9 deletions frontend/src/containers/ReportStep/ChartAndTitleWrapper/index.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
import {
ChartTitle,
StyledToolTipContent,
StyledTooltipContent,
StyledTooltipWrapper,
TrendContainer,
TrendIcon,
TrendTypeIcon,
} from '@src/containers/ReportStep/ChartAndTitleWrapper/style';
import { CHART_TREND_TIP, CHART_TYPE, TREND_ICON, UP_TREND_IS_BETTER } from '@src/constants/resources';
import { CHART_TREND_TIP, CHART_TYPE, TREND_ICON, TREND_TYPE, UP_TREND_IS_BETTER } from '@src/constants/resources';
import TrendingDownSharpIcon from '@mui/icons-material/TrendingDownSharp';
import TrendingUpSharpIcon from '@mui/icons-material/TrendingUpSharp';
import { ChartWrapper } from '@src/containers/MetricsStep/style';
import ThumbDownIcon from '@mui/icons-material/ThumbDown';
import { convertNumberToPercent } from '@src/utils/util';
import React, { ForwardedRef, forwardRef } from 'react';
import ThumbUpIcon from '@mui/icons-material/ThumbUp';
import { Tooltip } from '@mui/material';
import { theme } from '@src/theme';

export interface ITrendInfo {
color?: string;
icon?: TREND_ICON;
trendNumber?: number;
dateRangeList?: string[];
type: CHART_TYPE;
trendType?: TREND_TYPE;
}

const TREND_ICON_MAPPING = {
[TREND_ICON.UP]: <TrendingUpSharpIcon />,
[TREND_ICON.DOWN]: <TrendingDownSharpIcon />,
};

const TREND_TYPE_ICON_MAPPING = {
[TREND_TYPE.BETTER]: <ThumbUpIcon />,
[TREND_TYPE.WORSE]: <ThumbDownIcon />,
};

const TREND_COLOR_MAP = {
[TREND_TYPE.BETTER]: theme.main.chartTrend.betterColor,
[TREND_TYPE.WORSE]: theme.main.chartTrend.worseColor,
};

const DECREASE = 'decrease';
const INCREASE = 'increase';

Expand All @@ -50,10 +65,15 @@ const ChartAndTitleWrapper = forwardRef(
}
};
const tipContent = (
<StyledToolTipContent>
<p>{`The rate of ${trendDescribe()} for ${CHART_TREND_TIP[trendInfo.type]}: `}</p>
{trendInfo.dateRangeList?.map((dateRange) => <p key={dateRange}>{dateRange}</p>)}
</StyledToolTipContent>
<StyledTooltipWrapper>
<TrendTypeIcon color={TREND_COLOR_MAP[trendInfo.trendType!]}>
{TREND_TYPE_ICON_MAPPING[trendInfo.trendType!]}
</TrendTypeIcon>
<StyledTooltipContent>
<p>{`The rate of ${trendDescribe()} for ${CHART_TREND_TIP[trendInfo.type]}: `}</p>
{trendInfo.dateRangeList?.map((dateRange) => <p key={dateRange}>{dateRange}</p>)}
</StyledTooltipContent>
</StyledTooltipWrapper>
);

return (
Expand All @@ -62,9 +82,9 @@ const ChartAndTitleWrapper = forwardRef(
{trendInfo.type}
{trendInfo.trendNumber !== undefined && (
<Tooltip title={tipContent} arrow>
<TrendContainer color={trendInfo.color!}>
<TrendContainer color={TREND_COLOR_MAP[trendInfo.trendType!]}>
<TrendIcon>{TREND_ICON_MAPPING[trendInfo.icon!]}</TrendIcon>
{convertNumberToPercent(trendInfo.trendNumber)}
<span aria-label='trend number'>{convertNumberToPercent(trendInfo.trendNumber)}</span>
</TrendContainer>
</Tooltip>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,21 @@ export const TrendContainer = styled('div')(({ color }: { color: string }) => ({
fontSize: '1.125rem',
}));

export const StyledToolTipContent = styled('div')({
export const StyledTooltipContent = styled('div')({
fontSize: '0.85rem',
display: 'flex',
flexDirection: 'column',
gap: '0.5rem',
});

export const StyledTooltipWrapper = styled('div')({
display: 'flex',
});

export const TrendTypeIcon = styled('div')(({ color }: { color: string }) => ({
'& svg': {
color: color,
fontSize: '1rem',
marginRight: '0.5rem',
},
}));
13 changes: 7 additions & 6 deletions frontend/src/utils/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
DOWN_TREND_IS_BETTER,
METRICS_CONSTANTS,
TREND_ICON,
TREND_TYPE,
UP_TREND_IS_BETTER,
} from '@src/constants/resources';
import { CleanedBuildKiteEmoji, OriginBuildKiteEmoji } from '@src/constants/emojis/emoji';
Expand All @@ -17,7 +18,6 @@ import { DateRangeList } from '@src/context/config/configSlice';
import { BoardInfoResponse } from '@src/hooks/useGetBoardInfo';
import { DATE_FORMAT_TEMPLATE } from '@src/constants/template';
import duration from 'dayjs/plugin/duration';
import { theme } from '@src/theme';
import dayjs from 'dayjs';

dayjs.extend(duration);
Expand Down Expand Up @@ -225,19 +225,19 @@ export const getTrendInfo = (trendNumber: number, dateRangeList: string[], type:

if (UP_TREND_IS_BETTER.includes(type)) {
if (trendNumber >= 0) {
result.color = theme.main.chartTrend.betterColor;
result.icon = TREND_ICON.UP;
result.trendType = TREND_TYPE.BETTER;
} else {
result.color = theme.main.chartTrend.worseColor;
result.icon = TREND_ICON.DOWN;
result.trendType = TREND_TYPE.WORSE;
}
} else if (DOWN_TREND_IS_BETTER.includes(type)) {
if (trendNumber <= 0) {
result.color = theme.main.chartTrend.betterColor;
result.icon = TREND_ICON.DOWN;
result.trendType = TREND_TYPE.BETTER;
} else {
result.color = theme.main.chartTrend.worseColor;
result.icon = TREND_ICON.UP;
result.trendType = TREND_TYPE.WORSE;
}
}
return result;
Expand All @@ -262,7 +262,8 @@ export const calculateTrendInfo = (
};

export const convertNumberToPercent = (num: number): string => {
return (num * 100).toFixed(2) + '%';
const positiveNumber = num >= 0 ? num : -num;
return (positiveNumber * 100).toFixed(2) + '%';
};

export const percentageFormatter = (showPercentage = true) => {
Expand Down

0 comments on commit 9d8af33

Please sign in to comment.