mirror of
https://github.com/Unleash/unleash.git
synced 2025-08-09 13:47:13 +02:00
Change request UI improvements pt2 (#2624)
This commit is contained in:
parent
1e0602c134
commit
353f50237d
@ -24,9 +24,9 @@ export const ChangeRequestDialogue: FC<IChangeRequestDialogueProps> = ({
|
|||||||
messageComponent,
|
messageComponent,
|
||||||
}) => {
|
}) => {
|
||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
const { draft } = usePendingChangeRequests(projectId);
|
const { data } = usePendingChangeRequests(projectId);
|
||||||
const { changeRequestInReviewOrApproved, alert } =
|
const { changeRequestInReviewOrApproved, alert } =
|
||||||
useChangeRequestInReviewWarning(draft);
|
useChangeRequestInReviewWarning(data);
|
||||||
|
|
||||||
const hasChangeRequestInReviewForEnvironment =
|
const hasChangeRequestInReviewForEnvironment =
|
||||||
changeRequestInReviewOrApproved(environment || '');
|
changeRequestInReviewOrApproved(environment || '');
|
||||||
|
@ -11,15 +11,17 @@ const ChangeRequestCommentWrapper = styled(Box)(({ theme }) => ({
|
|||||||
}));
|
}));
|
||||||
const CommentPaper = styled(Paper)(({ theme }) => ({
|
const CommentPaper = styled(Paper)(({ theme }) => ({
|
||||||
width: '100%',
|
width: '100%',
|
||||||
padding: theme.spacing(2),
|
padding: theme.spacing(1.5, 3, 2.5, 3),
|
||||||
backgroundColor: theme.palette.tertiary.light,
|
backgroundColor: theme.palette.neutral.light,
|
||||||
|
borderRadius: theme.shape.borderRadiusLarge,
|
||||||
|
borderColor: theme.palette.divider,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const CommentHeader = styled(Box)(({ theme }) => ({
|
const CommentHeader = styled(Box)(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
borderBottom: '1px solid',
|
borderBottom: '1px solid',
|
||||||
borderColor: theme.palette.divider,
|
borderColor: theme.palette.dividerAlternative,
|
||||||
paddingBottom: theme.spacing(1),
|
paddingBottom: theme.spacing(1.5),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const ChangeRequestComment: FC<{ comment: IChangeRequestComment }> = ({
|
export const ChangeRequestComment: FC<{ comment: IChangeRequestComment }> = ({
|
||||||
@ -42,7 +44,7 @@ export const ChangeRequestComment: FC<{ comment: IChangeRequestComment }> = ({
|
|||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</CommentHeader>
|
</CommentHeader>
|
||||||
<Box sx={{ paddingTop: 2 }}>{comment.text}</Box>
|
<Box sx={{ paddingTop: 2.5 }}>{comment.text}</Box>
|
||||||
</CommentPaper>
|
</CommentPaper>
|
||||||
</ChangeRequestCommentWrapper>
|
</ChangeRequestCommentWrapper>
|
||||||
);
|
);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Avatar, styled } from '@mui/material';
|
import { Avatar, styled } from '@mui/material';
|
||||||
|
|
||||||
export const StyledAvatar = styled(Avatar)(({ theme }) => ({
|
export const StyledAvatar = styled(Avatar)(({ theme }) => ({
|
||||||
height: '30px',
|
height: '32px',
|
||||||
width: '30px',
|
width: '32px',
|
||||||
marginTop: theme.spacing(1),
|
marginTop: theme.spacing(1),
|
||||||
marginRight: theme.spacing(2),
|
marginRight: theme.spacing(2),
|
||||||
}));
|
}));
|
||||||
|
@ -23,7 +23,7 @@ export const ChangeRequestFeatureToggleChange: FC<
|
|||||||
<Box
|
<Box
|
||||||
sx={theme => ({
|
sx={theme => ({
|
||||||
backgroundColor: Boolean(conflict)
|
backgroundColor: Boolean(conflict)
|
||||||
? theme.palette.warning.light
|
? theme.palette.neutral.light
|
||||||
: theme.palette.tableHeaderBackground,
|
: theme.palette.tableHeaderBackground,
|
||||||
borderRadius: theme =>
|
borderRadius: theme =>
|
||||||
`${theme.shape.borderRadiusLarge}px ${theme.shape.borderRadiusLarge}px 0 0`,
|
`${theme.shape.borderRadiusLarge}px ${theme.shape.borderRadiusLarge}px 0 0`,
|
||||||
@ -31,7 +31,7 @@ export const ChangeRequestFeatureToggleChange: FC<
|
|||||||
borderColor: theme =>
|
borderColor: theme =>
|
||||||
conflict
|
conflict
|
||||||
? theme.palette.warning.border
|
? theme.palette.warning.border
|
||||||
: theme.palette.dividerAlternative,
|
: theme.palette.divider,
|
||||||
borderBottom: 'none',
|
borderBottom: 'none',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
})}
|
})}
|
||||||
|
@ -16,9 +16,16 @@ const ChangeItemInfo: FC = styled(Box)(({ theme }) => ({
|
|||||||
gap: theme.spacing(1),
|
gap: theme.spacing(1),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const StyledLink = styled(Link)(() => ({
|
||||||
|
textDecoration: 'none',
|
||||||
|
'&:hover, &:focus': {
|
||||||
|
textDecoration: 'underline',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
export const Discard: FC<IStrategyChangeProps> = ({ onDiscard }) => (
|
export const Discard: FC<IStrategyChangeProps> = ({ onDiscard }) => (
|
||||||
<Box>
|
<Box>
|
||||||
<Link onClick={onDiscard}>Discard</Link>
|
<StyledLink onClick={onDiscard}>Discard</StyledLink>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import { styled } from '@mui/material';
|
|||||||
import { Avatar, Box, Card, Paper, Typography } from '@mui/material';
|
import { Avatar, Box, Card, Paper, Typography } from '@mui/material';
|
||||||
|
|
||||||
export const StyledPaper = styled(Paper)(({ theme }) => ({
|
export const StyledPaper = styled(Paper)(({ theme }) => ({
|
||||||
padding: theme.spacing(2, 4),
|
padding: theme.spacing(3, 4),
|
||||||
borderRadius: `${theme.shape.borderRadiusLarge}px`,
|
borderRadius: `${theme.shape.borderRadiusLarge}px`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -32,6 +32,6 @@ export const StyledCard = styled(Card)(({ theme }) => ({
|
|||||||
export const StyledAvatar = styled(Avatar)(({ theme }) => ({
|
export const StyledAvatar = styled(Avatar)(({ theme }) => ({
|
||||||
marginLeft: theme.spacing(1),
|
marginLeft: theme.spacing(1),
|
||||||
marginRight: theme.spacing(1),
|
marginRight: theme.spacing(1),
|
||||||
height: '30px',
|
height: '24px',
|
||||||
width: '30px',
|
width: '24px',
|
||||||
}));
|
}));
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
StyledAvatar,
|
StyledAvatar,
|
||||||
StyledCard,
|
StyledCard,
|
||||||
} from './ChangeRequestHeader.styles';
|
} from './ChangeRequestHeader.styles';
|
||||||
|
import { Separator } from '../../ChangeRequestSidebar/ChangeRequestSidebar';
|
||||||
|
|
||||||
export const ChangeRequestHeader: FC<{ changeRequest: IChangeRequest }> = ({
|
export const ChangeRequestHeader: FC<{ changeRequest: IChangeRequest }> = ({
|
||||||
changeRequest,
|
changeRequest,
|
||||||
@ -19,7 +20,7 @@ export const ChangeRequestHeader: FC<{ changeRequest: IChangeRequest }> = ({
|
|||||||
return (
|
return (
|
||||||
<StyledPaper elevation={0}>
|
<StyledPaper elevation={0}>
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<StyledHeader variant="h1">
|
<StyledHeader variant="h1" sx={{ mr: 1.5 }}>
|
||||||
Change request #{changeRequest.id}
|
Change request #{changeRequest.id}
|
||||||
</StyledHeader>
|
</StyledHeader>
|
||||||
<ChangeRequestStatusBadge state={changeRequest.state} />
|
<ChangeRequestStatusBadge state={changeRequest.state} />
|
||||||
@ -32,7 +33,7 @@ export const ChangeRequestHeader: FC<{ changeRequest: IChangeRequest }> = ({
|
|||||||
<Tooltip title={changeRequest?.createdBy?.username}>
|
<Tooltip title={changeRequest?.createdBy?.username}>
|
||||||
<StyledAvatar src={changeRequest?.createdBy?.imageUrl} />
|
<StyledAvatar src={changeRequest?.createdBy?.imageUrl} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Box>
|
<Box sx={{ ml: 1.5 }}>
|
||||||
<StyledCard variant="outlined">
|
<StyledCard variant="outlined">
|
||||||
<Typography variant="body2">
|
<Typography variant="body2">
|
||||||
Environment:{' '}
|
Environment:{' '}
|
||||||
@ -44,7 +45,7 @@ export const ChangeRequestHeader: FC<{ changeRequest: IChangeRequest }> = ({
|
|||||||
>
|
>
|
||||||
{changeRequest?.environment}
|
{changeRequest?.environment}
|
||||||
</Typography>{' '}
|
</Typography>{' '}
|
||||||
| Updates:{' '}
|
<Separator /> Updates:{' '}
|
||||||
<Typography
|
<Typography
|
||||||
variant="body2"
|
variant="body2"
|
||||||
display="inline"
|
display="inline"
|
||||||
|
@ -24,6 +24,7 @@ import { AddCommentField } from './ChangeRequestComments/AddCommentField';
|
|||||||
import { usePendingChangeRequests } from 'hooks/api/getters/usePendingChangeRequests/usePendingChangeRequests';
|
import { usePendingChangeRequests } from 'hooks/api/getters/usePendingChangeRequests/usePendingChangeRequests';
|
||||||
import { useChangeRequestsEnabled } from '../../../hooks/useChangeRequestsEnabled';
|
import { useChangeRequestsEnabled } from '../../../hooks/useChangeRequestsEnabled';
|
||||||
import { Dialogue } from 'component/common/Dialogue/Dialogue';
|
import { Dialogue } from 'component/common/Dialogue/Dialogue';
|
||||||
|
import { changesCount } from '../changesCount';
|
||||||
|
|
||||||
const StyledAsideBox = styled(Box)(({ theme }) => ({
|
const StyledAsideBox = styled(Box)(({ theme }) => ({
|
||||||
width: '30%',
|
width: '30%',
|
||||||
@ -156,26 +157,21 @@ export const ChangeRequestOverview: FC = () => {
|
|||||||
<ChangeRequestBody>
|
<ChangeRequestBody>
|
||||||
<StyledAsideBox>
|
<StyledAsideBox>
|
||||||
<ChangeRequestTimeline state={changeRequest.state} />
|
<ChangeRequestTimeline state={changeRequest.state} />
|
||||||
<ConditionallyRender
|
<ChangeRequestReviewers>
|
||||||
condition={changeRequest.approvals?.length > 0}
|
{changeRequest.approvals?.map(approver => (
|
||||||
show={
|
<ChangeRequestReviewer
|
||||||
<ChangeRequestReviewers>
|
name={
|
||||||
{changeRequest.approvals?.map(approver => (
|
approver.createdBy.username ||
|
||||||
<ChangeRequestReviewer
|
'Unknown user'
|
||||||
name={
|
}
|
||||||
approver.createdBy.username ||
|
imageUrl={approver.createdBy.imageUrl}
|
||||||
'Test account'
|
/>
|
||||||
}
|
))}
|
||||||
imageUrl={approver.createdBy.imageUrl}
|
</ChangeRequestReviewers>{' '}
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</ChangeRequestReviewers>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</StyledAsideBox>
|
</StyledAsideBox>
|
||||||
<StyledPaper elevation={0}>
|
<StyledPaper elevation={0}>
|
||||||
<StyledInnerContainer>
|
<StyledInnerContainer>
|
||||||
Changes
|
Requested Changes ({changesCount(changeRequest)})
|
||||||
<ChangeRequest
|
<ChangeRequest
|
||||||
changeRequest={changeRequest}
|
changeRequest={changeRequest}
|
||||||
onRefetch={refetchChangeRequest}
|
onRefetch={refetchChangeRequest}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Box, Paper, styled, Typography } from '@mui/material';
|
import { Box, Paper, styled, Typography } from '@mui/material';
|
||||||
import { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
|
import { ConditionallyRender } from '../../../common/ConditionallyRender/ConditionallyRender';
|
||||||
|
|
||||||
const StyledBox = styled(Box)(({ theme }) => ({
|
const StyledBox = styled(Box)(({ theme }) => ({
|
||||||
marginBottom: theme.spacing(2),
|
marginBottom: theme.spacing(2),
|
||||||
@ -17,7 +18,11 @@ export const ChangeRequestReviewers: FC = ({ children }) => {
|
|||||||
>
|
>
|
||||||
<StyledBox>Reviewers</StyledBox>
|
<StyledBox>Reviewers</StyledBox>
|
||||||
<Typography variant="body1" color="text.secondary">
|
<Typography variant="body1" color="text.secondary">
|
||||||
Approved by
|
<ConditionallyRender
|
||||||
|
condition={React.Children.count(children) > 0}
|
||||||
|
show={'Approved by'}
|
||||||
|
elseShow={'No approvals yet'}
|
||||||
|
/>
|
||||||
</Typography>
|
</Typography>
|
||||||
{children}
|
{children}
|
||||||
</Paper>
|
</Paper>
|
||||||
|
@ -1,29 +1,16 @@
|
|||||||
import { FC, VFC } from 'react';
|
import { FC, VFC } from 'react';
|
||||||
import {
|
import { Box, Button, styled, Typography, useTheme } from '@mui/material';
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
Typography,
|
|
||||||
styled,
|
|
||||||
Tooltip,
|
|
||||||
Divider,
|
|
||||||
IconButton,
|
|
||||||
useTheme,
|
|
||||||
} from '@mui/material';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import { DynamicSidebarModal } from 'component/common/SidebarModal/SidebarModal';
|
import { DynamicSidebarModal } from 'component/common/SidebarModal/SidebarModal';
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||||
import { CheckCircle, HelpOutline } from '@mui/icons-material';
|
import { CheckCircle } from '@mui/icons-material';
|
||||||
import EnvironmentIcon from 'component/common/EnvironmentIcon/EnvironmentIcon';
|
|
||||||
import { ChangeRequest } from '../ChangeRequest/ChangeRequest';
|
import { ChangeRequest } from '../ChangeRequest/ChangeRequest';
|
||||||
import { usePendingChangeRequests } from 'hooks/api/getters/usePendingChangeRequests/usePendingChangeRequests';
|
import { usePendingChangeRequests } from 'hooks/api/getters/usePendingChangeRequests/usePendingChangeRequests';
|
||||||
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
||||||
import { ChangeRequestStatusBadge } from '../ChangeRequestStatusBadge/ChangeRequestStatusBadge';
|
|
||||||
import CloseIcon from '@mui/icons-material/Close';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
import { changesCount } from '../changesCount';
|
import { EnvironmentChangeRequest } from './EnvironmentChangeRequest/EnvironmentChangeRequest';
|
||||||
|
import { ReviewChangesHeader } from './ReviewChangesHeader/ReviewChangesHeader';
|
||||||
|
|
||||||
interface IChangeRequestSidebarProps {
|
interface IChangeRequestSidebarProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@ -35,7 +22,7 @@ const StyledPageContent = styled(PageContent)(({ theme }) => ({
|
|||||||
height: '100vh',
|
height: '100vh',
|
||||||
overflow: 'auto',
|
overflow: 'auto',
|
||||||
minWidth: '50vw',
|
minWidth: '50vw',
|
||||||
padding: theme.spacing(7.5, 6),
|
padding: theme.spacing(4, 6),
|
||||||
[theme.breakpoints.down('md')]: {
|
[theme.breakpoints.down('md')]: {
|
||||||
padding: theme.spacing(4, 2),
|
padding: theme.spacing(4, 2),
|
||||||
},
|
},
|
||||||
@ -48,31 +35,11 @@ const StyledPageContent = styled(PageContent)(({ theme }) => ({
|
|||||||
borderRadius: `${theme.spacing(1.5, 0, 0, 1.5)} !important`,
|
borderRadius: `${theme.spacing(1.5, 0, 0, 1.5)} !important`,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledHelpOutline = styled(HelpOutline)(({ theme }) => ({
|
|
||||||
fontSize: theme.fontSizes.mainHeader,
|
|
||||||
marginLeft: '0.3rem',
|
|
||||||
color: theme.palette.grey[700],
|
|
||||||
}));
|
|
||||||
|
|
||||||
const StyledHeaderHint = styled('div')(({ theme }) => ({
|
|
||||||
color: theme.palette.text.secondary,
|
|
||||||
fontSize: theme.fontSizes.smallBody,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const BackButton = styled(Button)(({ theme }) => ({
|
const BackButton = styled(Button)(({ theme }) => ({
|
||||||
marginTop: theme.spacing(2),
|
marginTop: theme.spacing(2),
|
||||||
marginLeft: 'auto',
|
marginLeft: 'auto',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const SubmitChangeRequestButton: FC<{ onClick: () => void; count: number }> = ({
|
|
||||||
onClick,
|
|
||||||
count,
|
|
||||||
}) => (
|
|
||||||
<Button sx={{ mt: 2, ml: 'auto' }} variant="contained" onClick={onClick}>
|
|
||||||
Submit change request ({count})
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const StyledSuccessIcon = styled(CheckCircle)(({ theme }) => ({
|
export const StyledSuccessIcon = styled(CheckCircle)(({ theme }) => ({
|
||||||
color: theme.palette.success.main,
|
color: theme.palette.success.main,
|
||||||
height: '25px',
|
height: '25px',
|
||||||
@ -91,9 +58,9 @@ export const Separator = () => (
|
|||||||
<Typography
|
<Typography
|
||||||
component="span"
|
component="span"
|
||||||
sx={{
|
sx={{
|
||||||
marginLeft: 2,
|
marginLeft: 1.5,
|
||||||
marginRight: 2,
|
marginRight: 1.5,
|
||||||
color: theme => theme.palette.neutral.light,
|
color: 'dividerAlternative',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
|
||||||
@ -122,13 +89,11 @@ export const ChangeRequestSidebar: VFC<IChangeRequestSidebarProps> = ({
|
|||||||
onClose,
|
onClose,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
draft,
|
data,
|
||||||
loading,
|
loading,
|
||||||
refetch: refetchChangeRequest,
|
refetch: refetchChangeRequest,
|
||||||
} = usePendingChangeRequests(project);
|
} = usePendingChangeRequests(project);
|
||||||
const { changeState, discardDraft } = useChangeRequestApi();
|
const { changeState, discardDraft } = useChangeRequestApi();
|
||||||
const theme = useTheme();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const { setToastApiError } = useToast();
|
const { setToastApiError } = useToast();
|
||||||
|
|
||||||
const onReview = async (draftId: number) => {
|
const onReview = async (draftId: number) => {
|
||||||
@ -149,7 +114,7 @@ export const ChangeRequestSidebar: VFC<IChangeRequestSidebarProps> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!loading && !draft) {
|
if (!loading && !data) {
|
||||||
return (
|
return (
|
||||||
<DynamicSidebarModal
|
<DynamicSidebarModal
|
||||||
open={open}
|
open={open}
|
||||||
@ -157,11 +122,9 @@ export const ChangeRequestSidebar: VFC<IChangeRequestSidebarProps> = ({
|
|||||||
label="Review changes"
|
label="Review changes"
|
||||||
>
|
>
|
||||||
<StyledPageContent
|
<StyledPageContent
|
||||||
|
disableBorder={true}
|
||||||
header={
|
header={
|
||||||
<PageHeader
|
<PageHeader titleElement="Review your changes"></PageHeader>
|
||||||
secondary
|
|
||||||
titleElement="Review your changes"
|
|
||||||
></PageHeader>
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
There are no changes to review.
|
There are no changes to review.
|
||||||
@ -179,155 +142,23 @@ export const ChangeRequestSidebar: VFC<IChangeRequestSidebarProps> = ({
|
|||||||
label="Review changes"
|
label="Review changes"
|
||||||
>
|
>
|
||||||
<StyledPageContent
|
<StyledPageContent
|
||||||
header={
|
disableBorder={true}
|
||||||
<PageHeader
|
header={<ReviewChangesHeader onClose={onClose} />}
|
||||||
secondary
|
|
||||||
actions={
|
|
||||||
<IconButton onClick={onClose}>
|
|
||||||
<CloseIcon />
|
|
||||||
</IconButton>
|
|
||||||
}
|
|
||||||
titleElement={
|
|
||||||
<>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Review your changes
|
|
||||||
<Tooltip
|
|
||||||
title="Here you can see all the changes that you are suggesting and you can send them for review. You can still discard the changes after you sent them for review or even cancel the entire review if you need it."
|
|
||||||
arrow
|
|
||||||
>
|
|
||||||
<StyledHelpOutline />
|
|
||||||
</Tooltip>
|
|
||||||
</Box>
|
|
||||||
<StyledHeaderHint>
|
|
||||||
Make sure you are sending the right changes
|
|
||||||
to be reviewed
|
|
||||||
</StyledHeaderHint>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
></PageHeader>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{draft?.map(environmentChangeRequest => (
|
{data?.map(environmentChangeRequest => (
|
||||||
<Box
|
<EnvironmentChangeRequest
|
||||||
key={environmentChangeRequest.id}
|
key={environmentChangeRequest.id}
|
||||||
sx={{
|
environmentChangeRequest={environmentChangeRequest}
|
||||||
padding: 2,
|
onClose={onClose}
|
||||||
mt: 2,
|
onReview={onReview}
|
||||||
border: '2px solid',
|
onDiscard={onDiscard}
|
||||||
borderColor: theme => theme.palette.neutral.light,
|
|
||||||
borderRadius: theme =>
|
|
||||||
`${theme.shape.borderRadiusLarge}px`,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<EnvironmentIcon enabled={true} />
|
|
||||||
<Typography component="span" variant="h2">
|
|
||||||
{environmentChangeRequest.environment}
|
|
||||||
</Typography>
|
|
||||||
<Separator />
|
|
||||||
<UpdateCount
|
|
||||||
count={
|
|
||||||
environmentChangeRequest.features.length
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<Box sx={{ ml: 'auto' }}>
|
|
||||||
<ChangeRequestStatusBadge
|
|
||||||
state={environmentChangeRequest.state}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
<Divider sx={{ my: 3 }} />
|
|
||||||
<Typography variant="body1" color="text.secondary">
|
|
||||||
You request changes for these feature toggles:
|
|
||||||
</Typography>
|
|
||||||
<ChangeRequest
|
<ChangeRequest
|
||||||
changeRequest={environmentChangeRequest}
|
changeRequest={environmentChangeRequest}
|
||||||
onNavigate={() => {
|
onNavigate={onClose}
|
||||||
onClose();
|
|
||||||
}}
|
|
||||||
onRefetch={refetchChangeRequest}
|
onRefetch={refetchChangeRequest}
|
||||||
/>
|
/>
|
||||||
<Box sx={{ display: 'flex' }}>
|
</EnvironmentChangeRequest>
|
||||||
<ConditionallyRender
|
|
||||||
condition={
|
|
||||||
environmentChangeRequest?.state === 'Draft'
|
|
||||||
}
|
|
||||||
show={
|
|
||||||
<>
|
|
||||||
<SubmitChangeRequestButton
|
|
||||||
onClick={() =>
|
|
||||||
onReview(
|
|
||||||
environmentChangeRequest.id
|
|
||||||
)
|
|
||||||
}
|
|
||||||
count={changesCount(
|
|
||||||
environmentChangeRequest
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
sx={{ mt: 2, ml: 2 }}
|
|
||||||
variant="outlined"
|
|
||||||
onClick={() =>
|
|
||||||
onDiscard(
|
|
||||||
environmentChangeRequest.id
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Discard changes
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={
|
|
||||||
environmentChangeRequest.state ===
|
|
||||||
'In review' ||
|
|
||||||
environmentChangeRequest.state ===
|
|
||||||
'Approved'
|
|
||||||
}
|
|
||||||
show={
|
|
||||||
<>
|
|
||||||
<StyledFlexAlignCenterBox>
|
|
||||||
<StyledSuccessIcon />
|
|
||||||
<Typography
|
|
||||||
color={
|
|
||||||
theme.palette.success.dark
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Draft successfully sent to
|
|
||||||
review
|
|
||||||
</Typography>
|
|
||||||
<Button
|
|
||||||
sx={{ marginLeft: 2 }}
|
|
||||||
variant="outlined"
|
|
||||||
onClick={() => {
|
|
||||||
onClose();
|
|
||||||
navigate(
|
|
||||||
`/projects/${environmentChangeRequest.project}/change-requests/${environmentChangeRequest.id}`
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
View change request page
|
|
||||||
</Button>
|
|
||||||
</StyledFlexAlignCenterBox>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
))}
|
))}
|
||||||
</StyledPageContent>
|
</StyledPageContent>
|
||||||
</DynamicSidebarModal>
|
</DynamicSidebarModal>
|
||||||
|
@ -0,0 +1,132 @@
|
|||||||
|
import { FC } from 'react';
|
||||||
|
import { Box, Button, Divider, Typography, useTheme } from '@mui/material';
|
||||||
|
import { IChangeRequest } from '../../changeRequest.types';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { ChangeRequestStatusBadge } from '../../ChangeRequestStatusBadge/ChangeRequestStatusBadge';
|
||||||
|
import { ConditionallyRender } from '../../../common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { changesCount } from '../../changesCount';
|
||||||
|
import {
|
||||||
|
Separator,
|
||||||
|
StyledFlexAlignCenterBox,
|
||||||
|
StyledSuccessIcon,
|
||||||
|
UpdateCount,
|
||||||
|
} from '../ChangeRequestSidebar';
|
||||||
|
import { CloudCircle } from '@mui/icons-material';
|
||||||
|
|
||||||
|
const SubmitChangeRequestButton: FC<{ onClick: () => void; count: number }> = ({
|
||||||
|
onClick,
|
||||||
|
count,
|
||||||
|
}) => (
|
||||||
|
<Button sx={{ mt: 2, ml: 'auto' }} variant="contained" onClick={onClick}>
|
||||||
|
Submit change request ({count})
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const EnvironmentChangeRequest: FC<{
|
||||||
|
environmentChangeRequest: IChangeRequest;
|
||||||
|
onClose: () => void;
|
||||||
|
onReview: (id: number) => void;
|
||||||
|
onDiscard: (id: number) => void;
|
||||||
|
}> = ({ environmentChangeRequest, onClose, onReview, onDiscard, children }) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
key={environmentChangeRequest.id}
|
||||||
|
sx={{
|
||||||
|
padding: 3,
|
||||||
|
border: '2px solid',
|
||||||
|
mb: 5,
|
||||||
|
borderColor: theme => theme.palette.secondaryContainer,
|
||||||
|
borderRadius: theme => `${theme.shape.borderRadiusLarge}px`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'end' }}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CloudCircle
|
||||||
|
sx={theme => ({
|
||||||
|
color: theme.palette.primary.light,
|
||||||
|
mr: 0.5,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
<Typography component="span" variant="h2">
|
||||||
|
{environmentChangeRequest.environment}
|
||||||
|
</Typography>
|
||||||
|
<Separator />
|
||||||
|
<UpdateCount
|
||||||
|
count={environmentChangeRequest.features.length}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Box sx={{ ml: 'auto' }}>
|
||||||
|
<ChangeRequestStatusBadge
|
||||||
|
state={environmentChangeRequest.state}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<Divider sx={{ my: 3 }} />
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
You request changes for these feature toggles:
|
||||||
|
</Typography>
|
||||||
|
{children}
|
||||||
|
<Box sx={{ display: 'flex' }}>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={environmentChangeRequest?.state === 'Draft'}
|
||||||
|
show={
|
||||||
|
<>
|
||||||
|
<SubmitChangeRequestButton
|
||||||
|
onClick={() =>
|
||||||
|
onReview(environmentChangeRequest.id)
|
||||||
|
}
|
||||||
|
count={changesCount(environmentChangeRequest)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
sx={{ mt: 2, ml: 2 }}
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() =>
|
||||||
|
onDiscard(environmentChangeRequest.id)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Discard changes
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={
|
||||||
|
environmentChangeRequest.state === 'In review' ||
|
||||||
|
environmentChangeRequest.state === 'Approved'
|
||||||
|
}
|
||||||
|
show={
|
||||||
|
<>
|
||||||
|
<StyledFlexAlignCenterBox>
|
||||||
|
<StyledSuccessIcon />
|
||||||
|
<Typography color={theme.palette.success.dark}>
|
||||||
|
Draft successfully sent to review
|
||||||
|
</Typography>
|
||||||
|
<Button
|
||||||
|
sx={{ marginLeft: 2 }}
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => {
|
||||||
|
onClose();
|
||||||
|
navigate(
|
||||||
|
`/projects/${environmentChangeRequest.project}/change-requests/${environmentChangeRequest.id}`
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
View change request page
|
||||||
|
</Button>
|
||||||
|
</StyledFlexAlignCenterBox>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,50 @@
|
|||||||
|
import { Box, IconButton, styled, Tooltip } from '@mui/material';
|
||||||
|
import { HelpOutline } from '@mui/icons-material';
|
||||||
|
import { FC } from 'react';
|
||||||
|
import { PageHeader } from '../../../common/PageHeader/PageHeader';
|
||||||
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
|
|
||||||
|
const StyledHelpOutline = styled(HelpOutline)(({ theme }) => ({
|
||||||
|
fontSize: theme.fontSizes.mainHeader,
|
||||||
|
marginLeft: '0.3rem',
|
||||||
|
color: theme.palette.grey[700],
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledHeaderHint = styled('div')(({ theme }) => ({
|
||||||
|
marginTop: theme.spacing(0.5),
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
fontSize: theme.fontSizes.smallBody,
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const ReviewChangesHeader: FC<{ onClose: () => void }> = ({
|
||||||
|
onClose,
|
||||||
|
}) => (
|
||||||
|
<PageHeader
|
||||||
|
actions={
|
||||||
|
<IconButton onClick={onClose}>
|
||||||
|
<CloseIcon />
|
||||||
|
</IconButton>
|
||||||
|
}
|
||||||
|
titleElement={
|
||||||
|
<>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Review your changes
|
||||||
|
<Tooltip
|
||||||
|
title="Here you can see all the changes that you are suggesting and you can send them for review. You can still discard the changes after you sent them for review or even cancel the entire review if you need it."
|
||||||
|
arrow
|
||||||
|
>
|
||||||
|
<StyledHelpOutline />
|
||||||
|
</Tooltip>
|
||||||
|
</Box>
|
||||||
|
<StyledHeaderHint>
|
||||||
|
Make sure you are sending the right changes to be reviewed
|
||||||
|
</StyledHeaderHint>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
@ -14,7 +14,10 @@ interface IDraftBannerProps {
|
|||||||
const DraftBannerContentWrapper = styled(Box)(({ theme }) => ({
|
const DraftBannerContentWrapper = styled(Box)(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
padding: theme.spacing(1, 1.5),
|
padding: theme.spacing(1, 0),
|
||||||
|
[theme.breakpoints.down('lg')]: {
|
||||||
|
padding: theme.spacing(1, 2),
|
||||||
|
},
|
||||||
color: theme.palette.warning.main,
|
color: theme.palette.warning.main,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -27,7 +30,7 @@ const DraftBannerContent: FC<{
|
|||||||
return (
|
return (
|
||||||
<Box className={classes.content}>
|
<Box className={classes.content}>
|
||||||
<DraftBannerContentWrapper>
|
<DraftBannerContentWrapper>
|
||||||
<Typography variant="body2">
|
<Typography variant="body2" sx={{ mr: 4 }}>
|
||||||
<strong>Change request mode</strong> – You have changes{' '}
|
<strong>Change request mode</strong> – You have changes{' '}
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(changeRequest.environment)}
|
condition={Boolean(changeRequest.environment)}
|
||||||
@ -75,30 +78,31 @@ const StickyBanner = styled(Box)(({ theme }) => ({
|
|||||||
|
|
||||||
export const DraftBanner: VFC<IDraftBannerProps> = ({ project }) => {
|
export const DraftBanner: VFC<IDraftBannerProps> = ({ project }) => {
|
||||||
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
||||||
const { draft, loading } = usePendingChangeRequests(project);
|
const { data, loading } = usePendingChangeRequests(project);
|
||||||
|
|
||||||
if ((!loading && !draft) || draft?.length === 0) {
|
if ((!loading && !data) || data?.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StickyBanner>
|
<StickyBanner>
|
||||||
{draft &&
|
{data?.length
|
||||||
draft
|
? data
|
||||||
.filter(changeRequest =>
|
.filter(changeRequest =>
|
||||||
['Draft', 'In review', 'Approved'].includes(
|
['Draft', 'In review', 'Approved'].includes(
|
||||||
changeRequest.state
|
changeRequest.state
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.map(changeRequest => (
|
.map(changeRequest => (
|
||||||
<DraftBannerContent
|
<DraftBannerContent
|
||||||
key={changeRequest.id}
|
key={changeRequest.id}
|
||||||
changeRequest={changeRequest}
|
changeRequest={changeRequest}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsSidebarOpen(true);
|
setIsSidebarOpen(true);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))
|
||||||
|
: null}
|
||||||
|
|
||||||
<ChangeRequestSidebar
|
<ChangeRequestSidebar
|
||||||
project={project}
|
project={project}
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
import { ArrowRight } from '@mui/icons-material';
|
|
||||||
import { useTheme } from '@mui/system';
|
|
||||||
import { TextCell } from '../../../../common/Table/cells/TextCell/TextCell';
|
|
||||||
|
|
||||||
export const ChangeRequestActionCell = () => {
|
|
||||||
const theme = useTheme();
|
|
||||||
return (
|
|
||||||
<TextCell sx={{ textAlign: 'right' }}>
|
|
||||||
<ArrowRight sx={{ color: theme.palette.secondary.main }} />{' '}
|
|
||||||
</TextCell>
|
|
||||||
);
|
|
||||||
};
|
|
@ -31,19 +31,22 @@ export const ChangeRequestTitleCell = ({
|
|||||||
return (
|
return (
|
||||||
<TextCell sx={{ minWidth: '200px' }}>
|
<TextCell sx={{ minWidth: '200px' }}>
|
||||||
<StyledLink>
|
<StyledLink>
|
||||||
<Link
|
|
||||||
component={RouterLink}
|
|
||||||
underline={'hover'}
|
|
||||||
to={path}
|
|
||||||
sx={{ pt: 0.2 }}
|
|
||||||
>
|
|
||||||
Change request
|
|
||||||
</Link>
|
|
||||||
<Typography
|
<Typography
|
||||||
component={'span'}
|
component={'span'}
|
||||||
|
variant={'body2'}
|
||||||
color={theme.palette.text.secondary}
|
color={theme.palette.text.secondary}
|
||||||
sx={{ margin: theme.spacing(0, 1), pt: 0 }}
|
|
||||||
>
|
>
|
||||||
|
<Link
|
||||||
|
component={RouterLink}
|
||||||
|
underline={'hover'}
|
||||||
|
to={path}
|
||||||
|
sx={theme => ({
|
||||||
|
paddingTop: theme.spacing(0.2),
|
||||||
|
marginRight: theme.spacing(1),
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
Change request
|
||||||
|
</Link>
|
||||||
{`#${id}`}
|
{`#${id}`}
|
||||||
</Typography>
|
</Typography>
|
||||||
</StyledLink>
|
</StyledLink>
|
||||||
|
@ -20,7 +20,6 @@ import { useSearchParams } from 'react-router-dom';
|
|||||||
import { TimeAgoCell } from '../../../common/Table/cells/TimeAgoCell/TimeAgoCell';
|
import { TimeAgoCell } from '../../../common/Table/cells/TimeAgoCell/TimeAgoCell';
|
||||||
import { TextCell } from '../../../common/Table/cells/TextCell/TextCell';
|
import { TextCell } from '../../../common/Table/cells/TextCell/TextCell';
|
||||||
import { ChangeRequestStatusCell } from './ChangeRequestStatusCell/ChangeRequestStatusCell';
|
import { ChangeRequestStatusCell } from './ChangeRequestStatusCell/ChangeRequestStatusCell';
|
||||||
import { ChangeRequestActionCell } from './ChangeRequestActionCell/ChangeRequestActionCell';
|
|
||||||
import { AvatarCell } from './AvatarCell/AvatarCell';
|
import { AvatarCell } from './AvatarCell/AvatarCell';
|
||||||
import { ChangeRequestTitleCell } from './ChangeRequestTitleCell/ChangeRequestTitleCell';
|
import { ChangeRequestTitleCell } from './ChangeRequestTitleCell/ChangeRequestTitleCell';
|
||||||
import { TableBody, TableRow } from '../../../common/Table';
|
import { TableBody, TableRow } from '../../../common/Table';
|
||||||
@ -120,14 +119,6 @@ export const ChangeRequestsTabs = ({
|
|||||||
width: 150,
|
width: 150,
|
||||||
Cell: ChangeRequestStatusCell,
|
Cell: ChangeRequestStatusCell,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Header: '',
|
|
||||||
id: 'Actions',
|
|
||||||
minWidth: 50,
|
|
||||||
width: 50,
|
|
||||||
canSort: false,
|
|
||||||
Cell: ChangeRequestActionCell,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
//eslint-disable-next-line
|
//eslint-disable-next-line
|
||||||
[projectId]
|
[projectId]
|
||||||
|
@ -28,6 +28,9 @@ export const useStyles = makeStyles()(theme => ({
|
|||||||
},
|
},
|
||||||
accordionRoot: {
|
accordionRoot: {
|
||||||
transition: 'all 0.1s ease',
|
transition: 'all 0.1s ease',
|
||||||
|
'&:before': {
|
||||||
|
opacity: '0 !important',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
accordionExpanded: {
|
accordionExpanded: {
|
||||||
backgroundColor: theme.palette.neutral.light,
|
backgroundColor: theme.palette.neutral.light,
|
||||||
|
@ -9,6 +9,9 @@ export const useStyles = makeStyles<{ lineClamp?: number }>()(
|
|||||||
WebkitLineClamp: lineClamp ? lineClamp : 'none',
|
WebkitLineClamp: lineClamp ? lineClamp : 'none',
|
||||||
WebkitBoxOrient: 'vertical',
|
WebkitBoxOrient: 'vertical',
|
||||||
wordBreak: 'break-all',
|
wordBreak: 'break-all',
|
||||||
|
[theme.breakpoints.down('sm')]: {
|
||||||
|
wordBreak: 'normal',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -27,7 +27,12 @@ export const TimeAgoCell: VFC<ITimeAgoCellProps> = ({
|
|||||||
return (
|
return (
|
||||||
<TextCell>
|
<TextCell>
|
||||||
<Tooltip title={title?.(date) ?? date} arrow>
|
<Tooltip title={title?.(date) ?? date} arrow>
|
||||||
<Typography noWrap variant="body2" data-loading>
|
<Typography
|
||||||
|
noWrap
|
||||||
|
component="span"
|
||||||
|
variant="body2"
|
||||||
|
data-loading
|
||||||
|
>
|
||||||
<TimeAgo date={new Date(value)} live={live} title={''} />
|
<TimeAgo date={new Date(value)} live={live} title={''} />
|
||||||
</Typography>
|
</Typography>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
@ -67,9 +67,9 @@ export const FeatureStrategyForm = ({
|
|||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
const { strategyDefinition } = useStrategy(strategy?.name);
|
const { strategyDefinition } = useStrategy(strategy?.name);
|
||||||
|
|
||||||
const { draft } = usePendingChangeRequests(feature.project);
|
const { data } = usePendingChangeRequests(feature.project);
|
||||||
const { changeRequestInReviewOrApproved, alert } =
|
const { changeRequestInReviewOrApproved, alert } =
|
||||||
useChangeRequestInReviewWarning(draft);
|
useChangeRequestInReviewWarning(data);
|
||||||
|
|
||||||
const hasChangeRequestInReviewForEnvironment =
|
const hasChangeRequestInReviewForEnvironment =
|
||||||
changeRequestInReviewOrApproved(environmentId || '');
|
changeRequestInReviewOrApproved(environmentId || '');
|
||||||
|
@ -84,7 +84,7 @@ const ChangeRequestStatusBadge = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Box sx={{ mr: 1.5 }}>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={change?.action === 'updateStrategy'}
|
condition={change?.action === 'updateStrategy'}
|
||||||
show={<Badge color="warning">Modified in draft</Badge>}
|
show={<Badge color="warning">Modified in draft</Badge>}
|
||||||
@ -93,6 +93,6 @@ const ChangeRequestStatusBadge = ({
|
|||||||
condition={change?.action === 'deleteStrategy'}
|
condition={change?.action === 'deleteStrategy'}
|
||||||
show={<Badge color="error">Deleted in draft</Badge>}
|
show={<Badge color="error">Deleted in draft</Badge>}
|
||||||
/>
|
/>
|
||||||
</>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -6,9 +6,9 @@ export const useStrategyChangeFromRequest = (
|
|||||||
environment: string,
|
environment: string,
|
||||||
strategyId: string
|
strategyId: string
|
||||||
) => {
|
) => {
|
||||||
const { draft } = usePendingChangeRequests(projectId);
|
const { data } = usePendingChangeRequests(projectId);
|
||||||
|
|
||||||
const environmentDraft = draft?.find(
|
const environmentDraft = data?.find(
|
||||||
draft => draft.environment === environment
|
draft => draft.environment === environment
|
||||||
);
|
);
|
||||||
const feature = environmentDraft?.features.find(
|
const feature = environmentDraft?.features.find(
|
||||||
|
@ -139,7 +139,6 @@ export const ChangeRequestTable: VFC = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: 'Required approvals',
|
Header: 'Required approvals',
|
||||||
align: 'center',
|
|
||||||
Cell: ({ row: { original } }: any) => {
|
Cell: ({ row: { original } }: any) => {
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
|
|
||||||
@ -149,6 +148,7 @@ export const ChangeRequestTable: VFC = () => {
|
|||||||
show={
|
show={
|
||||||
<StyledBox data-loading>
|
<StyledBox data-loading>
|
||||||
<GeneralSelect
|
<GeneralSelect
|
||||||
|
sx={{ width: '140px', marginLeft: 1 }}
|
||||||
options={approvalOptions}
|
options={approvalOptions}
|
||||||
value={original.requiredApprovals || 1}
|
value={original.requiredApprovals || 1}
|
||||||
onChange={approvals => {
|
onChange={approvals => {
|
||||||
|
@ -17,7 +17,7 @@ export const usePendingChangeRequests = (project: string) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
draft: data,
|
data,
|
||||||
loading: !error && !data,
|
loading: !error && !data,
|
||||||
refetch: mutate,
|
refetch: mutate,
|
||||||
error,
|
error,
|
||||||
|
Loading…
Reference in New Issue
Block a user