mirror of
https://github.com/Unleash/unleash.git
synced 2025-11-10 01:19:53 +01:00
1-3687/input mode separation (#9882)
This commit is contained in:
parent
1b9c0e5000
commit
3d84001273
@ -64,6 +64,13 @@ const resolveLegalValues = (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated; remove with `addEditStrategy` flag. Need an input? Prefer using specific input components.
|
||||||
|
*
|
||||||
|
* For the case of `ProjectActionsFilterItem.tsx`: it already excludes legal
|
||||||
|
* values and date operators. This leaves only free text and single value
|
||||||
|
* text/numeric operators. Alternatively, consider rewriting this component to only handle those cases.
|
||||||
|
*/
|
||||||
export const ResolveInput = ({
|
export const ResolveInput = ({
|
||||||
input,
|
input,
|
||||||
contextDefinition,
|
contextDefinition,
|
||||||
|
|||||||
@ -68,7 +68,7 @@ export const useConstraintInput = ({
|
|||||||
contextDefinition,
|
contextDefinition,
|
||||||
localConstraint,
|
localConstraint,
|
||||||
}: IUseConstraintInputProps): IUseConstraintOutput => {
|
}: IUseConstraintInputProps): IUseConstraintOutput => {
|
||||||
const [input, setInput] = useState<Input>(IN_OPERATORS_LEGAL_VALUES);
|
const [input, setInput] = useState<Input>(IN_OPERATORS_FREETEXT);
|
||||||
const [validator, setValidator] = useState<Validator>(
|
const [validator, setValidator] = useState<Validator>(
|
||||||
STRING_ARRAY_VALIDATOR,
|
STRING_ARRAY_VALIDATOR,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -25,12 +25,13 @@ import { ReactComponent as CaseSensitiveIcon } from 'assets/icons/case-sensitive
|
|||||||
import { ReactComponent as CaseInsensitiveIcon } from 'assets/icons/case-insensitive.svg';
|
import { ReactComponent as CaseInsensitiveIcon } from 'assets/icons/case-insensitive.svg';
|
||||||
import { ScreenReaderOnly } from 'component/common/ScreenReaderOnly/ScreenReaderOnly';
|
import { ScreenReaderOnly } from 'component/common/ScreenReaderOnly/ScreenReaderOnly';
|
||||||
import { AddValuesWidget } from './AddValuesWidget';
|
import { AddValuesWidget } from './AddValuesWidget';
|
||||||
import { ResolveInput } from 'component/common/NewConstraintAccordion/ConstraintAccordionEdit/ConstraintAccordionEditBody/ResolveInput/ResolveInput';
|
|
||||||
|
|
||||||
import { ReactComponent as EqualsIcon } from 'assets/icons/constraint-equals.svg';
|
import { ReactComponent as EqualsIcon } from 'assets/icons/constraint-equals.svg';
|
||||||
import { ReactComponent as NotEqualsIcon } from 'assets/icons/constraint-not-equals.svg';
|
import { ReactComponent as NotEqualsIcon } from 'assets/icons/constraint-not-equals.svg';
|
||||||
import { AddSingleValueWidget } from './AddSingleValueWidget';
|
import { AddSingleValueWidget } from './AddSingleValueWidget';
|
||||||
import { ConstraintDateInput } from './ConstraintDateInput';
|
import { ConstraintDateInput } from './ConstraintDateInput';
|
||||||
|
import { LegalValuesSelector } from './LegalValuesSelector';
|
||||||
|
import { resolveLegalValues } from './resolve-legal-values';
|
||||||
|
|
||||||
const Container = styled('article')(({ theme }) => ({
|
const Container = styled('article')(({ theme }) => ({
|
||||||
'--padding': theme.spacing(2),
|
'--padding': theme.spacing(2),
|
||||||
@ -68,7 +69,7 @@ const ConstraintDetails = styled('div')(({ theme }) => ({
|
|||||||
height: 'min-content',
|
height: 'min-content',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const InputContainer = styled('div')(({ theme }) => ({
|
const LegalValuesContainer = styled('div')(({ theme }) => ({
|
||||||
padding: 'var(--padding)',
|
padding: 'var(--padding)',
|
||||||
borderTop: `1px dashed ${theme.palette.divider}`,
|
borderTop: `1px dashed ${theme.palette.divider}`,
|
||||||
}));
|
}));
|
||||||
@ -145,15 +146,23 @@ const StyledCaseSensitiveIcon = styled(CaseSensitiveIcon)(({ theme }) => ({
|
|||||||
fill: 'currentcolor',
|
fill: 'currentcolor',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const OPERATORS_WITH_ADD_VALUES_WIDGET = [
|
const getInputType = (input: Input) => {
|
||||||
'IN_OPERATORS_FREETEXT',
|
switch (input) {
|
||||||
'STRING_OPERATORS_FREETEXT',
|
case 'IN_OPERATORS_LEGAL_VALUES':
|
||||||
];
|
case 'STRING_OPERATORS_LEGAL_VALUES':
|
||||||
|
case 'NUM_OPERATORS_LEGAL_VALUES':
|
||||||
const SINGLE_VALUE_OPERATORS = [
|
case 'SEMVER_OPERATORS_LEGAL_VALUES':
|
||||||
'NUM_OPERATORS_SINGLE_VALUE',
|
return 'legal values';
|
||||||
'SEMVER_OPERATORS_SINGLE_VALUE',
|
case 'DATE_OPERATORS_SINGLE_VALUE':
|
||||||
];
|
return 'date input';
|
||||||
|
case 'NUM_OPERATORS_SINGLE_VALUE':
|
||||||
|
case 'SEMVER_OPERATORS_SINGLE_VALUE':
|
||||||
|
return 'single text value';
|
||||||
|
case 'IN_OPERATORS_FREETEXT':
|
||||||
|
case 'STRING_OPERATORS_FREETEXT':
|
||||||
|
return 'free text';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
constraint: IConstraint;
|
constraint: IConstraint;
|
||||||
@ -206,11 +215,7 @@ export const EditableConstraint: FC<Props> = ({
|
|||||||
useState(false);
|
useState(false);
|
||||||
const deleteButtonRef = useRef<HTMLButtonElement>(null);
|
const deleteButtonRef = useRef<HTMLButtonElement>(null);
|
||||||
const addValuesButtonRef = useRef<HTMLButtonElement>(null);
|
const addValuesButtonRef = useRef<HTMLButtonElement>(null);
|
||||||
const showSingleValueButton = SINGLE_VALUE_OPERATORS.includes(input);
|
const inputType = getInputType(input);
|
||||||
const showAddValuesButton =
|
|
||||||
OPERATORS_WITH_ADD_VALUES_WIDGET.includes(input);
|
|
||||||
const showDateInput = input.includes('DATE');
|
|
||||||
const showInputField = input.includes('LEGAL_VALUES');
|
|
||||||
|
|
||||||
/* We need a special case to handle the currentTime context field. Since
|
/* We need a special case to handle the currentTime context field. Since
|
||||||
this field will be the only one to allow DATE_BEFORE and DATE_AFTER operators
|
this field will be the only one to allow DATE_BEFORE and DATE_AFTER operators
|
||||||
@ -267,6 +272,46 @@ export const EditableConstraint: FC<Props> = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const TopRowInput = () => {
|
||||||
|
switch (inputType) {
|
||||||
|
case 'date input':
|
||||||
|
return (
|
||||||
|
<ConstraintDateInput
|
||||||
|
setValue={setValue}
|
||||||
|
value={localConstraint.value}
|
||||||
|
error={error}
|
||||||
|
setError={setError}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case 'single text value':
|
||||||
|
return (
|
||||||
|
<AddSingleValueWidget
|
||||||
|
onAddValue={(newValue) => {
|
||||||
|
setValue(newValue);
|
||||||
|
}}
|
||||||
|
removeValue={() => setValue('')}
|
||||||
|
currentValue={localConstraint.value}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case 'free text':
|
||||||
|
return (
|
||||||
|
<AddValuesWidget
|
||||||
|
ref={addValuesButtonRef}
|
||||||
|
onAddValues={(newValues) => {
|
||||||
|
// todo (`addEditStrategy`): move deduplication logic higher up in the context handling
|
||||||
|
const combinedValues = new Set([
|
||||||
|
...(localConstraint.values || []),
|
||||||
|
...newValues,
|
||||||
|
]);
|
||||||
|
setValuesWithRecord(Array.from(combinedValues));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<TopRow>
|
<TopRow>
|
||||||
@ -339,39 +384,8 @@ export const EditableConstraint: FC<Props> = ({
|
|||||||
deleteButtonRef.current
|
deleteButtonRef.current
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{showAddValuesButton ? (
|
<TopRowInput />
|
||||||
<AddValuesWidget
|
|
||||||
ref={addValuesButtonRef}
|
|
||||||
onAddValues={(newValues) => {
|
|
||||||
// todo (`addEditStrategy`): move deduplication logic higher up in the context handling
|
|
||||||
const combinedValues = new Set([
|
|
||||||
...(localConstraint.values || []),
|
|
||||||
...newValues,
|
|
||||||
]);
|
|
||||||
setValuesWithRecord(
|
|
||||||
Array.from(combinedValues),
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</ValueList>
|
</ValueList>
|
||||||
{showSingleValueButton ? (
|
|
||||||
<AddSingleValueWidget
|
|
||||||
onAddValue={(newValue) => {
|
|
||||||
setValue(newValue);
|
|
||||||
}}
|
|
||||||
removeValue={() => setValue('')}
|
|
||||||
currentValue={localConstraint.value}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
{showDateInput ? (
|
|
||||||
<ConstraintDateInput
|
|
||||||
setValue={setValue}
|
|
||||||
value={localConstraint.value}
|
|
||||||
error={error}
|
|
||||||
setError={setError}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</ConstraintDetails>
|
</ConstraintDetails>
|
||||||
<ButtonPlaceholder />
|
<ButtonPlaceholder />
|
||||||
<HtmlTooltip title='Delete constraint' arrow>
|
<HtmlTooltip title='Delete constraint' arrow>
|
||||||
@ -386,22 +400,19 @@ export const EditableConstraint: FC<Props> = ({
|
|||||||
</StyledIconButton>
|
</StyledIconButton>
|
||||||
</HtmlTooltip>
|
</HtmlTooltip>
|
||||||
</TopRow>
|
</TopRow>
|
||||||
{showInputField ? (
|
{inputType === 'legal values' ? (
|
||||||
<InputContainer>
|
<LegalValuesContainer>
|
||||||
<ResolveInput
|
<LegalValuesSelector
|
||||||
setValues={setValues}
|
data={resolveLegalValues(
|
||||||
|
constraintValues,
|
||||||
|
contextDefinition.legalValues,
|
||||||
|
)}
|
||||||
|
constraintValues={constraintValues}
|
||||||
|
values={localConstraint.values || []}
|
||||||
setValuesWithRecord={setValuesWithRecord}
|
setValuesWithRecord={setValuesWithRecord}
|
||||||
setValue={setValue}
|
setValues={setValues}
|
||||||
setError={setError}
|
/>{' '}
|
||||||
localConstraint={localConstraint}
|
</LegalValuesContainer>
|
||||||
constraintValues={constraint?.values || []}
|
|
||||||
constraintValue={constraint?.value || ''}
|
|
||||||
input={input}
|
|
||||||
error={error}
|
|
||||||
contextDefinition={contextDefinition}
|
|
||||||
removeValue={removeValue}
|
|
||||||
/>
|
|
||||||
</InputContainer>
|
|
||||||
) : null}
|
) : null}
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -0,0 +1,27 @@
|
|||||||
|
import type {
|
||||||
|
IUnleashContextDefinition,
|
||||||
|
ILegalValue,
|
||||||
|
} from 'interfaces/context';
|
||||||
|
import type { IConstraint } from 'interfaces/strategy';
|
||||||
|
|
||||||
|
export const resolveLegalValues = (
|
||||||
|
values: IConstraint['values'] = [],
|
||||||
|
legalValues: IUnleashContextDefinition['legalValues'] = [],
|
||||||
|
): { legalValues: ILegalValue[]; deletedLegalValues: ILegalValue[] } => {
|
||||||
|
if (legalValues.length === 0) {
|
||||||
|
return {
|
||||||
|
legalValues: [],
|
||||||
|
deletedLegalValues: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingLegalValues = new Set(legalValues.map(({ value }) => value));
|
||||||
|
const deletedLegalValues = values
|
||||||
|
.filter((value) => !existingLegalValues.has(value))
|
||||||
|
.map((v) => ({ value: v, description: '' }));
|
||||||
|
|
||||||
|
return {
|
||||||
|
legalValues,
|
||||||
|
deletedLegalValues,
|
||||||
|
};
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user