diff --git a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/EnvironmentAccordionBody.tsx b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/EnvironmentAccordionBody.tsx
index 4c3a94ce86..26b630d5df 100644
--- a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/EnvironmentAccordionBody.tsx
+++ b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/EnvironmentAccordionBody.tsx
@@ -234,7 +234,11 @@ const EnvironmentAccordionBody = ({
show={
<>
{releasePlans.map((plan) => (
-
+
))}
{releasePlans.map((plan) => (
-
+
))}
prop !== 'disabled',
-})<{ disabled?: boolean }>(({ theme, disabled }) => ({
+const StyledContainer = styled('div')(({ theme }) => ({
padding: theme.spacing(2),
borderRadius: theme.shape.borderRadiusMedium,
border: `1px solid ${theme.palette.divider}`,
'& + &': {
marginTop: theme.spacing(2),
},
- background: disabled
- ? theme.palette.envAccordion.disabled
- : theme.palette.background.paper,
+ background: theme.palette.background.paper,
}));
-const StyledHeader = styled('div', {
- shouldForwardProp: (prop) => prop !== 'disabled',
-})<{ disabled?: boolean }>(({ theme, disabled }) => ({
+const StyledHeader = styled('div')(({ theme }) => ({
display: 'flex',
justifyContent: 'space-between',
- color: disabled ? theme.palette.text.secondary : theme.palette.text.primary,
+ color: theme.palette.text.primary,
}));
const StyledHeaderTitleContainer = styled('div')(({ theme }) => ({
@@ -73,9 +67,13 @@ const StyledConnection = styled('div')(({ theme }) => ({
interface IReleasePlanProps {
plan: IReleasePlan;
+ environmentIsDisabled: boolean;
}
-export const ReleasePlan = ({ plan }: IReleasePlanProps) => {
+export const ReleasePlan = ({
+ plan,
+ environmentIsDisabled,
+}: IReleasePlanProps) => {
const {
id,
name,
@@ -132,14 +130,13 @@ export const ReleasePlan = ({ plan }: IReleasePlanProps) => {
}
};
- const disabled = !activeMilestoneId;
const activeIndex = milestones.findIndex(
(milestone) => milestone.id === activeMilestoneId,
);
return (
-
-
+
+
Release plan
@@ -168,7 +165,9 @@ export const ReleasePlan = ({ plan }: IReleasePlanProps) => {
milestone={milestone}
status={
milestone.id === activeMilestoneId
- ? 'active'
+ ? environmentIsDisabled
+ ? 'paused'
+ : 'active'
: index < activeIndex
? 'completed'
: 'not-started'
diff --git a/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone.tsx b/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestone.tsx
similarity index 55%
rename from frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone.tsx
rename to frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestone.tsx
index 3213ce37f9..4013ee9776 100644
--- a/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone.tsx
+++ b/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestone.tsx
@@ -3,17 +3,16 @@ import {
Accordion,
AccordionDetails,
AccordionSummary,
- Link,
styled,
} from '@mui/material';
-import PlayCircleIcon from '@mui/icons-material/PlayCircle';
-import TripOriginIcon from '@mui/icons-material/TripOrigin';
import type { IReleasePlanMilestone } from 'interfaces/releasePlans';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { ReleasePlanMilestoneStrategy } from './ReleasePlanMilestoneStrategy';
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
-
-type MilestoneStatus = 'not-started' | 'active' | 'completed';
+import {
+ ReleasePlanMilestoneStatus,
+ type MilestoneStatus,
+} from './ReleasePlanMilestoneStatus';
const StyledAccordion = styled(Accordion, {
shouldForwardProp: (prop) => prop !== 'status',
@@ -31,6 +30,7 @@ const StyledAccordionSummary = styled(AccordionSummary)({
'& .MuiAccordionSummary-content': {
justifyContent: 'space-between',
alignItems: 'center',
+ minHeight: '30px',
},
});
@@ -45,33 +45,6 @@ const StyledTitle = styled('span')(({ theme }) => ({
fontWeight: theme.fontWeight.bold,
}));
-const StyledStatus = styled('div', {
- shouldForwardProp: (prop) => prop !== 'status',
-})<{ status: MilestoneStatus }>(({ theme, status }) => ({
- display: 'flex',
- alignItems: 'center',
- gap: theme.spacing(1),
- paddingRight: theme.spacing(1),
- fontSize: theme.fontSizes.smallerBody,
- borderRadius: theme.shape.borderRadiusMedium,
- backgroundColor:
- status === 'active' ? theme.palette.success.light : 'transparent',
- color:
- status === 'active'
- ? theme.palette.success.contrastText
- : status === 'completed'
- ? theme.palette.text.secondary
- : theme.palette.text.primary,
- '& svg': {
- color:
- status === 'active'
- ? theme.palette.success.main
- : status === 'completed'
- ? theme.palette.neutral.border
- : theme.palette.primary.main,
- },
-}));
-
const StyledSecondaryLabel = styled('span')(({ theme }) => ({
color: theme.palette.text.secondary,
fontSize: theme.fontSizes.smallBody,
@@ -94,41 +67,38 @@ export const ReleasePlanMilestone = ({
status,
onStartMilestone,
}: IReleasePlanMilestoneProps) => {
- const statusText =
- status === 'active'
- ? 'Running'
- : status === 'completed'
- ? 'Restart'
- : 'Start';
+ if (!milestone.strategies.length) {
+ return (
+
+
+
+ {milestone.name}
+ onStartMilestone(milestone)}
+ />
+
+ No strategies
+
+
+ );
+ }
return (
}>
{milestone.name}
-
- }
- elseShow={}
- />
- {statusText}}
- elseShow={
- {
- e.stopPropagation();
- onStartMilestone(milestone);
- }}
- >
- {statusText}
-
- }
- />
-
+ onStartMilestone(milestone)}
+ />
- View strategies
+
+ {milestone.strategies.length === 1
+ ? 'View strategy'
+ : `View ${milestone.strategies.length} strategies`}
+
{milestone.strategies.map((strategy, index) => (
diff --git a/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestoneStatus.tsx b/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestoneStatus.tsx
new file mode 100644
index 0000000000..ccfc191258
--- /dev/null
+++ b/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestoneStatus.tsx
@@ -0,0 +1,78 @@
+import { Link, styled } from '@mui/material';
+import PlayCircleIcon from '@mui/icons-material/PlayCircle';
+import PauseCircleIcon from '@mui/icons-material/PauseCircle';
+import TripOriginIcon from '@mui/icons-material/TripOrigin';
+
+export type MilestoneStatus = 'not-started' | 'active' | 'paused' | 'completed';
+
+const StyledStatus = styled('div', {
+ shouldForwardProp: (prop) => prop !== 'status',
+})<{ status: MilestoneStatus }>(({ theme, status }) => ({
+ display: 'flex',
+ alignItems: 'center',
+ gap: theme.spacing(1),
+ paddingRight: theme.spacing(1),
+ fontSize: theme.fontSizes.smallerBody,
+ borderRadius: theme.shape.borderRadiusMedium,
+ backgroundColor:
+ status === 'active' ? theme.palette.success.light : 'transparent',
+ color:
+ status === 'active'
+ ? theme.palette.success.contrastText
+ : status === 'completed'
+ ? theme.palette.text.secondary
+ : theme.palette.text.primary,
+ '& svg': {
+ color:
+ status === 'active'
+ ? theme.palette.success.main
+ : status === 'paused'
+ ? theme.palette.text.disabled
+ : status === 'completed'
+ ? theme.palette.neutral.border
+ : theme.palette.primary.main,
+ },
+}));
+
+interface IReleasePlanMilestoneStatusProps {
+ status: MilestoneStatus;
+ onStartMilestone: () => void;
+}
+
+export const ReleasePlanMilestoneStatus = ({
+ status,
+ onStartMilestone,
+}: IReleasePlanMilestoneStatusProps) => {
+ const statusText =
+ status === 'active'
+ ? 'Running'
+ : status === 'paused'
+ ? 'Paused (disabled in environment)'
+ : status === 'completed'
+ ? 'Restart'
+ : 'Start';
+
+ return (
+
+ {status === 'active' ? (
+
+ ) : status === 'paused' ? (
+
+ ) : (
+
+ )}
+ {status === 'not-started' || status === 'completed' ? (
+ {
+ e.stopPropagation();
+ onStartMilestone();
+ }}
+ >
+ {statusText}
+
+ ) : (
+ {statusText}
+ )}
+
+ );
+};
diff --git a/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestoneStrategy.tsx b/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestoneStrategy.tsx
similarity index 90%
rename from frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestoneStrategy.tsx
rename to frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestoneStrategy.tsx
index 7ce6d6421a..0f421af5ec 100644
--- a/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestoneStrategy.tsx
+++ b/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestoneStrategy.tsx
@@ -1,5 +1,5 @@
import { Box, styled } from '@mui/material';
-import { StrategyExecution } from '../FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/StrategyExecution';
+import { StrategyExecution } from '../../FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/StrategyExecution';
import SplitPreviewSlider from 'component/feature/StrategyTypes/SplitPreviewSlider/SplitPreviewSlider';
import {
formatStrategyName,
diff --git a/frontend/src/component/releases/ReleaseManagement/ReleasePlanTemplateCard.tsx b/frontend/src/component/releases/ReleaseManagement/ReleasePlanTemplateCard.tsx
index a0ab28934c..00a658b5a1 100644
--- a/frontend/src/component/releases/ReleaseManagement/ReleasePlanTemplateCard.tsx
+++ b/frontend/src/component/releases/ReleaseManagement/ReleasePlanTemplateCard.tsx
@@ -3,9 +3,12 @@ import { ReactComponent as ReleaseTemplateIcon } from 'assets/img/releaseTemplat
import { styled, Typography } from '@mui/material';
import { ReleasePlanTemplateCardMenu } from './ReleasePlanTemplateCardMenu';
import { useNavigate } from 'react-router-dom';
+import { UserAvatar } from 'component/common/UserAvatar/UserAvatar';
+import useUserInfo from 'hooks/api/getters/useUserInfo/useUserInfo';
const StyledTemplateCard = styled('aside')(({ theme }) => ({
height: '100%',
+ cursor: 'pointer',
'&:hover': {
transition: 'background-color 0.2s ease-in-out',
backgroundColor: theme.palette.neutral.light,
@@ -45,6 +48,12 @@ const StyledCreatedBy = styled(Typography)(({ theme }) => ({
display: 'flex',
alignItems: 'center',
marginRight: 'auto',
+ gap: theme.spacing(1),
+}));
+
+const StyledCreatedByAvatar = styled(UserAvatar)(({ theme }) => ({
+ width: theme.spacing(3),
+ height: theme.spacing(3),
}));
const StyledMenu = styled('div')(({ theme }) => ({
@@ -63,6 +72,7 @@ export const ReleasePlanTemplateCard = ({
const onClick = () => {
navigate(`/release-management/edit/${template.id}`);
};
+ const { user: createdBy } = useUserInfo(`${template.createdByUserId}`);
return (
@@ -75,7 +85,7 @@ export const ReleasePlanTemplateCard = ({
{template.name}
- Created by {template.createdByUserId}
+ Created by
{
diff --git a/frontend/src/component/releases/ReleasePlanTemplate/CreateReleasePlanTemplate.tsx b/frontend/src/component/releases/ReleasePlanTemplate/CreateReleasePlanTemplate.tsx
index 621bc11630..5b89933805 100644
--- a/frontend/src/component/releases/ReleasePlanTemplate/CreateReleasePlanTemplate.tsx
+++ b/frontend/src/component/releases/ReleasePlanTemplate/CreateReleasePlanTemplate.tsx
@@ -61,7 +61,7 @@ export const CreateReleasePlanTemplate = () => {
type: 'success',
title: 'Release plan template created',
});
- navigate(`/release-management/edit/${template.id}`);
+ navigate('/release-management');
} catch (error: unknown) {
setToastApiError(formatUnknownError(error));
}
diff --git a/frontend/src/component/releases/ReleasePlanTemplate/EditReleasePlanTemplate.tsx b/frontend/src/component/releases/ReleasePlanTemplate/EditReleasePlanTemplate.tsx
index 87113926d7..622fd7961d 100644
--- a/frontend/src/component/releases/ReleasePlanTemplate/EditReleasePlanTemplate.tsx
+++ b/frontend/src/component/releases/ReleasePlanTemplate/EditReleasePlanTemplate.tsx
@@ -68,6 +68,7 @@ export const EditReleasePlanTemplate = () => {
type: 'success',
title: 'Release plan template updated',
});
+ navigate('/release-management');
} catch (error: unknown) {
setToastApiError(formatUnknownError(error));
}