1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-08-04 13:48:56 +02:00

fix: grey out text and icons for disabled strategies in playground (#5113)

What it says on the tin

Closes #
[1-1512](https://linear.app/unleash/issue/1-1512/grey-out-everything-icons-labels-etc-when-strategy-is-disabled)
<img width="689" alt="Screenshot 2023-10-20 at 12 25 51"
src="https://github.com/Unleash/unleash/assets/104830839/3192a125-0e2a-46f2-a266-e4d6c171bdad">
<img width="711" alt="Screenshot 2023-10-20 at 14 52 30"
src="https://github.com/Unleash/unleash/assets/104830839/15040439-c059-4725-9518-82e363fd7230">

---------

Signed-off-by: andreas-unleash <andreas@getunleash.ai>
This commit is contained in:
andreas-unleash 2023-10-23 15:12:15 +03:00 committed by GitHub
parent 03faffa1d6
commit 69d050a70f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 213 additions and 36 deletions

View File

@ -23,6 +23,7 @@ interface IConstraintAccordionViewProps {
onEdit?: () => void; onEdit?: () => void;
sx?: SxProps<Theme>; sx?: SxProps<Theme>;
compact?: boolean; compact?: boolean;
disabled?: boolean;
renderAfter?: JSX.Element; renderAfter?: JSX.Element;
} }
@ -68,6 +69,7 @@ export const ConstraintAccordionView = ({
onDelete, onDelete,
sx = undefined, sx = undefined,
compact = false, compact = false,
disabled = false,
renderAfter, renderAfter,
}: IConstraintAccordionViewProps) => { }: IConstraintAccordionViewProps) => {
const [expandable, setExpandable] = useState(true); const [expandable, setExpandable] = useState(true);
@ -102,6 +104,7 @@ export const ConstraintAccordionView = ({
onDelete={onDelete} onDelete={onDelete}
singleValue={singleValue} singleValue={singleValue}
allowExpand={setExpandable} allowExpand={setExpandable}
disabled={disabled}
expanded={expanded} expanded={expanded}
compact={compact} compact={compact}
/> />

View File

@ -13,6 +13,7 @@ interface IConstraintAccordionViewHeaderProps {
expanded: boolean; expanded: boolean;
allowExpand: (shouldExpand: boolean) => void; allowExpand: (shouldExpand: boolean) => void;
compact?: boolean; compact?: boolean;
disabled?: boolean;
} }
const StyledContainer = styled('div')(({ theme }) => ({ const StyledContainer = styled('div')(({ theme }) => ({
@ -34,6 +35,7 @@ export const ConstraintAccordionViewHeader = ({
allowExpand, allowExpand,
expanded, expanded,
compact, compact,
disabled,
}: IConstraintAccordionViewHeaderProps) => { }: IConstraintAccordionViewHeaderProps) => {
const { context } = useUnleashContext(); const { context } = useUnleashContext();
const { contextName } = constraint; const { contextName } = constraint;
@ -44,12 +46,13 @@ export const ConstraintAccordionViewHeader = ({
return ( return (
<StyledContainer> <StyledContainer>
<ConstraintIcon compact={compact} /> <ConstraintIcon compact={compact} disabled={disabled} />
<ConstraintAccordionViewHeaderInfo <ConstraintAccordionViewHeaderInfo
constraint={constraint} constraint={constraint}
singleValue={singleValue} singleValue={singleValue}
allowExpand={allowExpand} allowExpand={allowExpand}
expanded={expanded} expanded={expanded}
disabled={disabled}
/> />
<ConstraintAccordionHeaderActions <ConstraintAccordionHeaderActions
onEdit={onEdit} onEdit={onEdit}

View File

@ -50,6 +50,7 @@ interface ConstraintAccordionViewHeaderMetaInfoProps {
singleValue: boolean; singleValue: boolean;
expanded: boolean; expanded: boolean;
allowExpand: (shouldExpand: boolean) => void; allowExpand: (shouldExpand: boolean) => void;
disabled?: boolean;
maxLength?: number; maxLength?: number;
} }
@ -58,23 +59,34 @@ export const ConstraintAccordionViewHeaderInfo = ({
singleValue, singleValue,
allowExpand, allowExpand,
expanded, expanded,
disabled = false,
maxLength = 112, //The max number of characters in the values text for NOT allowing expansion maxLength = 112, //The max number of characters in the values text for NOT allowing expansion
}: ConstraintAccordionViewHeaderMetaInfoProps) => { }: ConstraintAccordionViewHeaderMetaInfoProps) => {
return ( return (
<StyledHeaderWrapper> <StyledHeaderWrapper>
<StyledHeaderMetaInfo> <StyledHeaderMetaInfo>
<Tooltip title={constraint.contextName} arrow> <Tooltip title={constraint.contextName} arrow>
<StyledHeaderText> <StyledHeaderText
sx={(theme) => ({
color: disabled
? theme.palette.text.secondary
: 'inherit',
})}
>
{constraint.contextName} {constraint.contextName}
</StyledHeaderText> </StyledHeaderText>
</Tooltip> </Tooltip>
<ConstraintViewHeaderOperator constraint={constraint} /> <ConstraintViewHeaderOperator
constraint={constraint}
disabled={disabled}
/>
<ConditionallyRender <ConditionallyRender
condition={singleValue} condition={singleValue}
show={ show={
<ConstraintAccordionViewHeaderSingleValue <ConstraintAccordionViewHeaderSingleValue
constraint={constraint} constraint={constraint}
allowExpand={allowExpand} allowExpand={allowExpand}
disabled={disabled}
/> />
} }
elseShow={ elseShow={
@ -83,6 +95,7 @@ export const ConstraintAccordionViewHeaderInfo = ({
expanded={expanded} expanded={expanded}
allowExpand={allowExpand} allowExpand={allowExpand}
maxLength={maxLength} maxLength={maxLength}
disabled={disabled}
/> />
} }
/> />

View File

@ -22,6 +22,7 @@ interface ConstraintSingleValueProps {
expanded: boolean; expanded: boolean;
maxLength: number; maxLength: number;
allowExpand: (shouldExpand: boolean) => void; allowExpand: (shouldExpand: boolean) => void;
disabled?: boolean;
} }
const StyledHeaderValuesContainerWrapper = styled('div')(({ theme }) => ({ const StyledHeaderValuesContainerWrapper = styled('div')(({ theme }) => ({
@ -55,6 +56,7 @@ export const ConstraintAccordionViewHeaderMultipleValues = ({
expanded, expanded,
allowExpand, allowExpand,
maxLength, maxLength,
disabled = false,
}: ConstraintSingleValueProps) => { }: ConstraintSingleValueProps) => {
const [expandable, setExpandable] = useState(false); const [expandable, setExpandable] = useState(false);
@ -72,7 +74,15 @@ export const ConstraintAccordionViewHeaderMultipleValues = ({
return ( return (
<StyledHeaderValuesContainerWrapper> <StyledHeaderValuesContainerWrapper>
<StyledHeaderValuesContainer> <StyledHeaderValuesContainer>
<StyledValuesSpan>{text}</StyledValuesSpan> <StyledValuesSpan
sx={(theme) => ({
color: disabled
? theme.palette.text.secondary
: 'inherit',
})}
>
{text}
</StyledValuesSpan>
<ConditionallyRender <ConditionallyRender
condition={expandable} condition={expandable}
show={ show={

View File

@ -15,6 +15,7 @@ const StyledSingleValueChip = styled(Chip)(({ theme }) => ({
interface ConstraintSingleValueProps { interface ConstraintSingleValueProps {
constraint: IConstraint; constraint: IConstraint;
allowExpand: (shouldExpand: boolean) => void; allowExpand: (shouldExpand: boolean) => void;
disabled?: boolean;
} }
const StyledHeaderValuesContainerWrapper = styled('div')(({ theme }) => ({ const StyledHeaderValuesContainerWrapper = styled('div')(({ theme }) => ({
@ -26,6 +27,7 @@ const StyledHeaderValuesContainerWrapper = styled('div')(({ theme }) => ({
export const ConstraintAccordionViewHeaderSingleValue = ({ export const ConstraintAccordionViewHeaderSingleValue = ({
constraint, constraint,
allowExpand, allowExpand,
disabled = false,
}: ConstraintSingleValueProps) => { }: ConstraintSingleValueProps) => {
const { locationSettings } = useLocationSettings(); const { locationSettings } = useLocationSettings();
@ -36,6 +38,9 @@ export const ConstraintAccordionViewHeaderSingleValue = ({
return ( return (
<StyledHeaderValuesContainerWrapper> <StyledHeaderValuesContainerWrapper>
<StyledSingleValueChip <StyledSingleValueChip
sx={(theme) => ({
color: disabled ? theme.palette.text.secondary : 'inherit',
})}
label={formatConstraintValue(constraint, locationSettings)} label={formatConstraintValue(constraint, locationSettings)}
/> />
</StyledHeaderValuesContainerWrapper> </StyledHeaderValuesContainerWrapper>

View File

@ -10,6 +10,7 @@ import { oneOf } from 'utils/oneOf';
interface ConstraintViewHeaderOperatorProps { interface ConstraintViewHeaderOperatorProps {
constraint: IConstraint; constraint: IConstraint;
disabled?: boolean;
} }
const StyledHeaderValuesContainerWrapper = styled('div')(({ theme }) => ({ const StyledHeaderValuesContainerWrapper = styled('div')(({ theme }) => ({
@ -28,6 +29,7 @@ const StyledHeaderConstraintContainer = styled('div')(({ theme }) => ({
export const ConstraintViewHeaderOperator = ({ export const ConstraintViewHeaderOperator = ({
constraint, constraint,
disabled = false,
}: ConstraintViewHeaderOperatorProps) => { }: ConstraintViewHeaderOperatorProps) => {
return ( return (
<StyledHeaderValuesContainerWrapper> <StyledHeaderValuesContainerWrapper>
@ -47,6 +49,7 @@ export const ConstraintViewHeaderOperator = ({
<ConstraintOperator <ConstraintOperator
constraint={constraint} constraint={constraint}
hasPrefix={Boolean(constraint.inverted)} hasPrefix={Boolean(constraint.inverted)}
disabled={disabled}
/> />
</StyledHeaderConstraintContainer> </StyledHeaderConstraintContainer>
<ConditionallyRender <ConditionallyRender

View File

@ -4,18 +4,24 @@ import { TrackChanges } from '@mui/icons-material';
interface IConstraintIconProps { interface IConstraintIconProps {
compact?: boolean; compact?: boolean;
disabled?: boolean;
} }
export const ConstraintIcon: VFC<IConstraintIconProps> = ({ compact }) => ( export const ConstraintIcon: VFC<IConstraintIconProps> = ({
compact,
disabled,
}) => (
<Box <Box
sx={{ sx={(theme) => ({
backgroundColor: 'primary.light', backgroundColor: disabled
? theme.palette.neutral.border
: 'primary.light',
p: compact ? '1px' : '2px', p: compact ? '1px' : '2px',
borderRadius: '50%', borderRadius: '50%',
width: compact ? '18px' : '24px', width: compact ? '18px' : '24px',
height: compact ? '18px' : '24px', height: compact ? '18px' : '24px',
marginRight: '13px', marginRight: '13px',
}} })}
> >
<TrackChanges <TrackChanges
sx={(theme) => ({ sx={(theme) => ({

View File

@ -6,6 +6,7 @@ import { styled } from '@mui/material';
interface IConstraintOperatorProps { interface IConstraintOperatorProps {
constraint: IConstraint; constraint: IConstraint;
hasPrefix?: boolean; hasPrefix?: boolean;
disabled?: boolean;
} }
const StyledContainer = styled('div')(({ theme }) => ({ const StyledContainer = styled('div')(({ theme }) => ({
@ -15,19 +16,25 @@ const StyledContainer = styled('div')(({ theme }) => ({
lineHeight: 1.25, lineHeight: 1.25,
})); }));
const StyledName = styled('div')(({ theme }) => ({ const StyledName = styled('div', {
shouldForwardProp: (prop) => prop !== 'disabled',
})<{ disabled: boolean }>(({ theme, disabled }) => ({
fontSize: theme.fontSizes.smallBody, fontSize: theme.fontSizes.smallBody,
lineHeight: 17 / 14, lineHeight: 17 / 14,
color: disabled ? theme.palette.text.secondary : theme.palette.text.primary,
})); }));
const StyledText = styled('div')(({ theme }) => ({ const StyledText = styled('div', {
shouldForwardProp: (prop) => prop !== 'disabled',
})<{ disabled: boolean }>(({ theme, disabled }) => ({
fontSize: theme.fontSizes.smallerBody, fontSize: theme.fontSizes.smallerBody,
color: theme.palette.neutral.main, color: disabled ? theme.palette.text.secondary : theme.palette.neutral.main,
})); }));
export const ConstraintOperator = ({ export const ConstraintOperator = ({
constraint, constraint,
hasPrefix, hasPrefix,
disabled = false,
}: IConstraintOperatorProps) => { }: IConstraintOperatorProps) => {
const operatorName = constraint.operator; const operatorName = constraint.operator;
const operatorText = formatOperatorDescription(constraint.operator); const operatorText = formatOperatorDescription(constraint.operator);
@ -40,8 +47,8 @@ export const ConstraintOperator = ({
paddingLeft: hasPrefix ? 0 : undefined, paddingLeft: hasPrefix ? 0 : undefined,
}} }}
> >
<StyledName>{operatorName}</StyledName> <StyledName disabled={disabled}>{operatorName}</StyledName>
<StyledText>{operatorText}</StyledText> <StyledText disabled={disabled}>{operatorText}</StyledText>
</StyledContainer> </StyledContainer>
); );
}; };

View File

@ -0,0 +1,46 @@
import { useTheme } from '@mui/material';
import { CSSProperties } from 'react';
interface IPercentageCircleProps {
percentage: number;
size?: `${number}rem`;
}
const PercentageCircle = ({
percentage,
size = '4rem',
}: IPercentageCircleProps) => {
const theme = useTheme();
const style: CSSProperties = {
display: 'block',
borderRadius: '100%',
transform: 'rotate(-90deg)',
height: size,
width: size,
background: theme.palette.background.elevation2,
};
// The percentage circle used to be drawn by CSS with a conic-gradient,
// but the result was either jagged or blurry. SVG seems to look better.
// See https://stackoverflow.com/a/70659532.
const radius = 100 / (2 * Math.PI);
const diameter = 2 * radius;
return (
<svg viewBox={`0 0 ${diameter} ${diameter}`} style={style} aria-hidden>
<title>A circle progress bar with {percentage}% completion.</title>
<circle
r={radius}
cx={radius}
cy={radius}
fill='none'
stroke={theme.palette.neutral.border}
strokeWidth={diameter}
strokeDasharray={`${percentage} 100`}
/>
</svg>
);
};
export default PercentageCircle;

View File

@ -16,6 +16,7 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
interface ISegmentItemProps { interface ISegmentItemProps {
segment: Partial<ISegment>; segment: Partial<ISegment>;
isExpanded?: boolean; isExpanded?: boolean;
disabled?: boolean;
constraintList?: JSX.Element; constraintList?: JSX.Element;
headerContent?: JSX.Element; headerContent?: JSX.Element;
} }
@ -49,20 +50,33 @@ const StyledLink = styled(Link)(({ theme }) => ({
textDecoration: 'underline', textDecoration: 'underline',
}, },
})); }));
const StyledText = styled('span', {
shouldForwardProp: (prop) => prop !== 'disabled',
})<{ disabled: boolean }>(({ theme, disabled }) => ({
color: disabled ? theme.palette.text.secondary : 'inherit',
}));
export const SegmentItem: VFC<ISegmentItemProps> = ({ export const SegmentItem: VFC<ISegmentItemProps> = ({
segment, segment,
isExpanded, isExpanded,
headerContent, headerContent,
constraintList, constraintList,
disabled = false,
}) => { }) => {
const [isOpen, setIsOpen] = useState(isExpanded || false); const [isOpen, setIsOpen] = useState(isExpanded || false);
return ( return (
<StyledAccordion expanded={isOpen}> <StyledAccordion expanded={isOpen}>
<StyledAccordionSummary id={`segment-accordion-${segment.id}`}> <StyledAccordionSummary id={`segment-accordion-${segment.id}`}>
<DonutLarge color='secondary' sx={{ mr: 1 }} /> <DonutLarge
<span>Segment:</span> sx={(theme) => ({
mr: 1,
color: disabled
? theme.palette.neutral.border
: theme.palette.secondary.main,
})}
/>
<StyledText disabled={disabled}>Segment:</StyledText>
<StyledLink to={`/segments/edit/${segment.id}`}> <StyledLink to={`/segments/edit/${segment.id}`}>
{segment.name} {segment.name}
</StyledLink> </StyledLink>

View File

@ -9,8 +9,6 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator'; import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
import { styled } from '@mui/material'; import { styled } from '@mui/material';
import { ConstraintAccordionView } from 'component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView'; import { ConstraintAccordionView } from 'component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView';
import { ConstraintError } from './ConstraintError/ConstraintError';
import { ConstraintOk } from './ConstraintOk/ConstraintOk';
interface IConstraintExecutionWithoutResultsProps { interface IConstraintExecutionWithoutResultsProps {
constraints?: PlaygroundConstraintSchema[]; constraints?: PlaygroundConstraintSchema[];
@ -35,7 +33,11 @@ export const ConstraintExecutionWithoutResults: VFC<
condition={index > 0} condition={index > 0}
show={<StrategySeparator text='AND' />} show={<StrategySeparator text='AND' />}
/> />
<ConstraintAccordionView constraint={constraint} compact /> <ConstraintAccordionView
constraint={constraint}
compact
disabled
/>
</Fragment> </Fragment>
))} ))}
</ConstraintExecutionWrapper> </ConstraintExecutionWrapper>

View File

@ -52,6 +52,7 @@ export const DisabledStrategyExecution: VFC<IDisabledStrategyExecutionProps> =
parameters={parameters} parameters={parameters}
constraints={constraints} constraints={constraints}
input={input} input={input}
disabled
/> />
), ),
hasCustomStrategyParameters && ( hasCustomStrategyParameters && (
@ -61,9 +62,14 @@ export const DisabledStrategyExecution: VFC<IDisabledStrategyExecutionProps> =
/> />
), ),
name === 'default' && ( name === 'default' && (
<StyledBoxSummary sx={{ width: '100%' }}> <StyledBoxSummary
The standard strategy is <Badge color='success'>ON</Badge>{' '} sx={(theme) => ({
for all users. width: '100%',
color: theme.palette.text.secondary,
})}
>
The standard strategy is{' '}
<Badge color={'disabled'}>ON</Badge> for all users.
</StyledBoxSummary> </StyledBoxSummary>
), ),
].filter(Boolean); ].filter(Boolean);
@ -74,7 +80,12 @@ export const DisabledStrategyExecution: VFC<IDisabledStrategyExecutionProps> =
// biome-ignore lint/suspicious/noArrayIndexKey: <explanation> // biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
<Fragment key={index}> <Fragment key={index}>
<ConditionallyRender <ConditionallyRender
condition={index > 0} condition={
index > 0 &&
(strategyResult.name === 'flexibleRollout'
? index < items.length
: index < items.length - 1)
}
show={<StrategySeparator text='AND' />} show={<StrategySeparator text='AND' />}
/> />
{item} {item}

View File

@ -8,6 +8,7 @@ interface IConstraintItemProps {
text: string; text: string;
input?: string | number | boolean | 'no value'; input?: string | number | boolean | 'no value';
showReason?: boolean; showReason?: boolean;
disabled?: boolean;
} }
const StyledDivContainer = styled('div', { const StyledDivContainer = styled('div', {
@ -34,12 +35,15 @@ const StyledChip = styled(Chip)(({ theme }) => ({
margin: theme.spacing(0.5), margin: theme.spacing(0.5),
})); }));
const StyledParagraph = styled('p')(({ theme }) => ({ const StyledParagraph = styled('p', {
shouldForwardProp: (prop) => prop !== 'disabled',
})<{ disabled: boolean }>(({ theme, disabled }) => ({
display: 'inline', display: 'inline',
margin: theme.spacing(0.5, 0), margin: theme.spacing(0.5, 0),
maxWidth: '95%', maxWidth: '95%',
textAlign: 'center', textAlign: 'center',
wordBreak: 'break-word', wordBreak: 'break-word',
color: disabled ? theme.palette.text.secondary : 'inherit',
})); }));
export const PlaygroundParameterItem = ({ export const PlaygroundParameterItem = ({
@ -47,10 +51,11 @@ export const PlaygroundParameterItem = ({
text, text,
input, input,
showReason = false, showReason = false,
disabled = false,
}: IConstraintItemProps) => { }: IConstraintItemProps) => {
const theme = useTheme(); const theme = useTheme();
const color = input === 'no value' ? 'error' : 'neutral'; const color = input === 'no value' && !disabled ? 'error' : 'neutral';
const reason = `value does not match any ${text}`; const reason = `value does not match any ${text}`;
return ( return (
@ -64,7 +69,11 @@ export const PlaygroundParameterItem = ({
show={ show={
<Typography <Typography
variant='subtitle1' variant='subtitle1'
color={theme.palette.error.main} color={
disabled
? theme.palette.text.secondary
: theme.palette.error.main
}
> >
{reason} {reason}
</Typography> </Typography>
@ -75,7 +84,7 @@ export const PlaygroundParameterItem = ({
show={<p>No {text}s added yet.</p>} show={<p>No {text}s added yet.</p>}
elseShow={ elseShow={
<div> <div>
<StyledParagraph> <StyledParagraph disabled={disabled}>
{value.length}{' '} {value.length}{' '}
{value.length > 1 ? `${text}s` : text} will get {value.length > 1 ? `${text}s` : text} will get
access. access.
@ -83,6 +92,7 @@ export const PlaygroundParameterItem = ({
{value.map((v: string | number) => ( {value.map((v: string | number) => (
<StyledChip <StyledChip
key={v} key={v}
disabled={disabled}
label={ label={
<StringTruncator <StringTruncator
maxWidth='300' maxWidth='300'
@ -98,7 +108,9 @@ export const PlaygroundParameterItem = ({
</StyledDivColumn> </StyledDivColumn>
<ConditionallyRender <ConditionallyRender
condition={Boolean(showReason)} condition={Boolean(showReason)}
show={<CancelOutlined color={'error'} />} show={
<CancelOutlined color={disabled ? 'disabled' : 'error'} />
}
elseShow={<div />} elseShow={<div />}
/> />
</StyledDivContainer> </StyledDivContainer>

View File

@ -29,6 +29,7 @@ export const SegmentExecutionWithoutResult: VFC<
/> />
} }
isExpanded isExpanded
disabled
/> />
<ConditionallyRender <ConditionallyRender
condition={ condition={

View File

@ -71,7 +71,12 @@ export const StrategyExecution: VFC<IStrategyExecutionProps> = ({
// biome-ignore lint/suspicious/noArrayIndexKey: <explanation> // biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
<Fragment key={index}> <Fragment key={index}>
<ConditionallyRender <ConditionallyRender
condition={index > 0} condition={
index > 0 &&
(strategyResult.name === 'flexibleRollout'
? index < items.length
: index < items.length - 1)
}
show={<StrategySeparator text='AND' />} show={<StrategySeparator text='AND' />}
/> />
{item} {item}

View File

@ -2,24 +2,34 @@ import {
parseParameterNumber, parseParameterNumber,
parseParameterStrings, parseParameterStrings,
} from 'utils/parseParameter'; } from 'utils/parseParameter';
import { Box } from '@mui/material'; import { Box, styled } from '@mui/material';
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle'; import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
import { PlaygroundParameterItem } from '../PlaygroundParameterItem/PlaygroundParameterItem'; import { PlaygroundParameterItem } from '../PlaygroundParameterItem/PlaygroundParameterItem';
import { StyledBoxSummary } from '../StrategyExecution.styles'; import { StyledBoxSummary } from '../StrategyExecution.styles';
import { PlaygroundConstraintSchema, PlaygroundRequestSchema } from 'openapi'; import { PlaygroundConstraintSchema, PlaygroundRequestSchema } from 'openapi';
import { getMappedParam } from '../helpers'; import { getMappedParam } from '../helpers';
import { Badge } from 'component/common/Badge/Badge'; import { Badge } from 'component/common/Badge/Badge';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import DisabledPercentageCircle from 'component/common/PercentageCircle/DisabledPercentageCircle';
export interface PlaygroundResultStrategyExecutionParametersProps { export interface PlaygroundResultStrategyExecutionParametersProps {
parameters: { [key: string]: string }; parameters: { [key: string]: string };
constraints: PlaygroundConstraintSchema[]; constraints: PlaygroundConstraintSchema[];
input?: PlaygroundRequestSchema; input?: PlaygroundRequestSchema;
disabled?: boolean;
} }
const StyledText = styled('div', {
shouldForwardProp: (prop) => prop !== 'disabled',
})<{ disabled: boolean }>(({ theme, disabled }) => ({
color: disabled ? theme.palette.text.secondary : theme.palette.neutral.main,
}));
export const PlaygroundResultStrategyExecutionParameters = ({ export const PlaygroundResultStrategyExecutionParameters = ({
parameters, parameters,
constraints, constraints,
input, input,
disabled = false,
}: PlaygroundResultStrategyExecutionParametersProps) => { }: PlaygroundResultStrategyExecutionParametersProps) => {
return ( return (
<> <>
@ -35,20 +45,44 @@ export const PlaygroundResultStrategyExecutionParameters = ({
key={key} key={key}
sx={{ display: 'flex', alignItems: 'center' }} sx={{ display: 'flex', alignItems: 'center' }}
> >
<Box sx={{ mr: '1rem' }}> <Box
<PercentageCircle sx={(theme) => ({
percentage={percentage} mr: '1rem',
size='2rem' color: disabled
? theme.palette.neutral.border
: theme.palette.text.secondary,
})}
>
<ConditionallyRender
condition={disabled}
show={
<DisabledPercentageCircle
percentage={percentage}
size='2rem'
/>
}
elseShow={
<PercentageCircle
percentage={percentage}
size='2rem'
/>
}
/> />
</Box> </Box>
<div> <StyledText disabled={disabled}>
<Badge color='success'>{percentage}%</Badge>{' '} <Badge
color={
disabled ? 'disabled' : 'success'
}
>
{percentage}%
</Badge>{' '}
of your base{' '} of your base{' '}
{constraints.length > 0 {constraints.length > 0
? 'who match constraints' ? 'who match constraints'
: ''}{' '} : ''}{' '}
is included. is included.
</div> </StyledText>
</StyledBoxSummary> </StyledBoxSummary>
); );
} }
@ -87,6 +121,7 @@ export const PlaygroundResultStrategyExecutionParameters = ({
text={'host'} text={'host'}
input={'no value'} input={'no value'}
showReason={undefined} showReason={undefined}
disabled={disabled}
/> />
); );
} }
@ -97,6 +132,7 @@ export const PlaygroundResultStrategyExecutionParameters = ({
key={key} key={key}
value={IPs} value={IPs}
text={'IP'} text={'IP'}
disabled={disabled}
input={ input={
input?.context?.[getMappedParam(key)] input?.context?.[getMappedParam(key)]
? input?.context?.[getMappedParam(key)] ? input?.context?.[getMappedParam(key)]