Skip to content

Commit

Permalink
Feat/review page timeline (#2310)
Browse files Browse the repository at this point in the history
* fix: styling

* feat: overview timeline

* fix: rename types

* fix: pr comments
  • Loading branch information
FredrikOseberg committed Nov 2, 2022
1 parent 9fb431a commit 9b10a88
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 53 deletions.
Expand Up @@ -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');
Expand Down Expand Up @@ -46,7 +46,7 @@ export const ChangeRequestOverview: FC = () => {
flexDirection: 'column',
}}
>
<ChangeRequestTimeline />
<ChangeRequestTimeline state={changeRequest.state} />
<ChangeRequestReviewers />
</Box>
<Paper
Expand All @@ -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 }}
Expand Down
Expand Up @@ -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',
Expand Down
Expand Up @@ -12,7 +12,6 @@ import {
StyledReviewTitle,
StyledDivider,
} from './ChangeRequestReviewStatus.styles';

interface ISuggestChangeReviewsStatusProps {
approved: boolean;
}
Expand All @@ -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>
);
Expand Down
@@ -1,52 +1,129 @@
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';
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;
}

export const ChangeRequestTimeline: FC = () => {
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);
};

return (
<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 (
<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>
<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';
2 changes: 2 additions & 0 deletions frontend/src/component/feature/FeatureView/FeatureView.tsx
Expand Up @@ -84,6 +84,8 @@ export const FeatureView = () => {
return <FeatureNotFound />;
}

console.log(uiConfig?.flags);

return (
<MainLayout
ref={ref}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/component/project/Project/Project.tsx
Expand Up @@ -124,7 +124,7 @@ const Project = () => {
<MainLayout
ref={ref}
subheader={
!uiConfig?.flags?.changeRequests ? (
uiConfig?.flags?.changeRequests ? (
<DraftBanner project={projectId} />
) : null
}
Expand Down

0 comments on commit 9b10a88

Please sign in to comment.