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 type { ConstraintSchema } from 'openapi';
|
||||
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 }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
@ -60,9 +67,15 @@ const StyledConstraintName = styled('div')(({ theme }) => ({
|
||||
overflow: 'hidden',
|
||||
}));
|
||||
|
||||
export const ConstraintItemHeader: FC<
|
||||
ConstraintSchema & Pick<ComponentProps<typeof ValuesList>, 'onSetTruncated'>
|
||||
> = ({ onSetTruncated, ...constraint }) => {
|
||||
type ConstraintItemHeaderProps = ConstraintSchema & {
|
||||
viewMore?: ReactNode;
|
||||
} & Pick<ComponentProps<typeof ValuesList>, 'onSetTruncated'>;
|
||||
|
||||
export const ConstraintItemHeader: FC<ConstraintItemHeaderProps> = ({
|
||||
onSetTruncated,
|
||||
viewMore,
|
||||
...constraint
|
||||
}) => {
|
||||
const { caseInsensitive, contextName, inverted, operator, value, values } =
|
||||
constraint;
|
||||
const { locationSettings } = useLocationSettings();
|
||||
@ -77,22 +90,29 @@ export const ConstraintItemHeader: FC<
|
||||
|
||||
return (
|
||||
<StrategyEvaluationItem type='Constraint'>
|
||||
<StyledConstraintName>
|
||||
<Truncator lines={2} title={contextName} arrow>
|
||||
{contextName}
|
||||
</Truncator>
|
||||
</StyledConstraintName>
|
||||
<StyledOperatorGroup>
|
||||
<Operator label={operator} inverted={inverted} />
|
||||
{isCaseSensitive(operator, caseInsensitive) ? (
|
||||
<CaseSensitive />
|
||||
) : null}
|
||||
</StyledOperatorGroup>
|
||||
<ValuesList
|
||||
values={items}
|
||||
onSetTruncated={onSetTruncated}
|
||||
tooltips={tooltips}
|
||||
/>
|
||||
<StyledConstraintContainer>
|
||||
<StyledConstraintName>
|
||||
<Truncator title={contextName} arrow>
|
||||
{contextName}
|
||||
</Truncator>
|
||||
</StyledConstraintName>
|
||||
<StyledOperatorGroup>
|
||||
<Operator label={operator} inverted={inverted} />
|
||||
{isCaseSensitive(operator, caseInsensitive) ? (
|
||||
<CaseSensitive />
|
||||
) : null}
|
||||
</StyledOperatorGroup>
|
||||
<div>
|
||||
<div>
|
||||
<ValuesList
|
||||
values={items}
|
||||
onSetTruncated={onSetTruncated}
|
||||
tooltips={tooltips}
|
||||
/>
|
||||
{viewMore}
|
||||
</div>
|
||||
</div>
|
||||
</StyledConstraintContainer>
|
||||
</StrategyEvaluationItem>
|
||||
);
|
||||
};
|
||||
|
@ -1,9 +1,10 @@
|
||||
import type { FC } from 'react';
|
||||
import { styled, Tooltip } from '@mui/material';
|
||||
import { styled } from '@mui/material';
|
||||
import {
|
||||
Truncator,
|
||||
type TruncatorProps,
|
||||
} from 'component/common/Truncator/Truncator';
|
||||
import { TooltipResolver } from 'component/common/TooltipResolver/TooltipResolver';
|
||||
|
||||
export type ValuesListProps = {
|
||||
values?: string[];
|
||||
@ -14,7 +15,12 @@ const StyledValuesContainer = styled('div')({
|
||||
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),
|
||||
display: 'inline-block',
|
||||
span: {
|
||||
@ -45,22 +51,30 @@ export const ValuesList: FC<ValuesListProps> = ({
|
||||
lines={2}
|
||||
onSetTruncated={() => onSetTruncated?.(false)}
|
||||
>
|
||||
<Tooltip title={tooltips?.[values[0]] || ''}>
|
||||
<TooltipResolver title={tooltips?.[values[0]] || ''}>
|
||||
<span>{values[0]}</span>
|
||||
</Tooltip>
|
||||
</TooltipResolver>
|
||||
</Truncator>
|
||||
</StyledSingleValue>
|
||||
) : null}
|
||||
{values && values?.length > 1 ? (
|
||||
<Truncator title='' lines={2} onSetTruncated={onSetTruncated}>
|
||||
<StyledTruncator
|
||||
title=''
|
||||
lines={2}
|
||||
onSetTruncated={onSetTruncated}
|
||||
component='ul'
|
||||
>
|
||||
{values.map((value) => (
|
||||
<Tooltip title={tooltips?.[value] || ''} key={value}>
|
||||
<TooltipResolver
|
||||
title={tooltips?.[value] || ''}
|
||||
key={value}
|
||||
>
|
||||
<StyledValueItem>
|
||||
<span>{value}</span>
|
||||
</StyledValueItem>
|
||||
</Tooltip>
|
||||
</TooltipResolver>
|
||||
))}
|
||||
</Truncator>
|
||||
</StyledTruncator>
|
||||
) : null}
|
||||
</StyledValuesContainer>
|
||||
);
|
||||
|
@ -30,7 +30,6 @@ interface IConstraintAccordionViewProps {
|
||||
const StyledAccordion = styled(Accordion)(({ theme }) => ({
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
borderRadius: theme.shape.borderRadiusMedium,
|
||||
backgroundColor: 'transparent',
|
||||
boxShadow: 'none',
|
||||
margin: 0,
|
||||
'&:before': {
|
||||
|
@ -10,7 +10,7 @@ interface IConstraintAccordionViewBodyProps {
|
||||
}
|
||||
|
||||
const StyledValueContainer = styled('div')(({ theme }) => ({
|
||||
padding: theme.spacing(2, 0),
|
||||
padding: theme.spacing(1, 0),
|
||||
maxHeight: '400px',
|
||||
overflowY: 'auto',
|
||||
}));
|
||||
|
@ -55,7 +55,6 @@ export const ConstraintAccordionViewHeader = ({
|
||||
{flagOverviewRedesign ? (
|
||||
<ConstraintAccordionViewHeaderInfo
|
||||
constraint={constraint}
|
||||
singleValue={singleValue}
|
||||
allowExpand={allowExpand}
|
||||
expanded={expanded}
|
||||
disabled={disabled}
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { IconButton, styled } from '@mui/material';
|
||||
import { styled } from '@mui/material';
|
||||
import type { IConstraint } from 'interfaces/strategy';
|
||||
import { ConstraintItemHeader } from 'component/common/ConstraintsList/ConstraintItemHeader/ConstraintItemHeader';
|
||||
import { useState } from 'react';
|
||||
import VisibilityIcon from '@mui/icons-material/Visibility';
|
||||
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
|
||||
|
||||
const StyledHeaderWrapper = styled('div')(({ theme }) => ({
|
||||
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 {
|
||||
constraint: IConstraint;
|
||||
singleValue: boolean;
|
||||
expanded: boolean;
|
||||
allowExpand: (shouldExpand: boolean) => void;
|
||||
disabled?: boolean;
|
||||
@ -49,12 +52,16 @@ export const ConstraintAccordionViewHeaderInfo = ({
|
||||
setExpandable(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>
|
||||
</StyledHeaderWrapper>
|
||||
);
|
||||
|
@ -20,10 +20,10 @@ export const ConstraintValueSearch = ({
|
||||
value={filter}
|
||||
onChange={(e) => setFilter(e.target.value)}
|
||||
placeholder='Filter values'
|
||||
style={{
|
||||
sx={(theme) => ({
|
||||
width: '100%',
|
||||
margin: '1rem 0',
|
||||
}}
|
||||
margin: theme.spacing(1, 0, 2),
|
||||
})}
|
||||
variant='outlined'
|
||||
size='small'
|
||||
InputProps={{
|
||||
|
@ -3,7 +3,7 @@ import type { FeatureStrategySchema } from 'openapi';
|
||||
import type { IFeatureStrategyPayload } from 'interfaces/strategy';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
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 { objectId } from 'utils/objectId';
|
||||
import { useCustomStrategyParameters } from './hooks/useCustomStrategyParameters';
|
||||
@ -53,10 +53,10 @@ export const StrategyExecution: FC<StrategyExecutionProps> = ({
|
||||
<SegmentItem segment={segment} key={segment.id} />
|
||||
))}
|
||||
{constraints?.map((constraint, index) => (
|
||||
<ConstraintListItem key={`${objectId(constraint)}-${index}`}>
|
||||
{/* FIXME: use constraint accordion */}
|
||||
<ConstraintItemHeader {...constraint} />
|
||||
</ConstraintListItem>
|
||||
<ConstraintAccordionView
|
||||
key={`${objectId(constraint)}-${index}`}
|
||||
constraint={constraint}
|
||||
/>
|
||||
))}
|
||||
{(isCustomStrategy ? customStrategyItems : strategyParameters).map(
|
||||
(item, index) => (
|
||||
|
Loading…
Reference in New Issue
Block a user