diff --git a/frontend/src/component/common/ConstraintAccordion/ConstraintAccordion.styles.ts b/frontend/src/component/common/ConstraintAccordion/ConstraintAccordion.styles.ts index a0e75639cc..16d7d51548 100644 --- a/frontend/src/component/common/ConstraintAccordion/ConstraintAccordion.styles.ts +++ b/frontend/src/component/common/ConstraintAccordion/ConstraintAccordion.styles.ts @@ -1,20 +1,6 @@ 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(710)]: { - marginRight: 0, - }, - }, - constraintIcon: { - fill: '#fff', - }, accordion: { border: `1px solid ${theme.palette.dividerAlternative}`, borderRadius: theme.shape.borderRadiusMedium, @@ -33,9 +19,12 @@ export const useStyles = makeStyles()(theme => ({ headerMetaInfo: { display: 'flex', alignItems: 'stretch', + marginLeft: theme.spacing(1), [theme.breakpoints.down(710)]: { + marginLeft: 0, flexDirection: 'column', alignItems: 'center', + width: '100%', }, }, headerContainer: { @@ -58,6 +47,10 @@ export const useStyles = makeStyles()(theme => ({ justifyContent: 'stretch', margin: 'auto 0', flexDirection: 'column', + marginLeft: theme.spacing(1), + [theme.breakpoints.down(710)]: { + marginLeft: 0, + }, }, headerValues: { fontSize: theme.fontSizes.smallBody, @@ -71,13 +64,8 @@ export const useStyles = makeStyles()(theme => ({ }, }, headerConstraintContainer: { - minWidth: '220px', + minWidth: '152px', position: 'relative', - paddingRight: '1rem', - [theme.breakpoints.between(1101, 1365)]: { - minWidth: '152px', - paddingRight: '0.5rem', - }, [theme.breakpoints.down(710)]: { paddingRight: 0, }, diff --git a/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView.tsx b/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView.tsx index bead8645b0..382aea7266 100644 --- a/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView.tsx +++ b/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView.tsx @@ -22,6 +22,8 @@ interface IConstraintAccordionViewProps { onDelete?: () => void; onEdit?: () => void; sx?: SxProps; + compact?: boolean; + renderAfter?: JSX.Element; } export const ConstraintAccordionView = ({ @@ -29,6 +31,8 @@ export const ConstraintAccordionView = ({ onEdit, onDelete, sx = undefined, + compact = false, + renderAfter, }: IConstraintAccordionViewProps) => { const { classes: styles } = useStyles(); const [expandable, setExpandable] = useState(true); @@ -62,14 +66,24 @@ export const ConstraintAccordionView = ({ }, }} > - +
+ + {renderAfter} +
diff --git a/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeader.tsx b/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeader.tsx index 897304438d..bf09761625 100644 --- a/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeader.tsx +++ b/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeader.tsx @@ -11,6 +11,7 @@ interface IConstraintAccordionViewHeaderProps { singleValue: boolean; expanded: boolean; allowExpand: (shouldExpand: boolean) => void; + compact?: boolean; } export const ConstraintAccordionViewHeader = ({ @@ -20,12 +21,13 @@ export const ConstraintAccordionViewHeader = ({ singleValue, allowExpand, expanded, + compact, }: IConstraintAccordionViewHeaderProps) => { const { classes: styles } = useStyles(); return (
- + ({ diff --git a/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ContraintAccordionViewHeaderMultipleValues/ConstraintAccordionViewHeaderMultipleValues.tsx b/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ContraintAccordionViewHeaderMultipleValues/ConstraintAccordionViewHeaderMultipleValues.tsx index 9d063c1c94..d3aff894fb 100644 --- a/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ContraintAccordionViewHeaderMultipleValues/ConstraintAccordionViewHeaderMultipleValues.tsx +++ b/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ContraintAccordionViewHeaderMultipleValues/ConstraintAccordionViewHeaderMultipleValues.tsx @@ -1,8 +1,8 @@ -import { ConditionallyRender } from '../../../../ConditionallyRender/ConditionallyRender'; +import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { styled } from '@mui/material'; import React, { useEffect, useMemo, useState } from 'react'; import classnames from 'classnames'; -import { IConstraint } from '../../../../../../interfaces/strategy'; +import { IConstraint } from 'interfaces/strategy'; import { useStyles } from '../../../ConstraintAccordion.styles'; const StyledValuesSpan = styled('span')(({ theme }) => ({ diff --git a/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ContraintAccordionViewHeaderSingleValue/ConstraintAccordionViewHeaderSingleValue.tsx b/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ContraintAccordionViewHeaderSingleValue/ConstraintAccordionViewHeaderSingleValue.tsx index 78ac4dae81..64a3cab927 100644 --- a/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ContraintAccordionViewHeaderSingleValue/ConstraintAccordionViewHeaderSingleValue.tsx +++ b/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ContraintAccordionViewHeaderSingleValue/ConstraintAccordionViewHeaderSingleValue.tsx @@ -2,11 +2,12 @@ import React, { useEffect } from 'react'; import { Chip, styled } from '@mui/material'; import { formatConstraintValue } from 'utils/formatConstraintValue'; import { useStyles } from '../../../ConstraintAccordion.styles'; -import { IConstraint } from '../../../../../../interfaces/strategy'; +import { IConstraint } from 'interfaces/strategy'; import { useLocationSettings } from 'hooks/useLocationSettings'; const StyledSingleValueChip = styled(Chip)(({ theme }) => ({ margin: 'auto 0', + marginLeft: theme.spacing(1), [theme.breakpoints.down(710)]: { margin: theme.spacing(1, 0), }, diff --git a/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/StyledIconWrapper/StyledIconWrapper.tsx b/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/StyledIconWrapper/StyledIconWrapper.tsx index d4b6ad8169..f12acf3f2f 100644 --- a/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/StyledIconWrapper/StyledIconWrapper.tsx +++ b/frontend/src/component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/StyledIconWrapper/StyledIconWrapper.tsx @@ -12,12 +12,12 @@ export const StyledIconWrapperBase = styled('div')<{ justifyContent: 'center', alignSelf: 'stretch', color: theme.palette.primary.main, - marginRight: theme.spacing(1), + marginLeft: theme.spacing(1), borderRadius: theme.shape.borderRadius, })); const StyledPrefixIconWrapper = styled(StyledIconWrapperBase)(() => ({ - marginRight: 0, + marginLeft: 0, borderTopRightRadius: 0, borderBottomRightRadius: 0, })); diff --git a/frontend/src/component/common/ConstraintAccordion/ConstraintIcon.tsx b/frontend/src/component/common/ConstraintAccordion/ConstraintIcon.tsx index 08d0db19f8..c70b77a522 100644 --- a/frontend/src/component/common/ConstraintAccordion/ConstraintIcon.tsx +++ b/frontend/src/component/common/ConstraintAccordion/ConstraintIcon.tsx @@ -1,12 +1,28 @@ -import { useStyles } from './ConstraintAccordion.styles'; +import { VFC } from 'react'; +import { Box } from '@mui/material'; import { TrackChanges } from '@mui/icons-material'; -export const ConstraintIcon = () => { - const { classes: styles } = useStyles(); +interface IConstraintIconProps { + compact?: boolean; +} - return ( -
- -
- ); -}; +export const ConstraintIcon: VFC = ({ compact }) => ( + + + +); diff --git a/frontend/src/component/common/SegmentItem/SegmentItem.tsx b/frontend/src/component/common/SegmentItem/SegmentItem.tsx index be5f240b6b..79a5ced0a7 100644 --- a/frontend/src/component/common/SegmentItem/SegmentItem.tsx +++ b/frontend/src/component/common/SegmentItem/SegmentItem.tsx @@ -14,13 +14,17 @@ import { ConditionallyRender } from '../ConditionallyRender/ConditionallyRender' import { useStyles } from './SegmentItem.styles'; interface ISegmentItemProps { - segment: ISegment; + segment: Partial; isExpanded?: boolean; + constraintList?: JSX.Element; + headerContent?: JSX.Element; } export const SegmentItem: VFC = ({ segment, isExpanded, + headerContent, + constraintList, }) => { const { classes } = useStyles(); const [isOpen, setIsOpen] = useState(isExpanded || false); @@ -46,6 +50,10 @@ export const SegmentItem: VFC = ({ > {segment.name} + = ({ 0} - show={ - - } + condition={Boolean(constraintList)} + show={constraintList} elseShow={ - - This segment has no constraints. - + 0} + show={ + + } + elseShow={ + + This segment has no constraints. + + } + /> } /> diff --git a/frontend/src/component/feature/StrategyTypes/RolloutSlider/RolloutSlider.tsx b/frontend/src/component/feature/StrategyTypes/RolloutSlider/RolloutSlider.tsx index 695ac5054e..959950c7b2 100644 --- a/frontend/src/component/feature/StrategyTypes/RolloutSlider/RolloutSlider.tsx +++ b/frontend/src/component/feature/StrategyTypes/RolloutSlider/RolloutSlider.tsx @@ -17,11 +17,11 @@ const StyledSlider = withStyles(Slider, theme => ({ valueLabel: {}, track: { height: 8, - borderRadius: 4, + borderRadius: theme.shape.borderRadius, }, rail: { height: 8, - borderRadius: 4, + borderRadius: theme.shape.borderRadius, }, })); diff --git a/frontend/src/component/playground/Playground/PlaygroundGuidancePopper/PlaygroundGuidancePopper.tsx b/frontend/src/component/playground/Playground/PlaygroundGuidancePopper/PlaygroundGuidancePopper.tsx index ba48b82884..9971cc7f61 100644 --- a/frontend/src/component/playground/Playground/PlaygroundGuidancePopper/PlaygroundGuidancePopper.tsx +++ b/frontend/src/component/playground/Playground/PlaygroundGuidancePopper/PlaygroundGuidancePopper.tsx @@ -32,7 +32,7 @@ export const PlaygroundGuidancePopper = () => { sx={theme => ({ padding: theme.spacing(8, 4), maxWidth: '500px', - borderRadius: theme.shape.borderRadiusExtraLarge, + borderRadius: `${theme.shape.borderRadiusExtraLarge}px`, })} > {reason} + + . +
- {customStrategiesTxt} + + {customStrategiesTxt} + } /> diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureResultInfoPopoverCell.styles.ts b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureResultInfoPopoverCell.styles.ts index 3ad2f16301..b127736865 100644 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureResultInfoPopoverCell.styles.ts +++ b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureResultInfoPopoverCell.styles.ts @@ -10,5 +10,6 @@ export const useStyles = makeStyles()(theme => ({ height: 'auto', overflowY: 'auto', backgroundColor: theme.palette.tertiary.light, + borderRadius: theme.shape.borderRadiusLarge, }, })); diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/PlaygroundResultFeatureStrategyList.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/PlaygroundResultFeatureStrategyList.tsx index d80dd2a9cb..40887bd9d0 100644 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/PlaygroundResultFeatureStrategyList.tsx +++ b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/PlaygroundResultFeatureStrategyList.tsx @@ -17,16 +17,25 @@ export const PlaygroundResultFeatureStrategyList = ({ }: PlaygroundResultFeatureStrategyListProps) => { return ( <> + + There are no strategies added to this feature toggle in + selected environment. + + } + /> 0 } show={ - - If environment would be enabled then this feature would - be {feature.strategies?.result ? 'TRUE' : 'FALSE'} and - the strategies would evaluate like this:{' '} + + If environment was enabled, then this feature toggle + would be {feature.strategies?.result ? 'TRUE' : 'FALSE'}{' '} + with strategies evaluated like so:{' '} } /> diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/FeatureStrategyItem.styles.ts b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/FeatureStrategyItem.styles.ts index a6721ebb07..6b78c5ed5e 100644 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/FeatureStrategyItem.styles.ts +++ b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/FeatureStrategyItem.styles.ts @@ -35,6 +35,6 @@ export const useStyles = makeStyles()(theme => ({ background: theme.palette.background.default, }, successBorder: { - border: `1px solid ${theme.palette.success.main}`, + borderColor: theme.palette.success.main, }, })); diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordion.styles.ts b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordion.styles.ts deleted file mode 100644 index 64e00cc2f9..0000000000 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordion.styles.ts +++ /dev/null @@ -1,106 +0,0 @@ -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.dividerAlternative}`, - borderRadius: theme.spacing(1), - backgroundColor: '#fff', - boxShadow: 'none', - margin: 0, - }, - accordionRoot: { - '&:before': { - opacity: '0 !important', - }, - }, - headerMetaInfo: { - display: 'flex', - alignItems: 'stretch', - [theme.breakpoints.down(710)]: { flexDirection: 'column' }, - }, - headerContainer: { - display: 'flex', - alignItems: 'center', - [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', - }, - }, - headerText: { - maxWidth: '400px', - fontSize: theme.fontSizes.smallBody, - [theme.breakpoints.down('xl')]: { - display: 'none', - }, - }, - chip: { - margin: '0 0.5rem 0.5rem 0', - }, - chipValue: { - whiteSpace: 'pre', - }, - 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', - }, - }, -})); diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView.tsx deleted file mode 100644 index c55a819b92..0000000000 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { useState, VFC } from 'react'; -import { - Accordion, - AccordionSummary, - AccordionDetails, - SxProps, - Theme, - useTheme, -} from '@mui/material'; -import { ConstraintAccordionViewHeader } from './ConstraintAccordionViewHeader/ConstraintAccordionViewHeader'; -import { oneOf } from 'utils/oneOf'; -import { - dateOperators, - numOperators, - semVerOperators, -} from 'constants/operators'; -import { useStyles } from './ConstraintAccordion.styles'; -import { - PlaygroundConstraintSchema, - PlaygroundRequestSchema, -} from 'component/playground/Playground/interfaces/playground.model'; -import { ConstraintAccordionViewBody } from 'component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewBody/ConstraintAccordionViewBody'; - -interface IConstraintAccordionViewProps { - constraint: PlaygroundConstraintSchema; - playgroundInput?: PlaygroundRequestSchema; - maxLength?: number; - sx?: SxProps; -} - -export const ConstraintAccordionView: VFC = ({ - constraint, - sx = undefined, - maxLength, - playgroundInput, -}) => { - 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 ( - - - - - - - - - - ); -}; diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeader.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeader.tsx deleted file mode 100644 index ee3d96c529..0000000000 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeader.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { ConstraintIcon } from 'component/common/ConstraintAccordion/ConstraintIcon'; -import { ConstraintAccordionViewHeaderInfo } from './ConstraintAccordionViewHeaderInfo/ConstraintAccordionViewHeaderInfo'; -import { useStyles } from 'component/common/ConstraintAccordion/ConstraintAccordion.styles'; -import { - PlaygroundConstraintSchema, - PlaygroundRequestSchema, -} from 'component/playground/Playground/interfaces/playground.model'; - -interface PlaygroundConstraintAccordionViewHeaderProps { - constraint: PlaygroundConstraintSchema; - singleValue: boolean; - expanded: boolean; - allowExpand: (shouldExpand: boolean) => void; - playgroundInput?: PlaygroundRequestSchema; - maxLength?: number; -} - -export const ConstraintAccordionViewHeader = ({ - constraint, - singleValue, - allowExpand, - expanded, - maxLength, - playgroundInput, -}: PlaygroundConstraintAccordionViewHeaderProps) => { - const { classes: styles } = useStyles(); - - return ( -
- - -
- ); -}; diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeaderInfo/ConstraintAccordionViewHeaderInfo.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeaderInfo/ConstraintAccordionViewHeaderInfo.tsx deleted file mode 100644 index 3daacc5912..0000000000 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeaderInfo/ConstraintAccordionViewHeaderInfo.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { styled, Tooltip, Typography, useTheme } from '@mui/material'; -import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; -import { PlaygroundSingleValue } from './PlaygroundSingleValue/PlaygroundSingleValue'; -import { PLaygroundMultipleValues } from './PlaygroundMultipleValues/PlaygroundMultipleValues'; -import React from 'react'; -import { useStyles } from '../../ConstraintAccordion.styles'; -import { CancelOutlined } from '@mui/icons-material'; -import { - PlaygroundConstraintSchema, - PlaygroundRequestSchema, -} from 'component/playground/Playground/interfaces/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 ConstraintAccordionViewHeaderInfo = ({ - constraint, - singleValue, - allowExpand, - expanded, - result, - playgroundInput, - maxLength = 112, -}: PlaygroundConstraintAccordionViewHeaderInfoProps) => { - const { classes: styles } = useStyles(); - const theme = useTheme(); - - const constraintExistsInContext = Boolean( - playgroundInput?.context[constraint.contextName] - ); - - return ( - -
- - - {constraint.contextName} - - {playgroundInput?.context[constraint.contextName] || - 'no value'} - - - - - - } - elseShow={ - - } - /> -
- } - /> -
- ); -}; diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeaderInfo/PlaygroundMultipleValues/PlaygroundMultipleValues.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeaderInfo/PlaygroundMultipleValues/PlaygroundMultipleValues.tsx deleted file mode 100644 index e5a3bf43de..0000000000 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeaderInfo/PlaygroundMultipleValues/PlaygroundMultipleValues.tsx +++ /dev/null @@ -1,85 +0,0 @@ -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 '../../../ConstraintAccordion.styles'; -import { PlaygroundConstraintSchema } from 'component/playground/Playground/interfaces/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 PLaygroundConstraintAccordionViewHeaderMultipleValueProps { - constraint: PlaygroundConstraintSchema; - expanded: boolean; - maxLength: number; - allowExpand: (shouldExpand: boolean) => void; -} - -export const PLaygroundMultipleValues = ({ - constraint, - expanded, - allowExpand, - maxLength, -}: PLaygroundConstraintAccordionViewHeaderMultipleValueProps) => { - 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 ( -
-
- - does not match values{' '} - - } - /> - {text} - - {!expanded - ? `View all (${constraint?.values?.length})` - : 'View less'} -

- } - /> -
-
- ); -}; diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeaderInfo/PlaygroundSingleValue/PlaygroundSingleValue.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeaderInfo/PlaygroundSingleValue/PlaygroundSingleValue.tsx deleted file mode 100644 index 10c01a0750..0000000000 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionViewHeader/ConstraintAccordionViewHeaderInfo/PlaygroundSingleValue/PlaygroundSingleValue.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React, { useEffect } from 'react'; -import { Chip, styled, Typography } from '@mui/material'; -import { formatConstraintValue } from 'utils/formatConstraintValue'; -import { useStyles } from '../../../ConstraintAccordion.styles'; -import { useLocationSettings } from 'hooks/useLocationSettings'; -import { PlaygroundConstraintSchema } from 'component/playground/Playground/interfaces/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 PlaygroundConstraintAccordionViewHeaderSingleValueProps { - constraint: PlaygroundConstraintSchema; - allowExpand: (shouldExpand: boolean) => void; -} - -export const PlaygroundSingleValue = ({ - constraint, - allowExpand, -}: PlaygroundConstraintAccordionViewHeaderSingleValueProps) => { - const { locationSettings } = useLocationSettings(); - const { classes: styles } = useStyles(); - - useEffect(() => { - allowExpand(false); - }, [allowExpand]); - - return ( -
- - does not match values{' '} - - } - /> - -
- ); -}; diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintError/ConstraintError.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintError/ConstraintError.tsx new file mode 100644 index 0000000000..e95245acc2 --- /dev/null +++ b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintError/ConstraintError.tsx @@ -0,0 +1,40 @@ +import { styled, Typography } from '@mui/material'; +import { CancelOutlined } from '@mui/icons-material'; +import { + PlaygroundConstraintSchema, + PlaygroundRequestSchema, +} from 'component/playground/Playground/interfaces/playground.model'; + +const StyledConstraintErrorDiv = styled('div')(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + marginTop: theme.spacing(1), + color: theme.palette.error.main, +})); + +interface IConstraintErrorProps { + constraint: PlaygroundConstraintSchema; + input?: PlaygroundRequestSchema; +} + +export const ConstraintError = ({ + constraint, + input, +}: IConstraintErrorProps) => { + const formatText = () => { + const value = input?.context[constraint.contextName]; + + if (value) { + return `Constraint not met – the value in the context: { ${value} } is not ${constraint.operator} ${constraint.contextName}`; + } + + return `Constraint not met – no value was specified for ${constraint.contextName}`; + }; + + return ( + + + {formatText()} + + ); +}; diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintExecution.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintExecution.tsx index 5b74d5af3d..333196b556 100644 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintExecution.tsx +++ b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintExecution.tsx @@ -7,11 +7,12 @@ import { objectId } from 'utils/objectId'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator'; import { styled } from '@mui/material'; -import { ConstraintAccordionView } from './ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView'; +import { ConstraintAccordionView } from 'component/common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView'; +import { ConstraintError } from './ConstraintError/ConstraintError'; +import { ConstraintOk } from './ConstraintOk/ConstraintOk'; interface IConstraintExecutionProps { constraints?: PlaygroundConstraintSchema[]; - compact: boolean; input?: PlaygroundRequestSchema; } @@ -23,7 +24,6 @@ export const ConstraintExecutionWrapper = styled('div')(() => ({ export const ConstraintExecution: VFC = ({ constraints, - compact, input, }) => { if (!constraints) return null; @@ -33,16 +33,24 @@ export const ConstraintExecution: VFC = ({ {constraints?.map((constraint, index) => ( 0 && constraints?.length > 1} + condition={index > 0} show={} /> } + elseShow={ + + } + /> + } /> ))} diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintOk/ConstraintOk.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintOk/ConstraintOk.tsx new file mode 100644 index 0000000000..8864f5d616 --- /dev/null +++ b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/ConstraintExecution/ConstraintOk/ConstraintOk.tsx @@ -0,0 +1,24 @@ +import { CheckCircleOutline } from '@mui/icons-material'; +import { styled, Typography } from '@mui/material'; + +const StyledCheckOutline = styled(CheckCircleOutline)(({ theme }) => ({ + color: theme.palette.success.main, +})); + +const StyledConstraintOKDiv = styled('div')(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + marginTop: theme.spacing(1), + color: theme.palette.success.main, +})); + +export const ConstraintOk = () => { + return ( + + + + Constraint met by value in context + + + ); +}; diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/SegmentExecution/SegmentExecution.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/SegmentExecution/SegmentExecution.tsx index 50dfd47536..0873403bd2 100644 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/SegmentExecution/SegmentExecution.tsx +++ b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/SegmentExecution/SegmentExecution.tsx @@ -1,118 +1,77 @@ -import { VFC } from 'react'; +import { Fragment, VFC } from 'react'; import { PlaygroundSegmentSchema, PlaygroundRequestSchema, } from 'component/playground/Playground/interfaces/playground.model'; import { ConstraintExecution } from '../ConstraintExecution/ConstraintExecution'; -import { CancelOutlined, DonutLarge } from '@mui/icons-material'; -import { Link } from 'react-router-dom'; +import { CancelOutlined } from '@mui/icons-material'; import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator'; -import { useStyles } from './SegmentExecution.styles'; import { styled, Typography } from '@mui/material'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; +import { SegmentItem } from 'component/common/SegmentItem/SegmentItem'; interface ISegmentExecutionProps { segments?: PlaygroundSegmentSchema[]; input?: PlaygroundRequestSchema; - hasConstraints: boolean; } -const SegmentExecutionLinkWrapper = styled('div')(({ theme }) => ({ - padding: theme.spacing(2, 3), - display: 'flex', - alignItems: 'center', - justifyContent: 'flex-start', - fontSize: theme.fontSizes.smallBody, - position: 'relative', -})); - -const SegmentExecutionHeader = styled('div')(({ theme }) => ({ - width: '100%', - display: 'inline-flex', - alignItems: 'center', - justifyContent: 'space-between', - '& + &': { - margin: theme.spacing(2), - }, -})); - -const SegmentExecutionWrapper = styled('div')(({ theme }) => ({ - flexDirection: 'column', - borderRadius: theme.shape.borderRadiusMedium, - border: `1px solid ${theme.palette.dividerAlternative}`, - '& + &': { - marginTop: theme.spacing(2), - }, - background: theme.palette.neutral.light, - marginBottom: theme.spacing(1), -})); - -const SegmentExecutionConstraintWrapper = styled('div')(() => ({ - padding: '12px', -})); - const SegmentResultTextWrapper = styled('div')(({ theme }) => ({ color: theme.palette.error.main, display: 'inline-flex', justifyContent: 'center', - marginRight: '12px', + marginLeft: 'auto', gap: theme.spacing(1), })); export const SegmentExecution: VFC = ({ segments, input, - hasConstraints, }) => { - const { classes: styles } = useStyles(); - if (!segments) return null; + return ( <> {segments.map((segment, index) => ( - - - - {' '} - Segment:{' '} - - {segment.name} - - - - - segment is false - - - - - - } - /> - - - - + + + } + headerContent={ + + + segment is false + + + + + + } + /> + } + isExpanded + /> = 0 && + segments.length > 1 && + // Don't add if it's the last segment item + index !== segments.length - 1 } show={} /> - + ))} ); diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/StrategyExecution.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/StrategyExecution.tsx index 1c548c7d88..1defd97410 100644 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/StrategyExecution.tsx +++ b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/StrategyExecution.tsx @@ -1,4 +1,4 @@ -import { VFC } from 'react'; +import { Fragment, VFC } from 'react'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator'; import { Box, Chip, styled } from '@mui/material'; @@ -12,6 +12,7 @@ import { ConstraintExecution } from './ConstraintExecution/ConstraintExecution'; import { SegmentExecution } from './SegmentExecution/SegmentExecution'; import { PlaygroundResultStrategyExecutionParameters } from './StrategyExecutionParameters/StrategyExecutionParameters'; import { CustomStrategyParams } from './CustomStrategyParams/CustomStrategyParams'; +import { formattedStrategyNames } from 'utils/strategyNames'; interface IStrategyExecutionProps { strategyResult: PlaygroundStrategySchema; @@ -32,72 +33,60 @@ export const StrategyExecution: VFC = ({ const { uiConfig } = useUiConfig(); const { classes: styles } = useStyles(); + const hasSegments = + Boolean(uiConfig.flags.SE) && Boolean(segments && segments.length > 0); const hasConstraints = Boolean(constraints && constraints?.length > 0); - const hasParameters = Object.keys(parameters).length === 0; + const hasExecutionParameters = + name !== 'default' && + Object.keys(formattedStrategyNames).includes(name); + const hasCustomStrategyParameters = + Object.keys(parameters).length > 0 && + strategyResult.result.evaluationStatus === 'incomplete'; // Use of custom strategy can be more explicit from the API if (!parameters) { return null; } - return ( - - 0) - } - show={ - - } - /> - 0)} - show={ - <> - - 0 && - !hasParameters - )} - show={} - /> - - } - /> - - The standard strategyResult is{' '} - {' '} - for all users. - - } - /> + const items = [ + hasSegments && , + hasConstraints && ( + + ), + hasExecutionParameters && ( - + ), + hasCustomStrategyParameters && ( + + ), + name === 'default' && ( + + The standard strategy is{' '} + {' '} + for all users. + + ), + ].filter(Boolean); + + return ( + + {items.map((item, index) => ( + + 0} + show={} + /> + {item} + + ))} ); }; diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/StrategyExecutionParameters/StrategyExecutionParameters.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/StrategyExecutionParameters/StrategyExecutionParameters.tsx index 2a283cff32..a3c8418654 100644 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/StrategyExecutionParameters/StrategyExecutionParameters.tsx +++ b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureResultInfoPopoverCell/FeatureStrategyList/StrategyList/StrategyItem/StrategyExecution/StrategyExecutionParameters/StrategyExecutionParameters.tsx @@ -25,102 +25,117 @@ export const PlaygroundResultStrategyExecutionParameters = ({ 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 ( - - - - -
- {' '} - of your base{' '} - {constraints.length > 0 - ? 'who match constraints' - : ''}{' '} - is included. -
-
- ); - case 'userIds': - case 'UserIds': - const users = parseParameterStrings(parameters[key]); - return ( - - ); - case 'hostNames': - case 'HostNames': - const hosts = parseParameterStrings(parameters[key]); - return ( - - ); - case 'IPs': - const IPs = parseParameterStrings(parameters[key]); - return ( - - ); - case 'stickiness': - case 'groupId': - return null; - default: - return null; - } - }); - }; - return <>{renderParameters()}; + return ( + <> + {Object.keys(parameters).map(key => { + switch (key) { + case 'rollout': + case 'Rollout': + const percentage = parseParameterNumber( + parameters[key] + ); + return ( + + + + +
+ {' '} + of your base{' '} + {constraints.length > 0 + ? 'who match constraints' + : ''}{' '} + is included. +
+
+ ); + case 'userIds': + case 'UserIds': + const users = parseParameterStrings(parameters[key]); + return ( + + ); + case 'hostNames': + case 'HostNames': + const hosts = parseParameterStrings(parameters[key]); + return ( + + ); + case 'IPs': + const IPs = parseParameterStrings(parameters[key]); + return ( + + ); + case 'stickiness': + case 'groupId': + return null; + default: + return null; + } + })} + + ); }; diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureStatusCell/FeatureStatusCell.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureStatusCell/FeatureStatusCell.tsx index 2759a3f715..997b5585fd 100644 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureStatusCell/FeatureStatusCell.tsx +++ b/frontend/src/component/playground/Playground/PlaygroundResultsTable/FeatureStatusCell/FeatureStatusCell.tsx @@ -22,10 +22,10 @@ export const FeatureStatusCell = ({ feature }: IFeatureStatusCellProps) => { if (feature?.isEnabled) { return [true, 'True']; } - if (feature?.strategies?.result === false) { - return [false, 'False']; + if (feature?.strategies?.result === 'unknown') { + return ['unknown', 'Unknown']; } - return ['unknown', 'Unknown']; + return [false, 'False']; })(); return ( diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/PlaygroundResultsTable.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/PlaygroundResultsTable.tsx index fac8ab4921..f14da299a2 100644 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/PlaygroundResultsTable.tsx +++ b/frontend/src/component/playground/Playground/PlaygroundResultsTable/PlaygroundResultsTable.tsx @@ -101,14 +101,19 @@ export const PlaygroundResultsTable = ({ ), }, { + id: 'isEnabled', Header: 'isEnabled', - accessor: 'isEnabled', filterName: 'isEnabled', - filterParsing: (value: boolean) => (value ? 'true' : 'false'), + accessor: (row: PlaygroundFeatureSchema) => + row?.isEnabled + ? 'true' + : row?.strategies?.result === 'unknown' + ? 'unknown' + : 'false', Cell: ({ row }: any) => ( ), - sortType: 'boolean', + sortType: 'playgroundResultState', maxWidth: 120, sortInverted: true, }, diff --git a/frontend/src/component/playground/Playground/PlaygroundResultsTable/VariantCell/VariantCell.tsx b/frontend/src/component/playground/Playground/PlaygroundResultsTable/VariantCell/VariantCell.tsx index a9e81f000f..b51ee0b119 100644 --- a/frontend/src/component/playground/Playground/PlaygroundResultsTable/VariantCell/VariantCell.tsx +++ b/frontend/src/component/playground/Playground/PlaygroundResultsTable/VariantCell/VariantCell.tsx @@ -53,8 +53,7 @@ export const VariantCell: VFC = ({ id={`${feature}-result-variants`} PaperProps={{ sx: { - borderRadius: - theme.shape.borderRadiusExtraLarge, + borderRadius: `${theme.shape.borderRadiusLarge}px`, }, }} onClose={onClose} diff --git a/frontend/src/utils/sortTypes.ts b/frontend/src/utils/sortTypes.ts index 42313e4c49..3dd6a6c1eb 100644 --- a/frontend/src/utils/sortTypes.ts +++ b/frontend/src/utils/sortTypes.ts @@ -18,4 +18,14 @@ export const sortTypes = { (a?.values?.[id] || '') ?.toLowerCase() .localeCompare(b?.values?.[id]?.toLowerCase() || ''), + playgroundResultState: (v1: any, v2: any, id: string) => { + const a = v1?.values?.[id]; + const b = v2?.values?.[id]; + if (a === b) return 0; + if (a === 'true') return 1; + if (b === 'true') return -1; + if (a === 'false') return -1; + if (b === 'false') return 1; + return 0; + }, }; diff --git a/frontend/src/utils/strategyNames.tsx b/frontend/src/utils/strategyNames.tsx index e5b2bd500b..cea5275588 100644 --- a/frontend/src/utils/strategyNames.tsx +++ b/frontend/src/utils/strategyNames.tsx @@ -36,7 +36,7 @@ export const getFeatureStrategyIcon = (strategyName: string): ElementType => { } }; -const formattedStrategyNames: Record = { +export const formattedStrategyNames: Record = { applicationHostname: 'Hosts', default: 'Standard', flexibleRollout: 'Gradual rollout',