mirror of
https://github.com/Unleash/unleash.git
synced 2025-08-23 13:46:45 +02:00
feat: move apply button to a separate section (#10324)
This commit is contained in:
parent
59990fb503
commit
068ef585be
@ -1,7 +1,15 @@
|
||||
import { Alert, Box, Button, styled, Typography } from '@mui/material';
|
||||
import {
|
||||
Alert,
|
||||
Box,
|
||||
Button,
|
||||
styled,
|
||||
Typography,
|
||||
useTheme,
|
||||
} from '@mui/material';
|
||||
import { type FC, useContext, useState } from 'react';
|
||||
import { useChangeRequest } from 'hooks/api/getters/useChangeRequest/useChangeRequest';
|
||||
import { ChangeRequestHeader } from './ChangeRequestHeader/ChangeRequestHeader.tsx';
|
||||
import { ReactComponent as ApprovedIcon } from 'assets/icons/merge.svg';
|
||||
import {
|
||||
ChangeRequestTimeline,
|
||||
type ISuggestChangeTimelineProps,
|
||||
@ -49,9 +57,19 @@ const StyledAsideBox = styled(Box)(({ theme }) => ({
|
||||
}));
|
||||
|
||||
const StyledPaper = styled(Paper)(({ theme }) => ({
|
||||
padding: theme.spacing(1, 2),
|
||||
borderRadius: theme.shape.borderRadiusLarge,
|
||||
}));
|
||||
|
||||
const StyledApplyPaper = styled(Paper)(({ theme }) => ({
|
||||
padding: theme.spacing(1, 2),
|
||||
borderRadius: theme.shape.borderRadiusLarge,
|
||||
marginTop: theme.spacing(2),
|
||||
}));
|
||||
|
||||
const StyledDiv = styled('div')(({ theme }) => ({
|
||||
marginTop: theme.spacing(2),
|
||||
width: '70%',
|
||||
padding: theme.spacing(1, 2),
|
||||
borderRadius: theme.shape.borderRadiusLarge,
|
||||
[theme.breakpoints.down(breakpoint)]: {
|
||||
width: '100%',
|
||||
@ -68,6 +86,15 @@ const StyledInnerContainer = styled(Box)(({ theme }) => ({
|
||||
padding: theme.spacing(2),
|
||||
}));
|
||||
|
||||
const StyledApplyInnerContainer = styled(Box)(({ theme }) => ({
|
||||
paddingBottom: theme.spacing(1.5),
|
||||
}));
|
||||
|
||||
const StyledOuterContainer = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
marginTop: theme.spacing(2),
|
||||
}));
|
||||
|
||||
const StyledButton = styled(Button)(({ theme }) => ({
|
||||
marginLeft: theme.spacing(2),
|
||||
}));
|
||||
@ -80,6 +107,36 @@ const ChangeRequestBody = styled(Box)(({ theme }) => ({
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledApplyContainer = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
width: '100%',
|
||||
}));
|
||||
|
||||
const StyledBox = styled(Box)(({ theme }) => ({
|
||||
width: '100%',
|
||||
}));
|
||||
|
||||
const StyledTypography = styled(Typography)(({ theme }) => ({
|
||||
fontWeight: 'bold',
|
||||
}));
|
||||
|
||||
const StyledButtonContainer = styled(Box)(({ theme }) => ({
|
||||
borderRadius: `${theme.shape.borderRadiusMedium}px`,
|
||||
backgroundColor: theme.palette.primary.main!,
|
||||
padding: theme.spacing(1, 2),
|
||||
marginRight: theme.spacing(2),
|
||||
height: '45px',
|
||||
width: '45px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
svg: {
|
||||
color: theme.palette.background.paper,
|
||||
},
|
||||
}));
|
||||
|
||||
export const ChangeRequestOverview: FC = () => {
|
||||
const projectId = useRequiredPathParam('projectId');
|
||||
const [showCancelDialog, setShowCancelDialog] = useState(false);
|
||||
@ -110,6 +167,7 @@ export const ChangeRequestOverview: FC = () => {
|
||||
const [disabled, setDisabled] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
const approversEnabled = useUiFlag('changeRequestApproverEmails');
|
||||
const theme = useTheme();
|
||||
|
||||
if (!changeRequest) {
|
||||
return null;
|
||||
@ -306,175 +364,237 @@ export const ChangeRequestOverview: FC = () => {
|
||||
}
|
||||
/>
|
||||
</StyledAsideBox>
|
||||
<StyledPaper elevation={0}>
|
||||
<StyledInnerContainer>
|
||||
Requested Changes ({countOfChanges})
|
||||
<ChangeRequest
|
||||
changeRequest={changeRequest}
|
||||
onRefetch={refetchChangeRequest}
|
||||
/>
|
||||
{changeRequest.comments?.map((comment) => (
|
||||
<ChangeRequestComment
|
||||
key={comment.id}
|
||||
comment={comment}
|
||||
<StyledDiv>
|
||||
<StyledPaper elevation={0}>
|
||||
<StyledInnerContainer>
|
||||
Requested Changes ({countOfChanges})
|
||||
<ChangeRequest
|
||||
changeRequest={changeRequest}
|
||||
onRefetch={refetchChangeRequest}
|
||||
/>
|
||||
))}
|
||||
<AddCommentField
|
||||
user={user}
|
||||
commentText={commentText}
|
||||
onTypeComment={setCommentText}
|
||||
>
|
||||
<Button
|
||||
variant='outlined'
|
||||
onClick={onAddComment}
|
||||
disabled={
|
||||
!allowChangeRequestActions ||
|
||||
commentText.trim().length === 0 ||
|
||||
commentText.trim().length > 1000 ||
|
||||
disabled
|
||||
}
|
||||
{changeRequest.comments?.map((comment) => (
|
||||
<ChangeRequestComment
|
||||
key={comment.id}
|
||||
comment={comment}
|
||||
/>
|
||||
))}
|
||||
<AddCommentField
|
||||
user={user}
|
||||
commentText={commentText}
|
||||
onTypeComment={setCommentText}
|
||||
>
|
||||
Comment
|
||||
</Button>
|
||||
</AddCommentField>
|
||||
<ConditionallyRender
|
||||
condition={isSelfReview}
|
||||
show={
|
||||
<Alert
|
||||
sx={(theme) => ({
|
||||
marginTop: theme.spacing(1.5),
|
||||
})}
|
||||
severity='info'
|
||||
<Button
|
||||
variant='outlined'
|
||||
onClick={onAddComment}
|
||||
disabled={
|
||||
!allowChangeRequestActions ||
|
||||
commentText.trim().length === 0 ||
|
||||
commentText.trim().length > 1000 ||
|
||||
disabled
|
||||
}
|
||||
>
|
||||
You can not approve your own change request
|
||||
</Alert>
|
||||
}
|
||||
/>
|
||||
<ChangeRequestReviewStatus
|
||||
changeRequest={changeRequest}
|
||||
onEditClick={() =>
|
||||
setShowScheduleChangeDialog(true)
|
||||
}
|
||||
/>
|
||||
<StyledButtonBox>
|
||||
Comment
|
||||
</Button>
|
||||
</AddCommentField>
|
||||
<ConditionallyRender
|
||||
condition={
|
||||
changeRequest.state === 'In review' &&
|
||||
!hasApprovedAlready
|
||||
}
|
||||
condition={isSelfReview}
|
||||
show={
|
||||
<ReviewButton
|
||||
onReject={() =>
|
||||
setShowRejectDialog(true)
|
||||
}
|
||||
onApprove={onApprove}
|
||||
disabled={
|
||||
!allowChangeRequestActions ||
|
||||
disabled
|
||||
}
|
||||
<Alert
|
||||
sx={(theme) => ({
|
||||
marginTop: theme.spacing(1.5),
|
||||
})}
|
||||
severity='info'
|
||||
>
|
||||
Review changes ({countOfChanges})
|
||||
</ReviewButton>
|
||||
You can not approve your own change
|
||||
request
|
||||
</Alert>
|
||||
}
|
||||
/>
|
||||
<ChangeRequestReviewStatus
|
||||
changeRequest={changeRequest}
|
||||
onEditClick={() =>
|
||||
setShowScheduleChangeDialog(true)
|
||||
}
|
||||
/>
|
||||
<StyledButtonBox>
|
||||
<ConditionallyRender
|
||||
condition={
|
||||
changeRequest.state === 'In review' &&
|
||||
!hasApprovedAlready
|
||||
}
|
||||
show={
|
||||
<ReviewButton
|
||||
onReject={() =>
|
||||
setShowRejectDialog(true)
|
||||
}
|
||||
onApprove={onApprove}
|
||||
disabled={
|
||||
!allowChangeRequestActions ||
|
||||
disabled
|
||||
}
|
||||
>
|
||||
Review changes ({countOfChanges})
|
||||
</ReviewButton>
|
||||
}
|
||||
/>
|
||||
|
||||
<ConditionallyRender
|
||||
condition={changeRequest.state === 'Approved'}
|
||||
show={
|
||||
<ApplyButton
|
||||
onApply={onApplyChanges}
|
||||
disabled={
|
||||
!allowChangeRequestActions ||
|
||||
disabled
|
||||
}
|
||||
onSchedule={() =>
|
||||
setShowScheduleChangeDialog(true)
|
||||
}
|
||||
>
|
||||
Apply or schedule changes
|
||||
</ApplyButton>
|
||||
}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={changeRequest.state === 'Scheduled'}
|
||||
show={
|
||||
<ApplyButton
|
||||
onApply={() =>
|
||||
setShowApplyScheduledDialog(true)
|
||||
}
|
||||
disabled={
|
||||
!allowChangeRequestActions ||
|
||||
disabled
|
||||
}
|
||||
onSchedule={() =>
|
||||
setShowScheduleChangeDialog(true)
|
||||
}
|
||||
variant={'update'}
|
||||
>
|
||||
Apply or schedule changes
|
||||
</ApplyButton>
|
||||
}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={
|
||||
changeRequest.state === 'Approved' &&
|
||||
!approversEnabled
|
||||
}
|
||||
show={
|
||||
<ApplyButton
|
||||
onApply={onApplyChanges}
|
||||
disabled={
|
||||
!allowChangeRequestActions ||
|
||||
disabled
|
||||
}
|
||||
onSchedule={() =>
|
||||
setShowScheduleChangeDialog(
|
||||
true,
|
||||
)
|
||||
}
|
||||
>
|
||||
Apply or schedule changes
|
||||
</ApplyButton>
|
||||
}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={
|
||||
changeRequest.state === 'Scheduled'
|
||||
}
|
||||
show={
|
||||
<ApplyButton
|
||||
onApply={() =>
|
||||
setShowApplyScheduledDialog(
|
||||
true,
|
||||
)
|
||||
}
|
||||
disabled={
|
||||
!allowChangeRequestActions ||
|
||||
disabled
|
||||
}
|
||||
onSchedule={() =>
|
||||
setShowScheduleChangeDialog(
|
||||
true,
|
||||
)
|
||||
}
|
||||
variant={'update'}
|
||||
>
|
||||
Apply or schedule changes
|
||||
</ApplyButton>
|
||||
}
|
||||
/>
|
||||
|
||||
<ConditionallyRender
|
||||
condition={
|
||||
changeRequest.state === 'In review' ||
|
||||
changeRequest.state === 'Approved' ||
|
||||
changeRequest.state === 'Scheduled'
|
||||
}
|
||||
show={
|
||||
<StyledButton
|
||||
variant='outlined'
|
||||
onClick={() => {
|
||||
navigate(
|
||||
`/playground?changeRequest=${changeRequest.id}&projects=${projectId}&environments=${changeRequest.environment}`,
|
||||
);
|
||||
}}
|
||||
>
|
||||
Preview changes
|
||||
</StyledButton>
|
||||
}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={
|
||||
changeRequest.state === 'In review' ||
|
||||
changeRequest.state === 'Approved' ||
|
||||
changeRequest.state === 'Scheduled'
|
||||
}
|
||||
show={
|
||||
<StyledButton
|
||||
variant='outlined'
|
||||
onClick={() => {
|
||||
navigate(
|
||||
`/playground?changeRequest=${changeRequest.id}&projects=${projectId}&environments=${changeRequest.environment}`,
|
||||
);
|
||||
}}
|
||||
>
|
||||
Preview changes
|
||||
</StyledButton>
|
||||
}
|
||||
/>
|
||||
|
||||
<ConditionallyRender
|
||||
condition={
|
||||
changeRequest.state !== 'Applied' &&
|
||||
changeRequest.state !== 'Rejected' &&
|
||||
changeRequest.state !== 'Cancelled' &&
|
||||
(changeRequest.createdBy.id === user?.id ||
|
||||
isAdmin)
|
||||
}
|
||||
show={
|
||||
<ConditionallyRender
|
||||
condition={Boolean(scheduledAt)}
|
||||
show={
|
||||
<StyledButton
|
||||
variant='outlined'
|
||||
onClick={() =>
|
||||
setShowRejectScheduledDialog(
|
||||
<ConditionallyRender
|
||||
condition={
|
||||
changeRequest.state !== 'Applied' &&
|
||||
changeRequest.state !== 'Rejected' &&
|
||||
changeRequest.state !== 'Cancelled' &&
|
||||
(changeRequest.createdBy.id ===
|
||||
user?.id ||
|
||||
isAdmin)
|
||||
}
|
||||
show={
|
||||
<ConditionallyRender
|
||||
condition={Boolean(scheduledAt)}
|
||||
show={
|
||||
<StyledButton
|
||||
variant='outlined'
|
||||
onClick={() =>
|
||||
setShowRejectScheduledDialog(
|
||||
true,
|
||||
)
|
||||
}
|
||||
disabled={disabled}
|
||||
>
|
||||
Reject changes
|
||||
</StyledButton>
|
||||
}
|
||||
elseShow={
|
||||
<StyledButton
|
||||
variant='outlined'
|
||||
onClick={onCancel}
|
||||
disabled={disabled}
|
||||
>
|
||||
Cancel changes
|
||||
</StyledButton>
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</StyledButtonBox>
|
||||
</StyledInnerContainer>
|
||||
</StyledPaper>
|
||||
<ConditionallyRender
|
||||
condition={
|
||||
changeRequest.state === 'Approved' &&
|
||||
approversEnabled
|
||||
}
|
||||
show={
|
||||
<StyledApplyPaper elevation={0}>
|
||||
<StyledApplyInnerContainer>
|
||||
<StyledOuterContainer>
|
||||
<StyledButtonContainer>
|
||||
<ApprovedIcon
|
||||
style={{
|
||||
transform: `scale(1.5)`,
|
||||
}}
|
||||
/>
|
||||
</StyledButtonContainer>
|
||||
<StyledBox>
|
||||
<StyledTypography>
|
||||
Apply changes
|
||||
</StyledTypography>
|
||||
<Typography>
|
||||
The change request has been
|
||||
reviewed and approved
|
||||
</Typography>
|
||||
</StyledBox>
|
||||
|
||||
<StyledApplyContainer>
|
||||
<ApplyButton
|
||||
onApply={onApplyChanges}
|
||||
disabled={
|
||||
!allowChangeRequestActions ||
|
||||
disabled
|
||||
}
|
||||
onSchedule={() =>
|
||||
setShowScheduleChangeDialog(
|
||||
true,
|
||||
)
|
||||
}
|
||||
disabled={disabled}
|
||||
>
|
||||
Reject changes
|
||||
</StyledButton>
|
||||
}
|
||||
elseShow={
|
||||
<StyledButton
|
||||
variant='outlined'
|
||||
onClick={onCancel}
|
||||
disabled={disabled}
|
||||
>
|
||||
Cancel changes
|
||||
</StyledButton>
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</StyledButtonBox>
|
||||
</StyledInnerContainer>
|
||||
</StyledPaper>
|
||||
Apply or schedule changes
|
||||
</ApplyButton>
|
||||
</StyledApplyContainer>
|
||||
</StyledOuterContainer>
|
||||
</StyledApplyInnerContainer>
|
||||
</StyledApplyPaper>
|
||||
}
|
||||
/>
|
||||
</StyledDiv>
|
||||
<Dialogue
|
||||
open={showCancelDialog}
|
||||
onClick={onCancelChanges}
|
||||
|
Loading…
Reference in New Issue
Block a user