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

refactor constraint values

This commit is contained in:
Tymoteusz Czech 2025-03-20 19:03:28 +01:00
parent 9b19d519ed
commit 6129565828
No known key found for this signature in database
GPG Key ID: 133555230D88D75F
7 changed files with 131 additions and 65 deletions

View File

@ -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 = () => (
<Tooltip title='NOT (operator is negated)' arrow>
@ -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<StrategyEvaluationItemProps, 'onSetTruncated'>
> = ({
caseInsensitive,
contextName,
inverted,
operator,
value,
values,
onSetTruncated,
}) => {
const items = value ? [value, ...(values || [])] : values || [];
ConstraintSchema & Pick<ComponentProps<typeof ValuesList>, '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 (
<StrategyEvaluationItem
type='Constraint'
values={items}
onSetTruncated={onSetTruncated}
>
{contextName}
<StrategyEvaluationItem type='Constraint'>
<StyledConstraintName>
<Truncator lines={2} title={contextName} arrow>
{contextName}
</Truncator>
</StyledConstraintName>
<StyledOperatorGroup>
{inverted ? <Inverted /> : null}
<Operator label={operator} />
{caseInsensitive ? <CaseInsensitive /> : null}
</StyledOperatorGroup>
<ValuesList
values={items}
onSetTruncated={onSetTruncated}
tooltips={tooltips}
/>
</StrategyEvaluationItem>
);
};

View File

@ -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<TruncatorProps, 'onSetTruncated'>;
};
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<StrategyEvaluationItemProps> = ({
type,
children,
values,
onSetTruncated,
}) => (
<StyledContainer>
<StyledType>{type}</StyledType>
<StyledContent>
{children}
{values && values?.length === 1 ? (
<Truncator
title={values[0]}
arrow
lines={2}
onSetTruncated={() => onSetTruncated?.(false)}
>
{values[0]}
</Truncator>
) : null}
{values && values?.length > 1 ? (
<Truncator title='' lines={2} onSetTruncated={onSetTruncated}>
{values.join(', ')}
</Truncator>
) : null}
</StyledContent>
</StyledContainer>
);
}) => {
return (
<StyledContainer>
<StyledType>{type}</StyledType>
<StyledContent>{children}</StyledContent>
</StyledContainer>
);
};

View File

@ -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<string, string | undefined>;
} & Pick<TruncatorProps, 'onSetTruncated'>;
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<ValuesListProps> = ({
values,
tooltips,
onSetTruncated,
}) => (
<StyledValuesContainer>
{values && values?.length === 1 ? (
<StyledSingleValue>
<Truncator
title={values[0]}
arrow
lines={2}
onSetTruncated={() => onSetTruncated?.(false)}
>
{values[0]}
</Truncator>
</StyledSingleValue>
) : null}
{values && values?.length > 1 ? (
<Truncator title='' lines={2} onSetTruncated={onSetTruncated}>
{values.map((value) => (
<Tooltip title={tooltips?.[value] || ''} arrow key={value}>
<StyledValueItem>
<span>{value}</span>
{tooltips?.[value]}
</StyledValueItem>
</Tooltip>
))}
</Truncator>
) : null}
</StyledValuesContainer>
);

View File

@ -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)({

View File

@ -51,7 +51,7 @@ export const useCustomStrategyParameters = (
<StrategyEvaluationItem
key={key}
type={typeItem}
values={values}
// values={values} // FIXME: values
>
{values.length === 1
? 'has 1 item:'
@ -85,7 +85,7 @@ export const useCustomStrategyParameters = (
<StrategyEvaluationItem
key={key}
type={typeItem}
values={value === '' ? undefined : [value]}
// values={value === '' ? undefined : [value]} // FIXME: values
>
{value === '' ? 'is an empty string' : 'is set to'}
</StrategyEvaluationItem>
@ -98,7 +98,7 @@ export const useCustomStrategyParameters = (
<StrategyEvaluationItem
key={key}
type={typeItem}
values={[`${value}`]}
// values={[`${value}`]} // FIXME: values
>
is a number set to
</StrategyEvaluationItem>

View File

@ -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 = (
<StrategyEvaluationItem
key={key}
type={key}
values={parseParameterStrings(value)}
// values={parseParameterStrings(value)} // FIXME: values
/>
);
}

View File

@ -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<ConstraintSchema, 'value' | 'contextName'>,
locationSettings: ILocationSettings,
): string | undefined => {
if (