diff --git a/frontend/src/component/changeRequest/ChangeRequestOverview/ApplyButton/ApplyButton.tsx b/frontend/src/component/changeRequest/ChangeRequestOverview/ApplyButton/ApplyButton.tsx
index d3262017bdce..66493b496f13 100644
--- a/frontend/src/component/changeRequest/ChangeRequestOverview/ApplyButton/ApplyButton.tsx
+++ b/frontend/src/component/changeRequest/ChangeRequestOverview/ApplyButton/ApplyButton.tsx
@@ -9,7 +9,8 @@ export const ApplyButton: FC<{
disabled: boolean;
onSchedule: () => void;
onApply: () => void;
-}> = ({ disabled, onSchedule, onApply, children }) => (
+ variant?: 'create' | 'update';
+}> = ({ disabled, onSchedule, onApply, variant = 'create', children }) => (
,
},
{
- label: 'Schedule changes',
+ label:
+ variant === 'create'
+ ? 'Schedule changes'
+ : 'Update schedule',
onSelect: onSchedule,
icon: ,
},
diff --git a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestOverview.tsx b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestOverview.tsx
index dbe21e4ad6e2..7a0ef34dfbe6 100644
--- a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestOverview.tsx
+++ b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestOverview.tsx
@@ -26,7 +26,6 @@ import { ChangeRequestReviewers } from './ChangeRequestReviewers/ChangeRequestRe
import { ChangeRequestRejectDialogue } from './ChangeRequestRejectDialog/ChangeRequestRejectDialog';
import { ApplyButton } from './ApplyButton/ApplyButton';
import { useUiFlag } from 'hooks/useUiFlag';
-import { scheduler } from 'timers/promises';
const StyledAsideBox = styled(Box)(({ theme }) => ({
width: '30%',
@@ -85,7 +84,6 @@ export const ChangeRequestOverview: FC = () => {
const { setToastData, setToastApiError } = useToast();
const { isChangeRequestConfiguredForReview } =
useChangeRequestsEnabled(projectId);
-
const scheduleChangeRequests = useUiFlag('scheduledConfigurationChanges');
if (!changeRequest) {
@@ -191,7 +189,7 @@ export const ChangeRequestOverview: FC = () => {
changeRequest.state === 'In review' &&
!isAdmin;
- const hasApprovedAlready = changeRequest.approvals.some(
+ const hasApprovedAlready = changeRequest.approvals?.some(
(approval) => approval.createdBy.id === user?.id,
);
@@ -312,6 +310,35 @@ export const ChangeRequestOverview: FC = () => {
/>
}
/>
+ {
+ console.log(
+ 'I would show the apply now dialog',
+ );
+ }}
+ disabled={
+ !allowChangeRequestActions ||
+ loading
+ }
+ onSchedule={() => {
+ console.log(
+ 'I would schedule changes now',
+ );
+ }}
+ variant={'update'}
+ >
+ Apply or schedule changes
+
+ }
+ />
+
{
variant='outlined'
onClick={onCancel}
>
- Cancel changes
+ {changeRequest.schedule
+ ? 'Reject'
+ : 'Cancel'}{' '}
+ changes
}
/>
diff --git a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestReviewStatus/ChangeRequestReviewStatus.styles.ts b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestReviewStatus/ChangeRequestReviewStatus.styles.ts
index 535396453d3f..ff08ed468e71 100644
--- a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestReviewStatus/ChangeRequestReviewStatus.styles.ts
+++ b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestReviewStatus/ChangeRequestReviewStatus.styles.ts
@@ -1,5 +1,5 @@
import { styled } from '@mui/material';
-import { Cancel, CheckCircle } from '@mui/icons-material';
+import { Cancel, CheckCircle, Schedule, Edit } from '@mui/icons-material';
import { Box, Typography, Divider } from '@mui/material';
const styledComponentPropCheck = () => (prop: string) =>
@@ -36,6 +36,18 @@ export const StyledSuccessIcon = styled(CheckCircle)(({ theme }) => ({
marginRight: theme.spacing(1),
}));
+export const StyledScheduledIcon = styled(Schedule)(({ theme }) => ({
+ color: theme.palette.warning.main,
+ height: '35px',
+ width: '35px',
+ marginRight: theme.spacing(1),
+}));
+export const StyledEditIcon = styled(Edit)(({ theme }) => ({
+ color: theme.palette.text.secondary,
+ height: '24px',
+ width: '24px',
+}));
+
export const StyledOuterContainer = styled(Box)(({ theme }) => ({
display: 'flex',
marginTop: theme.spacing(2),
@@ -77,3 +89,10 @@ export const StyledReviewTitle = styled(Typography, {
fontWeight: 'bold',
color,
}));
+
+export const StyledScheduledBox = styled(Box)({
+ display: 'flex',
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ width: '100%',
+});
diff --git a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestReviewStatus/ChangeRequestReviewStatus.tsx b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestReviewStatus/ChangeRequestReviewStatus.tsx
index d27611fd894f..96864362f35a 100644
--- a/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestReviewStatus/ChangeRequestReviewStatus.tsx
+++ b/frontend/src/component/changeRequest/ChangeRequestOverview/ChangeRequestReviewStatus/ChangeRequestReviewStatus.tsx
@@ -1,5 +1,5 @@
import React, { FC } from 'react';
-import { Box, Theme, Typography, useTheme } from '@mui/material';
+import { Box, IconButton, Theme, Typography, useTheme } from '@mui/material';
import { ReactComponent as ChangesAppliedIcon } from 'assets/icons/merge.svg';
import {
StyledOuterContainer,
@@ -11,6 +11,9 @@ import {
StyledWarningIcon,
StyledReviewTitle,
StyledDivider,
+ StyledScheduledIcon,
+ StyledEditIcon,
+ StyledScheduledBox,
} from './ChangeRequestReviewStatus.styles';
import {
ChangeRequestState,
@@ -21,7 +24,7 @@ interface ISuggestChangeReviewsStatusProps {
changeRequest: IChangeRequest;
}
const resolveBorder = (state: ChangeRequestState, theme: Theme) => {
- if (state === 'Approved') {
+ if (state === 'Approved' || state === 'Scheduled') {
return `2px solid ${theme.palette.success.main}`;
}
@@ -109,6 +112,12 @@ const ResolveComponent = ({ changeRequest }: IResolveComponentProps) => {
return ;
}
+ if (state === 'Scheduled') {
+ return (
+
+ );
+ }
+
return ;
};
@@ -194,6 +203,69 @@ const Applied = () => {
);
};
+interface IScheduledProps {
+ scheduledDate?: string;
+}
+const Scheduled = ({ scheduledDate }: IScheduledProps) => {
+ const theme = useTheme();
+
+ if (!scheduledDate) {
+ return null;
+ }
+
+ const getBrowserTimezone = (): string => {
+ const offset = -new Date().getTimezoneOffset();
+ const hours = Math.floor(Math.abs(offset) / 60);
+ const minutes = Math.abs(offset) % 60;
+ let sign = '+';
+ if (offset < 0) {
+ sign = '-';
+ }
+
+ // Ensure that hours and minutes are two digits
+ const zeroPaddedHours = hours.toString().padStart(2, '0');
+ const zeroPaddedMinutes = minutes.toString().padStart(2, '0');
+
+ return `UTC${sign}${zeroPaddedHours}:${zeroPaddedMinutes}`;
+ };
+
+ const timezone = getBrowserTimezone();
+
+ return (
+ <>
+
+
+
+
+ Changes approved
+
+
+ One approving review from requested approvers
+
+
+
+
+
+
+
+
+
+
+
+ Changes are scheduled to be applied on:{' '}
+ {new Date(scheduledDate).toLocaleString()}
+
+ Your timezone is {timezone}
+
+
+
+
+
+
+ >
+ );
+};
+
const Cancelled = () => {
const theme = useTheme();
diff --git a/frontend/src/component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge.tsx b/frontend/src/component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge.tsx
index 35d4999ca939..67e6bca33294 100644
--- a/frontend/src/component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge.tsx
+++ b/frontend/src/component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge.tsx
@@ -1,7 +1,7 @@
import { VFC } from 'react';
import { ChangeRequestState } from '../changeRequest.types';
import { Badge } from 'component/common/Badge/Badge';
-import { Check, CircleOutlined, Close } from '@mui/icons-material';
+import { AccessTime, Check, CircleOutlined, Close } from '@mui/icons-material';
interface IChangeRequestStatusBadgeProps {
state: ChangeRequestState;
@@ -47,6 +47,12 @@ export const ChangeRequestStatusBadge: VFC = ({
Rejected
);
+ case 'Scheduled':
+ return (
+ }>
+ Scheduled
+
+ );
default:
return ;
}
diff --git a/frontend/src/component/changeRequest/changeRequest.types.ts b/frontend/src/component/changeRequest/changeRequest.types.ts
index e882d6d6a356..e79a42fddb0c 100644
--- a/frontend/src/component/changeRequest/changeRequest.types.ts
+++ b/frontend/src/component/changeRequest/changeRequest.types.ts
@@ -18,6 +18,12 @@ export interface IChangeRequest {
rejections: IChangeRequestApproval[];
comments: IChangeRequestComment[];
conflict?: string;
+ schedule?: IChangeRequestSchedule;
+}
+
+export interface IChangeRequestSchedule {
+ scheduledAt: string;
+ status: 'pending' | 'failed';
}
export interface IChangeRequestEnvironmentConfig {
@@ -67,6 +73,7 @@ export type ChangeRequestState =
| 'Approved'
| 'In review'
| 'Applied'
+ | 'Scheduled'
| 'Cancelled'
| 'Rejected';