mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-27 01:19:00 +02:00
Constraint values preview and filtering (#9603)
Restore constraint accordion to flag page.
This commit is contained in:
parent
c161291d09
commit
d8c7e31b18
@ -1,4 +1,4 @@
|
|||||||
import type { ComponentProps, FC } from 'react';
|
import type { ComponentProps, FC, ReactNode } from 'react';
|
||||||
import { StrategyEvaluationItem } from '../StrategyEvaluationItem/StrategyEvaluationItem';
|
import { StrategyEvaluationItem } 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';
|
||||||
@ -48,6 +48,13 @@ const CaseSensitive: FC = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const StyledConstraintContainer = styled('div')(({ theme }) => ({
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateColumns: 'repeat(3, auto)',
|
||||||
|
gap: theme.spacing(2),
|
||||||
|
placeItems: 'center',
|
||||||
|
}));
|
||||||
|
|
||||||
const StyledOperatorGroup = styled('div')(({ theme }) => ({
|
const StyledOperatorGroup = styled('div')(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
@ -60,9 +67,15 @@ const StyledConstraintName = styled('div')(({ theme }) => ({
|
|||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const ConstraintItemHeader: FC<
|
type ConstraintItemHeaderProps = ConstraintSchema & {
|
||||||
ConstraintSchema & Pick<ComponentProps<typeof ValuesList>, 'onSetTruncated'>
|
viewMore?: ReactNode;
|
||||||
> = ({ onSetTruncated, ...constraint }) => {
|
} & Pick<ComponentProps<typeof ValuesList>, 'onSetTruncated'>;
|
||||||
|
|
||||||
|
export const ConstraintItemHeader: FC<ConstraintItemHeaderProps> = ({
|
||||||
|
onSetTruncated,
|
||||||
|
viewMore,
|
||||||
|
...constraint
|
||||||
|
}) => {
|
||||||
const { caseInsensitive, contextName, inverted, operator, value, values } =
|
const { caseInsensitive, contextName, inverted, operator, value, values } =
|
||||||
constraint;
|
constraint;
|
||||||
const { locationSettings } = useLocationSettings();
|
const { locationSettings } = useLocationSettings();
|
||||||
@ -77,22 +90,29 @@ export const ConstraintItemHeader: FC<
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StrategyEvaluationItem type='Constraint'>
|
<StrategyEvaluationItem type='Constraint'>
|
||||||
<StyledConstraintName>
|
<StyledConstraintContainer>
|
||||||
<Truncator lines={2} title={contextName} arrow>
|
<StyledConstraintName>
|
||||||
{contextName}
|
<Truncator title={contextName} arrow>
|
||||||
</Truncator>
|
{contextName}
|
||||||
</StyledConstraintName>
|
</Truncator>
|
||||||
<StyledOperatorGroup>
|
</StyledConstraintName>
|
||||||
<Operator label={operator} inverted={inverted} />
|
<StyledOperatorGroup>
|
||||||
{isCaseSensitive(operator, caseInsensitive) ? (
|
<Operator label={operator} inverted={inverted} />
|
||||||
<CaseSensitive />
|
{isCaseSensitive(operator, caseInsensitive) ? (
|
||||||
) : null}
|
<CaseSensitive />
|
||||||
</StyledOperatorGroup>
|
) : null}
|
||||||
<ValuesList
|
</StyledOperatorGroup>
|
||||||
values={items}
|
<div>
|
||||||
onSetTruncated={onSetTruncated}
|
<div>
|
||||||
tooltips={tooltips}
|
<ValuesList
|
||||||
/>
|
values={items}
|
||||||
|
onSetTruncated={onSetTruncated}
|
||||||
|
tooltips={tooltips}
|
||||||
|
/>
|
||||||
|
{viewMore}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</StyledConstraintContainer>
|
||||||
</StrategyEvaluationItem>
|
</StrategyEvaluationItem>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import { styled, Tooltip } from '@mui/material';
|
import { styled } from '@mui/material';
|
||||||
import {
|
import {
|
||||||
Truncator,
|
Truncator,
|
||||||
type TruncatorProps,
|
type TruncatorProps,
|
||||||
} from 'component/common/Truncator/Truncator';
|
} from 'component/common/Truncator/Truncator';
|
||||||
|
import { TooltipResolver } from 'component/common/TooltipResolver/TooltipResolver';
|
||||||
|
|
||||||
export type ValuesListProps = {
|
export type ValuesListProps = {
|
||||||
values?: string[];
|
values?: string[];
|
||||||
@ -14,7 +15,12 @@ const StyledValuesContainer = styled('div')({
|
|||||||
flex: '1 1 0',
|
flex: '1 1 0',
|
||||||
});
|
});
|
||||||
|
|
||||||
const StyledValueItem = styled('span')(({ theme }) => ({
|
const StyledTruncator = styled(Truncator)({
|
||||||
|
padding: 0,
|
||||||
|
margin: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const StyledValueItem = styled('li')(({ theme }) => ({
|
||||||
padding: theme.spacing(0.25),
|
padding: theme.spacing(0.25),
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
span: {
|
span: {
|
||||||
@ -45,22 +51,30 @@ export const ValuesList: FC<ValuesListProps> = ({
|
|||||||
lines={2}
|
lines={2}
|
||||||
onSetTruncated={() => onSetTruncated?.(false)}
|
onSetTruncated={() => onSetTruncated?.(false)}
|
||||||
>
|
>
|
||||||
<Tooltip title={tooltips?.[values[0]] || ''}>
|
<TooltipResolver title={tooltips?.[values[0]] || ''}>
|
||||||
<span>{values[0]}</span>
|
<span>{values[0]}</span>
|
||||||
</Tooltip>
|
</TooltipResolver>
|
||||||
</Truncator>
|
</Truncator>
|
||||||
</StyledSingleValue>
|
</StyledSingleValue>
|
||||||
) : null}
|
) : null}
|
||||||
{values && values?.length > 1 ? (
|
{values && values?.length > 1 ? (
|
||||||
<Truncator title='' lines={2} onSetTruncated={onSetTruncated}>
|
<StyledTruncator
|
||||||
|
title=''
|
||||||
|
lines={2}
|
||||||
|
onSetTruncated={onSetTruncated}
|
||||||
|
component='ul'
|
||||||
|
>
|
||||||
{values.map((value) => (
|
{values.map((value) => (
|
||||||
<Tooltip title={tooltips?.[value] || ''} key={value}>
|
<TooltipResolver
|
||||||
|
title={tooltips?.[value] || ''}
|
||||||
|
key={value}
|
||||||
|
>
|
||||||
<StyledValueItem>
|
<StyledValueItem>
|
||||||
<span>{value}</span>
|
<span>{value}</span>
|
||||||
</StyledValueItem>
|
</StyledValueItem>
|
||||||
</Tooltip>
|
</TooltipResolver>
|
||||||
))}
|
))}
|
||||||
</Truncator>
|
</StyledTruncator>
|
||||||
) : null}
|
) : null}
|
||||||
</StyledValuesContainer>
|
</StyledValuesContainer>
|
||||||
);
|
);
|
||||||
|
@ -30,7 +30,6 @@ interface IConstraintAccordionViewProps {
|
|||||||
const StyledAccordion = styled(Accordion)(({ theme }) => ({
|
const StyledAccordion = styled(Accordion)(({ theme }) => ({
|
||||||
border: `1px solid ${theme.palette.divider}`,
|
border: `1px solid ${theme.palette.divider}`,
|
||||||
borderRadius: theme.shape.borderRadiusMedium,
|
borderRadius: theme.shape.borderRadiusMedium,
|
||||||
backgroundColor: 'transparent',
|
|
||||||
boxShadow: 'none',
|
boxShadow: 'none',
|
||||||
margin: 0,
|
margin: 0,
|
||||||
'&:before': {
|
'&:before': {
|
||||||
|
@ -10,7 +10,7 @@ interface IConstraintAccordionViewBodyProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const StyledValueContainer = styled('div')(({ theme }) => ({
|
const StyledValueContainer = styled('div')(({ theme }) => ({
|
||||||
padding: theme.spacing(2, 0),
|
padding: theme.spacing(1, 0),
|
||||||
maxHeight: '400px',
|
maxHeight: '400px',
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
}));
|
}));
|
||||||
|
@ -55,7 +55,6 @@ export const ConstraintAccordionViewHeader = ({
|
|||||||
{flagOverviewRedesign ? (
|
{flagOverviewRedesign ? (
|
||||||
<ConstraintAccordionViewHeaderInfo
|
<ConstraintAccordionViewHeaderInfo
|
||||||
constraint={constraint}
|
constraint={constraint}
|
||||||
singleValue={singleValue}
|
|
||||||
allowExpand={allowExpand}
|
allowExpand={allowExpand}
|
||||||
expanded={expanded}
|
expanded={expanded}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import { IconButton, styled } from '@mui/material';
|
import { styled } from '@mui/material';
|
||||||
import type { IConstraint } from 'interfaces/strategy';
|
import type { IConstraint } from 'interfaces/strategy';
|
||||||
import { ConstraintItemHeader } from 'component/common/ConstraintsList/ConstraintItemHeader/ConstraintItemHeader';
|
import { ConstraintItemHeader } from 'component/common/ConstraintsList/ConstraintItemHeader/ConstraintItemHeader';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import VisibilityIcon from '@mui/icons-material/Visibility';
|
|
||||||
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
|
|
||||||
|
|
||||||
const StyledHeaderWrapper = styled('div')(({ theme }) => ({
|
const StyledHeaderWrapper = styled('div')(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -24,9 +22,14 @@ const StyledHeaderMetaInfo = styled('div')(({ theme }) => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const StyledExpandItem = styled('div')(({ theme }) => ({
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
margin: theme.spacing(0.25, 0, 0, 0.75),
|
||||||
|
fontSize: theme.fontSizes.smallerBody,
|
||||||
|
}));
|
||||||
|
|
||||||
interface ConstraintAccordionViewHeaderMetaInfoProps {
|
interface ConstraintAccordionViewHeaderMetaInfoProps {
|
||||||
constraint: IConstraint;
|
constraint: IConstraint;
|
||||||
singleValue: boolean;
|
|
||||||
expanded: boolean;
|
expanded: boolean;
|
||||||
allowExpand: (shouldExpand: boolean) => void;
|
allowExpand: (shouldExpand: boolean) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
@ -49,12 +52,16 @@ export const ConstraintAccordionViewHeaderInfo = ({
|
|||||||
setExpandable(state);
|
setExpandable(state);
|
||||||
allowExpand(state);
|
allowExpand(state);
|
||||||
}}
|
}}
|
||||||
|
viewMore={
|
||||||
|
expandable ? (
|
||||||
|
<StyledExpandItem>
|
||||||
|
{expanded
|
||||||
|
? 'View less'
|
||||||
|
: `View all (${constraint.values?.length})`}
|
||||||
|
</StyledExpandItem>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
{expandable ? (
|
|
||||||
<IconButton type='button'>
|
|
||||||
{expanded ? <VisibilityOffIcon /> : <VisibilityIcon />}
|
|
||||||
</IconButton>
|
|
||||||
) : null}
|
|
||||||
</StyledHeaderMetaInfo>
|
</StyledHeaderMetaInfo>
|
||||||
</StyledHeaderWrapper>
|
</StyledHeaderWrapper>
|
||||||
);
|
);
|
||||||
|
@ -20,10 +20,10 @@ export const ConstraintValueSearch = ({
|
|||||||
value={filter}
|
value={filter}
|
||||||
onChange={(e) => setFilter(e.target.value)}
|
onChange={(e) => setFilter(e.target.value)}
|
||||||
placeholder='Filter values'
|
placeholder='Filter values'
|
||||||
style={{
|
sx={(theme) => ({
|
||||||
width: '100%',
|
width: '100%',
|
||||||
margin: '1rem 0',
|
margin: theme.spacing(1, 0, 2),
|
||||||
}}
|
})}
|
||||||
variant='outlined'
|
variant='outlined'
|
||||||
size='small'
|
size='small'
|
||||||
InputProps={{
|
InputProps={{
|
||||||
|
@ -3,7 +3,7 @@ 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 { ConstraintItemHeader } from 'component/common/ConstraintsList/ConstraintItemHeader/ConstraintItemHeader';
|
import { ConstraintAccordionView } from 'component/common/NewConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView';
|
||||||
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';
|
||||||
@ -53,10 +53,10 @@ 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) => (
|
||||||
<ConstraintListItem key={`${objectId(constraint)}-${index}`}>
|
<ConstraintAccordionView
|
||||||
{/* FIXME: use constraint accordion */}
|
key={`${objectId(constraint)}-${index}`}
|
||||||
<ConstraintItemHeader {...constraint} />
|
constraint={constraint}
|
||||||
</ConstraintListItem>
|
/>
|
||||||
))}
|
))}
|
||||||
{(isCustomStrategy ? customStrategyItems : strategyParameters).map(
|
{(isCustomStrategy ? customStrategyItems : strategyParameters).map(
|
||||||
(item, index) => (
|
(item, index) => (
|
||||||
|
Loading…
Reference in New Issue
Block a user