mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-10 01:16:39 +02:00
Chore(1-3449): release plans in strategy env (#9441)
Use new design for release plans in flag environments. - Move old ReleasePlanMilestone into Legacy file and update imports - In the new version, use the same strategy list and item as in the general strategy list and milestone template creation (components to be extracted in the future) - Fix an issue with the border being obscured by overflow by hiding overflow 
This commit is contained in:
parent
7db692e976
commit
f6987909e7
@ -12,7 +12,7 @@ import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePla
|
|||||||
import { TooltipLink } from 'component/common/TooltipLink/TooltipLink';
|
import { TooltipLink } from 'component/common/TooltipLink/TooltipLink';
|
||||||
import EventDiff from 'component/events/EventDiff/EventDiff';
|
import EventDiff from 'component/events/EventDiff/EventDiff';
|
||||||
import { ReleasePlan } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlan';
|
import { ReleasePlan } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlan';
|
||||||
import { ReleasePlanMilestone } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestone';
|
import { ReleasePlanMilestone } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/LegacyReleasePlanMilestone';
|
||||||
import type { IReleasePlan } from 'interfaces/releasePlans';
|
import type { IReleasePlan } from 'interfaces/releasePlans';
|
||||||
|
|
||||||
export const ChangeItemWrapper = styled(Box)({
|
export const ChangeItemWrapper = styled(Box)({
|
||||||
|
@ -6,7 +6,7 @@ import { Box } from '@mui/material';
|
|||||||
import { StrategyItemContainer as NewStrategyItemContainer } from 'component/common/StrategyItemContainer/StrategyItemContainer';
|
import { StrategyItemContainer as NewStrategyItemContainer } from 'component/common/StrategyItemContainer/StrategyItemContainer';
|
||||||
|
|
||||||
type StrategyItemProps = {
|
type StrategyItemProps = {
|
||||||
headerItemsRight: ReactNode;
|
headerItemsRight?: ReactNode;
|
||||||
strategy: IFeatureStrategy;
|
strategy: IFeatureStrategy;
|
||||||
onDragStart?: DragEventHandler<HTMLButtonElement>;
|
onDragStart?: DragEventHandler<HTMLButtonElement>;
|
||||||
onDragEnd?: DragEventHandler<HTMLButtonElement>;
|
onDragEnd?: DragEventHandler<HTMLButtonElement>;
|
||||||
|
@ -13,7 +13,7 @@ import type {
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
import { ReleasePlanRemoveDialog } from './ReleasePlanRemoveDialog';
|
import { ReleasePlanRemoveDialog } from './ReleasePlanRemoveDialog';
|
||||||
import { ReleasePlanMilestone } from './ReleasePlanMilestone/ReleasePlanMilestone';
|
import { ReleasePlanMilestone } from './ReleasePlanMilestone/LegacyReleasePlanMilestone';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
import { useUiFlag } from 'hooks/useUiFlag';
|
||||||
|
@ -0,0 +1,130 @@
|
|||||||
|
// deprecated; remove with `flagOverviewRedesign` flag
|
||||||
|
import ExpandMore from '@mui/icons-material/ExpandMore';
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionDetails,
|
||||||
|
AccordionSummary,
|
||||||
|
styled,
|
||||||
|
} from '@mui/material';
|
||||||
|
import type { IReleasePlanMilestone } from 'interfaces/releasePlans';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { ReleasePlanMilestoneStrategy } from './ReleasePlanMilestoneStrategy';
|
||||||
|
import { StrategySeparator } from 'component/common/StrategySeparator/LegacyStrategySeparator';
|
||||||
|
import {
|
||||||
|
ReleasePlanMilestoneStatus,
|
||||||
|
type MilestoneStatus,
|
||||||
|
} from './ReleasePlanMilestoneStatus';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
const StyledAccordion = styled(Accordion, {
|
||||||
|
shouldForwardProp: (prop) => prop !== 'status',
|
||||||
|
})<{ status: MilestoneStatus }>(({ theme, status }) => ({
|
||||||
|
border: `1px solid ${status === 'active' ? theme.palette.success.border : theme.palette.divider}`,
|
||||||
|
boxShadow: 'none',
|
||||||
|
margin: 0,
|
||||||
|
backgroundColor: theme.palette.background.paper,
|
||||||
|
'&:before': {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledAccordionSummary = styled(AccordionSummary)({
|
||||||
|
'& .MuiAccordionSummary-content': {
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
minHeight: '30px',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const StyledTitleContainer = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'start',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: theme.spacing(0.5),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledTitle = styled('span')(({ theme }) => ({
|
||||||
|
fontWeight: theme.fontWeight.bold,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledSecondaryLabel = styled('span')(({ theme }) => ({
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
fontSize: theme.fontSizes.smallBody,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledAccordionDetails = styled(AccordionDetails)(({ theme }) => ({
|
||||||
|
borderBottomLeftRadius: theme.shape.borderRadiusLarge,
|
||||||
|
borderBottomRightRadius: theme.shape.borderRadiusLarge,
|
||||||
|
}));
|
||||||
|
|
||||||
|
interface IReleasePlanMilestoneProps {
|
||||||
|
milestone: IReleasePlanMilestone;
|
||||||
|
status?: MilestoneStatus;
|
||||||
|
onStartMilestone?: (milestone: IReleasePlanMilestone) => void;
|
||||||
|
readonly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ReleasePlanMilestone = ({
|
||||||
|
milestone,
|
||||||
|
status = 'not-started',
|
||||||
|
onStartMilestone,
|
||||||
|
readonly,
|
||||||
|
}: IReleasePlanMilestoneProps) => {
|
||||||
|
const [expanded, setExpanded] = useState(false);
|
||||||
|
|
||||||
|
if (!milestone.strategies.length) {
|
||||||
|
return (
|
||||||
|
<StyledAccordion status={status}>
|
||||||
|
<StyledAccordionSummary>
|
||||||
|
<StyledTitleContainer>
|
||||||
|
<StyledTitle>{milestone.name}</StyledTitle>
|
||||||
|
{!readonly && onStartMilestone && (
|
||||||
|
<ReleasePlanMilestoneStatus
|
||||||
|
status={status}
|
||||||
|
onStartMilestone={() =>
|
||||||
|
onStartMilestone(milestone)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</StyledTitleContainer>
|
||||||
|
<StyledSecondaryLabel>No strategies</StyledSecondaryLabel>
|
||||||
|
</StyledAccordionSummary>
|
||||||
|
</StyledAccordion>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledAccordion
|
||||||
|
status={status}
|
||||||
|
onChange={(evt, expanded) => setExpanded(expanded)}
|
||||||
|
>
|
||||||
|
<StyledAccordionSummary expandIcon={<ExpandMore />}>
|
||||||
|
<StyledTitleContainer>
|
||||||
|
<StyledTitle>{milestone.name}</StyledTitle>
|
||||||
|
{!readonly && onStartMilestone && (
|
||||||
|
<ReleasePlanMilestoneStatus
|
||||||
|
status={status}
|
||||||
|
onStartMilestone={() => onStartMilestone(milestone)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</StyledTitleContainer>
|
||||||
|
<StyledSecondaryLabel>
|
||||||
|
{milestone.strategies.length === 1
|
||||||
|
? `${expanded ? 'Hide' : 'View'} strategy`
|
||||||
|
: `${expanded ? 'Hide' : 'View'} ${milestone.strategies.length} strategies`}
|
||||||
|
</StyledSecondaryLabel>
|
||||||
|
</StyledAccordionSummary>
|
||||||
|
<StyledAccordionDetails>
|
||||||
|
{milestone.strategies.map((strategy, index) => (
|
||||||
|
<div key={strategy.id}>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={index > 0}
|
||||||
|
show={<StrategySeparator text='OR' />}
|
||||||
|
/>
|
||||||
|
<ReleasePlanMilestoneStrategy strategy={strategy} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</StyledAccordionDetails>
|
||||||
|
</StyledAccordion>
|
||||||
|
);
|
||||||
|
};
|
@ -6,19 +6,23 @@ import {
|
|||||||
styled,
|
styled,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import type { IReleasePlanMilestone } from 'interfaces/releasePlans';
|
import type { IReleasePlanMilestone } from 'interfaces/releasePlans';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import { ReleasePlanMilestoneStrategy } from './ReleasePlanMilestoneStrategy';
|
|
||||||
import { StrategySeparator } from 'component/common/StrategySeparator/LegacyStrategySeparator';
|
|
||||||
import {
|
import {
|
||||||
ReleasePlanMilestoneStatus,
|
ReleasePlanMilestoneStatus,
|
||||||
type MilestoneStatus,
|
type MilestoneStatus,
|
||||||
} from './ReleasePlanMilestoneStatus';
|
} from './ReleasePlanMilestoneStatus';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import {
|
||||||
|
StyledContentList,
|
||||||
|
StyledListItem,
|
||||||
|
} from '../../FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/EnvironmentAccordionBody';
|
||||||
|
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
|
||||||
|
import { StrategyItem } from '../../FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyItem';
|
||||||
|
|
||||||
const StyledAccordion = styled(Accordion, {
|
const StyledAccordion = styled(Accordion, {
|
||||||
shouldForwardProp: (prop) => prop !== 'status',
|
shouldForwardProp: (prop) => prop !== 'status',
|
||||||
})<{ status: MilestoneStatus }>(({ theme, status }) => ({
|
})<{ status: MilestoneStatus }>(({ theme, status }) => ({
|
||||||
border: `1px solid ${status === 'active' ? theme.palette.success.border : theme.palette.divider}`,
|
border: `1px solid ${status === 'active' ? theme.palette.success.border : theme.palette.divider}`,
|
||||||
|
overflow: 'hidden',
|
||||||
boxShadow: 'none',
|
boxShadow: 'none',
|
||||||
margin: 0,
|
margin: 0,
|
||||||
backgroundColor: theme.palette.background.paper,
|
backgroundColor: theme.palette.background.paper,
|
||||||
@ -52,8 +56,7 @@ const StyledSecondaryLabel = styled('span')(({ theme }) => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledAccordionDetails = styled(AccordionDetails)(({ theme }) => ({
|
const StyledAccordionDetails = styled(AccordionDetails)(({ theme }) => ({
|
||||||
borderBottomLeftRadius: theme.shape.borderRadiusLarge,
|
padding: 0,
|
||||||
borderBottomRightRadius: theme.shape.borderRadiusLarge,
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
interface IReleasePlanMilestoneProps {
|
interface IReleasePlanMilestoneProps {
|
||||||
@ -114,15 +117,23 @@ export const ReleasePlanMilestone = ({
|
|||||||
</StyledSecondaryLabel>
|
</StyledSecondaryLabel>
|
||||||
</StyledAccordionSummary>
|
</StyledAccordionSummary>
|
||||||
<StyledAccordionDetails>
|
<StyledAccordionDetails>
|
||||||
{milestone.strategies.map((strategy, index) => (
|
<StyledContentList>
|
||||||
<div key={strategy.id}>
|
{milestone.strategies.map((strategy, index) => (
|
||||||
<ConditionallyRender
|
<StyledListItem key={strategy.id}>
|
||||||
condition={index > 0}
|
{index > 0 ? <StrategySeparator /> : null}
|
||||||
show={<StrategySeparator text='OR' />}
|
|
||||||
/>
|
<StrategyItem
|
||||||
<ReleasePlanMilestoneStrategy strategy={strategy} />
|
strategy={{
|
||||||
</div>
|
...strategy,
|
||||||
))}
|
name:
|
||||||
|
strategy.name ||
|
||||||
|
strategy.strategyName ||
|
||||||
|
'',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</StyledListItem>
|
||||||
|
))}
|
||||||
|
</StyledContentList>
|
||||||
</StyledAccordionDetails>
|
</StyledAccordionDetails>
|
||||||
</StyledAccordion>
|
</StyledAccordion>
|
||||||
);
|
);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// deprecated; remove with `flagOverviewRedesign` flag
|
||||||
import { Box, styled } from '@mui/material';
|
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 SplitPreviewSlider from 'component/feature/StrategyTypes/SplitPreviewSlider/SplitPreviewSlider';
|
||||||
|
@ -38,6 +38,22 @@ export const MilestoneList = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dragIndex !== dropIndex) {
|
if (dragIndex !== dropIndex) {
|
||||||
|
// todo! See if there's a way to make this snippet to stabilize dragging before removing flag `flagOverviewRedesign`
|
||||||
|
// We don't have a reference to `ref` or `event` here, but maybe we can make it work? Somehow?
|
||||||
|
|
||||||
|
// const { top, bottom } = ref.current.getBoundingClientRect();
|
||||||
|
// const overTargetTop = event.clientY - top < dragItem.height;
|
||||||
|
// const overTargetBottom =
|
||||||
|
// bottom - event.clientY < dragItem.height;
|
||||||
|
// const draggingUp = dragItem.index > targetIndex;
|
||||||
|
|
||||||
|
// // prevent oscillating by only reordering if there is sufficient space
|
||||||
|
// if (
|
||||||
|
// (overTargetTop && draggingUp) ||
|
||||||
|
// (overTargetBottom && !draggingUp)
|
||||||
|
// ) {
|
||||||
|
// // reorder here
|
||||||
|
// }
|
||||||
const oldMilestones = milestones || [];
|
const oldMilestones = milestones || [];
|
||||||
const newMilestones = [...oldMilestones];
|
const newMilestones = [...oldMilestones];
|
||||||
const movedMilestone = newMilestones.splice(dragIndex, 1)[0];
|
const movedMilestone = newMilestones.splice(dragIndex, 1)[0];
|
||||||
|
Loading…
Reference in New Issue
Block a user