mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-09 01:17:06 +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';
|
import type { FC, ReactNode } from 'react';
|
||||||
|
|
||||||
type StrategyItemProps = {
|
type StrategyItemProps = {
|
||||||
@ -19,6 +20,10 @@ const StyledContent = styled('div')(({ theme }) => ({
|
|||||||
gap: theme.spacing(1),
|
gap: theme.spacing(1),
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
[`.${disabledStrategyClassName} &`]: {
|
||||||
|
filter: 'grayscale(1)',
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledType = styled('span')(({ theme }) => ({
|
const StyledType = styled('span')(({ theme }) => ({
|
||||||
@ -30,17 +35,23 @@ const StyledType = styled('span')(({ theme }) => ({
|
|||||||
width: theme.spacing(10),
|
width: theme.spacing(10),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledValuesGroup = styled('div')(({ theme }) => ({
|
const StyledValuesGroup = styled('ul')(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
flexFlow: 'row wrap',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: theme.spacing(0.5),
|
gap: theme.spacing(0.5),
|
||||||
|
listStyle: 'none',
|
||||||
|
padding: 0,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledValue = styled(({ ...props }: ChipProps) => (
|
const StyledValue = styled('li')(({ theme }) => ({
|
||||||
<Chip size='small' {...props} />
|
[`.${disabledStrategyClassName} &`]: {
|
||||||
))(({ theme }) => ({
|
filter: 'grayscale(1)',
|
||||||
padding: theme.spacing(0.5),
|
color: theme.palette.text.secondary,
|
||||||
background: theme.palette.background.elevation1,
|
},
|
||||||
|
':not(&:last-of-type)::after': {
|
||||||
|
content: '", "',
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,7 +69,9 @@ export const StrategyEvaluationItem: FC<StrategyItemProps> = ({
|
|||||||
{values && values?.length > 0 ? (
|
{values && values?.length > 0 ? (
|
||||||
<StyledValuesGroup>
|
<StyledValuesGroup>
|
||||||
{values?.map((value, index) => (
|
{values?.map((value, index) => (
|
||||||
<StyledValue key={`${value}#${index}`} label={value} />
|
<StyledValue key={`${value}#${index}`}>
|
||||||
|
{value}
|
||||||
|
</StyledValue>
|
||||||
))}
|
))}
|
||||||
</StyledValuesGroup>
|
</StyledValuesGroup>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -8,6 +8,7 @@ import type { PlaygroundStrategySchema } from 'openapi';
|
|||||||
import { Badge } from '../Badge/Badge';
|
import { Badge } from '../Badge/Badge';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Truncator } from '../Truncator/Truncator';
|
import { Truncator } from '../Truncator/Truncator';
|
||||||
|
import { disabledStrategyClassName } from './disabled-strategy-utils';
|
||||||
|
|
||||||
type StrategyItemContainerProps = {
|
type StrategyItemContainerProps = {
|
||||||
strategyHeaderLevel?: 1 | 2 | 3 | 4 | 5 | 6;
|
strategyHeaderLevel?: 1 | 2 | 3 | 4 | 5 | 6;
|
||||||
@ -87,7 +88,10 @@ export const StrategyItemContainer: FC<StrategyItemContainerProps> = ({
|
|||||||
: ({ children }) => <> {children} </>;
|
: ({ children }) => <> {children} </>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ position: 'relative' }}>
|
<Box
|
||||||
|
className={strategy.disabled ? disabledStrategyClassName : ''}
|
||||||
|
sx={{ position: 'relative' }}
|
||||||
|
>
|
||||||
<StyledContainer style={style} className={className}>
|
<StyledContainer style={style} className={className}>
|
||||||
<StyledHeader disabled={Boolean(strategy?.disabled)}>
|
<StyledHeader disabled={Boolean(strategy?.disabled)}>
|
||||||
{onDragStart ? (
|
{onDragStart ? (
|
||||||
@ -136,9 +140,6 @@ export const StrategyItemContainer: FC<StrategyItemContainerProps> = ({
|
|||||||
</StyledHeaderContainer>
|
</StyledHeaderContainer>
|
||||||
</StrategyHeaderLink>
|
</StrategyHeaderLink>
|
||||||
|
|
||||||
{strategy.disabled ? (
|
|
||||||
<Badge color='disabled'>Disabled</Badge>
|
|
||||||
) : null}
|
|
||||||
{headerItemsLeft}
|
{headerItemsLeft}
|
||||||
</StyledHeaderInner>
|
</StyledHeaderInner>
|
||||||
<Box
|
<Box
|
||||||
@ -148,6 +149,9 @@ export const StrategyItemContainer: FC<StrategyItemContainerProps> = ({
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{strategy.disabled ? (
|
||||||
|
<Badge color='warning'>Strategy disabled</Badge>
|
||||||
|
) : null}
|
||||||
{headerItemsRight}
|
{headerItemsRight}
|
||||||
</Box>
|
</Box>
|
||||||
</StyledHeader>
|
</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),
|
left: theme.spacing(4),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const StrategySeparator = () => {
|
export const StrategySeparator = ({ className }: { className?: string }) => {
|
||||||
return <Chip role='separator'>OR</Chip>;
|
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 { ReleasePlan } from '../../../ReleasePlan/ReleasePlan';
|
||||||
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
|
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
|
||||||
import { ProjectEnvironmentStrategyDraggableItem } from './StrategyDraggableItem/ProjectEnvironmentStrategyDraggableItem';
|
import { ProjectEnvironmentStrategyDraggableItem } from './StrategyDraggableItem/ProjectEnvironmentStrategyDraggableItem';
|
||||||
|
import { disabledStrategyClassName } from 'component/common/StrategyItemContainer/disabled-strategy-utils';
|
||||||
|
|
||||||
interface IEnvironmentAccordionBodyProps {
|
interface IEnvironmentAccordionBodyProps {
|
||||||
isDisabled: boolean;
|
isDisabled: boolean;
|
||||||
@ -77,6 +78,13 @@ const StyledAlert = styled(Alert)(({ theme }) => ({
|
|||||||
marginInline: theme.spacing(2), // should consider finding a variable here
|
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 = ({
|
export const EnvironmentAccordionBody = ({
|
||||||
featureEnvironment,
|
featureEnvironment,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
@ -243,7 +251,7 @@ export const EnvironmentAccordionBody = ({
|
|||||||
<StyledContentList>
|
<StyledContentList>
|
||||||
{strategies.map((strategy, index) => (
|
{strategies.map((strategy, index) => (
|
||||||
<StyledListItem key={strategy.id}>
|
<StyledListItem key={strategy.id}>
|
||||||
{index > 0 ? <StrategySeparator /> : null}
|
{index > 0 ? <StyledStrategySeparator /> : null}
|
||||||
|
|
||||||
<ProjectEnvironmentStrategyDraggableItem
|
<ProjectEnvironmentStrategyDraggableItem
|
||||||
strategy={strategy}
|
strategy={strategy}
|
||||||
@ -268,7 +276,7 @@ export const EnvironmentAccordionBody = ({
|
|||||||
<StyledContentList>
|
<StyledContentList>
|
||||||
{page.map((strategy, index) => (
|
{page.map((strategy, index) => (
|
||||||
<StyledListItem key={strategy.id}>
|
<StyledListItem key={strategy.id}>
|
||||||
{index > 0 ? <StrategySeparator /> : null}
|
{index > 0 ? <StyledStrategySeparator /> : null}
|
||||||
|
|
||||||
<ProjectEnvironmentStrategyDraggableItem
|
<ProjectEnvironmentStrategyDraggableItem
|
||||||
strategy={strategy}
|
strategy={strategy}
|
||||||
@ -303,7 +311,7 @@ export const EnvironmentAccordionBody = ({
|
|||||||
))}
|
))}
|
||||||
{strategies.length > 0 ? (
|
{strategies.length > 0 ? (
|
||||||
<li>
|
<li>
|
||||||
<StrategySeparator />
|
<StyledStrategySeparator />
|
||||||
{strategyList}
|
{strategyList}
|
||||||
</li>
|
</li>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -17,6 +17,7 @@ import { UPDATE_FEATURE_STRATEGY } from '@server/types/permissions';
|
|||||||
import { StrategyDraggableItem } from './StrategyDraggableItem';
|
import { StrategyDraggableItem } from './StrategyDraggableItem';
|
||||||
|
|
||||||
type ProjectEnvironmentStrategyDraggableItemProps = {
|
type ProjectEnvironmentStrategyDraggableItemProps = {
|
||||||
|
className?: string;
|
||||||
strategy: IFeatureStrategy;
|
strategy: IFeatureStrategy;
|
||||||
environmentName: string;
|
environmentName: string;
|
||||||
index: number;
|
index: number;
|
||||||
@ -36,6 +37,7 @@ type ProjectEnvironmentStrategyDraggableItemProps = {
|
|||||||
const onDragNoOp = () => () => {};
|
const onDragNoOp = () => () => {};
|
||||||
|
|
||||||
export const ProjectEnvironmentStrategyDraggableItem = ({
|
export const ProjectEnvironmentStrategyDraggableItem = ({
|
||||||
|
className,
|
||||||
strategy,
|
strategy,
|
||||||
index,
|
index,
|
||||||
environmentName,
|
environmentName,
|
||||||
@ -74,6 +76,7 @@ export const ProjectEnvironmentStrategyDraggableItem = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
className={className}
|
||||||
key={strategy.id}
|
key={strategy.id}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
onDragOver={onDragOver(ref, index)}
|
onDragOver={onDragOver(ref, index)}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import { styled } from '@mui/material';
|
|
||||||
import type { FeatureStrategySchema } from 'openapi';
|
import type { FeatureStrategySchema } from 'openapi';
|
||||||
import type { IFeatureStrategyPayload } from 'interfaces/strategy';
|
import type { IFeatureStrategyPayload } from 'interfaces/strategy';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
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 { SegmentItem } from 'component/common/SegmentItem/SegmentItem';
|
||||||
import { ConstraintsList } from 'component/common/ConstraintsList/ConstraintsList';
|
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 = {
|
type StrategyExecutionProps = {
|
||||||
strategy: IFeatureStrategyPayload | FeatureStrategySchema;
|
strategy: IFeatureStrategyPayload | FeatureStrategySchema;
|
||||||
displayGroupId?: boolean;
|
displayGroupId?: boolean;
|
||||||
@ -52,7 +45,6 @@ export const StrategyExecution: FC<StrategyExecutionProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FilterContainer grayscale={strategy.disabled === true}>
|
|
||||||
<ConstraintsList>
|
<ConstraintsList>
|
||||||
{strategySegments?.map((segment) => (
|
{strategySegments?.map((segment) => (
|
||||||
<SegmentItem segment={segment} key={segment.id} />
|
<SegmentItem segment={segment} key={segment.id} />
|
||||||
@ -65,6 +57,5 @@ export const StrategyExecution: FC<StrategyExecutionProps> = ({
|
|||||||
))}
|
))}
|
||||||
{isCustomStrategy ? customStrategyItems : strategyParameters}
|
{isCustomStrategy ? customStrategyItems : strategyParameters}
|
||||||
</ConstraintsList>
|
</ConstraintsList>
|
||||||
</FilterContainer>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user