mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: new constraint view for flag edit page (#9567)
Refactor components in Targeting (Edit strategy)
This commit is contained in:
		
							parent
							
								
									a10dca44f6
								
							
						
					
					
						commit
						2d47fb3827
					
				@ -1,5 +1,8 @@
 | 
				
			|||||||
import type { FC } from 'react';
 | 
					import type { FC } from 'react';
 | 
				
			||||||
import { StrategyEvaluationItem } from '../StrategyEvaluationItem/StrategyEvaluationItem';
 | 
					import {
 | 
				
			||||||
 | 
					    StrategyEvaluationItem,
 | 
				
			||||||
 | 
					    type StrategyEvaluationItemProps,
 | 
				
			||||||
 | 
					} from '../StrategyEvaluationItem/StrategyEvaluationItem';
 | 
				
			||||||
import type { ConstraintSchema } from 'openapi';
 | 
					import type { ConstraintSchema } from 'openapi';
 | 
				
			||||||
import { formatOperatorDescription } from 'component/common/ConstraintAccordion/ConstraintOperator/formatOperatorDescription';
 | 
					import { formatOperatorDescription } from 'component/common/ConstraintAccordion/ConstraintOperator/formatOperatorDescription';
 | 
				
			||||||
import { StrategyEvaluationChip } from '../StrategyEvaluationChip/StrategyEvaluationChip';
 | 
					import { StrategyEvaluationChip } from '../StrategyEvaluationChip/StrategyEvaluationChip';
 | 
				
			||||||
@ -29,18 +32,25 @@ const StyledOperatorGroup = styled('div')(({ theme }) => ({
 | 
				
			|||||||
    gap: theme.spacing(0.5),
 | 
					    gap: theme.spacing(0.5),
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ConstraintItem: FC<ConstraintSchema> = ({
 | 
					export const ConstraintItemHeader: FC<
 | 
				
			||||||
 | 
					    ConstraintSchema & Pick<StrategyEvaluationItemProps, 'onSetTruncated'>
 | 
				
			||||||
 | 
					> = ({
 | 
				
			||||||
    caseInsensitive,
 | 
					    caseInsensitive,
 | 
				
			||||||
    contextName,
 | 
					    contextName,
 | 
				
			||||||
    inverted,
 | 
					    inverted,
 | 
				
			||||||
    operator,
 | 
					    operator,
 | 
				
			||||||
    value,
 | 
					    value,
 | 
				
			||||||
    values,
 | 
					    values,
 | 
				
			||||||
 | 
					    onSetTruncated,
 | 
				
			||||||
}) => {
 | 
					}) => {
 | 
				
			||||||
    const items = value ? [value, ...(values || [])] : values || [];
 | 
					    const items = value ? [value, ...(values || [])] : values || [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <StrategyEvaluationItem type='Constraint' values={items}>
 | 
					        <StrategyEvaluationItem
 | 
				
			||||||
 | 
					            type='Constraint'
 | 
				
			||||||
 | 
					            values={items}
 | 
				
			||||||
 | 
					            onSetTruncated={onSetTruncated}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
            {contextName}
 | 
					            {contextName}
 | 
				
			||||||
            <StyledOperatorGroup>
 | 
					            <StyledOperatorGroup>
 | 
				
			||||||
                {inverted ? <Inverted /> : null}
 | 
					                {inverted ? <Inverted /> : null}
 | 
				
			||||||
@ -10,17 +10,21 @@ const StyledList = styled('ul')(({ theme }) => ({
 | 
				
			|||||||
    gap: theme.spacing(1),
 | 
					    gap: theme.spacing(1),
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledListItem = styled('li')(({ theme }) => ({
 | 
					export const ConstraintListItem = styled('div')(({ theme }) => ({
 | 
				
			||||||
    position: 'relative',
 | 
					    position: 'relative',
 | 
				
			||||||
    border: `1px solid ${theme.palette.divider}`,
 | 
					    border: `1px solid ${theme.palette.divider}`,
 | 
				
			||||||
    borderRadius: theme.shape.borderRadiusMedium,
 | 
					    borderRadius: theme.shape.borderRadiusMedium,
 | 
				
			||||||
    background: theme.palette.background.default,
 | 
					    background: theme.palette.background.default,
 | 
				
			||||||
    padding: theme.spacing(2, 3),
 | 
					    padding: theme.spacing(1.5, 3),
 | 
				
			||||||
    display: 'flex',
 | 
					    display: 'flex',
 | 
				
			||||||
    flexFlow: 'column',
 | 
					    flexFlow: 'column',
 | 
				
			||||||
    gap: theme.spacing(2),
 | 
					    gap: theme.spacing(1),
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const StyledListItem = styled('li')({
 | 
				
			||||||
 | 
					    position: 'relative',
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledAnd = styled('div')(({ theme }) => ({
 | 
					const StyledAnd = styled('div')(({ theme }) => ({
 | 
				
			||||||
    position: 'absolute',
 | 
					    position: 'absolute',
 | 
				
			||||||
    top: theme.spacing(-0.5),
 | 
					    top: theme.spacing(-0.5),
 | 
				
			||||||
 | 
				
			|||||||
@ -1,24 +1,28 @@
 | 
				
			|||||||
import { styled } from '@mui/material';
 | 
					import { styled } from '@mui/material';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    Truncator,
 | 
				
			||||||
 | 
					    type TruncatorProps,
 | 
				
			||||||
 | 
					} from 'component/common/Truncator/Truncator';
 | 
				
			||||||
import { disabledStrategyClassName } from 'component/common/StrategyItemContainer/disabled-strategy-utils';
 | 
					import { disabledStrategyClassName } from 'component/common/StrategyItemContainer/disabled-strategy-utils';
 | 
				
			||||||
import type { FC, ReactNode } from 'react';
 | 
					import type { FC, ReactNode } from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type StrategyItemProps = {
 | 
					export type StrategyEvaluationItemProps = {
 | 
				
			||||||
    type?: ReactNode;
 | 
					    type?: ReactNode;
 | 
				
			||||||
    children?: ReactNode;
 | 
					    children?: ReactNode;
 | 
				
			||||||
    values?: string[];
 | 
					    values?: string[];
 | 
				
			||||||
};
 | 
					} & Pick<TruncatorProps, 'onSetTruncated'>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledContainer = styled('div')(({ theme }) => ({
 | 
					const StyledContainer = styled('div')(({ theme }) => ({
 | 
				
			||||||
    display: 'flex',
 | 
					    display: 'flex',
 | 
				
			||||||
    gap: theme.spacing(1),
 | 
					    gap: theme.spacing(1),
 | 
				
			||||||
    alignItems: 'center',
 | 
					    alignItems: 'center',
 | 
				
			||||||
    fontSize: theme.typography.body2.fontSize,
 | 
					    fontSize: theme.typography.body2.fontSize,
 | 
				
			||||||
 | 
					    minHeight: theme.spacing(4),
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledContent = styled('div')(({ theme }) => ({
 | 
					const StyledContent = styled('div')(({ theme }) => ({
 | 
				
			||||||
    display: 'flex',
 | 
					    display: 'flex',
 | 
				
			||||||
    gap: theme.spacing(1),
 | 
					    gap: theme.spacing(1),
 | 
				
			||||||
    flexWrap: 'wrap',
 | 
					 | 
				
			||||||
    alignItems: 'center',
 | 
					    alignItems: 'center',
 | 
				
			||||||
    [`.${disabledStrategyClassName} &`]: {
 | 
					    [`.${disabledStrategyClassName} &`]: {
 | 
				
			||||||
        filter: 'grayscale(1)',
 | 
					        filter: 'grayscale(1)',
 | 
				
			||||||
@ -35,45 +39,33 @@ const StyledType = styled('span')(({ theme }) => ({
 | 
				
			|||||||
    width: theme.spacing(10),
 | 
					    width: theme.spacing(10),
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledValuesGroup = styled('ul')(({ theme }) => ({
 | 
					 | 
				
			||||||
    display: 'flex',
 | 
					 | 
				
			||||||
    flexFlow: 'row wrap',
 | 
					 | 
				
			||||||
    alignItems: 'center',
 | 
					 | 
				
			||||||
    gap: theme.spacing(0.5),
 | 
					 | 
				
			||||||
    listStyle: 'none',
 | 
					 | 
				
			||||||
    padding: 0,
 | 
					 | 
				
			||||||
}));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const StyledValue = styled('li')(({ theme }) => ({
 | 
					 | 
				
			||||||
    [`.${disabledStrategyClassName} &`]: {
 | 
					 | 
				
			||||||
        filter: 'grayscale(1)',
 | 
					 | 
				
			||||||
        color: theme.palette.text.secondary,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    ':not(&:last-of-type)::after': {
 | 
					 | 
				
			||||||
        content: '", "',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
}));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Abstract building block for a list of constraints, segments and other items inside a strategy
 | 
					 * Abstract building block for a list of constraints, segments and other items inside a strategy
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export const StrategyEvaluationItem: FC<StrategyItemProps> = ({
 | 
					export const StrategyEvaluationItem: FC<StrategyEvaluationItemProps> = ({
 | 
				
			||||||
    type,
 | 
					    type,
 | 
				
			||||||
    children,
 | 
					    children,
 | 
				
			||||||
    values,
 | 
					    values,
 | 
				
			||||||
 | 
					    onSetTruncated,
 | 
				
			||||||
}) => (
 | 
					}) => (
 | 
				
			||||||
    <StyledContainer>
 | 
					    <StyledContainer>
 | 
				
			||||||
        <StyledType>{type}</StyledType>
 | 
					        <StyledType>{type}</StyledType>
 | 
				
			||||||
        <StyledContent>
 | 
					        <StyledContent>
 | 
				
			||||||
            {children}
 | 
					            {children}
 | 
				
			||||||
            {values && values?.length > 0 ? (
 | 
					            {values && values?.length === 1 ? (
 | 
				
			||||||
                <StyledValuesGroup>
 | 
					                <Truncator
 | 
				
			||||||
                    {values?.map((value, index) => (
 | 
					                    title={values[0]}
 | 
				
			||||||
                        <StyledValue key={`${value}#${index}`}>
 | 
					                    arrow
 | 
				
			||||||
                            {value}
 | 
					                    lines={2}
 | 
				
			||||||
                        </StyledValue>
 | 
					                    onSetTruncated={() => onSetTruncated?.(false)}
 | 
				
			||||||
                    ))}
 | 
					                >
 | 
				
			||||||
                </StyledValuesGroup>
 | 
					                    {values[0]}
 | 
				
			||||||
 | 
					                </Truncator>
 | 
				
			||||||
 | 
					            ) : null}
 | 
				
			||||||
 | 
					            {values && values?.length > 1 ? (
 | 
				
			||||||
 | 
					                <Truncator title='' lines={2} onSetTruncated={onSetTruncated}>
 | 
				
			||||||
 | 
					                    {values.join(', ')}
 | 
				
			||||||
 | 
					                </Truncator>
 | 
				
			||||||
            ) : null}
 | 
					            ) : null}
 | 
				
			||||||
        </StyledContent>
 | 
					        </StyledContent>
 | 
				
			||||||
    </StyledContainer>
 | 
					    </StyledContainer>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,11 @@
 | 
				
			|||||||
import { ConstraintIcon } from 'component/common/ConstraintAccordion/ConstraintIcon';
 | 
					import { ConstraintIcon } from 'component/common/ConstraintAccordion/ConstraintIcon';
 | 
				
			||||||
import type { IConstraint } from 'interfaces/strategy';
 | 
					import type { IConstraint } from 'interfaces/strategy';
 | 
				
			||||||
import { ConstraintAccordionViewHeaderInfo } from './ConstraintAccordionViewHeaderInfo';
 | 
					import { ConstraintAccordionViewHeaderInfo } from './ConstraintAccordionViewHeaderInfo';
 | 
				
			||||||
 | 
					import { ConstraintAccordionViewHeaderInfo as LegacyConstraintAccordionViewHeaderInfo } from './LegacyConstraintAccordionViewHeaderInfo';
 | 
				
			||||||
import { ConstraintAccordionHeaderActions } from '../../ConstraintAccordionHeaderActions/ConstraintAccordionHeaderActions';
 | 
					import { ConstraintAccordionHeaderActions } from '../../ConstraintAccordionHeaderActions/ConstraintAccordionHeaderActions';
 | 
				
			||||||
import { styled } from '@mui/system';
 | 
					import { styled } from '@mui/system';
 | 
				
			||||||
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
 | 
					import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
 | 
				
			||||||
 | 
					import { useUiFlag } from 'hooks/useUiFlag';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface IConstraintAccordionViewHeaderProps {
 | 
					interface IConstraintAccordionViewHeaderProps {
 | 
				
			||||||
    constraint: IConstraint;
 | 
					    constraint: IConstraint;
 | 
				
			||||||
@ -38,6 +40,7 @@ export const ConstraintAccordionViewHeader = ({
 | 
				
			|||||||
    disabled,
 | 
					    disabled,
 | 
				
			||||||
}: IConstraintAccordionViewHeaderProps) => {
 | 
					}: IConstraintAccordionViewHeaderProps) => {
 | 
				
			||||||
    const { context } = useUnleashContext();
 | 
					    const { context } = useUnleashContext();
 | 
				
			||||||
 | 
					    const flagOverviewRedesign = useUiFlag('flagOverviewRedesign');
 | 
				
			||||||
    const { contextName } = constraint;
 | 
					    const { contextName } = constraint;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const disableEdit = !context
 | 
					    const disableEdit = !context
 | 
				
			||||||
@ -46,14 +49,26 @@ export const ConstraintAccordionViewHeader = ({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <StyledContainer>
 | 
					        <StyledContainer>
 | 
				
			||||||
            <ConstraintIcon compact={compact} disabled={disabled} />
 | 
					            {!flagOverviewRedesign ? (
 | 
				
			||||||
            <ConstraintAccordionViewHeaderInfo
 | 
					                <ConstraintIcon compact={compact} disabled={disabled} />
 | 
				
			||||||
                constraint={constraint}
 | 
					            ) : null}
 | 
				
			||||||
                singleValue={singleValue}
 | 
					            {flagOverviewRedesign ? (
 | 
				
			||||||
                allowExpand={allowExpand}
 | 
					                <ConstraintAccordionViewHeaderInfo
 | 
				
			||||||
                expanded={expanded}
 | 
					                    constraint={constraint}
 | 
				
			||||||
                disabled={disabled}
 | 
					                    singleValue={singleValue}
 | 
				
			||||||
            />
 | 
					                    allowExpand={allowExpand}
 | 
				
			||||||
 | 
					                    expanded={expanded}
 | 
				
			||||||
 | 
					                    disabled={disabled}
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					            ) : (
 | 
				
			||||||
 | 
					                <LegacyConstraintAccordionViewHeaderInfo
 | 
				
			||||||
 | 
					                    constraint={constraint}
 | 
				
			||||||
 | 
					                    singleValue={singleValue}
 | 
				
			||||||
 | 
					                    allowExpand={allowExpand}
 | 
				
			||||||
 | 
					                    expanded={expanded}
 | 
				
			||||||
 | 
					                    disabled={disabled}
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					            )}
 | 
				
			||||||
            <ConstraintAccordionHeaderActions
 | 
					            <ConstraintAccordionHeaderActions
 | 
				
			||||||
                onEdit={onEdit}
 | 
					                onEdit={onEdit}
 | 
				
			||||||
                onDelete={onDelete}
 | 
					                onDelete={onDelete}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,29 +1,9 @@
 | 
				
			|||||||
import { styled, Tooltip } from '@mui/material';
 | 
					import { IconButton, styled } from '@mui/material';
 | 
				
			||||||
import { ConstraintViewHeaderOperator } from './ConstraintViewHeaderOperator';
 | 
					 | 
				
			||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
					 | 
				
			||||||
import { ConstraintAccordionViewHeaderSingleValue } from './ConstraintAccordionViewHeaderSingleValue';
 | 
					 | 
				
			||||||
import { ConstraintAccordionViewHeaderMultipleValues } from './ConstraintAccordionViewHeaderMultipleValues';
 | 
					 | 
				
			||||||
import type { IConstraint } from 'interfaces/strategy';
 | 
					import type { IConstraint } from 'interfaces/strategy';
 | 
				
			||||||
 | 
					import { ConstraintItemHeader } from 'component/common/ConstraintsList/ConstraintItemHeader/ConstraintItemHeader';
 | 
				
			||||||
const StyledHeaderText = styled('span')(({ theme }) => ({
 | 
					import { useState } from 'react';
 | 
				
			||||||
    display: '-webkit-box',
 | 
					import VisibilityIcon from '@mui/icons-material/Visibility';
 | 
				
			||||||
    WebkitLineClamp: 3,
 | 
					import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
 | 
				
			||||||
    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 }) => ({
 | 
					const StyledHeaderWrapper = styled('div')(({ theme }) => ({
 | 
				
			||||||
    display: 'flex',
 | 
					    display: 'flex',
 | 
				
			||||||
@ -55,49 +35,26 @@ interface ConstraintAccordionViewHeaderMetaInfoProps {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export const ConstraintAccordionViewHeaderInfo = ({
 | 
					export const ConstraintAccordionViewHeaderInfo = ({
 | 
				
			||||||
    constraint,
 | 
					    constraint,
 | 
				
			||||||
    singleValue,
 | 
					 | 
				
			||||||
    allowExpand,
 | 
					    allowExpand,
 | 
				
			||||||
    expanded,
 | 
					    expanded,
 | 
				
			||||||
    disabled = false,
 | 
					 | 
				
			||||||
    maxLength = 112, //The max number of characters in the values text for NOT allowing expansion
 | 
					 | 
				
			||||||
}: ConstraintAccordionViewHeaderMetaInfoProps) => {
 | 
					}: ConstraintAccordionViewHeaderMetaInfoProps) => {
 | 
				
			||||||
 | 
					    const [expandable, setExpandable] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <StyledHeaderWrapper>
 | 
					        <StyledHeaderWrapper>
 | 
				
			||||||
            <StyledHeaderMetaInfo>
 | 
					            <StyledHeaderMetaInfo>
 | 
				
			||||||
                <Tooltip title={constraint.contextName} arrow>
 | 
					                <ConstraintItemHeader
 | 
				
			||||||
                    <StyledHeaderText
 | 
					                    {...constraint}
 | 
				
			||||||
                        sx={(theme) => ({
 | 
					                    onSetTruncated={(state: boolean) => {
 | 
				
			||||||
                            color: disabled
 | 
					                        setExpandable(state);
 | 
				
			||||||
                                ? theme.palette.text.secondary
 | 
					                        allowExpand(state);
 | 
				
			||||||
                                : 'inherit',
 | 
					                    }}
 | 
				
			||||||
                        })}
 | 
					 | 
				
			||||||
                    >
 | 
					 | 
				
			||||||
                        {constraint.contextName}
 | 
					 | 
				
			||||||
                    </StyledHeaderText>
 | 
					 | 
				
			||||||
                </Tooltip>
 | 
					 | 
				
			||||||
                <ConstraintViewHeaderOperator
 | 
					 | 
				
			||||||
                    constraint={constraint}
 | 
					 | 
				
			||||||
                    disabled={disabled}
 | 
					 | 
				
			||||||
                />
 | 
					 | 
				
			||||||
                <ConditionallyRender
 | 
					 | 
				
			||||||
                    condition={singleValue}
 | 
					 | 
				
			||||||
                    show={
 | 
					 | 
				
			||||||
                        <ConstraintAccordionViewHeaderSingleValue
 | 
					 | 
				
			||||||
                            constraint={constraint}
 | 
					 | 
				
			||||||
                            allowExpand={allowExpand}
 | 
					 | 
				
			||||||
                            disabled={disabled}
 | 
					 | 
				
			||||||
                        />
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    elseShow={
 | 
					 | 
				
			||||||
                        <ConstraintAccordionViewHeaderMultipleValues
 | 
					 | 
				
			||||||
                            constraint={constraint}
 | 
					 | 
				
			||||||
                            expanded={expanded}
 | 
					 | 
				
			||||||
                            allowExpand={allowExpand}
 | 
					 | 
				
			||||||
                            maxLength={maxLength}
 | 
					 | 
				
			||||||
                            disabled={disabled}
 | 
					 | 
				
			||||||
                        />
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                />
 | 
					                />
 | 
				
			||||||
 | 
					                {expandable ? (
 | 
				
			||||||
 | 
					                    <IconButton type='button'>
 | 
				
			||||||
 | 
					                        {expanded ? <VisibilityOffIcon /> : <VisibilityIcon />}
 | 
				
			||||||
 | 
					                    </IconButton>
 | 
				
			||||||
 | 
					                ) : null}
 | 
				
			||||||
            </StyledHeaderMetaInfo>
 | 
					            </StyledHeaderMetaInfo>
 | 
				
			||||||
        </StyledHeaderWrapper>
 | 
					        </StyledHeaderWrapper>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,104 @@
 | 
				
			|||||||
 | 
					import { styled, Tooltip } from '@mui/material';
 | 
				
			||||||
 | 
					import { ConstraintViewHeaderOperator } from './ConstraintViewHeaderOperator';
 | 
				
			||||||
 | 
					import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
				
			||||||
 | 
					import { ConstraintAccordionViewHeaderSingleValue } from './ConstraintAccordionViewHeaderSingleValue';
 | 
				
			||||||
 | 
					import { ConstraintAccordionViewHeaderMultipleValues } from './ConstraintAccordionViewHeaderMultipleValues';
 | 
				
			||||||
 | 
					import type { IConstraint } from 'interfaces/strategy';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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),
 | 
				
			||||||
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const StyledHeaderMetaInfo = styled('div')(({ theme }) => ({
 | 
				
			||||||
 | 
					    display: 'flex',
 | 
				
			||||||
 | 
					    alignItems: 'stretch',
 | 
				
			||||||
 | 
					    marginLeft: theme.spacing(1),
 | 
				
			||||||
 | 
					    [theme.breakpoints.down('sm')]: {
 | 
				
			||||||
 | 
					        marginLeft: 0,
 | 
				
			||||||
 | 
					        flexDirection: 'column',
 | 
				
			||||||
 | 
					        alignItems: 'center',
 | 
				
			||||||
 | 
					        width: '100%',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface ConstraintAccordionViewHeaderMetaInfoProps {
 | 
				
			||||||
 | 
					    constraint: IConstraint;
 | 
				
			||||||
 | 
					    singleValue: boolean;
 | 
				
			||||||
 | 
					    expanded: boolean;
 | 
				
			||||||
 | 
					    allowExpand: (shouldExpand: boolean) => void;
 | 
				
			||||||
 | 
					    disabled?: boolean;
 | 
				
			||||||
 | 
					    maxLength?: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const ConstraintAccordionViewHeaderInfo = ({
 | 
				
			||||||
 | 
					    constraint,
 | 
				
			||||||
 | 
					    singleValue,
 | 
				
			||||||
 | 
					    allowExpand,
 | 
				
			||||||
 | 
					    expanded,
 | 
				
			||||||
 | 
					    disabled = false,
 | 
				
			||||||
 | 
					    maxLength = 112, //The max number of characters in the values text for NOT allowing expansion
 | 
				
			||||||
 | 
					}: ConstraintAccordionViewHeaderMetaInfoProps) => {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <StyledHeaderWrapper>
 | 
				
			||||||
 | 
					            <StyledHeaderMetaInfo>
 | 
				
			||||||
 | 
					                <Tooltip title={constraint.contextName} arrow>
 | 
				
			||||||
 | 
					                    <StyledHeaderText
 | 
				
			||||||
 | 
					                        sx={(theme) => ({
 | 
				
			||||||
 | 
					                            color: disabled
 | 
				
			||||||
 | 
					                                ? theme.palette.text.secondary
 | 
				
			||||||
 | 
					                                : 'inherit',
 | 
				
			||||||
 | 
					                        })}
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                        {constraint.contextName}
 | 
				
			||||||
 | 
					                    </StyledHeaderText>
 | 
				
			||||||
 | 
					                </Tooltip>
 | 
				
			||||||
 | 
					                <ConstraintViewHeaderOperator
 | 
				
			||||||
 | 
					                    constraint={constraint}
 | 
				
			||||||
 | 
					                    disabled={disabled}
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					                <ConditionallyRender
 | 
				
			||||||
 | 
					                    condition={singleValue}
 | 
				
			||||||
 | 
					                    show={
 | 
				
			||||||
 | 
					                        <ConstraintAccordionViewHeaderSingleValue
 | 
				
			||||||
 | 
					                            constraint={constraint}
 | 
				
			||||||
 | 
					                            allowExpand={allowExpand}
 | 
				
			||||||
 | 
					                            disabled={disabled}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    elseShow={
 | 
				
			||||||
 | 
					                        <ConstraintAccordionViewHeaderMultipleValues
 | 
				
			||||||
 | 
					                            constraint={constraint}
 | 
				
			||||||
 | 
					                            expanded={expanded}
 | 
				
			||||||
 | 
					                            allowExpand={allowExpand}
 | 
				
			||||||
 | 
					                            maxLength={maxLength}
 | 
				
			||||||
 | 
					                            disabled={disabled}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					            </StyledHeaderMetaInfo>
 | 
				
			||||||
 | 
					        </StyledHeaderWrapper>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -7,6 +7,9 @@ interface IConstraintIconProps {
 | 
				
			|||||||
    disabled?: boolean;
 | 
					    disabled?: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @deprecated remove with `flagOverviewRedesign`
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export const ConstraintIcon: VFC<IConstraintIconProps> = ({
 | 
					export const ConstraintIcon: VFC<IConstraintIconProps> = ({
 | 
				
			||||||
    compact,
 | 
					    compact,
 | 
				
			||||||
    disabled,
 | 
					    disabled,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,4 @@
 | 
				
			|||||||
import type { IConstraint } from 'interfaces/strategy';
 | 
					import type { IConstraint } from 'interfaces/strategy';
 | 
				
			||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { ConstraintAccordionEdit } from './ConstraintAccordionEdit/ConstraintAccordionEdit';
 | 
					import { ConstraintAccordionEdit } from './ConstraintAccordionEdit/ConstraintAccordionEdit';
 | 
				
			||||||
import { ConstraintAccordionView } from './ConstraintAccordionView/ConstraintAccordionView';
 | 
					import { ConstraintAccordionView } from './ConstraintAccordionView/ConstraintAccordionView';
 | 
				
			||||||
@ -27,26 +26,24 @@ export const NewConstraintAccordion = ({
 | 
				
			|||||||
}: IConstraintAccordionProps) => {
 | 
					}: IConstraintAccordionProps) => {
 | 
				
			||||||
    if (!constraint) return null;
 | 
					    if (!constraint) return null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (editing && onSave) {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <ConstraintAccordionEdit
 | 
				
			||||||
 | 
					                constraint={constraint}
 | 
				
			||||||
 | 
					                onCancel={onCancel}
 | 
				
			||||||
 | 
					                onSave={onSave!}
 | 
				
			||||||
 | 
					                onDelete={onDelete}
 | 
				
			||||||
 | 
					                onAutoSave={onAutoSave!}
 | 
				
			||||||
 | 
					                compact={compact}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <ConditionallyRender
 | 
					        <ConstraintAccordionView
 | 
				
			||||||
            condition={Boolean(editing && onSave)}
 | 
					            constraint={constraint}
 | 
				
			||||||
            show={
 | 
					            onEdit={onEdit}
 | 
				
			||||||
                <ConstraintAccordionEdit
 | 
					            onDelete={onDelete}
 | 
				
			||||||
                    constraint={constraint}
 | 
					 | 
				
			||||||
                    onCancel={onCancel}
 | 
					 | 
				
			||||||
                    onSave={onSave!}
 | 
					 | 
				
			||||||
                    onDelete={onDelete}
 | 
					 | 
				
			||||||
                    onAutoSave={onAutoSave!}
 | 
					 | 
				
			||||||
                    compact={compact}
 | 
					 | 
				
			||||||
                />
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            elseShow={
 | 
					 | 
				
			||||||
                <ConstraintAccordionView
 | 
					 | 
				
			||||||
                    constraint={constraint}
 | 
					 | 
				
			||||||
                    onEdit={onEdit}
 | 
					 | 
				
			||||||
                    onDelete={onDelete}
 | 
					 | 
				
			||||||
                />
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,6 @@
 | 
				
			|||||||
import type React from 'react';
 | 
					import type React from 'react';
 | 
				
			||||||
import { forwardRef, Fragment, useImperativeHandle } from 'react';
 | 
					import { forwardRef, Fragment, useImperativeHandle } from 'react';
 | 
				
			||||||
import { styled, Tooltip } from '@mui/material';
 | 
					import { styled } from '@mui/material';
 | 
				
			||||||
import HelpOutline from '@mui/icons-material/HelpOutline';
 | 
					 | 
				
			||||||
import type { IConstraint } from 'interfaces/strategy';
 | 
					import type { IConstraint } from 'interfaces/strategy';
 | 
				
			||||||
import produce from 'immer';
 | 
					import produce from 'immer';
 | 
				
			||||||
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
 | 
					import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
 | 
				
			||||||
@ -43,30 +42,6 @@ const StyledContainer = styled('div')({
 | 
				
			|||||||
    flexDirection: 'column',
 | 
					    flexDirection: 'column',
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledHelpWrapper = styled(Tooltip)(({ theme }) => ({
 | 
					 | 
				
			||||||
    marginLeft: theme.spacing(0.75),
 | 
					 | 
				
			||||||
    height: theme.spacing(1.5),
 | 
					 | 
				
			||||||
}));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const StyledHelp = styled(HelpOutline)(({ theme }) => ({
 | 
					 | 
				
			||||||
    fill: theme.palette.action.active,
 | 
					 | 
				
			||||||
    [theme.breakpoints.down(860)]: {
 | 
					 | 
				
			||||||
        display: 'none',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
}));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const StyledConstraintLabel = styled('p')(({ theme }) => ({
 | 
					 | 
				
			||||||
    marginBottom: theme.spacing(1),
 | 
					 | 
				
			||||||
    color: theme.palette.text.secondary,
 | 
					 | 
				
			||||||
}));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const StyledAddCustomLabel = styled('div')(({ theme }) => ({
 | 
					 | 
				
			||||||
    marginTop: theme.spacing(1),
 | 
					 | 
				
			||||||
    marginBottom: theme.spacing(1),
 | 
					 | 
				
			||||||
    color: theme.palette.text.primary,
 | 
					 | 
				
			||||||
    display: 'flex',
 | 
					 | 
				
			||||||
}));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const useConstraintAccordionList = (
 | 
					export const useConstraintAccordionList = (
 | 
				
			||||||
    setConstraints:
 | 
					    setConstraints:
 | 
				
			||||||
        | React.Dispatch<React.SetStateAction<IConstraint[]>>
 | 
					        | React.Dispatch<React.SetStateAction<IConstraint[]>>
 | 
				
			||||||
 | 
				
			|||||||
@ -9,9 +9,12 @@ import {
 | 
				
			|||||||
    styled,
 | 
					    styled,
 | 
				
			||||||
} from '@mui/material';
 | 
					} from '@mui/material';
 | 
				
			||||||
import { StrategyEvaluationItem } from 'component/common/ConstraintsList/StrategyEvaluationItem/StrategyEvaluationItem';
 | 
					import { StrategyEvaluationItem } from 'component/common/ConstraintsList/StrategyEvaluationItem/StrategyEvaluationItem';
 | 
				
			||||||
import { ConstraintItem } from 'component/common/ConstraintsList/ConstraintItem/ConstraintItem';
 | 
					import { ConstraintItemHeader } from 'component/common/ConstraintsList/ConstraintItemHeader/ConstraintItemHeader';
 | 
				
			||||||
import { objectId } from 'utils/objectId';
 | 
					import { objectId } from 'utils/objectId';
 | 
				
			||||||
import { ConstraintsList } from 'component/common/ConstraintsList/ConstraintsList';
 | 
					import {
 | 
				
			||||||
 | 
					    ConstraintListItem,
 | 
				
			||||||
 | 
					    ConstraintsList,
 | 
				
			||||||
 | 
					} from 'component/common/ConstraintsList/ConstraintsList';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type SegmentItemProps = {
 | 
					type SegmentItemProps = {
 | 
				
			||||||
    segment: Partial<ISegment>;
 | 
					    segment: Partial<ISegment>;
 | 
				
			||||||
@ -21,7 +24,11 @@ type SegmentItemProps = {
 | 
				
			|||||||
    headerContent?: JSX.Element;
 | 
					    headerContent?: JSX.Element;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledAccordion = styled(Accordion)(({ theme }) => ({
 | 
					const StyledConstraintListItem = styled(ConstraintListItem)(() => ({
 | 
				
			||||||
 | 
					    padding: 0,
 | 
				
			||||||
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const StyledAccordion = styled(Accordion)(() => ({
 | 
				
			||||||
    boxShadow: 'none',
 | 
					    boxShadow: 'none',
 | 
				
			||||||
    margin: 0,
 | 
					    margin: 0,
 | 
				
			||||||
    padding: 0,
 | 
					    padding: 0,
 | 
				
			||||||
@ -32,16 +39,14 @@ const StyledAccordion = styled(Accordion)(({ theme }) => ({
 | 
				
			|||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledAccordionSummary = styled(AccordionSummary)(({ theme }) => ({
 | 
					const StyledAccordionSummary = styled(AccordionSummary)(({ theme }) => ({
 | 
				
			||||||
    padding: 0,
 | 
					    padding: theme.spacing(0, 3),
 | 
				
			||||||
    fontSize: theme.typography.body2.fontSize,
 | 
					    fontSize: theme.typography.body2.fontSize,
 | 
				
			||||||
    minHeight: 'unset',
 | 
					    minHeight: 'unset',
 | 
				
			||||||
    '.MuiAccordionSummary-content, .MuiAccordionSummary-content.Mui-expanded': {
 | 
					 | 
				
			||||||
        margin: 0,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledAccordionDetails = styled(AccordionDetails)(({ theme }) => ({
 | 
					const StyledAccordionDetails = styled(AccordionDetails)(({ theme }) => ({
 | 
				
			||||||
    padding: theme.spacing(2, 0, 1),
 | 
					    borderTop: `1px dashed ${theme.palette.divider}`,
 | 
				
			||||||
 | 
					    padding: theme.spacing(1.5, 3, 2.5),
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledLink = styled(Link)({
 | 
					const StyledLink = styled(Link)({
 | 
				
			||||||
@ -55,8 +60,6 @@ const StyledActionsContainer = styled('div')(({ theme }) => ({
 | 
				
			|||||||
    display: 'flex',
 | 
					    display: 'flex',
 | 
				
			||||||
    alignItems: 'center',
 | 
					    alignItems: 'center',
 | 
				
			||||||
    marginLeft: 'auto',
 | 
					    marginLeft: 'auto',
 | 
				
			||||||
    marginTop: theme.spacing(-0.5),
 | 
					 | 
				
			||||||
    marginBottom: theme.spacing(-0.5),
 | 
					 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledButton = styled(Button)(({ theme }) => ({
 | 
					const StyledButton = styled(Button)(({ theme }) => ({
 | 
				
			||||||
@ -85,10 +88,12 @@ export const SegmentItem: FC<SegmentItemProps> = ({
 | 
				
			|||||||
            return (
 | 
					            return (
 | 
				
			||||||
                <ConstraintsList>
 | 
					                <ConstraintsList>
 | 
				
			||||||
                    {segment.constraints.map((constraint, index) => (
 | 
					                    {segment.constraints.map((constraint, index) => (
 | 
				
			||||||
                        <ConstraintItem
 | 
					                        <ConstraintListItem
 | 
				
			||||||
                            key={`${objectId(constraint)}-${index}`}
 | 
					                            key={`${objectId(constraint)}-${index}`}
 | 
				
			||||||
                            {...constraint}
 | 
					                        >
 | 
				
			||||||
                        />
 | 
					                            {/* FIXME: use accordion */}
 | 
				
			||||||
 | 
					                            <ConstraintItemHeader {...constraint} />
 | 
				
			||||||
 | 
					                        </ConstraintListItem>
 | 
				
			||||||
                    ))}
 | 
					                    ))}
 | 
				
			||||||
                </ConstraintsList>
 | 
					                </ConstraintsList>
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
@ -102,27 +107,29 @@ export const SegmentItem: FC<SegmentItemProps> = ({
 | 
				
			|||||||
    }, [constraintList, segment.constraints]);
 | 
					    }, [constraintList, segment.constraints]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <StyledAccordion expanded={isOpen} disableGutters>
 | 
					        <StyledConstraintListItem>
 | 
				
			||||||
            <StyledAccordionSummary id={`segment-accordion-${segment.id}`}>
 | 
					            <StyledAccordion expanded={isOpen} disableGutters>
 | 
				
			||||||
                <StrategyEvaluationItem type='Segment'>
 | 
					                <StyledAccordionSummary id={`segment-accordion-${segment.id}`}>
 | 
				
			||||||
                    <StyledLink to={`/segments/edit/${segment.id}`}>
 | 
					                    <StrategyEvaluationItem type='Segment'>
 | 
				
			||||||
                        {segment.name}
 | 
					                        <StyledLink to={`/segments/edit/${segment.id}`}>
 | 
				
			||||||
                    </StyledLink>
 | 
					                            {segment.name}
 | 
				
			||||||
                </StrategyEvaluationItem>
 | 
					                        </StyledLink>
 | 
				
			||||||
                {headerContent ? headerContent : null}
 | 
					                    </StrategyEvaluationItem>
 | 
				
			||||||
                {!isExpanded ? (
 | 
					                    {headerContent ? headerContent : null}
 | 
				
			||||||
                    <StyledActionsContainer>
 | 
					                    {!isExpanded ? (
 | 
				
			||||||
                        <StyledButton
 | 
					                        <StyledActionsContainer>
 | 
				
			||||||
                            size='small'
 | 
					                            <StyledButton
 | 
				
			||||||
                            variant='outlined'
 | 
					                                size='small'
 | 
				
			||||||
                            onClick={() => setIsOpen((value) => !value)}
 | 
					                                variant='outlined'
 | 
				
			||||||
                        >
 | 
					                                onClick={() => setIsOpen((value) => !value)}
 | 
				
			||||||
                            {isOpen ? 'Close preview' : 'Preview'}
 | 
					                            >
 | 
				
			||||||
                        </StyledButton>
 | 
					                                {isOpen ? 'Close preview' : 'Preview'}
 | 
				
			||||||
                    </StyledActionsContainer>
 | 
					                            </StyledButton>
 | 
				
			||||||
                ) : null}
 | 
					                        </StyledActionsContainer>
 | 
				
			||||||
            </StyledAccordionSummary>
 | 
					                    ) : null}
 | 
				
			||||||
            <StyledAccordionDetails>{constraints}</StyledAccordionDetails>
 | 
					                </StyledAccordionSummary>
 | 
				
			||||||
        </StyledAccordion>
 | 
					                <StyledAccordionDetails>{constraints}</StyledAccordionDetails>
 | 
				
			||||||
 | 
					            </StyledAccordion>
 | 
				
			||||||
 | 
					        </StyledConstraintListItem>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -25,13 +25,14 @@ const StyledTruncatorContainer = styled(Box, {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type OverridableTooltipProps = Omit<TooltipProps, 'children'>;
 | 
					type OverridableTooltipProps = Omit<TooltipProps, 'children'>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface ITruncatorProps extends BoxProps {
 | 
					export type TruncatorProps = {
 | 
				
			||||||
    lines?: number;
 | 
					    lines?: number;
 | 
				
			||||||
    title?: string;
 | 
					    title?: string;
 | 
				
			||||||
    arrow?: boolean;
 | 
					    arrow?: boolean;
 | 
				
			||||||
    tooltipProps?: OverridableTooltipProps;
 | 
					    tooltipProps?: OverridableTooltipProps;
 | 
				
			||||||
    children: React.ReactNode;
 | 
					    children: React.ReactNode;
 | 
				
			||||||
}
 | 
					    onSetTruncated?: (isTruncated: boolean) => void;
 | 
				
			||||||
 | 
					} & BoxProps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Truncator = ({
 | 
					export const Truncator = ({
 | 
				
			||||||
    lines = 1,
 | 
					    lines = 1,
 | 
				
			||||||
@ -40,8 +41,9 @@ export const Truncator = ({
 | 
				
			|||||||
    tooltipProps,
 | 
					    tooltipProps,
 | 
				
			||||||
    children,
 | 
					    children,
 | 
				
			||||||
    component = 'span',
 | 
					    component = 'span',
 | 
				
			||||||
 | 
					    onSetTruncated,
 | 
				
			||||||
    ...props
 | 
					    ...props
 | 
				
			||||||
}: ITruncatorProps) => {
 | 
					}: TruncatorProps) => {
 | 
				
			||||||
    const [isTruncated, setIsTruncated] = useState(false);
 | 
					    const [isTruncated, setIsTruncated] = useState(false);
 | 
				
			||||||
    const ref = useRef<HTMLDivElement>(null);
 | 
					    const ref = useRef<HTMLDivElement>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -50,7 +52,6 @@ export const Truncator = ({
 | 
				
			|||||||
            setIsTruncated(ref.current.scrollHeight > ref.current.offsetHeight);
 | 
					            setIsTruncated(ref.current.scrollHeight > ref.current.offsetHeight);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					 | 
				
			||||||
    useEffect(() => {
 | 
					    useEffect(() => {
 | 
				
			||||||
        const resizeObserver = new ResizeObserver(checkTruncation);
 | 
					        const resizeObserver = new ResizeObserver(checkTruncation);
 | 
				
			||||||
        if (ref.current) {
 | 
					        if (ref.current) {
 | 
				
			||||||
@ -59,6 +60,10 @@ export const Truncator = ({
 | 
				
			|||||||
        return () => resizeObserver.disconnect();
 | 
					        return () => resizeObserver.disconnect();
 | 
				
			||||||
    }, [title, children]);
 | 
					    }, [title, children]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        onSetTruncated?.(isTruncated);
 | 
				
			||||||
 | 
					    }, [isTruncated]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const overridableTooltipProps: OverridableTooltipProps = {
 | 
					    const overridableTooltipProps: OverridableTooltipProps = {
 | 
				
			||||||
        title,
 | 
					        title,
 | 
				
			||||||
        arrow,
 | 
					        arrow,
 | 
				
			||||||
 | 
				
			|||||||
@ -29,6 +29,12 @@ const StyledPayloadHeader = styled('div')(({ theme }) => ({
 | 
				
			|||||||
    marginBottom: theme.spacing(1),
 | 
					    marginBottom: theme.spacing(1),
 | 
				
			||||||
}));
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const StyledValuesContainer = styled('div')(({ theme }) => ({
 | 
				
			||||||
 | 
					    display: 'flex',
 | 
				
			||||||
 | 
					    gap: theme.spacing(0.75, 0.5),
 | 
				
			||||||
 | 
					    flexWrap: 'wrap',
 | 
				
			||||||
 | 
					}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const RolloutVariants: FC<{
 | 
					export const RolloutVariants: FC<{
 | 
				
			||||||
    variants?: StrategyVariantSchema[];
 | 
					    variants?: StrategyVariantSchema[];
 | 
				
			||||||
}> = ({ variants }) => {
 | 
					}> = ({ variants }) => {
 | 
				
			||||||
@ -38,34 +44,36 @@ export const RolloutVariants: FC<{
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <StrategyEvaluationItem type={`Variants (${variants.length})`}>
 | 
					        <StrategyEvaluationItem type={`Variants (${variants.length})`}>
 | 
				
			||||||
            {variants.map((variant, i) => (
 | 
					            <StyledValuesContainer>
 | 
				
			||||||
                <HtmlTooltip
 | 
					                {variants.map((variant, i) => (
 | 
				
			||||||
                    arrow
 | 
					                    <HtmlTooltip
 | 
				
			||||||
                    title={
 | 
					                        arrow
 | 
				
			||||||
                        variant.payload?.value ? (
 | 
					                        title={
 | 
				
			||||||
                            <div>
 | 
					                            variant.payload?.value ? (
 | 
				
			||||||
                                <StyledPayloadHeader>
 | 
					                                <div>
 | 
				
			||||||
                                    Payload:
 | 
					                                    <StyledPayloadHeader>
 | 
				
			||||||
                                </StyledPayloadHeader>
 | 
					                                        Payload:
 | 
				
			||||||
                                <code>{variant.payload?.value}</code>
 | 
					                                    </StyledPayloadHeader>
 | 
				
			||||||
                            </div>
 | 
					                                    <code>{variant.payload?.value}</code>
 | 
				
			||||||
                        ) : null
 | 
					                                </div>
 | 
				
			||||||
                    }
 | 
					                            ) : null
 | 
				
			||||||
                    key={variant.name}
 | 
					 | 
				
			||||||
                >
 | 
					 | 
				
			||||||
                    <StyledVariantChip
 | 
					 | 
				
			||||||
                        key={variant.name}
 | 
					 | 
				
			||||||
                        order={i}
 | 
					 | 
				
			||||||
                        label={
 | 
					 | 
				
			||||||
                            <>
 | 
					 | 
				
			||||||
                                <span>
 | 
					 | 
				
			||||||
                                    {variant.weight / 10}% – {variant.name}
 | 
					 | 
				
			||||||
                                </span>
 | 
					 | 
				
			||||||
                            </>
 | 
					 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    />
 | 
					                        key={variant.name}
 | 
				
			||||||
                </HtmlTooltip>
 | 
					                    >
 | 
				
			||||||
            ))}
 | 
					                        <StyledVariantChip
 | 
				
			||||||
 | 
					                            key={variant.name}
 | 
				
			||||||
 | 
					                            order={i}
 | 
				
			||||||
 | 
					                            label={
 | 
				
			||||||
 | 
					                                <>
 | 
				
			||||||
 | 
					                                    <span>
 | 
				
			||||||
 | 
					                                        {variant.weight / 10}% – {variant.name}
 | 
				
			||||||
 | 
					                                    </span>
 | 
				
			||||||
 | 
					                                </>
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                    </HtmlTooltip>
 | 
				
			||||||
 | 
					                ))}
 | 
				
			||||||
 | 
					            </StyledValuesContainer>
 | 
				
			||||||
        </StrategyEvaluationItem>
 | 
					        </StrategyEvaluationItem>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -3,14 +3,17 @@ import type { FeatureStrategySchema } from 'openapi';
 | 
				
			|||||||
import type { IFeatureStrategyPayload } from 'interfaces/strategy';
 | 
					import type { IFeatureStrategyPayload } from 'interfaces/strategy';
 | 
				
			||||||
import { useUiFlag } from 'hooks/useUiFlag';
 | 
					import { useUiFlag } from 'hooks/useUiFlag';
 | 
				
			||||||
import { StrategyExecution as LegacyStrategyExecution } from './LegacyStrategyExecution';
 | 
					import { StrategyExecution as LegacyStrategyExecution } from './LegacyStrategyExecution';
 | 
				
			||||||
import { ConstraintItem } from 'component/common/ConstraintsList/ConstraintItem/ConstraintItem';
 | 
					import { ConstraintItemHeader } from 'component/common/ConstraintsList/ConstraintItemHeader/ConstraintItemHeader';
 | 
				
			||||||
import { useStrategies } from 'hooks/api/getters/useStrategies/useStrategies';
 | 
					import { useStrategies } from 'hooks/api/getters/useStrategies/useStrategies';
 | 
				
			||||||
import { objectId } from 'utils/objectId';
 | 
					import { objectId } from 'utils/objectId';
 | 
				
			||||||
import { useCustomStrategyParameters } from './hooks/useCustomStrategyParameters';
 | 
					import { useCustomStrategyParameters } from './hooks/useCustomStrategyParameters';
 | 
				
			||||||
import { useStrategyParameters } from './hooks/useStrategyParameters';
 | 
					import { useStrategyParameters } from './hooks/useStrategyParameters';
 | 
				
			||||||
import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
 | 
					import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
 | 
				
			||||||
import { SegmentItem } from 'component/common/SegmentItem/SegmentItem';
 | 
					import { SegmentItem } from 'component/common/SegmentItem/SegmentItem';
 | 
				
			||||||
import { ConstraintsList } from 'component/common/ConstraintsList/ConstraintsList';
 | 
					import {
 | 
				
			||||||
 | 
					    ConstraintListItem,
 | 
				
			||||||
 | 
					    ConstraintsList,
 | 
				
			||||||
 | 
					} from 'component/common/ConstraintsList/ConstraintsList';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type StrategyExecutionProps = {
 | 
					type StrategyExecutionProps = {
 | 
				
			||||||
    strategy: IFeatureStrategyPayload | FeatureStrategySchema;
 | 
					    strategy: IFeatureStrategyPayload | FeatureStrategySchema;
 | 
				
			||||||
@ -50,12 +53,16 @@ export const StrategyExecution: FC<StrategyExecutionProps> = ({
 | 
				
			|||||||
                <SegmentItem segment={segment} key={segment.id} />
 | 
					                <SegmentItem segment={segment} key={segment.id} />
 | 
				
			||||||
            ))}
 | 
					            ))}
 | 
				
			||||||
            {constraints?.map((constraint, index) => (
 | 
					            {constraints?.map((constraint, index) => (
 | 
				
			||||||
                <ConstraintItem
 | 
					                <ConstraintListItem key={`${objectId(constraint)}-${index}`}>
 | 
				
			||||||
                    key={`${objectId(constraint)}-${index}`}
 | 
					                    {/* FIXME: use constraint accordion */}
 | 
				
			||||||
                    {...constraint}
 | 
					                    <ConstraintItemHeader {...constraint} />
 | 
				
			||||||
                />
 | 
					                </ConstraintListItem>
 | 
				
			||||||
            ))}
 | 
					            ))}
 | 
				
			||||||
            {isCustomStrategy ? customStrategyItems : strategyParameters}
 | 
					            {(isCustomStrategy ? customStrategyItems : strategyParameters).map(
 | 
				
			||||||
 | 
					                (item, index) => (
 | 
				
			||||||
 | 
					                    <ConstraintListItem key={index}>{item}</ConstraintListItem>
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            )}
 | 
				
			||||||
        </ConstraintsList>
 | 
					        </ConstraintsList>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -3,10 +3,11 @@ import type {
 | 
				
			|||||||
    PlaygroundConstraintSchema,
 | 
					    PlaygroundConstraintSchema,
 | 
				
			||||||
    PlaygroundRequestSchema,
 | 
					    PlaygroundRequestSchema,
 | 
				
			||||||
} from 'openapi';
 | 
					} from 'openapi';
 | 
				
			||||||
import { ConstraintItem } from 'component/common/ConstraintsList/ConstraintItem/ConstraintItem';
 | 
					import { ConstraintItemHeader } from 'component/common/ConstraintsList/ConstraintItemHeader/ConstraintItemHeader';
 | 
				
			||||||
import CheckCircle from '@mui/icons-material/CheckCircle';
 | 
					import CheckCircle from '@mui/icons-material/CheckCircle';
 | 
				
			||||||
import { styled } from '@mui/material';
 | 
					import { styled } from '@mui/material';
 | 
				
			||||||
import Cancel from '@mui/icons-material/Cancel';
 | 
					import Cancel from '@mui/icons-material/Cancel';
 | 
				
			||||||
 | 
					import { ConstraintListItem } from 'component/common/ConstraintsList/ConstraintsList';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface IConstraintExecutionProps {
 | 
					interface IConstraintExecutionProps {
 | 
				
			||||||
    constraint?: PlaygroundConstraintSchema;
 | 
					    constraint?: PlaygroundConstraintSchema;
 | 
				
			||||||
@ -20,7 +21,7 @@ const StyledContainer = styled('div', {
 | 
				
			|||||||
    display: 'flex',
 | 
					    display: 'flex',
 | 
				
			||||||
    alignItems: 'center',
 | 
					    alignItems: 'center',
 | 
				
			||||||
    gap: theme.spacing(1),
 | 
					    gap: theme.spacing(1),
 | 
				
			||||||
    paddingInline: theme.spacing(0.25),
 | 
					    padding: theme.spacing(0.5, 0.25),
 | 
				
			||||||
    color:
 | 
					    color:
 | 
				
			||||||
        variant === 'ok'
 | 
					        variant === 'ok'
 | 
				
			||||||
            ? theme.palette.success.dark
 | 
					            ? theme.palette.success.dark
 | 
				
			||||||
@ -67,13 +68,15 @@ export const ConstraintExecution: FC<IConstraintExecutionProps> = ({
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <>
 | 
					        <ConstraintListItem>
 | 
				
			||||||
            <ConstraintItem {...constraint} />
 | 
					            <div>
 | 
				
			||||||
            {constraint.result ? (
 | 
					                <ConstraintItemHeader {...constraint} />
 | 
				
			||||||
                <ConstraintOk />
 | 
					                {constraint.result ? (
 | 
				
			||||||
            ) : (
 | 
					                    <ConstraintOk />
 | 
				
			||||||
                <ConstraintError text={errorText()} />
 | 
					                ) : (
 | 
				
			||||||
            )}
 | 
					                    <ConstraintError text={errorText()} />
 | 
				
			||||||
        </>
 | 
					                )}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </ConstraintListItem>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,10 @@ import { ConstraintExecution } from './ConstraintExecution/ConstraintExecution';
 | 
				
			|||||||
import { formattedStrategyNames } from 'utils/strategyNames';
 | 
					import { formattedStrategyNames } from 'utils/strategyNames';
 | 
				
			||||||
import { StyledBoxSummary } from './StrategyExecution.styles';
 | 
					import { StyledBoxSummary } from './StrategyExecution.styles';
 | 
				
			||||||
import { Badge } from 'component/common/Badge/Badge';
 | 
					import { Badge } from 'component/common/Badge/Badge';
 | 
				
			||||||
import { ConstraintsList } from 'component/common/ConstraintsList/ConstraintsList';
 | 
					import {
 | 
				
			||||||
 | 
					    ConstraintListItem,
 | 
				
			||||||
 | 
					    ConstraintsList,
 | 
				
			||||||
 | 
					} from 'component/common/ConstraintsList/ConstraintsList';
 | 
				
			||||||
import { objectId } from 'utils/objectId';
 | 
					import { objectId } from 'utils/objectId';
 | 
				
			||||||
import type { FC } from 'react';
 | 
					import type { FC } from 'react';
 | 
				
			||||||
import { SegmentExecution } from './SegmentExecution/SegmentExecution';
 | 
					import { SegmentExecution } from './SegmentExecution/SegmentExecution';
 | 
				
			||||||
@ -60,8 +63,14 @@ export const StrategyExecution: FC<StrategyExecutionProps> = ({
 | 
				
			|||||||
                  />
 | 
					                  />
 | 
				
			||||||
              ))
 | 
					              ))
 | 
				
			||||||
            : []),
 | 
					            : []),
 | 
				
			||||||
        hasExecutionParameters && params,
 | 
					        hasExecutionParameters &&
 | 
				
			||||||
        isCustomStrategy && customStrategyItems,
 | 
					            params.map((param, index) => (
 | 
				
			||||||
 | 
					                <ConstraintListItem key={index}>{param}</ConstraintListItem>
 | 
				
			||||||
 | 
					            )),
 | 
				
			||||||
 | 
					        isCustomStrategy &&
 | 
				
			||||||
 | 
					            customStrategyItems.map((param, index) => (
 | 
				
			||||||
 | 
					                <ConstraintListItem key={index}>{param}</ConstraintListItem>
 | 
				
			||||||
 | 
					            )),
 | 
				
			||||||
        name === 'default' && (
 | 
					        name === 'default' && (
 | 
				
			||||||
            <StyledBoxSummary sx={{ width: '100%' }}>
 | 
					            <StyledBoxSummary sx={{ width: '100%' }}>
 | 
				
			||||||
                The standard strategy is <Badge color='success'>ON</Badge> for
 | 
					                The standard strategy is <Badge color='success'>ON</Badge> for
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user