mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: show failure reason for scheduled requests in timeline (#5639)
Adds an icon with a tooltip and changes the dot color to red for scheduled change requests Closes # [1-1768](https://linear.app/unleash/issue/1-1768/add-reason-and-icon-to-timeline) <img width="1668" alt="Screenshot 2023-12-14 at 10 20 27" src="https://github.com/Unleash/unleash/assets/104830839/dcf54834-ea9f-4e78-b69d-15d6179ffce3"> --------- Signed-off-by: andreas-unleash <andreas@getunleash.ai>
This commit is contained in:
		
							parent
							
								
									cbd50ac0f5
								
							
						
					
					
						commit
						a595c0fbcc
					
				| @ -241,6 +241,7 @@ export const ChangeRequestOverview: FC = () => { | ||||
|                     <ChangeRequestTimeline | ||||
|                         state={changeRequest.state} | ||||
|                         scheduledAt={changeRequest.schedule?.scheduledAt} | ||||
|                         failureReason={changeRequest.schedule?.failureReason} | ||||
|                     /> | ||||
|                     <ChangeRequestReviewers changeRequest={changeRequest} /> | ||||
|                 </StyledAsideBox> | ||||
|  | ||||
| @ -113,6 +113,18 @@ test('returns warning for Scheduled stage in Scheduled state', () => { | ||||
|     ).toBe('warning'); | ||||
| }); | ||||
| 
 | ||||
| test('returns error for Scheduled stage in Scheduled state with failure reason', () => { | ||||
|     expect( | ||||
|         determineColor( | ||||
|             'Scheduled', | ||||
|             irrelevantIndex, | ||||
|             'Scheduled', | ||||
|             irrelevantIndex, | ||||
|             'conflicts', | ||||
|         ), | ||||
|     ).toBe('error'); | ||||
| }); | ||||
| 
 | ||||
| test('returns success for stages at or before activeIndex', () => { | ||||
|     expect(determineColor('In review', 1, 'Draft', 0)).toBe('success'); | ||||
|     expect(determineColor('In review', 1, 'In review', 1)).toBe('success'); | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { FC } from 'react'; | ||||
| import { Box, Paper, styled, Typography } from '@mui/material'; | ||||
| import { Box, Paper, styled, Tooltip, Typography } from '@mui/material'; | ||||
| import Timeline from '@mui/lab/Timeline'; | ||||
| import TimelineItem, { timelineItemClasses } from '@mui/lab/TimelineItem'; | ||||
| import TimelineSeparator from '@mui/lab/TimelineSeparator'; | ||||
| @ -8,10 +8,13 @@ import TimelineConnector from '@mui/lab/TimelineConnector'; | ||||
| import TimelineContent from '@mui/lab/TimelineContent'; | ||||
| import { ChangeRequestState } from '../../changeRequest.types'; | ||||
| import { ConditionallyRender } from '../../../common/ConditionallyRender/ConditionallyRender'; | ||||
| import { HtmlTooltip } from '../../../common/HtmlTooltip/HtmlTooltip'; | ||||
| import { Info } from '@mui/icons-material'; | ||||
| 
 | ||||
| interface ISuggestChangeTimelineProps { | ||||
|     state: ChangeRequestState; | ||||
|     scheduledAt?: string; | ||||
|     failureReason?: string; | ||||
| } | ||||
| 
 | ||||
| const StyledPaper = styled(Paper)(({ theme }) => ({ | ||||
| @ -24,6 +27,11 @@ const StyledBox = styled(Box)(({ theme }) => ({ | ||||
|     marginBottom: `-${theme.spacing(4)}`, | ||||
| })); | ||||
| 
 | ||||
| const StyledSubtitle = styled(Box)(({ theme }) => ({ | ||||
|     display: 'flex', | ||||
|     flexDirection: 'row', | ||||
| })); | ||||
| 
 | ||||
| const StyledTimeline = styled(Timeline)(() => ({ | ||||
|     [`& .${timelineItemClasses.root}:before`]: { | ||||
|         flex: 0, | ||||
| @ -51,6 +59,7 @@ export const determineColor = ( | ||||
|     changeRequestStateIndex: number, | ||||
|     displayStage: ChangeRequestState, | ||||
|     displayStageIndex: number, | ||||
|     failureReason?: string, | ||||
| ) => { | ||||
|     if (changeRequestState === 'Cancelled') return 'grey'; | ||||
| 
 | ||||
| @ -65,7 +74,11 @@ export const determineColor = ( | ||||
|         changeRequestStateIndex !== -1 && | ||||
|         changeRequestStateIndex === displayStageIndex | ||||
|     ) { | ||||
|         return changeRequestState === 'Scheduled' ? 'warning' : 'success'; | ||||
|         return changeRequestState === 'Scheduled' | ||||
|             ? failureReason | ||||
|                 ? 'error' | ||||
|                 : 'warning' | ||||
|             : 'success'; | ||||
|     } | ||||
| 
 | ||||
|     if (changeRequestStateIndex + 1 === displayStageIndex) return 'primary'; | ||||
| @ -75,6 +88,7 @@ export const determineColor = ( | ||||
| export const ChangeRequestTimeline: FC<ISuggestChangeTimelineProps> = ({ | ||||
|     state, | ||||
|     scheduledAt, | ||||
|     failureReason, | ||||
| }) => { | ||||
|     let data; | ||||
|     switch (state) { | ||||
| @ -105,6 +119,7 @@ export const ChangeRequestTimeline: FC<ISuggestChangeTimelineProps> = ({ | ||||
|                             activeIndex, | ||||
|                             title, | ||||
|                             index, | ||||
|                             failureReason, | ||||
|                         ); | ||||
|                         let timelineDotProps = {}; | ||||
| 
 | ||||
| @ -120,6 +135,7 @@ export const ChangeRequestTimeline: FC<ISuggestChangeTimelineProps> = ({ | ||||
|                             color, | ||||
|                             title, | ||||
|                             subtitle, | ||||
|                             failureReason, | ||||
|                             index < data.length - 1, | ||||
|                             timelineDotProps, | ||||
|                         ); | ||||
| @ -134,6 +150,7 @@ const createTimelineItem = ( | ||||
|     color: 'primary' | 'success' | 'grey' | 'error' | 'warning', | ||||
|     title: string, | ||||
|     subtitle: string | undefined, | ||||
|     failureReason: string | undefined, | ||||
|     shouldConnectToNextItem: boolean, | ||||
|     timelineDotProps: { [key: string]: string | undefined } = {}, | ||||
| ) => ( | ||||
| @ -148,9 +165,23 @@ const createTimelineItem = ( | ||||
|             <ConditionallyRender | ||||
|                 condition={Boolean(subtitle)} | ||||
|                 show={ | ||||
|                     <Typography | ||||
|                         color={'text.secondary'} | ||||
|                     >{`(for ${subtitle})`}</Typography> | ||||
|                     <StyledSubtitle> | ||||
|                         <Typography | ||||
|                             color={'text.secondary'} | ||||
|                             sx={{ mr: 1 }} | ||||
|                         >{`(for ${subtitle})`}</Typography> | ||||
|                         <ConditionallyRender | ||||
|                             condition={Boolean(failureReason)} | ||||
|                             show={ | ||||
|                                 <HtmlTooltip | ||||
|                                     title={`Schedule failed because of ${failureReason}`} | ||||
|                                     arrow | ||||
|                                 > | ||||
|                                     <Info color={'error'} fontSize={'small'} /> | ||||
|                                 </HtmlTooltip> | ||||
|                             } | ||||
|                         /> | ||||
|                     </StyledSubtitle> | ||||
|                 } | ||||
|             /> | ||||
|         </TimelineContent> | ||||
|  | ||||
| @ -24,6 +24,7 @@ export interface IChangeRequest { | ||||
| export interface IChangeRequestSchedule { | ||||
|     scheduledAt: string; | ||||
|     status: 'pending' | 'failed'; | ||||
|     failureReason?: string; | ||||
| } | ||||
| 
 | ||||
| export interface IChangeRequestEnvironmentConfig { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user