mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-10 01:16:39 +02:00
constraint values with tooltips
This commit is contained in:
parent
6129565828
commit
7c472536aa
@ -1,4 +1,4 @@
|
||||
import { useMemo, type ComponentProps, type FC } from 'react';
|
||||
import type { ComponentProps, FC } from 'react';
|
||||
import { StrategyEvaluationItem } from '../StrategyEvaluationItem/StrategyEvaluationItem';
|
||||
import type { ConstraintSchema } from 'openapi';
|
||||
import { formatOperatorDescription } from 'component/common/ConstraintAccordion/ConstraintOperator/formatOperatorDescription';
|
||||
@ -8,7 +8,7 @@ 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';
|
||||
import { useConstraintTooltips } from './hooks/useConstraintTooltips';
|
||||
|
||||
const Inverted: FC = () => (
|
||||
<Tooltip title='NOT (operator is negated)' arrow>
|
||||
@ -45,7 +45,6 @@ export const ConstraintItemHeader: FC<
|
||||
> = ({ onSetTruncated, ...constraint }) => {
|
||||
const { caseInsensitive, contextName, inverted, operator, value, values } =
|
||||
constraint;
|
||||
const { context } = useUnleashContext();
|
||||
const { locationSettings } = useLocationSettings();
|
||||
const items = value
|
||||
? [
|
||||
@ -54,17 +53,7 @@ export const ConstraintItemHeader: FC<
|
||||
]
|
||||
: values || [];
|
||||
|
||||
const tooltips = useMemo(
|
||||
() =>
|
||||
// FIXME: tooltips
|
||||
Object.fromEntries(
|
||||
values?.map((value) => [
|
||||
value,
|
||||
context.find(({ name }) => name === value)?.description,
|
||||
]) || [],
|
||||
),
|
||||
[context, values],
|
||||
);
|
||||
const tooltips = useConstraintTooltips(contextName, values || []);
|
||||
|
||||
return (
|
||||
<StrategyEvaluationItem type='Constraint'>
|
||||
|
@ -0,0 +1,99 @@
|
||||
import { vi } from 'vitest';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useConstraintTooltips } from './useConstraintTooltips';
|
||||
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
|
||||
|
||||
vi.mock('hooks/api/getters/useUnleashContext/useUnleashContext', () => ({
|
||||
default: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('useConstraintTooltips', () => {
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
it('returns tooltip mapping for legal values with descriptions', () => {
|
||||
(
|
||||
useUnleashContext as unknown as ReturnType<typeof vi.fn>
|
||||
).mockReturnValue({
|
||||
context: [
|
||||
{
|
||||
name: 'contextA',
|
||||
description: 'Test context A',
|
||||
createdAt: '2021-01-01',
|
||||
sortOrder: 1,
|
||||
stickiness: false,
|
||||
legalValues: [
|
||||
{ value: 'value1', description: 'Tooltip 1' },
|
||||
{ value: 'value2', description: 'Tooltip 2' },
|
||||
{ value: 'value3' }, // No description provided
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useConstraintTooltips('contextA', [
|
||||
'value1',
|
||||
'value2',
|
||||
'value3',
|
||||
'nonExisting',
|
||||
]),
|
||||
);
|
||||
|
||||
expect(result.current).toEqual({
|
||||
value1: 'Tooltip 1',
|
||||
value2: 'Tooltip 2',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns an empty object when the context is not found', () => {
|
||||
(
|
||||
useUnleashContext as unknown as ReturnType<typeof vi.fn>
|
||||
).mockReturnValue({
|
||||
context: [
|
||||
{
|
||||
name: 'otherContext',
|
||||
description: 'Other context',
|
||||
createdAt: '2021-01-01',
|
||||
sortOrder: 1,
|
||||
stickiness: false,
|
||||
legalValues: [
|
||||
{ value: 'value1', description: 'Tooltip 1' },
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useConstraintTooltips('contextA', ['value1']),
|
||||
);
|
||||
|
||||
expect(result.current).toEqual({});
|
||||
});
|
||||
|
||||
it('returns an empty object when no values are provided', () => {
|
||||
(
|
||||
useUnleashContext as unknown as ReturnType<typeof vi.fn>
|
||||
).mockReturnValue({
|
||||
context: [
|
||||
{
|
||||
name: 'contextA',
|
||||
description: 'Test context A',
|
||||
createdAt: '2021-01-01',
|
||||
sortOrder: 1,
|
||||
stickiness: false,
|
||||
legalValues: [
|
||||
{ value: 'value1', description: 'Tooltip 1' },
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useConstraintTooltips('contextA', []),
|
||||
);
|
||||
|
||||
expect(result.current).toEqual({});
|
||||
});
|
||||
});
|
@ -0,0 +1,27 @@
|
||||
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useConstraintTooltips = (
|
||||
contextName: string,
|
||||
values: string[],
|
||||
) => {
|
||||
const { context } = useUnleashContext();
|
||||
const contextDefinition = useMemo(
|
||||
() => context.find(({ name }) => name === contextName),
|
||||
[contextName, context],
|
||||
);
|
||||
return useMemo<Record<string, string>>(
|
||||
() =>
|
||||
Object.fromEntries(
|
||||
values
|
||||
?.map((item) => [
|
||||
item,
|
||||
contextDefinition?.legalValues?.find(
|
||||
({ value }) => value === item,
|
||||
)?.description,
|
||||
])
|
||||
.filter(([_, tooltip]) => !!tooltip) || [],
|
||||
),
|
||||
[context, values],
|
||||
);
|
||||
};
|
@ -45,17 +45,18 @@ export const ValuesList: FC<ValuesListProps> = ({
|
||||
lines={2}
|
||||
onSetTruncated={() => onSetTruncated?.(false)}
|
||||
>
|
||||
{values[0]}
|
||||
<Tooltip title={tooltips?.[values[0]] || ''}>
|
||||
<span>{values[0]}</span>
|
||||
</Tooltip>
|
||||
</Truncator>
|
||||
</StyledSingleValue>
|
||||
) : null}
|
||||
{values && values?.length > 1 ? (
|
||||
<Truncator title='' lines={2} onSetTruncated={onSetTruncated}>
|
||||
{values.map((value) => (
|
||||
<Tooltip title={tooltips?.[value] || ''} arrow key={value}>
|
||||
<Tooltip title={tooltips?.[value] || ''} key={value}>
|
||||
<StyledValueItem>
|
||||
<span>{value}</span>
|
||||
{tooltips?.[value]}
|
||||
</StyledValueItem>
|
||||
</Tooltip>
|
||||
))}
|
||||
|
@ -13,6 +13,7 @@ import type {
|
||||
StrategySchemaParametersItem,
|
||||
} from 'openapi';
|
||||
import type { IFeatureStrategyPayload } from 'interfaces/strategy';
|
||||
import { ValuesList } from 'component/common/ConstraintsList/ValuesList/ValuesList';
|
||||
|
||||
export const useCustomStrategyParameters = (
|
||||
strategy: Pick<
|
||||
@ -48,14 +49,11 @@ export const useCustomStrategyParameters = (
|
||||
}
|
||||
|
||||
return (
|
||||
<StrategyEvaluationItem
|
||||
key={key}
|
||||
type={typeItem}
|
||||
// values={values} // FIXME: values
|
||||
>
|
||||
<StrategyEvaluationItem key={key} type={typeItem}>
|
||||
{values.length === 1
|
||||
? 'has 1 item:'
|
||||
: `has ${values.length} items:`}
|
||||
<ValuesList values={values} />
|
||||
</StrategyEvaluationItem>
|
||||
);
|
||||
}
|
||||
@ -82,12 +80,11 @@ export const useCustomStrategyParameters = (
|
||||
const value = parseParameterString(parameters[name]);
|
||||
|
||||
return (
|
||||
<StrategyEvaluationItem
|
||||
key={key}
|
||||
type={typeItem}
|
||||
// values={value === '' ? undefined : [value]} // FIXME: values
|
||||
>
|
||||
<StrategyEvaluationItem key={key} type={typeItem}>
|
||||
{value === '' ? 'is an empty string' : 'is set to'}
|
||||
<ValuesList
|
||||
values={value === '' ? undefined : [value]}
|
||||
/>
|
||||
</StrategyEvaluationItem>
|
||||
);
|
||||
}
|
||||
@ -95,12 +92,9 @@ export const useCustomStrategyParameters = (
|
||||
case 'number': {
|
||||
const value = parseParameterNumber(parameters[name]);
|
||||
return (
|
||||
<StrategyEvaluationItem
|
||||
key={key}
|
||||
type={typeItem}
|
||||
// values={[`${value}`]} // FIXME: values
|
||||
>
|
||||
<StrategyEvaluationItem key={key} type={typeItem}>
|
||||
is a number set to
|
||||
<ValuesList values={[`${value}`]} />
|
||||
</StrategyEvaluationItem>
|
||||
);
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ import { useMemo } from 'react';
|
||||
import { StrategyEvaluationItem } from 'component/common/ConstraintsList/StrategyEvaluationItem/StrategyEvaluationItem';
|
||||
import type { FeatureStrategySchema } from 'openapi';
|
||||
import { RolloutParameter } from '../RolloutParameter/RolloutParameter';
|
||||
import { ValuesList } from 'component/common/ConstraintsList/ValuesList/ValuesList';
|
||||
import { parseParameterStrings } from 'utils/parseParameter';
|
||||
|
||||
export const useStrategyParameters = (
|
||||
strategy: Partial<
|
||||
@ -35,11 +37,9 @@ export const useStrategyParameters = (
|
||||
|
||||
if (['userids', 'hostnames', 'ips'].includes(type)) {
|
||||
return (
|
||||
<StrategyEvaluationItem
|
||||
key={key}
|
||||
type={key}
|
||||
// values={parseParameterStrings(value)} // FIXME: values
|
||||
/>
|
||||
<StrategyEvaluationItem key={key} type={key}>
|
||||
<ValuesList values={parseParameterStrings(value)} />
|
||||
</StrategyEvaluationItem>
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user