mirror of
https://github.com/Unleash/unleash.git
synced 2025-08-09 13:47:13 +02:00
feat: Timeline for cancelled CRs
Shows the cancelled state in the timeline for cancelled CRs. Also, if timestamps are present, it will dynamically show the steps we have times for for rejected and cancelled CRs. CRs can be cancelled after: - In review - Approved CRs can be rejected after: - In review - Approved - Schedule For other states, use the existing steps. Cancelled and Rejected are both terminal states, so there's no future steps to show. Regardless of what we have timestamps for, always show 'Draft', 'In review' and the final state (Rejected | Cancelled).
This commit is contained in:
parent
8554eee37a
commit
e239014b24
@ -7,13 +7,13 @@ import {
|
||||
} from './ChangeRequestTimeline.tsx';
|
||||
import type { ChangeRequestState } from '../../changeRequest.types';
|
||||
|
||||
test('cancelled timeline shows all states', () => {
|
||||
test('cancelled timeline shows expected states', () => {
|
||||
render(<ChangeRequestTimeline state={'Cancelled'} />);
|
||||
|
||||
expect(screen.getByText('Draft')).toBeInTheDocument();
|
||||
expect(screen.getByText('In review')).toBeInTheDocument();
|
||||
expect(screen.getByText('Approved')).toBeInTheDocument();
|
||||
expect(screen.getByText('Applied')).toBeInTheDocument();
|
||||
expect(screen.getByText('Cancelled')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('approved timeline shows all states', () => {
|
||||
|
@ -15,6 +15,13 @@ import { HtmlTooltip } from '../../../common/HtmlTooltip/HtmlTooltip.tsx';
|
||||
import ErrorIcon from '@mui/icons-material/Error';
|
||||
import { useLocationSettings } from 'hooks/useLocationSettings';
|
||||
import { formatDateYMDHM } from 'utils/formatDate.ts';
|
||||
import {
|
||||
stepsFromTimestamps,
|
||||
rejectedSteps,
|
||||
scheduledSteps,
|
||||
cancelledSteps,
|
||||
steps,
|
||||
} from './change-request-timeline-steps.ts';
|
||||
|
||||
export type ISuggestChangeTimelineProps = {
|
||||
timestamps?: ChangeRequestType['stateTransitionTimestamps']; // todo: update with flag `timestampsInChangeRequestTimeline`
|
||||
@ -58,21 +65,6 @@ const StyledTimeline = styled(Timeline)(() => ({
|
||||
},
|
||||
}));
|
||||
|
||||
const steps: ChangeRequestState[] = [
|
||||
'Draft',
|
||||
'In review',
|
||||
'Approved',
|
||||
'Applied',
|
||||
];
|
||||
const rejectedSteps: ChangeRequestState[] = ['Draft', 'In review', 'Rejected'];
|
||||
const scheduledSteps: ChangeRequestState[] = [
|
||||
'Draft',
|
||||
'In review',
|
||||
'Approved',
|
||||
'Scheduled',
|
||||
'Applied',
|
||||
];
|
||||
|
||||
export const determineColor = (
|
||||
changeRequestState: ChangeRequestState,
|
||||
changeRequestStateIndex: number,
|
||||
@ -101,11 +93,22 @@ export const ChangeRequestTimeline: FC<ISuggestChangeTimelineProps> = ({
|
||||
let data: ChangeRequestState[];
|
||||
switch (state) {
|
||||
case 'Rejected':
|
||||
data = rejectedSteps;
|
||||
if (timestamps) {
|
||||
data = stepsFromTimestamps(timestamps, 'Rejected');
|
||||
} else {
|
||||
data = rejectedSteps;
|
||||
}
|
||||
break;
|
||||
case 'Scheduled':
|
||||
data = scheduledSteps;
|
||||
break;
|
||||
case 'Cancelled':
|
||||
if (timestamps) {
|
||||
data = stepsFromTimestamps(timestamps, 'Cancelled');
|
||||
} else {
|
||||
data = cancelledSteps;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
data = steps;
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
import { stepsFromTimestamps } from './change-request-timeline-steps.ts';
|
||||
|
||||
describe('stepsFromTimestamps', () => {
|
||||
test.each(['Rejected', 'Cancelled'])(
|
||||
"always includes 'Draft' and 'In review' and the current stage (%s)",
|
||||
(state) => {
|
||||
expect(
|
||||
stepsFromTimestamps({}, state as 'Rejected' | 'Cancelled'),
|
||||
).toStrictEqual(['Draft', 'In review', state]);
|
||||
},
|
||||
);
|
||||
|
||||
test('Includes all steps in the timestamps object', () => {
|
||||
expect(
|
||||
stepsFromTimestamps(
|
||||
{
|
||||
Draft: {},
|
||||
'In review': {},
|
||||
Approved: {},
|
||||
Rejected: {},
|
||||
},
|
||||
'Rejected',
|
||||
),
|
||||
).toStrictEqual(['Draft', 'In review', 'Approved', 'Rejected']);
|
||||
|
||||
expect(
|
||||
stepsFromTimestamps(
|
||||
{
|
||||
Draft: {},
|
||||
Approved: {},
|
||||
Scheduled: {},
|
||||
},
|
||||
'Rejected',
|
||||
),
|
||||
).toStrictEqual([
|
||||
'Draft',
|
||||
'In review',
|
||||
'Approved',
|
||||
'Scheduled',
|
||||
'Rejected',
|
||||
]);
|
||||
|
||||
// The implementation is naïve, so even if a CR must be approved to be
|
||||
// scheduled, if the timestamps object does not contain the 'Approved'
|
||||
// step, it will not be included.
|
||||
expect(
|
||||
stepsFromTimestamps(
|
||||
{
|
||||
Scheduled: {},
|
||||
},
|
||||
'Rejected',
|
||||
),
|
||||
).toStrictEqual(['Draft', 'In review', 'Scheduled', 'Rejected']);
|
||||
});
|
||||
});
|
@ -0,0 +1,49 @@
|
||||
import type { ChangeRequestState } from 'component/changeRequest/changeRequest.types';
|
||||
|
||||
export const stepsFromTimestamps = (
|
||||
timestamps: Partial<Record<ChangeRequestState, unknown>>,
|
||||
currentState: Extract<ChangeRequestState, 'Cancelled' | 'Rejected'>,
|
||||
): ChangeRequestState[] => {
|
||||
const optionalSteps: ChangeRequestState[] = [
|
||||
'Approved',
|
||||
'Applied',
|
||||
'Cancelled',
|
||||
'Scheduled',
|
||||
'Rejected',
|
||||
];
|
||||
|
||||
return [
|
||||
'Draft',
|
||||
'In review',
|
||||
...optionalSteps.filter(
|
||||
(step) => timestamps.hasOwnProperty(step) || step === currentState,
|
||||
),
|
||||
];
|
||||
};
|
||||
|
||||
export const steps: ChangeRequestState[] = [
|
||||
'Draft',
|
||||
'In review',
|
||||
'Approved',
|
||||
'Applied',
|
||||
];
|
||||
|
||||
export const rejectedSteps: ChangeRequestState[] = [
|
||||
'Draft',
|
||||
'In review',
|
||||
'Rejected',
|
||||
];
|
||||
export const cancelledSteps: ChangeRequestState[] = [
|
||||
'Draft',
|
||||
'In review',
|
||||
'Approved',
|
||||
'Cancelled',
|
||||
];
|
||||
|
||||
export const scheduledSteps: ChangeRequestState[] = [
|
||||
'Draft',
|
||||
'In review',
|
||||
'Approved',
|
||||
'Scheduled',
|
||||
'Applied',
|
||||
];
|
Loading…
Reference in New Issue
Block a user