1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-23 00:22:19 +01: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,17 +23,28 @@ export const PlaygroundResultFeatureDetails = ({
const { classes: styles } = useStyles(); const { classes: styles } = useStyles();
const theme = useTheme(); const theme = useTheme();
const description = feature.isEnabled console.log(feature);
const description =
feature.isEnabled === 'unevaluated'
? `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 = feature.isEnabled const reason =
feature.isEnabled === 'unevaluated'
? 'custom strategies are not evaluated yet'
: feature.isEnabled
? 'at least one strategy is True' ? 'at least one strategy is True'
: feature?.isEnabledInCurrentEnvironment : feature?.isEnabledInCurrentEnvironment
? 'the environment is disabled' ? 'the environment is disabled'
: 'all strategies are False'; : 'all strategies are False';
const color = feature.isEnabled const color =
feature.isEnabled === 'unevaluated'
? theme.palette.warning.main
: feature.isEnabled
? theme.palette.success.main ? theme.palette.success.main
: theme.palette.error.main; : theme.palette.error.main;
@ -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,12 +40,13 @@ 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 =
result.enabled && result.evaluationStatus === 'complete'
? `1px solid ${theme.palette.success.main}` ? `1px solid ${theme.palette.success.main}`
: `1px solid ${theme.palette.divider}`; : `1px solid ${theme.palette.divider}`;
@ -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,14 +6,16 @@ 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 }) => ({
width: width ?? 60,
height: 24, height: 24,
borderRadius: theme.shape.borderRadius, borderRadius: theme.shape.borderRadius,
fontWeight: theme.typography.fontWeightMedium, fontWeight: theme.typography.fontWeightMedium,
@ -21,7 +23,8 @@ export const StyledChip = styled(Chip)(({ theme }) => ({
padding: 0, padding: 0,
paddingLeft: theme.spacing(0.5), 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={
<ConditionallyRender
condition={enabled === 'unknown'}
show={
<StyledUnknownChip
label={label || 'Unknown'}
width={chipWidth}
/> />
} }
elseShow={ elseShow={
<StyledFalseChip <StyledFalseChip
icon={showIcon ? icon : undefined} icon={showIcon ? icon : undefined}
label={label || defaultLabel} label={label || defaultLabel}
width={chipWidth}
/>
}
/> />
} }
/> />