1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-11-10 01:19:53 +01:00

feat: first stab at updating timeline

This commit is contained in:
Thomas Heartman 2024-01-11 19:37:14 +05:30
parent 4d2eca0cf3
commit d250fc058f
No known key found for this signature in database
GPG Key ID: BD1F880DAED1EE78
2 changed files with 127 additions and 55 deletions

View File

@ -111,7 +111,7 @@ export const ChangeRequestOverview: FC = () => {
changeRequest.environment, changeRequest.environment,
); );
const hasSchedule = Boolean(changeRequest.schedule?.scheduledAt); const hasSchedule = Boolean('schedule' in changeRequest && changeRequest.schedule?.scheduledAt);
const onApplyChanges = async () => { const onApplyChanges = async () => {
try { try {
@ -266,8 +266,7 @@ export const ChangeRequestOverview: FC = () => {
<StyledAsideBox> <StyledAsideBox>
<ChangeRequestTimeline <ChangeRequestTimeline
state={changeRequest.state} state={changeRequest.state}
scheduledAt={changeRequest.schedule?.scheduledAt} schedule={'schedule' in changeRequest ? changeRequest.schedule : undefined}
failureReason={changeRequest.schedule?.failureReason}
/> />
<ChangeRequestReviewers changeRequest={changeRequest} /> <ChangeRequestReviewers changeRequest={changeRequest} />
</StyledAsideBox> </StyledAsideBox>

View File

@ -6,18 +6,25 @@ import TimelineSeparator from '@mui/lab/TimelineSeparator';
import TimelineDot from '@mui/lab/TimelineDot'; import TimelineDot from '@mui/lab/TimelineDot';
import TimelineConnector from '@mui/lab/TimelineConnector'; import TimelineConnector from '@mui/lab/TimelineConnector';
import TimelineContent from '@mui/lab/TimelineContent'; import TimelineContent from '@mui/lab/TimelineContent';
import { ChangeRequestState } from '../../changeRequest.types'; import {
ChangeRequestSchedule,
ChangeRequestState,
} from '../../changeRequest.types';
import { ConditionallyRender } from '../../../common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from '../../../common/ConditionallyRender/ConditionallyRender';
import { HtmlTooltip } from '../../../common/HtmlTooltip/HtmlTooltip'; import { HtmlTooltip } from '../../../common/HtmlTooltip/HtmlTooltip';
import { Error as ErrorIcon } from '@mui/icons-material'; import { Error as ErrorIcon } from '@mui/icons-material';
import { useLocationSettings } from 'hooks/useLocationSettings'; import { useLocationSettings } from 'hooks/useLocationSettings';
import { formatDateYMDHMS } from 'utils/formatDate'; import { formatDateYMDHMS } from 'utils/formatDate';
interface ISuggestChangeTimelineProps { type ISuggestChangeTimelineProps =
state: ChangeRequestState; | {
scheduledAt?: string; state: Exclude<ChangeRequestState, 'Scheduled'>;
failureReason?: string; schedule: undefined;
} }
| {
state: 'Scheduled';
schedule: ChangeRequestSchedule;
};
const StyledPaper = styled(Paper)(({ theme }) => ({ const StyledPaper = styled(Paper)(({ theme }) => ({
marginTop: theme.spacing(2), marginTop: theme.spacing(2),
@ -90,8 +97,7 @@ export const determineColor = (
export const ChangeRequestTimeline: FC<ISuggestChangeTimelineProps> = ({ export const ChangeRequestTimeline: FC<ISuggestChangeTimelineProps> = ({
state, state,
scheduledAt, schedule,
failureReason,
}) => { }) => {
let data; let data;
switch (state) { switch (state) {
@ -106,28 +112,39 @@ export const ChangeRequestTimeline: FC<ISuggestChangeTimelineProps> = ({
} }
const activeIndex = data.findIndex((item) => item === state); const activeIndex = data.findIndex((item) => item === state);
const { locationSettings } = useLocationSettings();
return ( return (
<StyledPaper elevation={0}> <StyledPaper elevation={0}>
<StyledBox> <StyledBox>
<StyledTimeline> <StyledTimeline>
{data.map((title, index) => { {data.map((title, index) => {
const subtitle = console.log('title and state ++', title, state);
scheduledAt && if (schedule && title === 'Scheduled') {
state === 'Scheduled' && console.log('Title for scheduled is', title, state);
state === title
? formatDateYMDHMS( return createTimelineScheduleItem(
new Date(scheduledAt), schedule,
locationSettings?.locale, // color,
) // title,
: undefined; // index < data.length - 1,
// timelineDotProps,
);
}
// const subtitle =
// scheduledAt &&
// state === 'Scheduled' &&
// state === title
// ? formatDateYMDHMS(
// new Date(scheduledAt),
// locationSettings?.locale,
// )
// : undefined;
const color = determineColor( const color = determineColor(
state, state,
activeIndex, activeIndex,
title, title,
index, index,
failureReason, // failureReason,
); );
let timelineDotProps = {}; let timelineDotProps = {};
@ -142,8 +159,6 @@ export const ChangeRequestTimeline: FC<ISuggestChangeTimelineProps> = ({
return createTimelineItem( return createTimelineItem(
color, color,
title, title,
subtitle,
failureReason,
index < data.length - 1, index < data.length - 1,
timelineDotProps, timelineDotProps,
); );
@ -154,11 +169,96 @@ export const ChangeRequestTimeline: FC<ISuggestChangeTimelineProps> = ({
); );
}; };
const createTimelineScheduleItem = (
schedule: ChangeRequestSchedule,
// color: 'primary' | 'success' | 'grey' | 'error' | 'warning',
// title: string,
// subtitle: string | undefined,
// failureReason: string | undefined,
// shouldConnectToNextItem: boolean,
// timelineDotProps: { [key: string]: string | undefined } = {},
) => {
const { locationSettings } = useLocationSettings();
const time = formatDateYMDHMS(
new Date(schedule.scheduledAt),
locationSettings?.locale,
);
const color = (() => {
switch (schedule.status) {
case 'suspended':
return 'grey';
case 'failed':
return 'error';
case 'pending':
default:
return 'warning';
}
})();
const title = `Schedule ${schedule.status}`;
const subtitle = (() => {
switch (schedule.status) {
case 'suspended':
return `was ${time}`;
case 'failed':
return `at ${time}`;
case 'pending':
default:
return `for ${time}`;
}
})();
const reason = (() => {
switch (schedule.status) {
case 'suspended':
return (
<HtmlTooltip title={schedule.reason} arrow>
<ErrorIcon color={'error'} fontSize={'small'} />
</HtmlTooltip>
);
case 'failed':
return (
<HtmlTooltip
title={`Schedule failed because of ${
schedule.reason || schedule.failureReason
}`}
arrow
>
<ErrorIcon color={'error'} fontSize={'small'} />
</HtmlTooltip>
);
case 'pending':
default:
return <></>;
}
})();
return (
<TimelineItem key={title}>
<TimelineSeparator>
<TimelineDot color={color} />
<TimelineConnector />
</TimelineSeparator>
<TimelineContent>
{title}
<StyledSubtitle>
<Typography
color={'text.secondary'}
sx={{ mr: 1 }}
>{`(${subtitle})`}</Typography>
{reason}
</StyledSubtitle>
</TimelineContent>
</TimelineItem>
);
};
const createTimelineItem = ( const createTimelineItem = (
color: 'primary' | 'success' | 'grey' | 'error' | 'warning', color: 'primary' | 'success' | 'grey' | 'error' | 'warning',
title: string, title: string,
subtitle: string | undefined,
failureReason: string | undefined,
shouldConnectToNextItem: boolean, shouldConnectToNextItem: boolean,
timelineDotProps: { [key: string]: string | undefined } = {}, timelineDotProps: { [key: string]: string | undefined } = {},
) => ( ) => (
@ -167,33 +267,6 @@ const createTimelineItem = (
<TimelineDot color={color} {...timelineDotProps} /> <TimelineDot color={color} {...timelineDotProps} />
{shouldConnectToNextItem && <TimelineConnector />} {shouldConnectToNextItem && <TimelineConnector />}
</TimelineSeparator> </TimelineSeparator>
<TimelineContent> <TimelineContent>{title}</TimelineContent>
{title}
<ConditionallyRender
condition={Boolean(subtitle)}
show={
<StyledSubtitle>
<Typography
color={'text.secondary'}
sx={{ mr: 1 }}
>{`(for ${subtitle})`}</Typography>
<ConditionallyRender
condition={Boolean(failureReason)}
show={
<HtmlTooltip
title={`Schedule failed because of ${failureReason}`}
arrow
>
<ErrorIcon
color={'error'}
fontSize={'small'}
/>
</HtmlTooltip>
}
/>
</StyledSubtitle>
}
/>
</TimelineContent>
</TimelineItem> </TimelineItem>
); );