Skip to content

Commit

Permalink
feat: change request header (#2317)
Browse files Browse the repository at this point in the history
* feat: change request header

* fix: dom nesting paragraphs

* fix: change path
  • Loading branch information
FredrikOseberg committed Nov 2, 2022
1 parent 6622346 commit 2f1f9ce
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 163 deletions.
@@ -0,0 +1,37 @@
import { styled } from '@mui/material';
import { Avatar, Box, Card, Paper, Typography } from '@mui/material';

export const StyledPaper = styled(Paper)(({ theme }) => ({
padding: theme.spacing(2, 4),
borderRadius: `${theme.shape.borderRadiusLarge}px`,
}));

export const StyledContainer = styled(Box)(({ theme }) => ({
display: 'flex',
alignItems: 'center',
gap: 2,
marginBottom: theme.spacing(2),
}));

export const StyledInnerContainer = styled(Box)(({ theme }) => ({
display: 'flex',
alignItems: 'center',
gap: theme.spacing(1.5),
}));

export const StyledHeader = styled(Typography)(({ theme }) => ({
display: 'flex',
alignItems: 'center',
marginRight: theme.spacing(1),
fontSize: theme.fontSizes.mainHeader,
}));

export const StyledCard = styled(Card)(({ theme }) => ({
padding: theme.spacing(0.5, 1),
backgroundColor: theme.palette.tertiary.light,
}));

export const StyledAvatar = styled(Avatar)(() => ({
height: '30px',
width: '30px',
}));
@@ -1,69 +1,60 @@
import { Box } from '@mui/material';
import { FC } from 'react';
import { Avatar, Box, Card, Paper, Typography } from '@mui/material';
import { PlaygroundResultChip } from 'component/playground/Playground/PlaygroundResultsTable/PlaygroundResultChip/PlaygroundResultChip';
import { ReactComponent as ChangesAppliedIcon } from 'assets/icons/merge.svg';
import { Typography } from '@mui/material';
import TimeAgo from 'react-timeago';
import { resolveChangeRequestStatusIcon } from 'component/changeRequest/changeRequest.utils';
import { IChangeRequest } from 'component/changeRequest/changeRequest.types';
import {
StyledPaper,
StyledContainer,
StyledHeader,
StyledInnerContainer,
StyledAvatar,
StyledCard,
} from './ChangeRequestHeader.styles';

export const ChangeRequestHeader: FC<{ changeRequest: any }> = ({
export const ChangeRequestHeader: FC<{ changeRequest: IChangeRequest }> = ({
changeRequest,
}) => {
return (
<Paper
elevation={0}
sx={theme => ({
p: theme.spacing(2, 4),
borderRadius: theme => `${theme.shape.borderRadiusLarge}px`,
})}
>
<Box
sx={theme => ({
display: 'flex',
alignItems: 'center',
gap: 2,
marginBottom: theme.spacing(2),
})}
>
<Typography
sx={{
display: 'flex',
alignItems: 'center',
}}
variant="h1"
>
Change request
<Typography variant="h1" component="p">
#{changeRequest.id}
</Typography>
</Typography>
<PlaygroundResultChip
// icon={<ChangesAppliedIcon strokeWidth="0.25" />}
label="Changes approved"
enabled
/>
</Box>
<Box sx={{ display: 'flex', verticalAlign: 'center', gap: 2 }}>
<Typography sx={{ margin: 'auto 0' }}>
<StyledPaper elevation={0}>
<StyledContainer>
<StyledHeader variant="h1">
Change request #{changeRequest.id}
</StyledHeader>
{resolveChangeRequestStatusIcon(changeRequest.state)}
</StyledContainer>
<StyledInnerContainer>
<Typography variant="body2" sx={{ margin: 'auto 0' }}>
Created <TimeAgo date={new Date(changeRequest.createdAt)} />{' '}
by
</Typography>
<Avatar src={changeRequest?.createdBy?.avatar} />
<Card
variant="outlined"
sx={theme => ({
padding: 1,
backgroundColor: theme.palette.tertiary.light,
})}
>
Environment:{' '}
<Typography display="inline" fontWeight="bold">
{changeRequest?.environment}
</Typography>{' '}
| Updates:{' '}
<Typography display="inline" fontWeight="bold">
{changeRequest?.features.length} feature toggles
</Typography>
</Card>
</Box>
</Paper>
<StyledAvatar src={changeRequest?.createdBy?.imageUrl} />
<Box>
<StyledCard variant="outlined">
<Typography variant="body2">
Environment:{' '}
<Typography
display="inline"
fontWeight="bold"
variant="body2"
component="span"
>
{changeRequest?.environment}
</Typography>{' '}
| Updates:{' '}
<Typography
variant="body2"
display="inline"
fontWeight="bold"
component="span"
>
{changeRequest?.features.length} feature toggles
</Typography>
</Typography>
</StyledCard>
</Box>
</StyledInnerContainer>
</StyledPaper>
);
};
Expand Up @@ -8,7 +8,7 @@ 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';
import { ChangeRequestState } from '../../changeRequest.types';
interface ISuggestChangeTimelineProps {
state: ChangeRequestState;
}
Expand Down

This file was deleted.

@@ -1,115 +1,23 @@
import { VFC } from 'react';
import { Chip, styled } from '@mui/material';
import { colors } from 'themes/colors';
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
import { Check, CircleOutlined, Close } from '@mui/icons-material';
import { resolveChangeRequestStatusIcon } from 'component/changeRequest/changeRequest.utils';
import { ChangeRequestState } from 'component/changeRequest/changeRequest.types';

interface IChangeRequestStatusCellProps {
value?: string | null;
}

export enum ChangeRequestState {
DRAFT = 'Draft',
APPROVED = 'Approved',
IN_REVIEW = 'In review',
APPLIED = 'Applied',
CANCELLED = 'Cancelled',
REJECTED = 'Rejected',
}

export const StyledChip = styled(Chip)(({ theme, icon }) => ({
padding: theme.spacing(0, 1),
height: 30,
borderRadius: theme.shape.borderRadius,
fontWeight: theme.typography.fontWeightMedium,
gap: theme.spacing(1, 1),
['& .MuiChip-label']: {
padding: 0,
paddingLeft: Boolean(icon) ? theme.spacing(0.5) : 0,
},
}));

export const StyledRejectedChip = styled(StyledChip)(({ theme }) => ({
border: `1px solid ${theme.palette.error.main}`,
backgroundColor: colors.red['100'],
['& .MuiChip-label']: {
color: theme.palette.error.main,
},
['& .MuiChip-icon']: {
color: theme.palette.error.main,
},
}));

export const StyledApprovedChip = styled(StyledChip)(({ theme }) => ({
border: `1px solid ${theme.palette.success.main}`,
backgroundColor: colors.green['100'],
['& .MuiChip-label']: {
color: theme.palette.success.main,
},
['& .MuiChip-icon']: {
color: theme.palette.success.main,
},
}));

export const StyledReviewChip = styled(StyledChip)(({ theme }) => ({
border: `1px solid ${theme.palette.primary.main}`,
backgroundColor: colors.purple['100'],
['& .MuiChip-label']: {
color: theme.palette.primary.main,
},
['& .MuiChip-icon']: {
color: theme.palette.primary.main,
},
}));

export const ChangeRequestStatusCell: VFC<IChangeRequestStatusCellProps> = ({
value,
}) => {
const renderState = (state: string) => {
switch (state) {
case ChangeRequestState.IN_REVIEW:
return (
<StyledReviewChip
label={'Review required'}
icon={<CircleOutlined fontSize={'small'} />}
/>
);
case ChangeRequestState.APPROVED:
return (
<StyledApprovedChip
label={'Approved'}
icon={<Check fontSize={'small'} />}
/>
);
case ChangeRequestState.APPLIED:
return (
<StyledApprovedChip
label={'Applied'}
icon={<Check fontSize={'small'} />}
/>
);
case ChangeRequestState.CANCELLED:
return (
<StyledRejectedChip
label={'Cancelled'}
icon={<Close fontSize={'small'} sx={{ mr: 8 }} />}
/>
);
case ChangeRequestState.REJECTED:
return (
<StyledRejectedChip
label={'Rejected'}
icon={<Close fontSize={'small'} sx={{ mr: 8 }} />}
/>
);
default:
return null;
}
const renderState = () => {
if (!value) return null;
return resolveChangeRequestStatusIcon(value as ChangeRequestState);
};

if (!value) {
return <TextCell />;
}

return <TextCell>{renderState(value)}</TextCell>;
return <TextCell>{renderState()}</TextCell>;
};
36 changes: 36 additions & 0 deletions frontend/src/component/changeRequest/changeRequest.types.ts
@@ -0,0 +1,36 @@
export type ChangeRequestState =
| 'Draft'
| 'Approved'
| 'In review'
| 'Applied'
| 'Cancelled';

export interface IChangeRequest {
id: number;
environment: string;
state: ChangeRequestState;
project: string;
createdBy: ICreatedBy;
createdAt: string;
features: IChangeRequestFeatures[];
}

interface ICreatedBy {
id: number;
username: string;
imageUrl: string;
}

interface IChangeRequestFeatures {
name: string;
changes: IChangeRequestFeatureChanges[];
}

interface IChangeRequestFeatureChanges {
id: number;
action: string;
payload: unknown;
createdAt: string;
createdBy: ICreatedBy;
warning?: string;
}
40 changes: 40 additions & 0 deletions frontend/src/component/changeRequest/changeRequest.utils.tsx
@@ -0,0 +1,40 @@
import { ChangeRequestState } from './changeRequest.types';
import { Badge } from 'component/common/Badge/Badge';
import { Check, CircleOutlined, Close } from '@mui/icons-material';

export const resolveChangeRequestStatusIcon = (state: ChangeRequestState) => {
const reviewRequired = (
<Badge color="secondary" icon={<CircleOutlined fontSize={'small'} />}>
Review required
</Badge>
);
switch (state) {
case 'Draft':
return reviewRequired;
case 'In review':
return reviewRequired;
case 'Approved':
return (
<Badge color="success" icon={<Check fontSize={'small'} />}>
Approved
</Badge>
);
case 'Applied':
return (
<Badge color="success" icon={<Check fontSize={'small'} />}>
Applied
</Badge>
);
case 'Cancelled':
return (
<Badge
color="error"
icon={<Close fontSize={'small'} sx={{ mr: 8 }} />}
>
Cancelled
</Badge>
);
default:
return reviewRequired;
}
};

0 comments on commit 2f1f9ce

Please sign in to comment.