diff --git a/frontend/src/component/common/ConstraintsList/ConstraintItemHeader/ConstraintItemHeader.tsx b/frontend/src/component/common/ConstraintsList/ConstraintItemHeader/ConstraintItemHeader.tsx index bcaf83b751..6e31653f00 100644 --- a/frontend/src/component/common/ConstraintsList/ConstraintItemHeader/ConstraintItemHeader.tsx +++ b/frontend/src/component/common/ConstraintsList/ConstraintItemHeader/ConstraintItemHeader.tsx @@ -1,12 +1,14 @@ -import type { FC } from 'react'; -import { - StrategyEvaluationItem, - type StrategyEvaluationItemProps, -} from '../StrategyEvaluationItem/StrategyEvaluationItem'; +import { useMemo, type ComponentProps, type FC } from 'react'; +import { StrategyEvaluationItem } from '../StrategyEvaluationItem/StrategyEvaluationItem'; import type { ConstraintSchema } from 'openapi'; import { formatOperatorDescription } from 'component/common/ConstraintAccordion/ConstraintOperator/formatOperatorDescription'; import { StrategyEvaluationChip } from '../StrategyEvaluationChip/StrategyEvaluationChip'; import { styled, Tooltip } from '@mui/material'; +import { Truncator } from 'component/common/Truncator/Truncator'; +import { ValuesList } from '../ValuesList/ValuesList'; +import { useLocationSettings } from 'hooks/useLocationSettings'; +import { formatConstraintValue } from 'utils/formatConstraintValue'; +import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext'; const Inverted: FC = () => ( @@ -32,31 +34,55 @@ const StyledOperatorGroup = styled('div')(({ theme }) => ({ gap: theme.spacing(0.5), })); +const StyledConstraintName = styled('div')(({ theme }) => ({ + maxWidth: '150px', + paddingRight: theme.spacing(0.5), + overflow: 'hidden', +})); + export const ConstraintItemHeader: FC< - ConstraintSchema & Pick -> = ({ - caseInsensitive, - contextName, - inverted, - operator, - value, - values, - onSetTruncated, -}) => { - const items = value ? [value, ...(values || [])] : values || []; + ConstraintSchema & Pick, 'onSetTruncated'> +> = ({ onSetTruncated, ...constraint }) => { + const { caseInsensitive, contextName, inverted, operator, value, values } = + constraint; + const { context } = useUnleashContext(); + const { locationSettings } = useLocationSettings(); + const items = value + ? [ + formatConstraintValue(constraint, locationSettings) || '', + ...(values || []), + ] + : values || []; + + const tooltips = useMemo( + () => + // FIXME: tooltips + Object.fromEntries( + values?.map((value) => [ + value, + context.find(({ name }) => name === value)?.description, + ]) || [], + ), + [context, values], + ); return ( - - {contextName} + + + + {contextName} + + {inverted ? : null} {caseInsensitive ? : null} + ); }; diff --git a/frontend/src/component/common/ConstraintsList/StrategyEvaluationItem/StrategyEvaluationItem.tsx b/frontend/src/component/common/ConstraintsList/StrategyEvaluationItem/StrategyEvaluationItem.tsx index 239fe69968..2fc8948c9a 100644 --- a/frontend/src/component/common/ConstraintsList/StrategyEvaluationItem/StrategyEvaluationItem.tsx +++ b/frontend/src/component/common/ConstraintsList/StrategyEvaluationItem/StrategyEvaluationItem.tsx @@ -1,16 +1,11 @@ -import { styled } from '@mui/material'; -import { - Truncator, - type TruncatorProps, -} from 'component/common/Truncator/Truncator'; -import { disabledStrategyClassName } from 'component/common/StrategyItemContainer/disabled-strategy-utils'; import type { FC, ReactNode } from 'react'; +import { styled } from '@mui/material'; +import { disabledStrategyClassName } from 'component/common/StrategyItemContainer/disabled-strategy-utils'; export type StrategyEvaluationItemProps = { type?: ReactNode; children?: ReactNode; - values?: string[]; -} & Pick; +}; const StyledContainer = styled('div')(({ theme }) => ({ display: 'flex', @@ -38,35 +33,17 @@ const StyledType = styled('span')(({ theme }) => ({ color: theme.palette.text.secondary, width: theme.spacing(10), })); - /** * Abstract building block for a list of constraints, segments and other items inside a strategy */ export const StrategyEvaluationItem: FC = ({ type, children, - values, - onSetTruncated, -}) => ( - - {type} - - {children} - {values && values?.length === 1 ? ( - onSetTruncated?.(false)} - > - {values[0]} - - ) : null} - {values && values?.length > 1 ? ( - - {values.join(', ')} - - ) : null} - - -); +}) => { + return ( + + {type} + {children} + + ); +}; diff --git a/frontend/src/component/common/ConstraintsList/ValuesList/ValuesList.tsx b/frontend/src/component/common/ConstraintsList/ValuesList/ValuesList.tsx new file mode 100644 index 0000000000..d1053c8d88 --- /dev/null +++ b/frontend/src/component/common/ConstraintsList/ValuesList/ValuesList.tsx @@ -0,0 +1,65 @@ +import type { FC } from 'react'; +import { styled, Tooltip } from '@mui/material'; +import { + Truncator, + type TruncatorProps, +} from 'component/common/Truncator/Truncator'; + +export type ValuesListProps = { + values?: string[]; + tooltips?: Record; +} & Pick; + +const StyledValuesContainer = styled('div')({ + flex: '1 1 0', +}); + +const StyledValueItem = styled('span')(({ theme }) => ({ + padding: theme.spacing(0.25), + display: 'inline-block', + span: { + background: theme.palette.background.elevation2, + borderRadius: theme.shape.borderRadiusLarge, + display: 'inline-block', + padding: theme.spacing(0.25, 1), + }, +})); + +const StyledSingleValue = styled('div')(({ theme }) => ({ + padding: theme.spacing(0.25, 1), + background: theme.palette.background.elevation2, + borderRadius: theme.shape.borderRadiusLarge, +})); + +export const ValuesList: FC = ({ + values, + tooltips, + onSetTruncated, +}) => ( + + {values && values?.length === 1 ? ( + + onSetTruncated?.(false)} + > + {values[0]} + + + ) : null} + {values && values?.length > 1 ? ( + + {values.map((value) => ( + + + {value} + {tooltips?.[value]} + + + ))} + + ) : null} + +); diff --git a/frontend/src/component/common/SegmentItem/SegmentItem.tsx b/frontend/src/component/common/SegmentItem/SegmentItem.tsx index 610b422fb7..33f2c2666b 100644 --- a/frontend/src/component/common/SegmentItem/SegmentItem.tsx +++ b/frontend/src/component/common/SegmentItem/SegmentItem.tsx @@ -45,8 +45,7 @@ const StyledAccordionSummary = styled(AccordionSummary)(({ theme }) => ({ })); const StyledAccordionDetails = styled(AccordionDetails)(({ theme }) => ({ - borderTop: `1px dashed ${theme.palette.divider}`, - padding: theme.spacing(1.5, 3, 2.5), + padding: theme.spacing(0.5, 3, 2.5), })); const StyledLink = styled(Link)({ diff --git a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/hooks/useCustomStrategyParameters.tsx b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/hooks/useCustomStrategyParameters.tsx index 2d7fd503a2..7888ec9ca2 100644 --- a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/hooks/useCustomStrategyParameters.tsx +++ b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/hooks/useCustomStrategyParameters.tsx @@ -51,7 +51,7 @@ export const useCustomStrategyParameters = ( {values.length === 1 ? 'has 1 item:' @@ -85,7 +85,7 @@ export const useCustomStrategyParameters = ( {value === '' ? 'is an empty string' : 'is set to'} @@ -98,7 +98,7 @@ export const useCustomStrategyParameters = ( is a number set to diff --git a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/hooks/useStrategyParameters.tsx b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/hooks/useStrategyParameters.tsx index f867c04a4f..9dd93f8a4a 100644 --- a/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/hooks/useStrategyParameters.tsx +++ b/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/hooks/useStrategyParameters.tsx @@ -1,5 +1,4 @@ import { useMemo } from 'react'; -import { parseParameterStrings } from 'utils/parseParameter'; import { StrategyEvaluationItem } from 'component/common/ConstraintsList/StrategyEvaluationItem/StrategyEvaluationItem'; import type { FeatureStrategySchema } from 'openapi'; import { RolloutParameter } from '../RolloutParameter/RolloutParameter'; @@ -39,7 +38,7 @@ export const useStrategyParameters = ( ); } diff --git a/frontend/src/utils/formatConstraintValue.ts b/frontend/src/utils/formatConstraintValue.ts index b7a73748a7..c4a098716b 100644 --- a/frontend/src/utils/formatConstraintValue.ts +++ b/frontend/src/utils/formatConstraintValue.ts @@ -1,10 +1,10 @@ -import type { IConstraint } from 'interfaces/strategy'; import { formatDateYMDHMS } from 'utils/formatDate'; import type { ILocationSettings } from 'hooks/useLocationSettings'; import { CURRENT_TIME_CONTEXT_FIELD } from 'utils/operatorsForContext'; +import type { ConstraintSchema } from 'openapi'; export const formatConstraintValue = ( - constraint: IConstraint, + constraint: Pick, locationSettings: ILocationSettings, ): string | undefined => { if (