Skip to content

Commit

Permalink
ADM-973 [frontend] retry all when retry (#1524)
Browse files Browse the repository at this point in the history
* ADM-973 [frontend] feat: fix share report style

* ADM-973 [frontend] feat: do not regenerate report Id when retry

* ADM-973 [frontend] feat: retry all when retry

* ADM-973 [frontend] feat: hide alert when close trigger

* ADM-973 [frontend] feat: add test for retry situation and sort reportInfo

* ADM-973 [frontend] feat: change download file name to reportId

* ADM-973 [frontend] feat: add test for sortReportInfo

* ADM-973 [frontend] feat: remove useless code

* ADM-973 [frontend] feat: fix sonar
  • Loading branch information
Mandy-Tang authored Jul 12, 2024
1 parent cf9bc63 commit 0b4d54a
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 52 deletions.
30 changes: 30 additions & 0 deletions frontend/__tests__/hooks/useGenerateReportEffect.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -280,3 +280,33 @@ describe('use generate report effect', () => {
expect(result.current.reportInfos[1].timeout4Dora.shouldShow).toEqual(true);
});
});

describe('generateReportId execution', () => {
it('should not call generateReportId when call startToRequestData method given reportId is already generated', async () => {
reportClient.generateReportId = jest.fn().mockResolvedValue({ reportId: 'mockReportId' });
reportClient.polling = jest
.fn()
.mockImplementation(async () => ({ status: HttpStatusCode.Ok, response: MOCK_REPORT_RESPONSE }));
reportClient.retrieveByUrl = jest.fn().mockImplementation(async () => MOCK_RETRIEVE_REPORT_RESPONSE);

const { result } = setup();

await waitFor(() => {
result.current.startToRequestData(MOCK_GENERATE_REPORT_REQUEST_PARAMS_WITH_BOARD_METRIC_TYPE);
});

jest.runOnlyPendingTimers();

await waitFor(() => {
expect(reportClient.generateReportId).toHaveBeenCalledTimes(1);
});

await waitFor(() => {
result.current.startToRequestData(MOCK_GENERATE_REPORT_REQUEST_PARAMS_WITH_BOARD_METRIC_TYPE);
});

await waitFor(() => {
expect(reportClient.generateReportId).toHaveBeenCalledTimes(1);
});
});
});
42 changes: 42 additions & 0 deletions frontend/__tests__/utils/Util.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
sortDateRanges,
sortDisabledOptions,
sortLegend,
sortReportInfos,
transformToCleanedBuildKiteEmoji,
updateResponseCrews,
valueFormatter,
Expand All @@ -33,6 +34,7 @@ import {
import { CleanedBuildKiteEmoji, OriginBuildKiteEmoji } from '@src/constants/emojis/emoji';
import { ICycleTimeSetting, IPipelineConfig } from '@src/context/Metrics/metricsSlice';
import { IPipeline } from '@src/context/config/pipelineTool/verifyResponseSlice';
import { IReportInfo } from '../../src/hooks/useGenerateReportEffect';
import { BoardInfoResponse } from '@src/hooks/useGetBoardInfo';
import { EMPTY_STRING } from '@src/constants/commons';
import { PIPELINE_TOOL_TYPES } from '../fixtures';
Expand Down Expand Up @@ -447,6 +449,46 @@ describe('sortDateRanges function', () => {
});
});

describe('sortReportInfos function', () => {
const reportInfos = [
{
id: '2024-03-19T00:00:00.000+08:00',
reportData: {},
},
{
id: '2024-02-01T00:00:00.000+08:00',
reportData: {},
},
{
id: '2024-04-01T00:00:00.000+08:00',
reportData: {},
},
];
const expectResult = [
{
id: '2024-04-01T00:00:00.000+08:00',
reportData: {},
},
{
id: '2024-03-19T00:00:00.000+08:00',
reportData: {},
},
{
id: '2024-02-01T00:00:00.000+08:00',
reportData: {},
},
];
it('should descend reportInfos', () => {
const sortedReportInfos = sortReportInfos(reportInfos as IReportInfo[]);
expect(sortedReportInfos).toStrictEqual(expectResult);
});

it('should ascend reportInfos', () => {
const sortedReportInfos = sortReportInfos(reportInfos as IReportInfo[], false);
expect(sortedReportInfos).toStrictEqual(expectResult.reverse());
});
});

