mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-04 01:18:20 +02:00
chore: finish up disabled strategies (#9579)
Aligns the design of disabled strategies with the sketches. Most notable changes: - makes the disabled badge warning yellow - greys out the preceding "or" separator - makes the segment "preview" button *not* grey (because it's still interactable) As a bonus: uses a list for the constraint value lists instead of a div and updates the design to match the sketches (no chips).  With strat variants:  Bonus fix: Lets the constraint value list wrap so that we avoid this kind of blowout:  Instead: 
This commit is contained in:
parent
f5b26340e7
commit
038c10f612
@ -1,4 +1,5 @@
|
||||
import { Chip, type ChipProps, styled } from '@mui/material';
|
||||
import { styled } from '@mui/material';
|
||||
import { disabledStrategyClassName } from 'component/common/StrategyItemContainer/disabled-strategy-utils';
|
||||
import type { FC, ReactNode } from 'react';
|
||||
|
||||
type StrategyItemProps = {
|
||||
@ -19,6 +20,10 @@ const StyledContent = styled('div')(({ theme }) => ({
|
||||
gap: theme.spacing(1),
|
||||
flexWrap: 'wrap',
|
||||
alignItems: 'center',
|
||||
[`.${disabledStrategyClassName} &`]: {
|
||||
filter: 'grayscale(1)',
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledType = styled('span')(({ theme }) => ({
|
||||
@ -30,17 +35,23 @@ const StyledType = styled('span')(({ theme }) => ({
|
||||
width: theme.spacing(10),
|
||||
}));
|
||||
|
||||
const StyledValuesGroup = styled('div')(({ theme }) => ({
|
||||
const StyledValuesGroup = styled('ul')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexFlow: 'row wrap',
|
||||
alignItems: 'center',
|
||||
gap: theme.spacing(0.5),
|
||||
listStyle: 'none',
|
||||
padding: 0,
|
||||
}));
|
||||
|
||||
const StyledValue = styled(({ ...props }: ChipProps) => (
|
||||
<Chip size='small' {...props} />
|
||||
))(({ theme }) => ({
|
||||
padding: theme.spacing(0.5),
|
||||
background: theme.palette.background.elevation1,
|
||||
const StyledValue = styled('li')(({ theme }) => ({
|
||||
[`.${disabledStrategyClassName} &`]: {
|
||||
filter: 'grayscale(1)',
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
':not(&:last-of-type)::after': {
|
||||
content: '", "',
|
||||
},
|
||||
}));
|
||||
|
||||
/**
|
||||
@ -58,7 +69,9 @@ export const StrategyEvaluationItem: FC<StrategyItemProps> = ({
|
||||
{values && values?.length > 0 ? (
|
||||
<StyledValuesGroup>
|
||||
{values?.map((value, index) => (
|
||||
<StyledValue key={`${value}#${index}`} label={value} />
|
||||
<StyledValue key={`${value}#${index}`}>
|
||||
{value}
|
||||
</StyledValue>
|
||||
))}
|
||||
</StyledValuesGroup>
|
||||
) : null}
|
||||
|
@ -8,6 +8,7 @@ import type { PlaygroundStrategySchema } from 'openapi';
|
||||
import { Badge } from '../Badge/Badge';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Truncator } from '../Truncator/Truncator';
|
||||
import { disabledStrategyClassName } from './disabled-strategy-utils';
|
||||
|
||||
type StrategyItemContainerProps = {
|
||||
strategyHeaderLevel?: 1 | 2 | 3 | 4 | 5 | 6;
|
||||
@ -87,7 +88,10 @@ export const StrategyItemContainer: FC<StrategyItemContainerProps> = ({
|
||||
: ({ children }) => <> {children} </>;
|
||||
|
||||
return (
|
||||
<Box sx={{ position: 'relative' }}>
|
||||
<Box
|
||||
className={strategy.disabled ? disabledStrategyClassName : ''}
|
||||
sx={{ position: 'relative' }}
|
||||
>
|
||||
<StyledContainer style={style} className={className}>
|
||||
<StyledHeader disabled={Boolean(strategy?.disabled)}>
|
||||
{onDragStart ? (
|
||||
@ -136,9 +140,6 @@ export const StrategyItemContainer: FC<StrategyItemContainerProps> = ({
|
||||
</StyledHeaderContainer>
|
||||
</StrategyHeaderLink>
|
||||
|
||||
{strategy.disabled ? (
|
||||
<Badge color='disabled'>Disabled</Badge>
|
||||
) : null}
|
||||
{headerItemsLeft}
|
||||
</StyledHeaderInner>
|
||||
<Box
|
||||
@ -148,6 +149,9 @@ export const StrategyItemContainer: FC<StrategyItemContainerProps> = ({
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{strategy.disabled ? (
|
||||
<Badge color='warning'>Strategy disabled</Badge>
|
||||
) : null}
|
||||
{headerItemsRight}
|
||||
</Box>
|
||||
</StyledHeader>
|
||||
|
@ -0,0 +1,2 @@
|
||||
export const disabledStrategyClassName =
|
||||
'disabled-strategy-55d37c31-ca3f-4c19-bf86-9158824899bf';
|
@ -13,6 +13,10 @@ const Chip = styled('div')(({ theme }) => ({
|
||||
left: theme.spacing(4),
|
||||
}));
|
||||
|
||||
export const StrategySeparator = () => {
|
||||
return <Chip role='separator'>OR</Chip>;
|
||||
export const StrategySeparator = ({ className }: { className?: string }) => {
|
||||
return (
|
||||
<Chip role='separator' className={className}>
|
||||
OR
|
||||
</Chip>
|
||||
);
|
||||
};
|
||||
|
@ -22,6 +22,7 @@ import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePla
|
||||
import { ReleasePlan } from '../../../ReleasePlan/ReleasePlan';
|
||||
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
|
||||
import { ProjectEnvironmentStrategyDraggableItem } from './StrategyDraggableItem/ProjectEnvironmentStrategyDraggableItem';
|
||||
import { disabledStrategyClassName } from 'component/common/StrategyItemContainer/disabled-strategy-utils';
|
||||
|
||||
interface IEnvironmentAccordionBodyProps {
|
||||
isDisabled: boolean;
|
||||
@ -77,6 +78,13 @@ const StyledAlert = styled(Alert)(({ theme }) => ({
|
||||
marginInline: theme.spacing(2), // should consider finding a variable here
|
||||
}));
|
||||
|
||||
const StyledStrategySeparator = styled(StrategySeparator)(({ theme }) => ({
|
||||
[`&:has(+ *:not(ol) .${disabledStrategyClassName}), &:has(+ ol > li:first-of-type .${disabledStrategyClassName})`]:
|
||||
{
|
||||
filter: 'grayscale(1)',
|
||||
},
|
||||
}));
|
||||
|
||||
export const EnvironmentAccordionBody = ({
|
||||
featureEnvironment,
|
||||
isDisabled,
|
||||
@ -243,7 +251,7 @@ export const EnvironmentAccordionBody = ({
|
||||
<StyledContentList>
|
||||
{strategies.map((strategy, index) => (
|
||||
<StyledListItem key={strategy.id}>
|
||||
{index > 0 ? <StrategySeparator /> : null}
|
||||
{index > 0 ? <StyledStrategySeparator /> : null}
|
||||
|
||||
<ProjectEnvironmentStrategyDraggableItem
|
||||
strategy={strategy}
|
||||
@ -268,7 +276,7 @@ export const EnvironmentAccordionBody = ({
|
||||
<StyledContentList>
|
||||
{page.map((strategy, index) => (
|
||||
<StyledListItem key={strategy.id}>
|
||||
{index > 0 ? <StrategySeparator /> : null}
|
||||
{index > 0 ? <StyledStrategySeparator /> : null}
|
||||
|
||||
<ProjectEnvironmentStrategyDraggableItem
|
||||
strategy={strategy}
|
||||
@ -303,7 +311,7 @@ export const EnvironmentAccordionBody = ({
|
||||
))}
|
||||
{strategies.length > 0 ? (
|
||||
<li>
|
||||
<StrategySeparator />
|
||||
<StyledStrategySeparator />
|
||||
{strategyList}
|
||||
</li>
|
||||
) : null}
|
||||
|
@ -17,6 +17,7 @@ import { UPDATE_FEATURE_STRATEGY } from '@server/types/permissions';
|
||||
import { StrategyDraggableItem } from './StrategyDraggableItem';
|
||||
|
||||
type ProjectEnvironmentStrategyDraggableItemProps = {
|
||||
className?: string;
|
||||
strategy: IFeatureStrategy;
|
||||
environmentName: string;
|
||||
index: number;
|
||||
@ -36,6 +37,7 @@ type ProjectEnvironmentStrategyDraggableItemProps = {
|
||||
const onDragNoOp = () => () => {};
|
||||
|
||||
export const ProjectEnvironmentStrategyDraggableItem = ({
|
||||
className,
|
||||
strategy,
|
||||
index,
|
||||
environmentName,
|
||||
@ -74,6 +76,7 @@ export const ProjectEnvironmentStrategyDraggableItem = ({
|
||||
|
||||
return (
|
||||
<Box
|
||||
className={className}
|
||||
key={strategy.id}
|
||||
ref={ref}
|
||||
onDragOver={onDragOver(ref, index)}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import type { FC } from 'react';
|
||||
import { styled } from '@mui/material';
|
||||
import type { FeatureStrategySchema } from 'openapi';
|
||||
import type { IFeatureStrategyPayload } from 'interfaces/strategy';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
@ -13,12 +12,6 @@ import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
|
||||
import { SegmentItem } from 'component/common/SegmentItem/SegmentItem';
|
||||
import { ConstraintsList } from 'component/common/ConstraintsList/ConstraintsList';
|
||||
|
||||
const FilterContainer = styled('div', {
|
||||
shouldForwardProp: (prop) => prop !== 'grayscale',
|
||||
})<{ grayscale: boolean }>(({ grayscale }) =>
|
||||
grayscale ? { filter: 'grayscale(1)', opacity: 0.67 } : {},
|
||||
);
|
||||
|
||||
type StrategyExecutionProps = {
|
||||
strategy: IFeatureStrategyPayload | FeatureStrategySchema;
|
||||
displayGroupId?: boolean;
|
||||
@ -52,19 +45,17 @@ export const StrategyExecution: FC<StrategyExecutionProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<FilterContainer grayscale={strategy.disabled === true}>
|
||||
<ConstraintsList>
|
||||
{strategySegments?.map((segment) => (
|
||||
<SegmentItem segment={segment} key={segment.id} />
|
||||
))}
|
||||
{constraints?.map((constraint, index) => (
|
||||
<ConstraintItem
|
||||
key={`${objectId(constraint)}-${index}`}
|
||||
{...constraint}
|
||||
/>
|
||||
))}
|
||||
{isCustomStrategy ? customStrategyItems : strategyParameters}
|
||||
</ConstraintsList>
|
||||
</FilterContainer>
|
||||
<ConstraintsList>
|
||||
{strategySegments?.map((segment) => (
|
||||
<SegmentItem segment={segment} key={segment.id} />
|
||||
))}
|
||||
{constraints?.map((constraint, index) => (
|
||||
<ConstraintItem
|
||||
key={`${objectId(constraint)}-${index}`}
|
||||
{...constraint}
|
||||
/>
|
||||
))}
|
||||
{isCustomStrategy ? customStrategyItems : strategyParameters}
|
||||
</ConstraintsList>
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user