Skip to content

Commit 732b7f3

Browse files
chore: Playground Strategy Lists (#9510)
Continue the implementation of Playground strategy lists. This PR also adjusts some existing strategy container and list items to accomodate more use cases (such as this). The playground strategy execution component is still the old design. After (playground results): ![image](https://github.com/user-attachments/assets/f32505ba-f040-4491-a298-6e8bf606536d) After (env strategy list): ![image](https://github.com/user-attachments/assets/b39174c7-3ee2-4fb4-aa7c-b51134c740b8) Before (env strategy list): ![image](https://github.com/user-attachments/assets/a0a045e5-3623-44ef-96fa-8ba2f5be6b98)
1 parent 4ddb8fe commit 732b7f3

File tree

10 files changed

+493
-200
lines changed

10 files changed

+493
-200
lines changed

frontend/src/component/common/StrategyItemContainer/StrategyItemContainer.tsx

+78-71
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import DragIndicator from '@mui/icons-material/DragIndicator';
44
import { Box, IconButton, Typography, styled } from '@mui/material';
55
import type { IFeatureStrategy } from 'interfaces/strategy';
66
import { formatStrategyName } from 'utils/strategyNames';
7-
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
87
import type { PlaygroundStrategySchema } from 'openapi';
98
import { Badge } from '../Badge/Badge';
109
import { Link } from 'react-router-dom';
@@ -16,16 +15,20 @@ type StrategyItemContainerProps = {
1615
onDragStart?: DragEventHandler<HTMLButtonElement>;
1716
onDragEnd?: DragEventHandler<HTMLButtonElement>;
1817
headerItemsRight?: ReactNode;
18+
headerItemsLeft?: ReactNode;
1919
className?: string;
2020
style?: React.CSSProperties;
2121
children?: React.ReactNode;
2222
};
2323

24-
const DragIcon = styled(IconButton)({
24+
const inlinePadding = 3;
25+
26+
const DragIcon = styled(IconButton)(({ theme }) => ({
27+
marginLeft: theme.spacing(-inlinePadding),
2528
padding: 0,
2629
cursor: 'inherit',
2730
transition: 'color 0.2s ease-in-out',
28-
});
31+
}));
2932

3033
const StyledHeaderContainer = styled('hgroup')(({ theme }) => ({
3134
display: 'flex',
@@ -38,9 +41,14 @@ const StyledHeaderContainer = styled('hgroup')(({ theme }) => ({
3841
},
3942
}));
4043

41-
const StyledContainer = styled('article')({
44+
const StyledContainer = styled('article')(({ theme }) => ({
4245
background: 'inherit',
43-
});
46+
padding: theme.spacing(inlinePadding),
47+
paddingTop: theme.spacing(0.5),
48+
display: 'flex',
49+
flexDirection: 'column',
50+
rowGap: theme.spacing(0.5),
51+
}));
4452

4553
const StyledTruncator = styled(Truncator)(({ theme }) => ({
4654
fontSize: theme.typography.body1.fontSize,
@@ -49,102 +57,101 @@ const StyledTruncator = styled(Truncator)(({ theme }) => ({
4957
}));
5058

5159
const StyledHeader = styled('div', {
52-
shouldForwardProp: (prop) => prop !== 'draggable' && prop !== 'disabled',
53-
})<{ draggable: boolean; disabled: boolean }>(
54-
({ theme, draggable, disabled }) => ({
55-
padding: theme.spacing(0.5, 2),
56-
display: 'flex',
57-
gap: theme.spacing(1),
58-
alignItems: 'center',
59-
paddingLeft: draggable ? theme.spacing(1) : theme.spacing(2),
60-
color: disabled
61-
? theme.palette.text.secondary
62-
: theme.palette.text.primary,
63-
}),
64-
);
60+
shouldForwardProp: (prop) => prop !== 'disabled',
61+
})<{ disabled: boolean }>(({ theme, disabled }) => ({
62+
display: 'flex',
63+
alignItems: 'center',
64+
color: disabled ? theme.palette.text.secondary : theme.palette.text.primary,
65+
}));
66+
67+
const StyledHeaderInner = styled('div')(({ theme }) => ({
68+
display: 'flex',
69+
alignItems: 'center',
70+
gap: theme.spacing(1),
71+
}));
6572

6673
export const StrategyItemContainer: FC<StrategyItemContainerProps> = ({
6774
strategy,
6875
onDragStart,
6976
onDragEnd,
7077
headerItemsRight,
78+
headerItemsLeft,
7179
strategyHeaderLevel = 3,
7280
children,
7381
style = {},
82+
className,
7483
}) => {
7584
const StrategyHeaderLink: React.FC<{ children?: React.ReactNode }> =
76-
'links' in strategy // todo: revisit this when we get to playground, related to flag `flagOverviewRedesign`
85+
'links' in strategy
7786
? ({ children }) => <Link to={strategy.links.edit}>{children}</Link>
7887
: ({ children }) => <> {children} </>;
7988

8089
return (
8190
<Box sx={{ position: 'relative' }}>
82-
<StyledContainer style={style}>
83-
<StyledHeader
84-
draggable={Boolean(onDragStart)}
85-
disabled={Boolean(strategy?.disabled)}
86-
>
87-
<ConditionallyRender
88-
condition={Boolean(onDragStart)}
89-
show={() => (
90-
<DragIcon
91-
draggable
92-
disableRipple
93-
size='small'
94-
onDragStart={onDragStart}
95-
onDragEnd={onDragEnd}
96-
sx={{ cursor: 'move' }}
97-
>
98-
<DragIndicator
99-
titleAccess='Drag to reorder'
100-
cursor='grab'
101-
sx={{ color: 'action.active' }}
102-
/>
103-
</DragIcon>
104-
)}
105-
/>
106-
<StrategyHeaderLink>
107-
<StyledHeaderContainer>
108-
{strategy.title ? (
109-
<>
110-
<p className='strategy-name'>
91+
<StyledContainer style={style} className={className}>
92+
<StyledHeader disabled={Boolean(strategy?.disabled)}>
93+
{onDragStart ? (
94+
<DragIcon
95+
draggable
96+
disableRipple
97+
size='small'
98+
onDragStart={onDragStart}
99+
onDragEnd={onDragEnd}
100+
sx={{ cursor: 'move' }}
101+
>
102+
<DragIndicator
103+
titleAccess='Drag to reorder'
104+
cursor='grab'
105+
sx={{ color: 'action.active' }}
106+
/>
107+
</DragIcon>
108+
) : null}
109+
<StyledHeaderInner>
110+
<StrategyHeaderLink>
111+
<StyledHeaderContainer>
112+
{strategy.title ? (
113+
<>
114+
<p className='strategy-name'>
115+
{formatStrategyName(
116+
String(strategy.name),
117+
)}
118+
:
119+
</p>
120+
<StyledTruncator
121+
component={`h${strategyHeaderLevel}`}
122+
>
123+
{strategy.title}
124+
</StyledTruncator>
125+
</>
126+
) : (
127+
<Typography
128+
className='strategy-name'
129+
component={`h${strategyHeaderLevel}`}
130+
>
111131
{formatStrategyName(
112132
String(strategy.name),
113133
)}
114-
:
115-
</p>
116-
<StyledTruncator
117-
component={`h${strategyHeaderLevel}`}
118-
>
119-
{strategy.title}
120-
</StyledTruncator>
121-
</>
122-
) : (
123-
<Typography
124-
className='strategy-name'
125-
component={`h${strategyHeaderLevel}`}
126-
>
127-
{formatStrategyName(String(strategy.name))}
128-
</Typography>
129-
)}
130-
</StyledHeaderContainer>
131-
</StrategyHeaderLink>
134+
</Typography>
135+
)}
136+
</StyledHeaderContainer>
137+
</StrategyHeaderLink>
132138

133-
{strategy.disabled ? (
134-
<Badge color='disabled'>Disabled</Badge>
135-
) : null}
139+
{strategy.disabled ? (
140+
<Badge color='disabled'>Disabled</Badge>
141+
) : null}
142+
{headerItemsLeft}
143+
</StyledHeaderInner>
136144
<Box
137145
sx={{
138146
marginLeft: 'auto',
139147
display: 'flex',
140-
minHeight: (theme) => theme.spacing(6),
141148
alignItems: 'center',
142149
}}
143150
>
144151
{headerItemsRight}
145152
</Box>
146153
</StyledHeader>
147-
<Box sx={{ p: 2, pt: 0 }}>{children}</Box>
154+
<Box>{children}</Box>
148155
</StyledContainer>
149156
</Box>
150157
);

frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/EnvironmentAccordionBody.tsx

+28-33
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ interface IEnvironmentAccordionBodyProps {
3030
}
3131

3232
const StyledAccordionBodyInnerContainer = styled('div')(({ theme }) => ({
33-
[theme.breakpoints.down(400)]: {
34-
padding: theme.spacing(1),
35-
},
33+
borderBottom: `1px solid ${theme.palette.divider}`,
3634
}));
3735

3836
export const StyledContentList = styled('ol')(({ theme }) => ({
@@ -44,6 +42,9 @@ export const StyledContentList = styled('ol')(({ theme }) => ({
4442
paddingBlock: theme.spacing(2.5),
4543
position: 'relative',
4644
},
45+
'& > li + li': {
46+
borderTop: `1px solid ${theme.palette.divider}`,
47+
},
4748
'&:not(li > &) > li:first-of-type': {
4849
// select first list elements in lists that are not directly nested
4950
// within other lists.
@@ -58,7 +59,6 @@ export const StyledContentList = styled('ol')(({ theme }) => ({
5859
export const StyledListItem = styled('li', {
5960
shouldForwardProp: (prop) => prop !== 'type',
6061
})<{ type?: 'release plan' | 'strategy' }>(({ theme, type }) => ({
61-
borderBottom: `1px solid ${theme.palette.divider}`,
6262
background:
6363
type === 'release plan'
6464
? theme.palette.background.elevation2
@@ -290,34 +290,29 @@ export const EnvironmentAccordionBody = ({
290290
};
291291

292292
return (
293-
<div>
294-
<StyledAccordionBodyInnerContainer>
295-
<StyledContentList>
296-
{releasePlans.length > 0 ? (
297-
<>
298-
{releasePlans.map((plan) => (
299-
<StyledListItem
300-
type='release plan'
301-
key={plan.id}
302-
>
303-
<ReleasePlan
304-
plan={plan}
305-
environmentIsDisabled={isDisabled}
306-
/>
307-
</StyledListItem>
308-
))}
309-
{strategies.length > 0 ? (
310-
<li>
311-
<StrategySeparator />
312-
<Strategies />
313-
</li>
314-
) : null}
315-
</>
316-
) : strategies.length > 0 ? (
317-
<Strategies />
318-
) : null}
319-
</StyledContentList>
320-
</StyledAccordionBodyInnerContainer>
321-
</div>
293+
<StyledAccordionBodyInnerContainer>
294+
<StyledContentList>
295+
{releasePlans.length > 0 ? (
296+
<>
297+
{releasePlans.map((plan) => (
298+
<StyledListItem type='release plan' key={plan.id}>
299+
<ReleasePlan
300+
plan={plan}
301+
environmentIsDisabled={isDisabled}
302+
/>
303+
</StyledListItem>
304+
))}
305+
{strategies.length > 0 ? (
306+
<li>
307+
<StrategySeparator />
308+
<Strategies />
309+
</li>
310+
) : null}
311+
</>
312+
) : strategies.length > 0 ? (
313+
<Strategies />
314+
) : null}
315+
</StyledContentList>
316+
</StyledAccordionBodyInnerContainer>
322317
);
323318
};

0 commit comments

Comments
 (0)