describe('combineBoardInfo function', () => {
const boardInfoResponses: BoardInfoResponse[] = [
{
Expand Down
5 changes: 1 addition & 4 deletions frontend/src/clients/report/CSVClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { downloadCSV } from '@src/utils/util';
import dayjs from 'dayjs';

export class CSVClient extends HttpClient {
parseTimeStampToHumanDate = (csvTimeStamp: number | undefined): string => dayjs(csvTimeStamp).format('HHmmSSS');
parseCollectionDateToHumanDate = (date: string) => dayjs(date).format('YYYYMMDD');

exportCSVData = async (params: CSVReportRequestDTO) => {
Expand All @@ -19,9 +18,7 @@ export class CSVClient extends HttpClient {
.then((res) => {
const exportedFilename = `${params.dataType}-${this.parseCollectionDateToHumanDate(
params.startDate,
)}-${this.parseCollectionDateToHumanDate(params.endDate)}-${this.parseTimeStampToHumanDate(
params.reportId,
)}.csv`;
)}-${this.parseCollectionDateToHumanDate(params.endDate)}-${params.reportId}.csv`;
downloadCSV(exportedFilename, res.data);
})
.catch((e) => {
Expand Down
32 changes: 10 additions & 22 deletions frontend/src/containers/ReportStep/ReportContent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
TimeoutErrorKey,
useGenerateReportEffect,
} from '@src/hooks/useGenerateReportEffect';
import { sortDateRanges } from '@src/utils/util';
import { sortDateRanges, sortReportInfos } from '@src/utils/util';

import {
addNotification,
Expand Down Expand Up @@ -54,8 +54,7 @@ import { uniqueId } from 'lodash';
export interface ReportContentProps {
metrics: string[];
dateRanges: DateRangeList;
startToRequestDoraData: () => void;
startToRequestBoardData: () => void;
startToRequestData: () => void;
reportInfos: IReportInfo[];
handleSave?: () => void;
reportId?: number;
Expand All @@ -75,16 +74,8 @@ export interface DateRangeRequestResult {
}

const ReportContent = (props: ReportContentProps) => {
const {
metrics,
dateRanges,
startToRequestDoraData,
startToRequestBoardData,
reportInfos,
handleSave,
reportId,
hideButtons = false,
} = props;
const { metrics, dateRanges, reportInfos, handleSave, reportId, startToRequestData, hideButtons = false } = props;

const dispatch = useAppDispatch();

const descendingDateRanges = sortDateRanges(dateRanges);
Expand All @@ -98,6 +89,7 @@ const ReportContent = (props: ReportContentProps) => {

return `${formattedStart}-${formattedEnd}`;
});
const ascendingReportInfos = sortReportInfos(reportInfos, false);

const [selectedDateRange, setSelectedDateRange] = useState<DateRange>(descendingDateRanges[0]);
const [currentDataInfo, setCurrentDataInfo] = useState<IReportInfo>(initReportInfo());
Expand Down Expand Up @@ -258,7 +250,7 @@ const ReportContent = (props: ReportContentProps) => {
<Box>
{shouldShowBoardMetrics && (
<BoardMetrics
startToRequestBoardData={startToRequestBoardData}
startToRequestBoardData={startToRequestData}
onShowDetail={() => setPageType(REPORT_PAGE_TYPE.BOARD)}
boardReport={currentDataInfo.reportData}
errorMessage={getErrorMessage4Board()}
Expand All @@ -267,7 +259,7 @@ const ReportContent = (props: ReportContentProps) => {
)}
{shouldShowDoraMetrics && (
<DoraMetrics
startToRequestDoraData={startToRequestDoraData}
startToRequestDoraData={startToRequestData}
onShowDetail={() => setPageType(REPORT_PAGE_TYPE.DORA)}
doraReport={currentDataInfo.reportData}
metrics={metrics}
Expand Down Expand Up @@ -383,10 +375,6 @@ const ReportContent = (props: ReportContentProps) => {
setPageType(newValue === CHART_INDEX.BOARD ? REPORT_PAGE_TYPE.BOARD_CHART : REPORT_PAGE_TYPE.DORA_CHART);
};

const handleChartRetry = () => {
pageType === REPORT_PAGE_TYPE.DORA_CHART ? startToRequestDoraData() : startToRequestBoardData();
};

const tabProps = (index: number) => {
return {
id: `simple-tab-${index}`,
Expand All @@ -403,9 +391,9 @@ const ReportContent = (props: ReportContentProps) => {
case REPORT_PAGE_TYPE.DORA:
return !!reportData && showDoraDetail(reportData);
case REPORT_PAGE_TYPE.BOARD_CHART:
return showBoardChart(reportInfos);
return showBoardChart(ascendingReportInfos);
case REPORT_PAGE_TYPE.DORA_CHART:
return showDoraChart(reportInfos.map((infos) => infos.reportData));
return showDoraChart(ascendingReportInfos.map((infos) => infos.reportData));
}
};

Expand All @@ -430,7 +418,7 @@ const ReportContent = (props: ReportContentProps) => {
{startDate && endDate && (
<StyledCalendarWrapper data-testid={'calendarWrapper'} justCalendar={!shouldShowTabs}>
{shouldShowChartRetryButton() && (
<StyledRetry aria-label='chart retry' onClick={handleChartRetry}>
<StyledRetry aria-label='chart retry' onClick={startToRequestData}>
<ReplayIcon />
</StyledRetry>
)}
Expand Down
20 changes: 2 additions & 18 deletions frontend/src/containers/ReportStep/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import {
selectConfig,
selectDateRange,
} from '@src/context/config/configSlice';
import { BOARD_METRICS, DORA_METRICS, MESSAGE, RequiredData } from '@src/constants/resources';
import { IPipelineConfig, selectMetricsContent } from '@src/context/Metrics/metricsSlice';
import { selectReportId, selectTimeStamp } from '@src/context/stepper/StepperSlice';
import { ReportResponseDTO } from '@src/clients/report/dto/response';
import { MESSAGE, RequiredData } from '@src/constants/resources';
import { useAppDispatch } from '@src/hooks/useAppDispatch';
import { MetricTypes } from '@src/constants/commons';
import ReportContent from './ReportContent';
Expand Down Expand Up @@ -170,21 +170,6 @@ const ReportStep = ({ handleSave }: ReportStepProps) => {
...(shouldShowDoraMetrics ? getDoraSetting() : {}),
};

const boardReportRequestBody = {
...basicReportRequestBody,
metrics: metrics.filter((metric) => BOARD_METRICS.includes(metric)),
metricTypes: [MetricTypes.Board],
buildKiteSetting: undefined,
codebaseSetting: undefined,
};

const doraReportRequestBody = {
...basicReportRequestBody,
metrics: metrics.filter((metric) => DORA_METRICS.includes(metric)),
metricTypes: [MetricTypes.DORA],
jiraBoardSetting: undefined,
};

useEffect(() => {
exportValidityTimeMin &&
isCsvFileGeneratedAtEnd &&
Expand Down Expand Up @@ -242,8 +227,7 @@ const ReportStep = ({ handleSave }: ReportStepProps) => {
<ReportContent
metrics={metrics}
dateRanges={dateRanges}
startToRequestDoraData={() => startToRequestData(doraReportRequestBody)}
startToRequestBoardData={() => startToRequestData(boardReportRequestBody)}
startToRequestData={() => startToRequestData(basicReportRequestBody)}
reportInfos={reportInfos}
handleSave={handleSave}
reportId={reportId}
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/containers/ShareReport/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ const ShareReport = () => {
metrics={metrics}
dateRanges={dateRanges}
reportInfos={reportInfos}
startToRequestBoardData={getData}
startToRequestDoraData={getData}
startToRequestData={getData}
hideButtons
/>
</StyledPageContentWrapper>
Expand Down
17 changes: 13 additions & 4 deletions frontend/src/hooks/useGenerateReportEffect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export const useGenerateReportEffect = (): IUseGenerateReportEffect => {
dateRangeList.map((dateRange) => ({ ...initReportInfo(), id: dateRange.startDate as string })),
);
const [hasPollingStarted, setHasPollingStarted] = useState<boolean>(false);
const [reportId, setReportId] = useState<string>('');
let nextHasPollingStarted = false;

const startToRequestData = async (params: ReportRequestDTO) => {
Expand All @@ -115,8 +116,17 @@ export const useGenerateReportEffect = (): IUseGenerateReportEffect => {

resetReportPageLoadingStatus(dateRangeList);

const reportIdRes = await reportClient.generateReportId();
if (!reportId) {
const reportIdRes = await reportClient.generateReportId();
setReportId(reportIdRes.reportId);
dispatch(updateReportId(reportIdRes.reportId));
await retrieveUrlAndPolling(params, reportIdRes.reportId);
} else {
await retrieveUrlAndPolling(params, reportId);
}
};

const retrieveUrlAndPolling = async (params: ReportRequestDTO, reportId: string) => {
const res: PromiseSettledResult<ReportCallbackResponse>[] = await Promise.allSettled(
dateRangeList.map(({ startDate, endDate }) =>
reportClient.retrieveByUrl(
Expand All @@ -125,16 +135,15 @@ export const useGenerateReportEffect = (): IUseGenerateReportEffect => {
startTime: formatDateToTimestampString(startDate!),
endTime: formatDateToTimestampString(endDate!),
},
`${reportPath}/${reportIdRes.reportId}`,
`${reportPath}/${reportId}`,
),
),
);

updateErrorAfterFetchReport(res, metricTypes);
updateErrorAfterFetchReport(res, params.metricTypes);

const { pollingInfos, pollingInterval } = assemblePollingParams(res);

dispatch(updateReportId(reportIdRes.reportId));
resetPollingLoadingStatusBeforePolling(pollingInfos.map((item) => item.id));
await pollingReport({ pollingInfos, interval: pollingInterval });
};
Expand Down
1 change: 1 addition & 0 deletions frontend/src/layouts/ShareReportTrigger/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const ShareReportTrigger = () => {
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
if (canShare) {
setAnchorEl(anchorEl ? null : event.currentTarget);
setShowAlert(false);
}
};

Expand Down
3 changes: 2 additions & 1 deletion frontend/src/layouts/ShareReportTrigger/style.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const LinkLine = styled.div({
display: 'flex',
alignItems: 'center',
margin: '1.5rem 0',
height: '2.125rem',
a: {
cursor: 'pointer',
marginRight: '0.625rem',
Expand All @@ -59,7 +60,7 @@ export const LinkLine = styled.div({

export const ShareIconWrapper = styled.span(({ disabled }: { disabled: boolean }) => ({
padding: '0.5rem',
cursor: disabled ? 'unset !important' : 'pointer',
cursor: disabled ? 'not-allowed !important' : 'pointer',
marginLeft: '0.2rem',
'> svg': {
color: disabled ? theme.main.errorMessage.color : 'white',
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/utils/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { IPipeline } from '@src/context/config/pipelineTool/verifyResponseSlice'
import { ITrendInfo } from '@src/containers/ReportStep/ChartAndTitleWrapper';
import { includes, isEqual, sortBy, uniq, uniqBy } from 'lodash';
import { DateRangeList } from '@src/context/config/configSlice';
import { IReportInfo } from '../hooks/useGenerateReportEffect';
import { BoardInfoResponse } from '@src/hooks/useGetBoardInfo';
import { DATE_FORMAT_TEMPLATE } from '@src/constants/template';
import duration from 'dayjs/plugin/duration';
Expand Down Expand Up @@ -115,7 +116,14 @@ export const formatDateToTimestampString = (date: string) => {

export const sortDateRanges = (dateRanges: DateRangeList, descending = true) => {
const result = [...dateRanges].sort((a, b) => {
return dayjs(b.startDate as string).diff(dayjs(a.startDate as string));
return dayjs(b.startDate).diff(dayjs(a.startDate));
});
return descending ? result : result.reverse();
};

export const sortReportInfos = (reportInfos: IReportInfo[], descending = true) => {
const result = [...reportInfos].sort((a, b) => {
return dayjs(b.id).diff(dayjs(a.id));
});
return descending ? result : result.reverse();
};
Expand Down

0 comments on commit 0b4d54a

Please sign in to comment.