mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-10 01:16:39 +02:00
Feat/review page timeline (#2310)
* fix: styling * feat: overview timeline * fix: rename types * fix: pr comments
This commit is contained in:
parent
9fb431aab7
commit
9b10a8815b
@ -7,9 +7,9 @@ import { ChangeRequestReviewers } from './ChangeRequestReviewers/ChangeRequestRe
|
||||
import { ChangeRequest } from '../ChangeRequest/ChangeRequest';
|
||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
||||
import { ChangeRequestReviewStatus } from './ChangeRequestReviewStatus/ChangeRequestReviewStatus';
|
||||
import useToast from 'hooks/useToast';
|
||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||
import { ChangeRequestReviewStatus } from './ChangeRequestReviewStatus/ChangeRequestReviewStatus';
|
||||
|
||||
export const ChangeRequestOverview: FC = () => {
|
||||
const projectId = useRequiredPathParam('projectId');
|
||||
@ -46,7 +46,7 @@ export const ChangeRequestOverview: FC = () => {
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
>
|
||||
<ChangeRequestTimeline />
|
||||
<ChangeRequestTimeline state={changeRequest.state} />
|
||||
<ChangeRequestReviewers />
|
||||
</Box>
|
||||
<Paper
|
||||
@ -66,7 +66,13 @@ export const ChangeRequestOverview: FC = () => {
|
||||
})}
|
||||
>
|
||||
<ChangeRequest changeRequest={changeRequest} />
|
||||
<ChangeRequestReviewStatus approved={true} />
|
||||
<ChangeRequestReviewStatus
|
||||
approved={
|
||||
changeRequest.state === 'Approved' ||
|
||||
changeRequest.state === 'Applied'
|
||||
}
|
||||
/>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{ marginTop: 2 }}
|
||||
|
@ -3,7 +3,7 @@ import { Cancel, CheckCircle } from '@mui/icons-material';
|
||||
import { Box, Typography, Divider } from '@mui/material';
|
||||
|
||||
const styledComponentPropCheck = () => (prop: string) =>
|
||||
prop !== 'color' && prop !== 'sx';
|
||||
prop !== 'color' && prop !== 'sx' && prop !== 'approved';
|
||||
|
||||
export const StyledFlexAlignCenterBox = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
|
@ -12,7 +12,6 @@ import {
|
||||
StyledReviewTitle,
|
||||
StyledDivider,
|
||||
} from './ChangeRequestReviewStatus.styles';
|
||||
|
||||
interface ISuggestChangeReviewsStatusProps {
|
||||
approved: boolean;
|
||||
}
|
||||
@ -30,13 +29,11 @@ export const ChangeRequestReviewStatus: FC<
|
||||
/>
|
||||
</StyledButtonContainer>
|
||||
<StyledReviewStatusContainer approved={approved}>
|
||||
<StyledFlexAlignCenterBox>
|
||||
<ConditionallyRender
|
||||
condition={approved}
|
||||
show={<Approved approved={approved} />}
|
||||
elseShow={<ReviewRequired approved={approved} />}
|
||||
/>
|
||||
</StyledFlexAlignCenterBox>
|
||||
<ConditionallyRender
|
||||
condition={approved}
|
||||
show={<Approved approved={approved} />}
|
||||
elseShow={<ReviewRequired approved={approved} />}
|
||||
/>
|
||||
</StyledReviewStatusContainer>
|
||||
</StyledOuterContainer>
|
||||
);
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { FC } from 'react';
|
||||
import { styled } from '@mui/material';
|
||||
import { Box, Paper } from '@mui/material';
|
||||
import Timeline from '@mui/lab/Timeline';
|
||||
import TimelineItem, { timelineItemClasses } from '@mui/lab/TimelineItem';
|
||||
@ -6,47 +7,123 @@ import TimelineSeparator from '@mui/lab/TimelineSeparator';
|
||||
import TimelineDot from '@mui/lab/TimelineDot';
|
||||
import TimelineConnector from '@mui/lab/TimelineConnector';
|
||||
import TimelineContent from '@mui/lab/TimelineContent';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { ChangeRequestState } from '../changeRequest.types';
|
||||
interface ISuggestChangeTimelineProps {
|
||||
state: ChangeRequestState;
|
||||
}
|
||||
interface ITimelineData {
|
||||
title: string;
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
const StyledPaper = styled(Paper)(({ theme }) => ({
|
||||
marginTop: theme.spacing(2),
|
||||
borderRadius: `${theme.shape.borderRadiusLarge}px`,
|
||||
}));
|
||||
|
||||
const StyledBox = styled(Box)(({ theme }) => ({
|
||||
padding: theme.spacing(2),
|
||||
marginBottom: `-${theme.spacing(4)}`,
|
||||
}));
|
||||
|
||||
const StyledTimeline = styled(Timeline)(() => ({
|
||||
[`& .${timelineItemClasses.root}:before`]: {
|
||||
flex: 0,
|
||||
padding: 0,
|
||||
},
|
||||
}));
|
||||
|
||||
export const ChangeRequestTimeline: FC<ISuggestChangeTimelineProps> = ({
|
||||
state,
|
||||
}) => {
|
||||
const createTimeLineData = (state: ChangeRequestState): ITimelineData[] => {
|
||||
const steps: ChangeRequestState[] = [
|
||||
'Draft',
|
||||
'In review',
|
||||
'Approved',
|
||||
'Applied',
|
||||
];
|
||||
|
||||
return steps.map(step => ({
|
||||
title: step,
|
||||
active: step === state,
|
||||
}));
|
||||
};
|
||||
|
||||
const renderTimeline = () => {
|
||||
const data = createTimeLineData(state);
|
||||
const index = data.findIndex(item => item.active);
|
||||
const activeIndex: number | null = index !== -1 ? index : null;
|
||||
|
||||
if (state === 'Cancelled') {
|
||||
return createCancelledTimeline(data);
|
||||
}
|
||||
|
||||
return createTimeline(data, activeIndex);
|
||||
};
|
||||
|
||||
export const ChangeRequestTimeline: FC = () => {
|
||||
return (
|
||||
<Paper
|
||||
elevation={0}
|
||||
sx={theme => ({
|
||||
marginTop: theme.spacing(2),
|
||||
borderRadius: theme => `${theme.shape.borderRadiusLarge}px`,
|
||||
})}
|
||||
>
|
||||
<Box sx={theme => ({ padding: theme.spacing(2) })}>
|
||||
<Timeline
|
||||
sx={{
|
||||
[`& .${timelineItemClasses.root}:before`]: {
|
||||
flex: 0,
|
||||
padding: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<TimelineItem>
|
||||
<TimelineSeparator>
|
||||
<TimelineDot color="success" />
|
||||
<TimelineConnector color="success" />
|
||||
</TimelineSeparator>
|
||||
<TimelineContent>Draft</TimelineContent>
|
||||
</TimelineItem>
|
||||
<TimelineItem>
|
||||
<TimelineSeparator>
|
||||
<TimelineDot color="success" />
|
||||
<TimelineConnector />
|
||||
</TimelineSeparator>
|
||||
<TimelineContent>Approved</TimelineContent>
|
||||
</TimelineItem>
|
||||
<TimelineItem>
|
||||
<TimelineSeparator>
|
||||
<TimelineDot />
|
||||
</TimelineSeparator>
|
||||
<TimelineContent>Applied</TimelineContent>
|
||||
</TimelineItem>
|
||||
</Timeline>
|
||||
</Box>
|
||||
</Paper>
|
||||
<StyledPaper elevation={0}>
|
||||
<StyledBox>
|
||||
<StyledTimeline>{renderTimeline()}</StyledTimeline>
|
||||
</StyledBox>
|
||||
</StyledPaper>
|
||||
);
|
||||
};
|
||||
|
||||
const createTimeline = (data: ITimelineData[], activeIndex: number | null) => {
|
||||
return data.map(({ title }, index) => {
|
||||
const shouldConnectToNextItem = index < data.length - 1;
|
||||
|
||||
const connector = (
|
||||
<ConditionallyRender
|
||||
condition={shouldConnectToNextItem}
|
||||
show={<TimelineConnector />}
|
||||
/>
|
||||
);
|
||||
|
||||
if (activeIndex !== null && activeIndex >= index) {
|
||||
return createTimelineItem('success', title, connector);
|
||||
}
|
||||
|
||||
if (activeIndex !== null && activeIndex + 1 === index) {
|
||||
return createTimelineItem('primary', title, connector, {
|
||||
variant: 'outlined',
|
||||
});
|
||||
}
|
||||
|
||||
return createTimelineItem('grey', title, connector);
|
||||
});
|
||||
};
|
||||
|
||||
const createCancelledTimeline = (data: ITimelineData[]) => {
|
||||
return data.map(({ title }, index) => {
|
||||
const shouldConnectToNextItem = index < data.length - 1;
|
||||
|
||||
const connector = (
|
||||
<ConditionallyRender
|
||||
condition={shouldConnectToNextItem}
|
||||
show={<TimelineConnector />}
|
||||
/>
|
||||
);
|
||||
return createTimelineItem('grey', title, connector);
|
||||
});
|
||||
};
|
||||
|
||||
const createTimelineItem = (
|
||||
color: 'primary' | 'success' | 'grey',
|
||||
title: string,
|
||||
connector: JSX.Element,
|
||||
timelineDotProps: { [key: string]: string } = {}
|
||||
) => {
|
||||
return (
|
||||
<TimelineItem key={title}>
|
||||
<TimelineSeparator>
|
||||
<TimelineDot color={color} {...timelineDotProps} />
|
||||
{connector}
|
||||
</TimelineSeparator>
|
||||
<TimelineContent>{title}</TimelineContent>
|
||||
</TimelineItem>
|
||||
);
|
||||
};
|
||||
|
@ -0,0 +1,6 @@
|
||||
export type ChangeRequestState =
|
||||
| 'Draft'
|
||||
| 'Approved'
|
||||
| 'In review'
|
||||
| 'Applied'
|
||||
| 'Cancelled';
|
@ -84,6 +84,8 @@ export const FeatureView = () => {
|
||||
return <FeatureNotFound />;
|
||||
}
|
||||
|
||||
console.log(uiConfig?.flags);
|
||||
|
||||
return (
|
||||
<MainLayout
|
||||
ref={ref}
|
||||
|
@ -124,7 +124,7 @@ const Project = () => {
|
||||
<MainLayout
|
||||
ref={ref}
|
||||
subheader={
|
||||
!uiConfig?.flags?.changeRequests ? (
|
||||
uiConfig?.flags?.changeRequests ? (
|
||||
<DraftBanner project={projectId} />
|
||||
) : null
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user