mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-23 01:16:27 +02:00
fmt and lint
This commit is contained in:
parent
2299eb9305
commit
2bd239f481
@ -17,17 +17,11 @@ import {
|
|||||||
semVerOperators,
|
semVerOperators,
|
||||||
} from 'constants/operators';
|
} from 'constants/operators';
|
||||||
import { useStyles } from '../ConstraintAccordion.styles';
|
import { useStyles } from '../ConstraintAccordion.styles';
|
||||||
import {
|
|
||||||
PlaygroundConstraintSchema,
|
|
||||||
PlaygroundRequestSchema,
|
|
||||||
} from '../../../../hooks/api/actions/usePlayground/playground.model';
|
|
||||||
|
|
||||||
interface IConstraintAccordionViewProps {
|
interface IConstraintAccordionViewProps {
|
||||||
constraint: IConstraint | PlaygroundConstraintSchema;
|
constraint: IConstraint;
|
||||||
onDelete?: () => void;
|
onDelete?: () => void;
|
||||||
onEdit?: () => void;
|
onEdit?: () => void;
|
||||||
playgroundInput?: PlaygroundRequestSchema;
|
|
||||||
maxLength?: number;
|
|
||||||
sx?: SxProps<Theme>;
|
sx?: SxProps<Theme>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,8 +30,6 @@ export const ConstraintAccordionView = ({
|
|||||||
onEdit,
|
onEdit,
|
||||||
onDelete,
|
onDelete,
|
||||||
sx = undefined,
|
sx = undefined,
|
||||||
maxLength,
|
|
||||||
playgroundInput,
|
|
||||||
}: IConstraintAccordionViewProps) => {
|
}: IConstraintAccordionViewProps) => {
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
const [expandable, setExpandable] = useState(true);
|
const [expandable, setExpandable] = useState(true);
|
||||||
@ -53,11 +45,6 @@ export const ConstraintAccordionView = ({
|
|||||||
setExpanded(!expanded);
|
setExpanded(!expanded);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const backgroundColor = Boolean(playgroundInput)
|
|
||||||
? !Boolean((constraint as PlaygroundConstraintSchema).result)
|
|
||||||
? theme.palette.neutral.light
|
|
||||||
: 'inherit'
|
|
||||||
: 'inherit';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Accordion
|
<Accordion
|
||||||
@ -75,7 +62,6 @@ export const ConstraintAccordionView = ({
|
|||||||
'&:hover': {
|
'&:hover': {
|
||||||
cursor: expandable ? 'pointer' : 'default!important',
|
cursor: expandable ? 'pointer' : 'default!important',
|
||||||
},
|
},
|
||||||
backgroundColor: backgroundColor,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ConstraintAccordionViewHeader
|
<ConstraintAccordionViewHeader
|
||||||
@ -85,8 +71,6 @@ export const ConstraintAccordionView = ({
|
|||||||
singleValue={singleValue}
|
singleValue={singleValue}
|
||||||
allowExpand={setExpandable}
|
allowExpand={setExpandable}
|
||||||
expanded={expanded}
|
expanded={expanded}
|
||||||
maxLength={maxLength ?? 112}
|
|
||||||
playgroundInput={playgroundInput}
|
|
||||||
/>
|
/>
|
||||||
</AccordionSummary>
|
</AccordionSummary>
|
||||||
|
|
||||||
|
@ -3,20 +3,14 @@ import { IConstraint } from 'interfaces/strategy';
|
|||||||
import { ConstraintAccordionViewHeaderInfo } from './ConstraintAccordionViewHeaderInfo/ConstraintAccordionViewHeaderInfo';
|
import { ConstraintAccordionViewHeaderInfo } from './ConstraintAccordionViewHeaderInfo/ConstraintAccordionViewHeaderInfo';
|
||||||
import { ConstraintAccordionHeaderActions } from '../../ConstraintAccordionHeaderActions/ConstraintAccordionHeaderActions';
|
import { ConstraintAccordionHeaderActions } from '../../ConstraintAccordionHeaderActions/ConstraintAccordionHeaderActions';
|
||||||
import { useStyles } from 'component/common/ConstraintAccordion/ConstraintAccordion.styles';
|
import { useStyles } from 'component/common/ConstraintAccordion/ConstraintAccordion.styles';
|
||||||
import {
|
|
||||||
PlaygroundConstraintSchema,
|
|
||||||
PlaygroundRequestSchema,
|
|
||||||
} from 'hooks/api/actions/usePlayground/playground.model';
|
|
||||||
|
|
||||||
interface IConstraintAccordionViewHeaderProps {
|
interface IConstraintAccordionViewHeaderProps {
|
||||||
constraint: IConstraint | PlaygroundConstraintSchema;
|
constraint: IConstraint;
|
||||||
onDelete?: () => void;
|
onDelete?: () => void;
|
||||||
onEdit?: () => void;
|
onEdit?: () => void;
|
||||||
singleValue: boolean;
|
singleValue: boolean;
|
||||||
expanded: boolean;
|
expanded: boolean;
|
||||||
allowExpand: (shouldExpand: boolean) => void;
|
allowExpand: (shouldExpand: boolean) => void;
|
||||||
playgroundInput?: PlaygroundRequestSchema;
|
|
||||||
maxLength?: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ConstraintAccordionViewHeader = ({
|
export const ConstraintAccordionViewHeader = ({
|
||||||
@ -26,8 +20,6 @@ export const ConstraintAccordionViewHeader = ({
|
|||||||
singleValue,
|
singleValue,
|
||||||
allowExpand,
|
allowExpand,
|
||||||
expanded,
|
expanded,
|
||||||
maxLength,
|
|
||||||
playgroundInput,
|
|
||||||
}: IConstraintAccordionViewHeaderProps) => {
|
}: IConstraintAccordionViewHeaderProps) => {
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
|
|
||||||
@ -39,9 +31,6 @@ export const ConstraintAccordionViewHeader = ({
|
|||||||
singleValue={singleValue}
|
singleValue={singleValue}
|
||||||
allowExpand={allowExpand}
|
allowExpand={allowExpand}
|
||||||
expanded={expanded}
|
expanded={expanded}
|
||||||
result={'result' in constraint ? constraint.result : undefined}
|
|
||||||
maxLength={maxLength}
|
|
||||||
playgroundInput={playgroundInput}
|
|
||||||
/>
|
/>
|
||||||
<ConstraintAccordionHeaderActions
|
<ConstraintAccordionHeaderActions
|
||||||
onEdit={onEdit}
|
onEdit={onEdit}
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
import { styled, Tooltip, Typography, useTheme } from '@mui/material';
|
import { styled, Tooltip } from '@mui/material';
|
||||||
import { ConstraintViewHeaderOperator } from '../ConstraintViewHeaderOperator/ConstraintViewHeaderOperator';
|
import { ConstraintViewHeaderOperator } from '../ConstraintViewHeaderOperator/ConstraintViewHeaderOperator';
|
||||||
import { ConditionallyRender } from '../../../../ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { ConstraintAccordionViewHeaderSingleValue } from '../ContraintAccordionViewHeaderSingleValue/ConstraintAccordionViewHeaderSingleValue';
|
import { ConstraintAccordionViewHeaderSingleValue } from '../ContraintAccordionViewHeaderSingleValue/ConstraintAccordionViewHeaderSingleValue';
|
||||||
import { ConstraintAccordionViewHeaderMultipleValues } from '../ContraintAccordionViewHeaderMultipleValues/ConstraintAccordionViewHeaderMultipleValues';
|
import { ConstraintAccordionViewHeaderMultipleValues } from '../ContraintAccordionViewHeaderMultipleValues/ConstraintAccordionViewHeaderMultipleValues';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { IConstraint } from '../../../../../../interfaces/strategy';
|
import { IConstraint } from '../../../../../../interfaces/strategy';
|
||||||
import { useStyles } from '../../../ConstraintAccordion.styles';
|
import { useStyles } from '../../../ConstraintAccordion.styles';
|
||||||
import { CancelOutlined } from '@mui/icons-material';
|
|
||||||
import { PlaygroundRequestSchema } from '../../../../../../hooks/api/actions/usePlayground/playground.model';
|
|
||||||
|
|
||||||
const StyledHeaderText = styled('span')(({ theme }) => ({
|
const StyledHeaderText = styled('span')(({ theme }) => ({
|
||||||
display: '-webkit-box',
|
display: '-webkit-box',
|
||||||
@ -41,9 +39,7 @@ interface ConstraintAccordionViewHeaderMetaInfoProps {
|
|||||||
singleValue: boolean;
|
singleValue: boolean;
|
||||||
expanded: boolean;
|
expanded: boolean;
|
||||||
allowExpand: (shouldExpand: boolean) => void;
|
allowExpand: (shouldExpand: boolean) => void;
|
||||||
result?: boolean;
|
|
||||||
maxLength?: number;
|
maxLength?: number;
|
||||||
playgroundInput?: PlaygroundRequestSchema;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ConstraintAccordionViewHeaderInfo = ({
|
export const ConstraintAccordionViewHeaderInfo = ({
|
||||||
@ -51,17 +47,9 @@ export const ConstraintAccordionViewHeaderInfo = ({
|
|||||||
singleValue,
|
singleValue,
|
||||||
allowExpand,
|
allowExpand,
|
||||||
expanded,
|
expanded,
|
||||||
result,
|
|
||||||
playgroundInput,
|
|
||||||
maxLength = 112,
|
maxLength = 112,
|
||||||
}: ConstraintAccordionViewHeaderMetaInfoProps) => {
|
}: ConstraintAccordionViewHeaderMetaInfoProps) => {
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
const isPlayground = Boolean(playgroundInput);
|
|
||||||
const constrainExistsInContext =
|
|
||||||
isPlayground &&
|
|
||||||
Boolean(playgroundInput?.context[constraint.contextName]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledHeaderWrapper>
|
<StyledHeaderWrapper>
|
||||||
@ -69,23 +57,6 @@ export const ConstraintAccordionViewHeaderInfo = ({
|
|||||||
<Tooltip title={constraint.contextName} arrow>
|
<Tooltip title={constraint.contextName} arrow>
|
||||||
<StyledHeaderText>
|
<StyledHeaderText>
|
||||||
{constraint.contextName}
|
{constraint.contextName}
|
||||||
<ConditionallyRender
|
|
||||||
condition={isPlayground}
|
|
||||||
show={
|
|
||||||
<Typography
|
|
||||||
variant={'body1'}
|
|
||||||
color={
|
|
||||||
constrainExistsInContext
|
|
||||||
? theme.palette.neutral.dark
|
|
||||||
: theme.palette.error.main
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{playgroundInput?.context[
|
|
||||||
constraint.contextName
|
|
||||||
] || 'no value'}
|
|
||||||
</Typography>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</StyledHeaderText>
|
</StyledHeaderText>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<ConstraintViewHeaderOperator constraint={constraint} />
|
<ConstraintViewHeaderOperator constraint={constraint} />
|
||||||
@ -107,10 +78,6 @@ export const ConstraintAccordionViewHeaderInfo = ({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ConditionallyRender
|
|
||||||
condition={result !== undefined && !Boolean(result)}
|
|
||||||
show={<CancelOutlined color="error" sx={{ mt: 1 }} />}
|
|
||||||
/>
|
|
||||||
</StyledHeaderWrapper>
|
</StyledHeaderWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -27,7 +27,9 @@ export const FeatureResultInfoPopoverCell = ({
|
|||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
|
|
||||||
const togglePopover = (event: React.SyntheticEvent) => {
|
console.log(feature)
|
||||||
|
|
||||||
|
const togglePopover = () => {
|
||||||
setOpen(!open);
|
setOpen(!open);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,7 +13,9 @@ export const useStyles = makeStyles()(theme => ({
|
|||||||
gap: '12px',
|
gap: '12px',
|
||||||
marginTop: '12px',
|
marginTop: '12px',
|
||||||
},
|
},
|
||||||
alertRow: {},
|
alertRow: {
|
||||||
|
margin: theme.spacing(1,0),
|
||||||
|
},
|
||||||
descriptionRow: {
|
descriptionRow: {
|
||||||
marginBottom: theme.spacing(2),
|
marginBottom: theme.spacing(2),
|
||||||
},
|
},
|
||||||
|
@ -24,25 +24,19 @@ export const PlaygroundResultFeatureDetails = ({
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const description =
|
const description =
|
||||||
feature.isEnabled === 'unevaluated'
|
feature.isEnabled
|
||||||
? `This feature toggle is Unevaluated in ${input?.environment} because `
|
|
||||||
: feature.isEnabled
|
|
||||||
? `This feature toggle is True in ${input?.environment} because `
|
? `This feature toggle is True in ${input?.environment} because `
|
||||||
: `This feature toggle is False in ${input?.environment} because `;
|
: `This feature toggle is False in ${input?.environment} because `;
|
||||||
|
|
||||||
const reason =
|
const reason =
|
||||||
feature.isEnabled === 'unevaluated'
|
feature.isEnabled
|
||||||
? 'custom strategies are not evaluated yet'
|
? 'at least one strategy is True'
|
||||||
: !feature.isEnabledInCurrentEnvironment
|
: !feature.isEnabledInCurrentEnvironment
|
||||||
? 'the environment is disabled'
|
? 'the environment is disabled'
|
||||||
: feature.isEnabled
|
|
||||||
? 'at least one strategy is True'
|
|
||||||
: 'all strategies are False';
|
: 'all strategies are False';
|
||||||
|
|
||||||
const color =
|
const color =
|
||||||
feature.isEnabled === 'unevaluated'
|
feature.isEnabled
|
||||||
? theme.palette.warning.main
|
|
||||||
: feature.isEnabled
|
|
||||||
? theme.palette.success.main
|
? theme.palette.success.main
|
||||||
: theme.palette.error.main;
|
: theme.palette.error.main;
|
||||||
|
|
||||||
@ -67,10 +61,7 @@ export const PlaygroundResultFeatureDetails = ({
|
|||||||
<span>
|
<span>
|
||||||
<PlaygroundResultChip
|
<PlaygroundResultChip
|
||||||
enabled={feature.isEnabled}
|
enabled={feature.isEnabled}
|
||||||
label={
|
label={feature.isEnabled
|
||||||
feature.isEnabled === 'unevaluated'
|
|
||||||
? '?'
|
|
||||||
: Boolean(feature.isEnabled)
|
|
||||||
? 'True'
|
? 'True'
|
||||||
: 'False'
|
: 'False'
|
||||||
}
|
}
|
||||||
|
@ -20,17 +20,17 @@ export const PlaygroundResultFeatureStrategyList = ({
|
|||||||
}: PlaygroundResultFeatureStrategyListProps) => {
|
}: PlaygroundResultFeatureStrategyListProps) => {
|
||||||
return (
|
return (
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={!feature.isEnabledInCurrentEnvironment}
|
condition={!feature.isEnabledInCurrentEnvironment && Boolean(feature?.strategies?.data)}
|
||||||
show={
|
show={
|
||||||
<WrappedPlaygroundResultStrategyList
|
<WrappedPlaygroundResultStrategyList
|
||||||
strategies={feature?.strategies}
|
strategies={feature?.strategies?.data!}
|
||||||
feature={feature}
|
feature={feature}
|
||||||
input={input}
|
input={input}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
elseShow={
|
elseShow={
|
||||||
<PlaygroundResultStrategyLists
|
<PlaygroundResultStrategyLists
|
||||||
strategies={feature?.strategies}
|
strategies={feature?.strategies?.data!}
|
||||||
input={input}
|
input={input}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ const StyledItemWrapper = styled('div')(({ theme }) => ({
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginTop: '4px',
|
margin: theme.spacing(0.5),
|
||||||
gap: '8px',
|
gap: theme.spacing(1),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const PlaygroundResultFeatureStrategyItem = ({
|
export const PlaygroundResultFeatureStrategyItem = ({
|
||||||
@ -63,8 +63,8 @@ export const PlaygroundResultFeatureStrategyItem = ({
|
|||||||
condition={index > 0}
|
condition={index > 0}
|
||||||
show={<StrategySeparator text="OR" />}
|
show={<StrategySeparator text="OR" />}
|
||||||
/>
|
/>
|
||||||
<StyledItemWrapper>
|
<StyledItemWrapper sx={{mr: 2}}>
|
||||||
<Typography variant={'subtitle1'} color={'text.secondary'}>
|
<Typography variant={'subtitle1'} color={'text.secondary'} sx={{ml: 1}}>
|
||||||
{index + 1}
|
{index + 1}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box className={styles.innerContainer} sx={{ border }}>
|
<Box className={styles.innerContainer} sx={{ border }}>
|
||||||
|
@ -0,0 +1,158 @@
|
|||||||
|
import { makeStyles } from 'tss-react/mui';
|
||||||
|
|
||||||
|
export const useStyles = makeStyles()(theme => ({
|
||||||
|
constraintIconContainer: {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
borderRadius: '50%',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
marginRight: theme.spacing(1),
|
||||||
|
[theme.breakpoints.down(650)]: {
|
||||||
|
marginBottom: '1rem',
|
||||||
|
marginRight: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
constraintIcon: {
|
||||||
|
fill: '#fff',
|
||||||
|
},
|
||||||
|
accordion: {
|
||||||
|
border: `1px solid ${theme.palette.grey[400]}`,
|
||||||
|
borderRadius: '8px',
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
boxShadow: 'none',
|
||||||
|
margin: 0,
|
||||||
|
},
|
||||||
|
accordionRoot: {
|
||||||
|
'&:before': {
|
||||||
|
opacity: '0 !important',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
accordionEdit: {
|
||||||
|
backgroundColor: '#F6F6FA',
|
||||||
|
},
|
||||||
|
headerMetaInfo: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'stretch',
|
||||||
|
[theme.breakpoints.down(710)]: { flexDirection: 'column' },
|
||||||
|
},
|
||||||
|
headerContainer: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
width: '100%',
|
||||||
|
[theme.breakpoints.down(710)]: {
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
position: 'relative',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
headerValuesContainerWrapper: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'stretch',
|
||||||
|
margin: 'auto 0',
|
||||||
|
},
|
||||||
|
headerValuesContainer: {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'stretch',
|
||||||
|
margin: 'auto 0',
|
||||||
|
flexDirection: 'column',
|
||||||
|
},
|
||||||
|
headerValues: {
|
||||||
|
fontSize: theme.fontSizes.smallBody,
|
||||||
|
},
|
||||||
|
headerValuesExpand: {
|
||||||
|
fontSize: theme.fontSizes.smallBody,
|
||||||
|
marginTop: '4px',
|
||||||
|
color: theme.palette.primary.dark,
|
||||||
|
[theme.breakpoints.down(710)]: {
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
headerConstraintContainer: {
|
||||||
|
minWidth: '220px',
|
||||||
|
position: 'relative',
|
||||||
|
paddingRight: '1rem',
|
||||||
|
[theme.breakpoints.between(1101, 1365)]: {
|
||||||
|
minWidth: '152px',
|
||||||
|
paddingRight: '0.5rem',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
editingBadge: {
|
||||||
|
borderRadius: theme.shape.borderRadiusExtraLarge,
|
||||||
|
padding: '0.25rem 0.5rem',
|
||||||
|
backgroundColor: '#635DC5',
|
||||||
|
color: '#fff',
|
||||||
|
marginLeft: 'auto',
|
||||||
|
fontSize: '0.9rem',
|
||||||
|
[theme.breakpoints.down(650)]: {
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
top: '-10px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
headerText: {
|
||||||
|
maxWidth: '400px',
|
||||||
|
fontSize: theme.fontSizes.smallBody,
|
||||||
|
[theme.breakpoints.down('xl')]: {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
selectContainer: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
[theme.breakpoints.down(770)]: {
|
||||||
|
flexDirection: 'column',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bottomSelect: {
|
||||||
|
[theme.breakpoints.down(770)]: {
|
||||||
|
marginTop: '1rem',
|
||||||
|
},
|
||||||
|
display: 'inline-flex',
|
||||||
|
},
|
||||||
|
headerSelect: {
|
||||||
|
marginRight: '1rem',
|
||||||
|
width: '200px',
|
||||||
|
[theme.breakpoints.between(1101, 1365)]: {
|
||||||
|
width: '170px',
|
||||||
|
marginRight: '8px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
chip: {
|
||||||
|
margin: '0 0.5rem 0.5rem 0',
|
||||||
|
},
|
||||||
|
chipValue: {
|
||||||
|
whiteSpace: 'pre',
|
||||||
|
},
|
||||||
|
headerActions: {
|
||||||
|
marginLeft: 'auto',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
[theme.breakpoints.down(710)]: {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
accordionDetails: {
|
||||||
|
borderTop: `1px dashed ${theme.palette.grey[300]}`,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
},
|
||||||
|
valuesContainer: {
|
||||||
|
padding: '1rem 0rem',
|
||||||
|
maxHeight: '400px',
|
||||||
|
overflowY: 'auto',
|
||||||
|
},
|
||||||
|
summary: {
|
||||||
|
border: 'none',
|
||||||
|
padding: theme.spacing(0.5, 3),
|
||||||
|
'&:hover .valuesExpandLabel': {
|
||||||
|
textDecoration: 'underline',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
settingsIcon: {
|
||||||
|
height: '32.5px',
|
||||||
|
width: '32.5px',
|
||||||
|
marginRight: '0.5rem',
|
||||||
|
fill: theme.palette.inactiveIcon,
|
||||||
|
},
|
||||||
|
form: { padding: 0, margin: 0, width: '100%' },
|
||||||
|
}));
|
@ -0,0 +1,41 @@
|
|||||||
|
import {ConstraintIcon} from 'component/common/ConstraintAccordion/ConstraintIcon';
|
||||||
|
import {
|
||||||
|
PlaygroundConstraintAccordionViewHeaderInfo
|
||||||
|
} from './PlaygroundConstraintAccordionViewHeaderInfo/PlaygroundConstraintAccordionViewHeaderInfo';
|
||||||
|
import {useStyles} from 'component/common/ConstraintAccordion/ConstraintAccordion.styles';
|
||||||
|
import {PlaygroundConstraintSchema, PlaygroundRequestSchema,} from 'hooks/api/actions/usePlayground/playground.model';
|
||||||
|
|
||||||
|
interface PlaygroundConstraintAccordionViewHeaderProps {
|
||||||
|
constraint: PlaygroundConstraintSchema;
|
||||||
|
singleValue: boolean;
|
||||||
|
expanded: boolean;
|
||||||
|
allowExpand: (shouldExpand: boolean) => void;
|
||||||
|
playgroundInput?: PlaygroundRequestSchema;
|
||||||
|
maxLength?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PlaygroundConstraintAccordionViewHeader = ({
|
||||||
|
constraint,
|
||||||
|
singleValue,
|
||||||
|
allowExpand,
|
||||||
|
expanded,
|
||||||
|
maxLength,
|
||||||
|
playgroundInput,
|
||||||
|
}: PlaygroundConstraintAccordionViewHeaderProps) => {
|
||||||
|
const { classes: styles } = useStyles();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.headerContainer}>
|
||||||
|
<ConstraintIcon />
|
||||||
|
<PlaygroundConstraintAccordionViewHeaderInfo
|
||||||
|
constraint={constraint}
|
||||||
|
singleValue={singleValue}
|
||||||
|
allowExpand={allowExpand}
|
||||||
|
expanded={expanded}
|
||||||
|
result={constraint.result}
|
||||||
|
maxLength={maxLength}
|
||||||
|
playgroundInput={playgroundInput}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,110 @@
|
|||||||
|
import { styled, Tooltip, Typography, useTheme } from '@mui/material';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { PlaygroundConstraintAccordionViewHeaderSingleValue } from '../PlaygroundContraintAccordionViewHeaderSingleValue/PlaygroundConstraintAccordionViewHeaderSingleValue';
|
||||||
|
import { PLaygroundConstraintAccordionViewHeaderMultipleValues } from '../PlaygroundContraintAccordionViewHeaderMultipleValues/PLaygroundConstraintAccordionViewHeaderMultipleValues';
|
||||||
|
import React from 'react';
|
||||||
|
import { useStyles } from '../../PlaygroundConstraintAccordion.styles';
|
||||||
|
import { CancelOutlined } from '@mui/icons-material';
|
||||||
|
import {PlaygroundConstraintSchema, PlaygroundRequestSchema} from 'hooks/api/actions/usePlayground/playground.model';
|
||||||
|
import {
|
||||||
|
ConstraintViewHeaderOperator
|
||||||
|
} from "component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintViewHeaderOperator/ConstraintViewHeaderOperator";
|
||||||
|
|
||||||
|
const StyledHeaderText = styled('span')(({ theme }) => ({
|
||||||
|
display: '-webkit-box',
|
||||||
|
WebkitLineClamp: 3,
|
||||||
|
WebkitBoxOrient: 'vertical',
|
||||||
|
overflow: 'hidden',
|
||||||
|
maxWidth: '100px',
|
||||||
|
minWidth: '100px',
|
||||||
|
marginRight: '10px',
|
||||||
|
marginTop: 'auto',
|
||||||
|
marginBottom: 'auto',
|
||||||
|
wordBreak: 'break-word',
|
||||||
|
fontSize: theme.fontSizes.smallBody,
|
||||||
|
[theme.breakpoints.down(710)]: {
|
||||||
|
textAlign: 'center',
|
||||||
|
padding: theme.spacing(1, 0),
|
||||||
|
marginRight: 'inherit',
|
||||||
|
maxWidth: 'inherit',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledHeaderWrapper = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
borderRadius: theme.spacing(1),
|
||||||
|
}));
|
||||||
|
|
||||||
|
interface PlaygroundConstraintAccordionViewHeaderInfoProps {
|
||||||
|
constraint: PlaygroundConstraintSchema;
|
||||||
|
singleValue: boolean;
|
||||||
|
expanded: boolean;
|
||||||
|
allowExpand: (shouldExpand: boolean) => void;
|
||||||
|
result?: boolean;
|
||||||
|
maxLength?: number;
|
||||||
|
playgroundInput?: PlaygroundRequestSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PlaygroundConstraintAccordionViewHeaderInfo = ({
|
||||||
|
constraint,
|
||||||
|
singleValue,
|
||||||
|
allowExpand,
|
||||||
|
expanded,
|
||||||
|
result,
|
||||||
|
playgroundInput,
|
||||||
|
maxLength = 112,
|
||||||
|
}: PlaygroundConstraintAccordionViewHeaderInfoProps) => {
|
||||||
|
const { classes: styles } = useStyles();
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const constraintExistsInContext =
|
||||||
|
Boolean(playgroundInput?.context[constraint.contextName]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledHeaderWrapper>
|
||||||
|
<div className={styles.headerMetaInfo}>
|
||||||
|
<Tooltip title={constraint.contextName} arrow>
|
||||||
|
<StyledHeaderText>
|
||||||
|
{constraint.contextName}
|
||||||
|
<Typography
|
||||||
|
variant={'body1'}
|
||||||
|
color={
|
||||||
|
constraintExistsInContext
|
||||||
|
? theme.palette.neutral.dark
|
||||||
|
: theme.palette.error.main
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{playgroundInput?.context[
|
||||||
|
constraint.contextName
|
||||||
|
] || 'no value'}
|
||||||
|
</Typography>
|
||||||
|
</StyledHeaderText>
|
||||||
|
</Tooltip>
|
||||||
|
<ConstraintViewHeaderOperator constraint={constraint} />
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={singleValue}
|
||||||
|
show={
|
||||||
|
<PlaygroundConstraintAccordionViewHeaderSingleValue
|
||||||
|
constraint={constraint}
|
||||||
|
allowExpand={allowExpand}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
elseShow={
|
||||||
|
<PLaygroundConstraintAccordionViewHeaderMultipleValues
|
||||||
|
constraint={constraint}
|
||||||
|
expanded={expanded}
|
||||||
|
allowExpand={allowExpand}
|
||||||
|
maxLength={maxLength}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={result !== undefined && !Boolean(result)}
|
||||||
|
show={<CancelOutlined color="error" sx={{ mt: 1 }} />}
|
||||||
|
/>
|
||||||
|
</StyledHeaderWrapper>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,85 @@
|
|||||||
|
import {ConditionallyRender} from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import {styled, Typography} from '@mui/material';
|
||||||
|
import React, {useEffect, useMemo, useState} from 'react';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import {useStyles} from '../../PlaygroundConstraintAccordion.styles';
|
||||||
|
import {PlaygroundConstraintSchema} from 'hooks/api/actions/usePlayground/playground.model';
|
||||||
|
|
||||||
|
const StyledValuesSpan = styled('span')(({ theme }) => ({
|
||||||
|
display: '-webkit-box',
|
||||||
|
WebkitLineClamp: 2,
|
||||||
|
WebkitBoxOrient: 'vertical',
|
||||||
|
overflow: 'hidden',
|
||||||
|
wordBreak: 'break-word',
|
||||||
|
fontSize: theme.fontSizes.smallBody,
|
||||||
|
margin: 'auto 0',
|
||||||
|
[theme.breakpoints.down(710)]: {
|
||||||
|
margin: theme.spacing(1, 0),
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
interface ConstraintSingleValueProps {
|
||||||
|
constraint: PlaygroundConstraintSchema;
|
||||||
|
expanded: boolean;
|
||||||
|
maxLength: number;
|
||||||
|
allowExpand: (shouldExpand: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PLaygroundConstraintAccordionViewHeaderMultipleValues = ({
|
||||||
|
constraint,
|
||||||
|
expanded,
|
||||||
|
allowExpand,
|
||||||
|
maxLength,
|
||||||
|
}: ConstraintSingleValueProps) => {
|
||||||
|
const { classes: styles } = useStyles();
|
||||||
|
|
||||||
|
const [expandable, setExpandable] = useState(false);
|
||||||
|
|
||||||
|
const text = useMemo(() => {
|
||||||
|
return constraint?.values?.map(value => value).join(', ');
|
||||||
|
}, [constraint]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (text) {
|
||||||
|
allowExpand((text?.length ?? 0) > maxLength);
|
||||||
|
setExpandable((text?.length ?? 0) > maxLength);
|
||||||
|
}
|
||||||
|
}, [text, maxLength, allowExpand, setExpandable]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.headerValuesContainerWrapper}>
|
||||||
|
<div className={styles.headerValuesContainer}>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={!Boolean(constraint.result)}
|
||||||
|
show={
|
||||||
|
<Typography
|
||||||
|
variant={'body2'}
|
||||||
|
color={'error'}
|
||||||
|
noWrap={true}
|
||||||
|
sx={{ mr: 1 }}
|
||||||
|
>
|
||||||
|
does not match any values{' '}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<StyledValuesSpan>{text}</StyledValuesSpan>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={expandable}
|
||||||
|
show={
|
||||||
|
<p
|
||||||
|
className={classnames(
|
||||||
|
styles.headerValuesExpand,
|
||||||
|
'valuesExpandLabel'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{!expanded
|
||||||
|
? `View all (${constraint?.values?.length})`
|
||||||
|
: 'View less'}
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,47 @@
|
|||||||
|
import React, {useEffect} from 'react';
|
||||||
|
import {Chip, styled, Typography} from '@mui/material';
|
||||||
|
import {formatConstraintValue} from 'utils/formatConstraintValue';
|
||||||
|
import {useStyles} from '../../PlaygroundConstraintAccordion.styles';
|
||||||
|
import {useLocationSettings} from 'hooks/useLocationSettings';
|
||||||
|
import {PlaygroundConstraintSchema} from 'hooks/api/actions/usePlayground/playground.model';
|
||||||
|
import {ConditionallyRender} from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
|
||||||
|
const StyledSingleValueChip = styled(Chip)(({ theme }) => ({
|
||||||
|
margin: 'auto 0',
|
||||||
|
[theme.breakpoints.down(710)]: {
|
||||||
|
margin: theme.spacing(1, 0),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
interface ConstraintSingleValueProps {
|
||||||
|
constraint: PlaygroundConstraintSchema;
|
||||||
|
allowExpand: (shouldExpand: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PlaygroundConstraintAccordionViewHeaderSingleValue = ({
|
||||||
|
constraint,
|
||||||
|
allowExpand,
|
||||||
|
}: ConstraintSingleValueProps) => {
|
||||||
|
const { locationSettings } = useLocationSettings();
|
||||||
|
const { classes: styles } = useStyles();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
allowExpand(false);
|
||||||
|
}, [allowExpand]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.headerValuesContainerWrapper}>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={!Boolean(constraint.result)}
|
||||||
|
show={
|
||||||
|
<Typography variant={'body1'} color={'error'}>
|
||||||
|
does not match any values{' '}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<StyledSingleValueChip
|
||||||
|
label={formatConstraintValue(constraint, locationSettings)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,93 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionSummary,
|
||||||
|
AccordionDetails,
|
||||||
|
SxProps,
|
||||||
|
Theme,
|
||||||
|
useTheme,
|
||||||
|
} from '@mui/material';
|
||||||
|
import { PlaygroundConstraintAccordionViewHeader } from './PlaygroundConstraintAccordionViewHeader/PlaygroundConstraintAccordionViewHeader';
|
||||||
|
import { oneOf } from 'utils/oneOf';
|
||||||
|
import {
|
||||||
|
dateOperators,
|
||||||
|
numOperators,
|
||||||
|
semVerOperators,
|
||||||
|
} from 'constants/operators';
|
||||||
|
import { useStyles } from './PlaygroundConstraintAccordion.styles';
|
||||||
|
import {
|
||||||
|
PlaygroundConstraintSchema,
|
||||||
|
PlaygroundRequestSchema,
|
||||||
|
} from 'hooks/api/actions/usePlayground/playground.model';
|
||||||
|
import {
|
||||||
|
ConstraintAccordionViewBody
|
||||||
|
} from "component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewBody/ConstraintAccordionViewBody";
|
||||||
|
|
||||||
|
interface IConstraintAccordionViewProps {
|
||||||
|
constraint: PlaygroundConstraintSchema;
|
||||||
|
playgroundInput?: PlaygroundRequestSchema;
|
||||||
|
maxLength?: number;
|
||||||
|
sx?: SxProps<Theme>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PlaygroundResultConstraintAccordionView = ({
|
||||||
|
constraint,
|
||||||
|
sx = undefined,
|
||||||
|
maxLength,
|
||||||
|
playgroundInput,
|
||||||
|
}: IConstraintAccordionViewProps) => {
|
||||||
|
const { classes: styles } = useStyles();
|
||||||
|
const [expandable, setExpandable] = useState(true);
|
||||||
|
const [expanded, setExpanded] = useState(false);
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const singleValue = oneOf(
|
||||||
|
[...semVerOperators, ...numOperators, ...dateOperators],
|
||||||
|
constraint.operator
|
||||||
|
);
|
||||||
|
const handleClick = () => {
|
||||||
|
if (expandable) {
|
||||||
|
setExpanded(!expanded);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const backgroundColor = Boolean(playgroundInput)
|
||||||
|
? !Boolean((constraint as PlaygroundConstraintSchema).result)
|
||||||
|
? theme.palette.neutral.light
|
||||||
|
: 'inherit'
|
||||||
|
: 'inherit';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Accordion
|
||||||
|
className={styles.accordion}
|
||||||
|
classes={{ root: styles.accordionRoot }}
|
||||||
|
expanded={expanded}
|
||||||
|
sx={sx}
|
||||||
|
>
|
||||||
|
<AccordionSummary
|
||||||
|
classes={{ root: styles.summary }}
|
||||||
|
expandIcon={null}
|
||||||
|
onClick={handleClick}
|
||||||
|
sx={{
|
||||||
|
cursor: expandable ? 'pointer' : 'default!important',
|
||||||
|
'&:hover': {
|
||||||
|
cursor: expandable ? 'pointer' : 'default!important',
|
||||||
|
},
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PlaygroundConstraintAccordionViewHeader
|
||||||
|
constraint={constraint}
|
||||||
|
singleValue={singleValue}
|
||||||
|
allowExpand={setExpandable}
|
||||||
|
expanded={expanded}
|
||||||
|
maxLength={maxLength ?? 112}
|
||||||
|
playgroundInput={playgroundInput}
|
||||||
|
/>
|
||||||
|
</AccordionSummary>
|
||||||
|
|
||||||
|
<AccordionDetails className={styles.accordionDetails}>
|
||||||
|
<ConstraintAccordionViewBody constraint={constraint} />
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
|
);
|
||||||
|
};
|
@ -3,11 +3,13 @@ import {
|
|||||||
PlaygroundRequestSchema,
|
PlaygroundRequestSchema,
|
||||||
} from 'hooks/api/actions/usePlayground/playground.model';
|
} from 'hooks/api/actions/usePlayground/playground.model';
|
||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import { objectId } from '../../../../../../../../../utils/objectId';
|
import { objectId } from '../../../../../../../../../../utils/objectId';
|
||||||
import { ConditionallyRender } from '../../../../../../../../common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from '../../../../../../../../../common/ConditionallyRender/ConditionallyRender';
|
||||||
import { StrategySeparator } from '../../../../../../../../common/StrategySeparator/StrategySeparator';
|
import { StrategySeparator } from '../../../../../../../../../common/StrategySeparator/StrategySeparator';
|
||||||
import { ConstraintAccordionView } from '../../../../../../../../common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView';
|
|
||||||
import { styled } from '@mui/material';
|
import { styled } from '@mui/material';
|
||||||
|
import {
|
||||||
|
PlaygroundResultConstraintAccordionView
|
||||||
|
} from "./PlaygroundResultConstraintAccordion/PlaygroundResultConstraintAccordionView/PlaygroundResultConstraintAccordionView";
|
||||||
|
|
||||||
interface PlaygroundResultConstraintExecutionProps {
|
interface PlaygroundResultConstraintExecutionProps {
|
||||||
constraints?: PlaygroundConstraintSchema[];
|
constraints?: PlaygroundConstraintSchema[];
|
||||||
@ -16,7 +18,7 @@ interface PlaygroundResultConstraintExecutionProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const PlaygroundResultConstraintExecutionWrapper = styled('div')(
|
export const PlaygroundResultConstraintExecutionWrapper = styled('div')(
|
||||||
({ theme }) => ({
|
() => ({
|
||||||
width: '100%',
|
width: '100%',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
@ -38,7 +40,7 @@ export const PlaygroundResultConstraintExecution = ({
|
|||||||
condition={index > 0}
|
condition={index > 0}
|
||||||
show={<StrategySeparator text="AND" />}
|
show={<StrategySeparator text="AND" />}
|
||||||
/>
|
/>
|
||||||
<ConstraintAccordionView
|
<PlaygroundResultConstraintAccordionView
|
||||||
constraint={constraint}
|
constraint={constraint}
|
||||||
playgroundInput={input}
|
playgroundInput={input}
|
||||||
maxLength={compact ? 25 : 50}
|
maxLength={compact ? 25 : 50}
|
@ -1,14 +1,14 @@
|
|||||||
import {
|
import {
|
||||||
PlaygroundSegmentSchema,
|
PlaygroundSegmentSchema,
|
||||||
PlaygroundRequestSchema,
|
PlaygroundRequestSchema,
|
||||||
} from '../../../../../../../../../hooks/api/actions/usePlayground/playground.model';
|
} from '../../../../../../../../../../hooks/api/actions/usePlayground/playground.model';
|
||||||
import { PlaygroundResultConstraintExecution } from '../PlaygroundResultConstraintExecution/PlaygroundResultConstraintExecution';
|
import { PlaygroundResultConstraintExecution } from '../PlaygroundResultConstraintExecution/PlaygroundResultConstraintExecution';
|
||||||
import { CancelOutlined, DonutLarge } from '@mui/icons-material';
|
import { CancelOutlined, DonutLarge } from '@mui/icons-material';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { StrategySeparator } from '../../../../../../../../common/StrategySeparator/StrategySeparator';
|
import { StrategySeparator } from '../../../../../../../../../common/StrategySeparator/StrategySeparator';
|
||||||
import { useStyles } from './PlaygroundResultSegmentExecution.styles';
|
import { useStyles } from './PlaygroundResultSegmentExecution.styles';
|
||||||
import { styled, Typography } from '@mui/material';
|
import { styled, Typography } from '@mui/material';
|
||||||
import { ConditionallyRender } from '../../../../../../../../common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from '../../../../../../../../../common/ConditionallyRender/ConditionallyRender';
|
||||||
|
|
||||||
interface PlaygroundResultSegmentExecutionProps {
|
interface PlaygroundResultSegmentExecutionProps {
|
||||||
segments?: PlaygroundSegmentSchema[];
|
segments?: PlaygroundSegmentSchema[];
|
||||||
@ -43,7 +43,7 @@ const SegmentExecutionWrapper = styled('div')(({ theme }) => ({
|
|||||||
marginTop: theme.spacing(2),
|
marginTop: theme.spacing(2),
|
||||||
},
|
},
|
||||||
background: theme.palette.neutral.light,
|
background: theme.palette.neutral.light,
|
||||||
marginBottom: '8px',
|
marginBottom: theme.spacing(1),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const SegmentExecutionConstraintWrapper = styled('div')(({ theme }) => ({
|
const SegmentExecutionConstraintWrapper = styled('div')(({ theme }) => ({
|
||||||
@ -55,7 +55,7 @@ const SegmentResultTextWrapper = styled('div')(({ theme }) => ({
|
|||||||
display: 'inline-flex',
|
display: 'inline-flex',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
marginRight: '12px',
|
marginRight: '12px',
|
||||||
gap: '8px',
|
gap: theme.spacing(1),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const PlaygroundResultSegmentExecution = ({
|
export const PlaygroundResultSegmentExecution = ({
|
@ -1,24 +1,17 @@
|
|||||||
import { ConditionallyRender } from '../../../../../../../../common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { StrategySeparator } from '../../../../../../../../common/StrategySeparator/StrategySeparator';
|
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
|
||||||
import { Box, Chip, styled } from '@mui/material';
|
import { Box, Chip, styled } from '@mui/material';
|
||||||
import { useStyles } from './PlaygroundResultStrategyExecution.styles';
|
import { useStyles } from './PlaygroundResultStrategyExecution.styles';
|
||||||
import {
|
import {
|
||||||
PlaygroundRequestSchema,
|
PlaygroundRequestSchema,
|
||||||
PlaygroundStrategySchema,
|
PlaygroundStrategySchema,
|
||||||
} from '../../../../../../../../../hooks/api/actions/usePlayground/playground.model';
|
} from 'hooks/api/actions/usePlayground/playground.model';
|
||||||
import useUiConfig from '../../../../../../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import React, { Fragment } from 'react';
|
import React from 'react';
|
||||||
import { PlaygroundResultConstraintExecution } from '../PlaygroundResultConstraintExecution/PlaygroundResultConstraintExecution';
|
import { PlaygroundResultConstraintExecution } from './PlaygroundResultConstraintExecution/PlaygroundResultConstraintExecution';
|
||||||
import { PlaygroundResultSegmentExecution } from '../PlaygroundResultSegmentExecution/PlaygroundResultSegmentExecution';
|
import { PlaygroundResultSegmentExecution } from './PlaygroundResultSegmentExecution/PlaygroundResultSegmentExecution';
|
||||||
import {
|
import { PlaygroundResultStrategyExecutionParameters } from './PlaygroundResultStrategyExecutionParameters/PlaygroundResultStrategyExecutionParameters';
|
||||||
parseParameterNumber,
|
import { PlaygroundResultStrategyExecutionCustomStrategyParams } from './PlaygroundResultStrategyExecutionCustomStrategyParams./PlaygroundResultStrategyExecutionCustomStrategyParams';
|
||||||
parseParameterString,
|
|
||||||
parseParameterStrings,
|
|
||||||
} from '../../../../../../../../../utils/parseParameter';
|
|
||||||
import PercentageCircle from '../../../../../../../../common/PercentageCircle/PercentageCircle';
|
|
||||||
import StringTruncator from '../../../../../../../../common/StringTruncator/StringTruncator';
|
|
||||||
import { useStrategies } from '../../../../../../../../../hooks/api/getters/useStrategies/useStrategies';
|
|
||||||
import { PlaygroundConstraintItem } from '../PlaygroundConstraintItem/PlaygroundConstraintItem';
|
|
||||||
|
|
||||||
interface PlaygroundResultStrategyExecutionProps {
|
interface PlaygroundResultStrategyExecutionProps {
|
||||||
strategyResult: PlaygroundStrategySchema;
|
strategyResult: PlaygroundStrategySchema;
|
||||||
@ -31,7 +24,7 @@ const StyledStrategyExecutionWrapper = styled('div')(({ theme }) => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledParamWrapper = styled('div')(({ theme }) => ({
|
const StyledParamWrapper = styled('div')(({ theme }) => ({
|
||||||
padding: theme.spacing(2, 1),
|
padding: theme.spacing(0, 0),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const PlaygroundResultStrategyExecution = ({
|
export const PlaygroundResultStrategyExecution = ({
|
||||||
@ -39,7 +32,7 @@ export const PlaygroundResultStrategyExecution = ({
|
|||||||
input,
|
input,
|
||||||
}: PlaygroundResultStrategyExecutionProps) => {
|
}: PlaygroundResultStrategyExecutionProps) => {
|
||||||
const { name, constraints, segments, parameters } = strategyResult;
|
const { name, constraints, segments, parameters } = strategyResult;
|
||||||
const { strategies } = useStrategies();
|
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
|
|
||||||
@ -49,267 +42,6 @@ export const PlaygroundResultStrategyExecution = ({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const definition = strategies.find(strategyDefinition => {
|
|
||||||
return strategyDefinition.name === strategyResult.name;
|
|
||||||
});
|
|
||||||
|
|
||||||
const renderParameters = () => {
|
|
||||||
return Object.keys(parameters).map(key => {
|
|
||||||
switch (key) {
|
|
||||||
case 'rollout':
|
|
||||||
case 'Rollout':
|
|
||||||
const percentage = parseParameterNumber(parameters[key]);
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
className={styles.summary}
|
|
||||||
key={key}
|
|
||||||
sx={{ display: 'flex', alignItems: 'center' }}
|
|
||||||
>
|
|
||||||
<Box sx={{ mr: '1rem' }}>
|
|
||||||
<PercentageCircle
|
|
||||||
percentage={percentage}
|
|
||||||
size="2rem"
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<div>
|
|
||||||
<Chip
|
|
||||||
color="success"
|
|
||||||
variant="outlined"
|
|
||||||
size="small"
|
|
||||||
label={`${percentage}%`}
|
|
||||||
/>{' '}
|
|
||||||
of your base{' '}
|
|
||||||
{constraints.length > 0
|
|
||||||
? 'who match constraints'
|
|
||||||
: ''}{' '}
|
|
||||||
is included.
|
|
||||||
</div>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
case 'userIds':
|
|
||||||
case 'UserIds':
|
|
||||||
const users = parseParameterStrings(parameters[key]);
|
|
||||||
return (
|
|
||||||
<PlaygroundConstraintItem
|
|
||||||
key={key}
|
|
||||||
value={users}
|
|
||||||
text="user"
|
|
||||||
input={
|
|
||||||
Boolean(input?.context?.[key])
|
|
||||||
? input?.context?.[key]
|
|
||||||
: 'no value'
|
|
||||||
}
|
|
||||||
showReason={
|
|
||||||
Boolean(input?.context?.[key])
|
|
||||||
? !users.includes(input?.context?.[key])
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'hostNames':
|
|
||||||
case 'HostNames':
|
|
||||||
const hosts = parseParameterStrings(parameters[key]);
|
|
||||||
console.log(input?.context);
|
|
||||||
console.log(key);
|
|
||||||
console.log(input?.context?.[key]);
|
|
||||||
console.log(hosts.includes(input?.context?.[key]));
|
|
||||||
return (
|
|
||||||
<PlaygroundConstraintItem
|
|
||||||
key={key}
|
|
||||||
value={hosts}
|
|
||||||
text={'host'}
|
|
||||||
input={
|
|
||||||
Boolean(input?.context?.[key])
|
|
||||||
? input?.context?.[key]
|
|
||||||
: 'no value'
|
|
||||||
}
|
|
||||||
showReason={
|
|
||||||
Boolean(input?.context?.[key])
|
|
||||||
? !hosts.includes(input?.context?.[key])
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'IPs':
|
|
||||||
const IPs = parseParameterStrings(parameters[key]);
|
|
||||||
return (
|
|
||||||
<PlaygroundConstraintItem
|
|
||||||
key={key}
|
|
||||||
value={IPs}
|
|
||||||
text={'IP'}
|
|
||||||
input={
|
|
||||||
Boolean(input?.context?.[key])
|
|
||||||
? input?.context?.[key]
|
|
||||||
: 'no value'
|
|
||||||
}
|
|
||||||
showReason={
|
|
||||||
Boolean(input?.context?.[key])
|
|
||||||
? !IPs.includes(input?.context?.[key])
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'stickiness':
|
|
||||||
case 'groupId':
|
|
||||||
return null;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderCustomStrategyParameters = () => {
|
|
||||||
if (!definition?.editable) return null;
|
|
||||||
return definition?.parameters.map((param: any, index: number) => {
|
|
||||||
const notLastItem = index !== definition?.parameters?.length - 1;
|
|
||||||
switch (param?.type) {
|
|
||||||
case 'list':
|
|
||||||
const values = parseParameterStrings(
|
|
||||||
strategyResult?.parameters[param.name]
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<Fragment key={param?.name}>
|
|
||||||
<PlaygroundConstraintItem
|
|
||||||
value={values}
|
|
||||||
text={param.name}
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={notLastItem}
|
|
||||||
show={<StrategySeparator text="AND" />}
|
|
||||||
/>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
case 'percentage':
|
|
||||||
return (
|
|
||||||
<Fragment key={param?.name}>
|
|
||||||
<div>
|
|
||||||
<Chip
|
|
||||||
size="small"
|
|
||||||
variant="outlined"
|
|
||||||
color="success"
|
|
||||||
label={`${
|
|
||||||
strategyResult?.parameters[param.name]
|
|
||||||
}%`}
|
|
||||||
/>{' '}
|
|
||||||
of your base{' '}
|
|
||||||
{constraints?.length > 0
|
|
||||||
? 'who match constraints'
|
|
||||||
: ''}{' '}
|
|
||||||
is included.
|
|
||||||
</div>
|
|
||||||
<PercentageCircle
|
|
||||||
percentage={parseParameterNumber(
|
|
||||||
strategyResult.parameters[param.name]
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={notLastItem}
|
|
||||||
show={<StrategySeparator text="AND" />}
|
|
||||||
/>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
case 'boolean':
|
|
||||||
return (
|
|
||||||
<Fragment key={param.name}>
|
|
||||||
<p key={param.name}>
|
|
||||||
<StringTruncator
|
|
||||||
maxLength={15}
|
|
||||||
maxWidth="150"
|
|
||||||
text={param.name}
|
|
||||||
/>{' '}
|
|
||||||
{strategyResult.parameters[param.name]}
|
|
||||||
</p>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={
|
|
||||||
typeof strategyResult.parameters[
|
|
||||||
param.name
|
|
||||||
] !== 'undefined'
|
|
||||||
}
|
|
||||||
show={
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={notLastItem}
|
|
||||||
show={<StrategySeparator text="AND" />}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
case 'string':
|
|
||||||
const value = parseParameterString(
|
|
||||||
strategyResult.parameters[param.name]
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={
|
|
||||||
typeof strategyResult.parameters[param.name] !==
|
|
||||||
'undefined'
|
|
||||||
}
|
|
||||||
key={param.name}
|
|
||||||
show={
|
|
||||||
<>
|
|
||||||
<p className={styles.valueContainer}>
|
|
||||||
<StringTruncator
|
|
||||||
maxWidth="150"
|
|
||||||
maxLength={15}
|
|
||||||
text={param.name}
|
|
||||||
/>
|
|
||||||
<span className={styles.valueSeparator}>
|
|
||||||
is set to
|
|
||||||
</span>
|
|
||||||
<StringTruncator
|
|
||||||
maxWidth="300"
|
|
||||||
text={value}
|
|
||||||
maxLength={50}
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={notLastItem}
|
|
||||||
show={<StrategySeparator text="AND" />}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'number':
|
|
||||||
const number = parseParameterNumber(
|
|
||||||
strategyResult.parameters[param.name]
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={number !== undefined}
|
|
||||||
key={param.name}
|
|
||||||
show={
|
|
||||||
<>
|
|
||||||
<p className={styles.valueContainer}>
|
|
||||||
<StringTruncator
|
|
||||||
maxLength={15}
|
|
||||||
maxWidth="150"
|
|
||||||
text={param.name}
|
|
||||||
/>
|
|
||||||
<span className={styles.valueSeparator}>
|
|
||||||
is set to
|
|
||||||
</span>
|
|
||||||
<StringTruncator
|
|
||||||
maxWidth="300"
|
|
||||||
text={String(number)}
|
|
||||||
maxLength={50}
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={notLastItem}
|
|
||||||
show={<StrategySeparator text="AND" />}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case 'default':
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledStrategyExecutionWrapper>
|
<StyledStrategyExecutionWrapper>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
@ -359,8 +91,18 @@ export const PlaygroundResultStrategyExecution = ({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<StyledParamWrapper>
|
<StyledParamWrapper>
|
||||||
{renderParameters()}
|
<PlaygroundResultStrategyExecutionParameters
|
||||||
{renderCustomStrategyParameters()}
|
parameters={parameters}
|
||||||
|
constraints={constraints}
|
||||||
|
input={input}
|
||||||
|
/>
|
||||||
|
<StyledParamWrapper sx={{ pt: 2}}>
|
||||||
|
<PlaygroundResultStrategyExecutionCustomStrategyParams
|
||||||
|
strategyName={strategyResult.name}
|
||||||
|
parameters={parameters}
|
||||||
|
constraints={constraints}
|
||||||
|
/>
|
||||||
|
</StyledParamWrapper>
|
||||||
</StyledParamWrapper>
|
</StyledParamWrapper>
|
||||||
</StyledStrategyExecutionWrapper>
|
</StyledStrategyExecutionWrapper>
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,181 @@
|
|||||||
|
import {
|
||||||
|
parseParameterNumber,
|
||||||
|
parseParameterString,
|
||||||
|
parseParameterStrings,
|
||||||
|
} from 'utils/parseParameter';
|
||||||
|
import React, { Fragment } from 'react';
|
||||||
|
import { PlaygroundConstraintItem } from '../PlaygroundConstraintItem/PlaygroundConstraintItem';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
|
||||||
|
import { Chip } from '@mui/material';
|
||||||
|
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
|
||||||
|
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
||||||
|
import { IStrategy } from 'interfaces/strategy';
|
||||||
|
import { PlaygroundConstraintSchema } from 'hooks/api/actions/usePlayground/playground.model';
|
||||||
|
import { useStyles } from '../PlaygroundResultStrategyExecution.styles';
|
||||||
|
import { useStrategies } from '../../../../../../../../../../hooks/api/getters/useStrategies/useStrategies';
|
||||||
|
|
||||||
|
interface PlaygroundResultStrategyExecutionCustomStrategyProps {
|
||||||
|
parameters: { [key: string]: string };
|
||||||
|
strategyName: string;
|
||||||
|
constraints: PlaygroundConstraintSchema[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PlaygroundResultStrategyExecutionCustomStrategyParams = ({
|
||||||
|
strategyName,
|
||||||
|
constraints,
|
||||||
|
parameters,
|
||||||
|
}: PlaygroundResultStrategyExecutionCustomStrategyProps) => {
|
||||||
|
const { classes: styles } = useStyles();
|
||||||
|
const { strategies } = useStrategies();
|
||||||
|
|
||||||
|
const definition = strategies.find(strategyDefinition => {
|
||||||
|
return strategyDefinition.name === strategyName;
|
||||||
|
});
|
||||||
|
|
||||||
|
const renderCustomStrategyParameters = () => {
|
||||||
|
if (!definition?.editable) return null;
|
||||||
|
return definition?.parameters.map((param: any, index: number) => {
|
||||||
|
const notLastItem = index !== definition?.parameters?.length - 1;
|
||||||
|
switch (param?.type) {
|
||||||
|
case 'list':
|
||||||
|
const values = parseParameterStrings(
|
||||||
|
parameters[param.name]
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<Fragment key={param?.name}>
|
||||||
|
<PlaygroundConstraintItem
|
||||||
|
value={values}
|
||||||
|
text={param.name}
|
||||||
|
/>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={notLastItem}
|
||||||
|
show={<StrategySeparator text="AND" />}
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
case 'percentage':
|
||||||
|
return (
|
||||||
|
<Fragment key={param?.name}>
|
||||||
|
<div>
|
||||||
|
<Chip
|
||||||
|
size="small"
|
||||||
|
variant="outlined"
|
||||||
|
color="success"
|
||||||
|
label={`${parameters[param.name]}%`}
|
||||||
|
/>{' '}
|
||||||
|
of your base{' '}
|
||||||
|
{constraints?.length > 0
|
||||||
|
? 'who match constraints'
|
||||||
|
: ''}{' '}
|
||||||
|
is included.
|
||||||
|
</div>
|
||||||
|
<PercentageCircle
|
||||||
|
percentage={parseParameterNumber(
|
||||||
|
parameters[param.name]
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={notLastItem}
|
||||||
|
show={<StrategySeparator text="AND" />}
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
case 'boolean':
|
||||||
|
return (
|
||||||
|
<Fragment key={param.name}>
|
||||||
|
<p key={param.name}>
|
||||||
|
<StringTruncator
|
||||||
|
maxLength={15}
|
||||||
|
maxWidth="150"
|
||||||
|
text={param.name}
|
||||||
|
/>{' '}
|
||||||
|
{parameters[param.name]}
|
||||||
|
</p>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={
|
||||||
|
typeof parameters[param.name] !==
|
||||||
|
'undefined'
|
||||||
|
}
|
||||||
|
show={
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={notLastItem}
|
||||||
|
show={<StrategySeparator text="AND" />}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
case 'string':
|
||||||
|
const value = parseParameterString(parameters[param.name]);
|
||||||
|
return (
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={
|
||||||
|
typeof parameters[param.name] !== 'undefined'
|
||||||
|
}
|
||||||
|
key={param.name}
|
||||||
|
show={
|
||||||
|
<>
|
||||||
|
<p className={styles.valueContainer}>
|
||||||
|
<StringTruncator
|
||||||
|
maxWidth="150"
|
||||||
|
maxLength={15}
|
||||||
|
text={param.name}
|
||||||
|
/>
|
||||||
|
<span className={styles.valueSeparator}>
|
||||||
|
is set to
|
||||||
|
</span>
|
||||||
|
<StringTruncator
|
||||||
|
maxWidth="300"
|
||||||
|
text={value}
|
||||||
|
maxLength={50}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={notLastItem}
|
||||||
|
show={<StrategySeparator text="AND" />}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case 'number':
|
||||||
|
const number = parseParameterNumber(parameters[param.name]);
|
||||||
|
return (
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={number !== undefined}
|
||||||
|
key={param.name}
|
||||||
|
show={
|
||||||
|
<>
|
||||||
|
<p className={styles.valueContainer}>
|
||||||
|
<StringTruncator
|
||||||
|
maxLength={15}
|
||||||
|
maxWidth="150"
|
||||||
|
text={param.name}
|
||||||
|
/>
|
||||||
|
<span className={styles.valueSeparator}>
|
||||||
|
is set to
|
||||||
|
</span>
|
||||||
|
<StringTruncator
|
||||||
|
maxWidth="300"
|
||||||
|
text={String(number)}
|
||||||
|
maxLength={50}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={notLastItem}
|
||||||
|
show={<StrategySeparator text="AND" />}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case 'default':
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return <>{renderCustomStrategyParameters()}</>;
|
||||||
|
};
|
@ -0,0 +1,130 @@
|
|||||||
|
import {
|
||||||
|
parseParameterNumber,
|
||||||
|
parseParameterStrings,
|
||||||
|
} from 'utils/parseParameter';
|
||||||
|
import { Box, Chip } from '@mui/material';
|
||||||
|
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
|
||||||
|
import { PlaygroundConstraintItem } from '../PlaygroundConstraintItem/PlaygroundConstraintItem';
|
||||||
|
import React from 'react';
|
||||||
|
import { useStyles } from '../PlaygroundResultStrategyExecution.styles';
|
||||||
|
import {
|
||||||
|
PlaygroundConstraintSchema,
|
||||||
|
PlaygroundRequestSchema,
|
||||||
|
} from 'hooks/api/actions/usePlayground/playground.model';
|
||||||
|
import {getMappedParam} from "../helepers";
|
||||||
|
|
||||||
|
export interface PlaygroundResultStrategyExecutionParametersProps {
|
||||||
|
parameters: { [key: string]: string };
|
||||||
|
constraints: PlaygroundConstraintSchema[];
|
||||||
|
input?: PlaygroundRequestSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PlaygroundResultStrategyExecutionParameters = ({
|
||||||
|
parameters,
|
||||||
|
constraints,
|
||||||
|
input,
|
||||||
|
}: PlaygroundResultStrategyExecutionParametersProps) => {
|
||||||
|
const { classes: styles } = useStyles();
|
||||||
|
const renderParameters = () => {
|
||||||
|
return Object.keys(parameters).map(key => {
|
||||||
|
switch (key) {
|
||||||
|
case 'rollout':
|
||||||
|
case 'Rollout':
|
||||||
|
const percentage = parseParameterNumber(parameters[key]);
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
className={styles.summary}
|
||||||
|
key={key}
|
||||||
|
sx={{ display: 'flex', alignItems: 'center' }}
|
||||||
|
>
|
||||||
|
<Box sx={{ mr: '1rem' }}>
|
||||||
|
<PercentageCircle
|
||||||
|
percentage={percentage}
|
||||||
|
size="2rem"
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<div>
|
||||||
|
<Chip
|
||||||
|
color="success"
|
||||||
|
variant="outlined"
|
||||||
|
size="small"
|
||||||
|
label={`${percentage}%`}
|
||||||
|
/>{' '}
|
||||||
|
of your base{' '}
|
||||||
|
{constraints.length > 0
|
||||||
|
? 'who match constraints'
|
||||||
|
: ''}{' '}
|
||||||
|
is included.
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
case 'userIds':
|
||||||
|
case 'UserIds':
|
||||||
|
const users = parseParameterStrings(parameters[key]);
|
||||||
|
return (
|
||||||
|
<PlaygroundConstraintItem
|
||||||
|
key={key}
|
||||||
|
value={users}
|
||||||
|
text="user"
|
||||||
|
input={
|
||||||
|
Boolean(input?.context?.[getMappedParam(key)])
|
||||||
|
? input?.context?.[getMappedParam(key)]
|
||||||
|
: 'no value'
|
||||||
|
}
|
||||||
|
showReason={
|
||||||
|
Boolean(input?.context?.[getMappedParam(key)])
|
||||||
|
? !users.includes(input?.context?.[getMappedParam(key)])
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case 'hostNames':
|
||||||
|
case 'HostNames':
|
||||||
|
const hosts = parseParameterStrings(parameters[key]);
|
||||||
|
return (
|
||||||
|
<PlaygroundConstraintItem
|
||||||
|
key={key}
|
||||||
|
value={hosts}
|
||||||
|
text={'host'}
|
||||||
|
input={
|
||||||
|
Boolean(input?.context?.[getMappedParam(key)])
|
||||||
|
? input?.context?.[getMappedParam(key)]
|
||||||
|
: 'no value'
|
||||||
|
}
|
||||||
|
showReason={
|
||||||
|
Boolean(input?.context?.[getMappedParam(key)])
|
||||||
|
? !hosts.includes(input?.context?.[getMappedParam(key)])
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case 'IPs':
|
||||||
|
const IPs = parseParameterStrings(parameters[key]);
|
||||||
|
return (
|
||||||
|
<PlaygroundConstraintItem
|
||||||
|
key={key}
|
||||||
|
value={IPs}
|
||||||
|
text={'IP'}
|
||||||
|
input={
|
||||||
|
Boolean(input?.context?.[getMappedParam(key)])
|
||||||
|
? input?.context?.[getMappedParam(key)]
|
||||||
|
: 'no value'
|
||||||
|
}
|
||||||
|
showReason={
|
||||||
|
Boolean(input?.context?.[getMappedParam(key)])
|
||||||
|
? !IPs.includes(input?.context?.[getMappedParam(key)])
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case 'stickiness':
|
||||||
|
case 'groupId':
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return <>{renderParameters()}</>;
|
||||||
|
};
|
@ -0,0 +1,14 @@
|
|||||||
|
export const getMappedParam = (key: string) => {
|
||||||
|
switch (key) {
|
||||||
|
case 'userIds':
|
||||||
|
case 'UserIds':
|
||||||
|
return 'userId';
|
||||||
|
case 'hostNames':
|
||||||
|
case 'HostNames':
|
||||||
|
return 'hostname';
|
||||||
|
case 'IPs':
|
||||||
|
return 'remoteAddress'
|
||||||
|
default:
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
@ -8,8 +8,8 @@ import { Alert, styled, Typography } from '@mui/material';
|
|||||||
import { PlaygroundResultFeatureStrategyItem } from './PlaygroundResultFeatureStrategyItem/PlaygroundResultFeatureStrategyItem';
|
import { PlaygroundResultFeatureStrategyItem } from './PlaygroundResultFeatureStrategyItem/PlaygroundResultFeatureStrategyItem';
|
||||||
|
|
||||||
const StyledAlertWrapper = styled('div')(({ theme }) => ({
|
const StyledAlertWrapper = styled('div')(({ theme }) => ({
|
||||||
width: '100%',
|
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
padding: `0, 4px`,
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
borderRadius: theme.shape.borderRadiusMedium,
|
borderRadius: theme.shape.borderRadiusMedium,
|
||||||
border: `1px solid ${theme.palette.info.border}`,
|
border: `1px solid ${theme.palette.info.border}`,
|
||||||
@ -70,10 +70,10 @@ export const WrappedPlaygroundResultStrategyList = ({
|
|||||||
input,
|
input,
|
||||||
}: WrappedPlaygroundResultStrategyListProps) => {
|
}: WrappedPlaygroundResultStrategyListProps) => {
|
||||||
return (
|
return (
|
||||||
<StyledAlertWrapper>
|
<StyledAlertWrapper sx={{pb: 1}}>
|
||||||
<StyledAlert severity={'info'} color={'info'}>
|
<StyledAlert severity={'info'} color={'info'}>
|
||||||
If environment would be enabled then this feature would be{' '}
|
If environment would be enabled then this feature would be{' '}
|
||||||
{feature.isEnabled ? 'TRUE' : 'FALSE'} and the strategies would
|
{feature.strategies.result ? 'TRUE' : 'FALSE'} and the strategies would
|
||||||
evaluate like this:{' '}
|
evaluate like this:{' '}
|
||||||
</StyledAlert>
|
</StyledAlert>
|
||||||
<StyledListWrapper>
|
<StyledListWrapper>
|
||||||
|
@ -3,7 +3,7 @@ import { Box, styled } from '@mui/material';
|
|||||||
import { PlaygroundResultChip } from '../PlaygroundResultChip/PlaygroundResultChip';
|
import { PlaygroundResultChip } from '../PlaygroundResultChip/PlaygroundResultChip';
|
||||||
|
|
||||||
interface IFeatureStatusCellProps {
|
interface IFeatureStatusCellProps {
|
||||||
enabled: boolean | 'unevaluated';
|
enabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyledCellBox = styled(Box)(({ theme }) => ({
|
const StyledCellBox = styled(Box)(({ theme }) => ({
|
||||||
@ -22,10 +22,7 @@ export const FeatureStatusCell = ({ enabled }: IFeatureStatusCellProps) => {
|
|||||||
<StyledChipWrapper data-loading>
|
<StyledChipWrapper data-loading>
|
||||||
<PlaygroundResultChip
|
<PlaygroundResultChip
|
||||||
enabled={enabled}
|
enabled={enabled}
|
||||||
label={
|
label={enabled
|
||||||
enabled === 'unevaluated'
|
|
||||||
? '?'
|
|
||||||
: Boolean(enabled)
|
|
||||||
? 'True'
|
? 'True'
|
||||||
: 'False'
|
: 'False'
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ export interface PlaygroundConstraintSchema {
|
|||||||
*/
|
*/
|
||||||
operator: Operator;
|
operator: Operator;
|
||||||
/**
|
/**
|
||||||
* Whether the operator should be case sensitive or not. Defaults to `false` (being case sensitive).
|
* Whether the operator should be case-sensitive or not. Defaults to `false` (being case-sensitive).
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
* @memberof PlaygroundConstraintSchema
|
* @memberof PlaygroundConstraintSchema
|
||||||
*/
|
*/
|
||||||
@ -64,7 +64,7 @@ export interface PlaygroundFeatureSchema {
|
|||||||
* @type {Array<PlaygroundStrategySchema>}
|
* @type {Array<PlaygroundStrategySchema>}
|
||||||
* @memberof PlaygroundFeatureSchema
|
* @memberof PlaygroundFeatureSchema
|
||||||
*/
|
*/
|
||||||
strategies: Array<PlaygroundStrategySchema>;
|
strategies: PlaygroundStrategyResultSchema;
|
||||||
/**
|
/**
|
||||||
* Whether the feature is active and would be evaluated in the provided environment in a normal SDK context.
|
* Whether the feature is active and would be evaluated in the provided environment in a normal SDK context.
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
@ -76,7 +76,7 @@ export interface PlaygroundFeatureSchema {
|
|||||||
* @type {boolean | 'unevaluated'}
|
* @type {boolean | 'unevaluated'}
|
||||||
* @memberof PlaygroundFeatureSchema
|
* @memberof PlaygroundFeatureSchema
|
||||||
*/
|
*/
|
||||||
isEnabled: boolean | 'unevaluated';
|
isEnabled: boolean;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {PlaygroundFeatureSchemaVariant}
|
* @type {PlaygroundFeatureSchemaVariant}
|
||||||
@ -200,6 +200,11 @@ export interface PlaygroundSegmentSchema {
|
|||||||
constraints: Array<PlaygroundConstraintSchema>;
|
constraints: Array<PlaygroundConstraintSchema>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PlaygroundStrategyResultSchema {
|
||||||
|
result: boolean | "unknown";
|
||||||
|
data?: Array<PlaygroundStrategySchema>
|
||||||
|
}
|
||||||
|
|
||||||
export interface PlaygroundStrategySchema {
|
export interface PlaygroundStrategySchema {
|
||||||
/**
|
/**
|
||||||
* The strategy's name.
|
* The strategy's name.
|
||||||
|
Loading…
Reference in New Issue
Block a user