1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-07-26 13:48:33 +02:00

improvements

This commit is contained in:
andreas-unleash 2022-08-03 16:19:48 +03:00
parent 76b33cdd11
commit 787c5f317c
6 changed files with 121 additions and 38 deletions

View File

@ -5,6 +5,7 @@ import {
AccordionDetails, AccordionDetails,
SxProps, SxProps,
Theme, Theme,
useTheme,
} from '@mui/material'; } from '@mui/material';
import { IConstraint } from 'interfaces/strategy'; import { IConstraint } from 'interfaces/strategy';
import { ConstraintAccordionViewBody } from './ConstraintAccordionViewBody/ConstraintAccordionViewBody'; import { ConstraintAccordionViewBody } from './ConstraintAccordionViewBody/ConstraintAccordionViewBody';
@ -17,12 +18,12 @@ import {
} from 'constants/operators'; } from 'constants/operators';
import { useStyles } from '../ConstraintAccordion.styles'; import { useStyles } from '../ConstraintAccordion.styles';
import { import {
PlaygroundFeatureStrategyConstraintResult, PlaygroundConstraintSchema,
PlaygroundRequestSchema, PlaygroundRequestSchema,
} from '../../../../hooks/api/actions/usePlayground/playground.model'; } from '../../../../hooks/api/actions/usePlayground/playground.model';
interface IConstraintAccordionViewProps { interface IConstraintAccordionViewProps {
constraint: IConstraint | PlaygroundFeatureStrategyConstraintResult; constraint: IConstraint | PlaygroundConstraintSchema;
onDelete?: () => void; onDelete?: () => void;
onEdit?: () => void; onEdit?: () => void;
playgroundInput?: PlaygroundRequestSchema; playgroundInput?: PlaygroundRequestSchema;
@ -41,6 +42,7 @@ export const ConstraintAccordionView = ({
const { classes: styles } = useStyles(); const { classes: styles } = useStyles();
const [expandable, setExpandable] = useState(true); const [expandable, setExpandable] = useState(true);
const [expanded, setExpanded] = useState(false); const [expanded, setExpanded] = useState(false);
const theme = useTheme();
const singleValue = oneOf( const singleValue = oneOf(
[...semVerOperators, ...numOperators, ...dateOperators], [...semVerOperators, ...numOperators, ...dateOperators],
@ -51,6 +53,11 @@ 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
@ -68,6 +75,7 @@ export const ConstraintAccordionView = ({
'&:hover': { '&:hover': {
cursor: expandable ? 'pointer' : 'default!important', cursor: expandable ? 'pointer' : 'default!important',
}, },
backgroundColor: backgroundColor,
}} }}
> >
<ConstraintAccordionViewHeader <ConstraintAccordionViewHeader

View File

@ -23,19 +23,30 @@ export const PlaygroundResultFeatureDetails = ({
const { classes: styles } = useStyles(); const { classes: styles } = useStyles();
const theme = useTheme(); const theme = useTheme();
const description = feature.isEnabled console.log(feature);
? `This feature toggle is True in ${input?.environment} because `
: `This feature toggle is False in ${input?.environment} because `;
const reason = feature.isEnabled const description =
? 'at least one strategy is True' feature.isEnabled === 'unevaluated'
: feature?.isEnabledInCurrentEnvironment ? `This feature toggle is Unevaluated in ${input?.environment} because `
? 'the environment is disabled' : feature.isEnabled
: 'all strategies are False'; ? `This feature toggle is True in ${input?.environment} because `
: `This feature toggle is False in ${input?.environment} because `;
const color = feature.isEnabled const reason =
? theme.palette.success.main feature.isEnabled === 'unevaluated'
: theme.palette.error.main; ? 'custom strategies are not evaluated yet'
: feature.isEnabled
? 'at least one strategy is True'
: feature?.isEnabledInCurrentEnvironment
? 'the environment is disabled'
: 'all strategies are False';
const color =
feature.isEnabled === 'unevaluated'
? theme.palette.warning.main
: feature.isEnabled
? theme.palette.success.main
: theme.palette.error.main;
const noValueTxt = checkForEmptyValues(input?.context) const noValueTxt = checkForEmptyValues(input?.context)
? 'You did not provide a value for your context field in step 2 of the configuration' ? 'You did not provide a value for your context field in step 2 of the configuration'
@ -56,7 +67,19 @@ export const PlaygroundResultFeatureDetails = ({
{feature.name} {feature.name}
</Typography> </Typography>
<span> <span>
<PlaygroundResultChip enabled={feature.isEnabled} /> <PlaygroundResultChip
enabled={
feature.isEnabled === 'unevaluated'
? 'unknown'
: feature.isEnabled
}
label={String(feature.isEnabled)}
size={
feature.isEnabled === 'unevaluated'
? 'large'
: 'default'
}
/>
</span> </span>
</div> </div>
<IconButton onClick={onCloseClick} className={styles.icon}> <IconButton onClick={onCloseClick} className={styles.icon}>

View File

@ -12,6 +12,10 @@ export const useStyles = makeStyles()(theme => ({
justifyContent: 'space-between', justifyContent: 'space-between',
gap: theme.spacing(2), gap: theme.spacing(2),
}, },
disabled: {
backgroundColor: theme.palette.neutral.light,
opacity: '90%',
},
chip: { chip: {
margin: '0.25rem', margin: '0.25rem',
}, },

View File

@ -3,6 +3,7 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
import { useStyles } from './PlaygroundConstraintItem.styles'; import { useStyles } from './PlaygroundConstraintItem.styles';
import StringTruncator from 'component/common/StringTruncator/StringTruncator'; import StringTruncator from 'component/common/StringTruncator/StringTruncator';
import { CancelOutlined } from '@mui/icons-material'; import { CancelOutlined } from '@mui/icons-material';
import classnames from 'classnames';
interface IConstraintItemProps { interface IConstraintItemProps {
value: string[]; value: string[];
@ -23,10 +24,13 @@ export const PlaygroundConstraintItem = ({
const color = input === 'no value' ? 'error' : 'neutral'; const color = input === 'no value' ? 'error' : 'neutral';
const reason = `value does not match any ${text}`; const reason = `value does not match any ${text}`;
console.log(value, text, input, showReason);
return ( return (
<div className={styles.container}> <div
className={classnames(
styles.container,
showReason ? styles.disabled : ''
)}
>
<Typography variant="subtitle1" color={theme.palette[color].main}> <Typography variant="subtitle1" color={theme.palette[color].main}>
{input} {input}
</Typography> </Typography>
@ -72,6 +76,7 @@ export const PlaygroundConstraintItem = ({
<ConditionallyRender <ConditionallyRender
condition={Boolean(showReason)} condition={Boolean(showReason)}
show={<CancelOutlined color={'error'} />} show={<CancelOutlined color={'error'} />}
elseShow={<div />}
/> />
</div> </div>
); );

View File

@ -40,14 +40,15 @@ export const PlaygroundResultFeatureStrategyItem = ({
const theme = useTheme(); const theme = useTheme();
const Icon = getFeatureStrategyIcon(strategy.name); const Icon = getFeatureStrategyIcon(strategy.name);
const label = const label =
result.evaluationStatus !== 'complete' result.evaluationStatus === 'incomplete'
? 'Unevaluated' ? 'Unknown'
: result.enabled : result.enabled
? 'True' ? 'True'
: 'False'; : 'False';
const border = result.enabled const border =
? `1px solid ${theme.palette.success.main}` result.enabled && result.evaluationStatus === 'complete'
: `1px solid ${theme.palette.divider}`; ? `1px solid ${theme.palette.success.main}`
: `1px solid ${theme.palette.divider}`;
return ( return (
<Box <Box
@ -77,6 +78,11 @@ export const PlaygroundResultFeatureStrategyItem = ({
showIcon={false} showIcon={false}
enabled={result.enabled} enabled={result.enabled}
label={label} label={label}
size={
result.evaluationStatus === 'incomplete'
? 'medium'
: 'default'
}
/> />
</div> </div>
<div className={styles.body}> <div className={styles.body}>

View File

@ -6,22 +6,25 @@ import { ReactComponent as FeatureEnabledIcon } from '../../../../../assets/icon
import { ReactComponent as FeatureDisabledIcon } from '../../../../../assets/icons/isenabled-false.svg'; import { ReactComponent as FeatureDisabledIcon } from '../../../../../assets/icons/isenabled-false.svg';
interface IResultChipProps { interface IResultChipProps {
enabled: boolean | 'unevaluated'; enabled: boolean | 'unknown';
// Result icon - defaults to true // Result icon - defaults to true
showIcon?: boolean; showIcon?: boolean;
label?: string; label?: string;
size?: 'default' | 'medium' | 'large';
} }
export const StyledChip = styled(Chip)(({ theme }) => ({ export const StyledChip = styled(Chip)<{ width?: number }>(
width: 60, ({ theme, width }) => ({
height: 24, width: width ?? 60,
borderRadius: theme.shape.borderRadius, height: 24,
fontWeight: theme.typography.fontWeightMedium, borderRadius: theme.shape.borderRadius,
['& .MuiChip-label']: { fontWeight: theme.typography.fontWeightMedium,
padding: 0, ['& .MuiChip-label']: {
paddingLeft: theme.spacing(0.5), padding: 0,
}, paddingLeft: theme.spacing(0.5),
})); },
})
);
export const StyledFalseChip = styled(StyledChip)(({ theme }) => ({ export const StyledFalseChip = styled(StyledChip)(({ theme }) => ({
border: `1px solid ${theme.palette.error.main}`, border: `1px solid ${theme.palette.error.main}`,
@ -45,15 +48,27 @@ export const StyledTrueChip = styled(StyledChip)(({ theme }) => ({
}, },
})); }));
export const StyledUnknownChip = styled(StyledChip)(({ theme }) => ({
border: `1px solid ${theme.palette.warning.main}`,
backgroundColor: colors.orange['100'],
['& .MuiChip-label']: {
color: theme.palette.warning.main,
},
['& .MuiChip-icon']: {
color: theme.palette.warning.main,
},
}));
export const PlaygroundResultChip = ({ export const PlaygroundResultChip = ({
enabled, enabled,
showIcon = true, showIcon = true,
label, label,
size = 'default',
}: IResultChipProps) => { }: IResultChipProps) => {
const theme = useTheme(); const theme = useTheme();
const icon = ( const icon = (
<ConditionallyRender <ConditionallyRender
condition={Boolean(enabled)} condition={enabled !== 'unknown' && enabled}
show={ show={
<FeatureEnabledIcon <FeatureEnabledIcon
color={theme.palette.success.main} color={theme.palette.success.main}
@ -71,19 +86,41 @@ export const PlaygroundResultChip = ({
const defaultLabel = enabled ? 'True' : 'False'; const defaultLabel = enabled ? 'True' : 'False';
let chipWidth = 60;
if (size === 'medium') {
chipWidth = 72;
}
if (size === 'large') {
chipWidth = 100;
}
return ( return (
<ConditionallyRender <ConditionallyRender
condition={Boolean(enabled)} condition={enabled !== 'unknown' && enabled}
show={ show={
<StyledTrueChip <StyledTrueChip
icon={showIcon ? icon : undefined} icon={showIcon ? icon : undefined}
label={label || defaultLabel} label={label || defaultLabel}
width={chipWidth}
/> />
} }
elseShow={ elseShow={
<StyledFalseChip <ConditionallyRender
icon={showIcon ? icon : undefined} condition={enabled === 'unknown'}
label={label || defaultLabel} show={
<StyledUnknownChip
label={label || 'Unknown'}
width={chipWidth}
/>
}
elseShow={
<StyledFalseChip
icon={showIcon ? icon : undefined}
label={label || defaultLabel}
width={chipWidth}
/>
}
/> />
} }
/> />