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

feat: add values button now actually adds value (#9768)

This commit is contained in:
Jaanus Sellin 2025-04-16 11:52:36 +03:00 committed by GitHub
parent e9c50a551f
commit 187f265680
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 140 additions and 45 deletions

View File

@ -383,6 +383,7 @@ export const EditableConstraint: FC<Props> = ({
<ValueList <ValueList
values={localConstraint.values} values={localConstraint.values}
removeValue={removeValue} removeValue={removeValue}
setValues={setValuesWithRecord}
/> />
)} )}

View File

@ -1,6 +1,13 @@
import Add from '@mui/icons-material/Add'; import Add from '@mui/icons-material/Add';
import Clear from '@mui/icons-material/Clear'; import Clear from '@mui/icons-material/Clear';
import { Button, Chip, type ChipProps, Popover, styled } from '@mui/material'; import {
Button,
Chip,
type ChipProps,
Popover,
styled,
TextField,
} from '@mui/material';
import { import {
type FC, type FC,
forwardRef, forwardRef,
@ -8,6 +15,7 @@ import {
useRef, useRef,
useState, useState,
} from 'react'; } from 'react';
import { parseParameterStrings } from 'utils/parseParameter';
const ValueListWrapper = styled('div')(({ theme }) => ({ const ValueListWrapper = styled('div')(({ theme }) => ({
display: 'flex', display: 'flex',
@ -79,59 +87,136 @@ const StyledPopover = styled(Popover)(({ theme }) => ({
'& .MuiPaper-root': { '& .MuiPaper-root': {
borderRadius: theme.shape.borderRadiusLarge, borderRadius: theme.shape.borderRadiusLarge,
border: `1px solid ${theme.palette.divider}`, border: `1px solid ${theme.palette.divider}`,
padding: theme.spacing(1), padding: theme.spacing(2),
width: '300px',
}, },
})); }));
const AddValues = forwardRef<HTMLButtonElement, {}>((props, ref) => { const StyledTextField = styled(TextField)(({ theme }) => ({
const [open, setOpen] = useState(false); width: '100%',
const positioningRef = useRef<HTMLButtonElement>(null); marginBottom: theme.spacing(1),
useImperativeHandle(ref, () => positioningRef.current as HTMLButtonElement); }));
return ( const ButtonContainer = styled('div')(({ theme }) => ({
<> display: 'flex',
<AddValuesButton justifyContent: 'flex-end',
ref={positioningRef} }));
onClick={() => setOpen(true)}
type='button' const ErrorMessage = styled('div')(({ theme }) => ({
> color: theme.palette.error.main,
<Add /> fontSize: theme.typography.caption.fontSize,
<span>Add values</span> marginBottom: theme.spacing(1),
</AddValuesButton> }));
<StyledPopover
open={open} interface AddValuesProps {
disableScrollLock onAddValues: (values: string[]) => void;
anchorEl={positioningRef.current} }
onClose={() => setOpen(false)}
anchorOrigin={{ const AddValues = forwardRef<HTMLButtonElement, AddValuesProps>(
vertical: 'bottom', ({ onAddValues }, ref) => {
horizontal: 'center', const [open, setOpen] = useState(false);
}} const [inputValues, setInputValues] = useState('');
transformOrigin={{ const [error, setError] = useState('');
vertical: 'top', const positioningRef = useRef<HTMLButtonElement>(null);
horizontal: 'center', useImperativeHandle(
}} ref,
> () => positioningRef.current as HTMLButtonElement,
<form action='' onSubmit={(e) => e.preventDefault()}> );
<input type='text' />
<Button const handleAdd = () => {
variant='text' const newValues = parseParameterStrings(inputValues);
onClick={() => console.log('clicked the add button')}
> if (newValues.length === 0) {
Add setError('Values cannot be empty');
</Button> return;
</form> }
</StyledPopover>
</> if (newValues.some((v) => v.length > 100)) {
); setError('Values cannot be longer than 100 characters');
}); return;
}
onAddValues(newValues);
setInputValues('');
setError('');
setOpen(false);
};
const handleKeyPress = (event: React.KeyboardEvent) => {
if (event.key === 'Enter') {
event.preventDefault();
handleAdd();
}
};
return (
<>
<AddValuesButton
ref={positioningRef}
onClick={() => setOpen(true)}
type='button'
>
<Add />
<span>Add values</span>
</AddValuesButton>
<StyledPopover
open={open}
disableScrollLock
anchorEl={positioningRef.current}
onClose={() => setOpen(false)}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
>
<div>
<StyledTextField
label='Values'
placeholder='value1, value2, value3...'
value={inputValues}
onChange={(e) => {
setInputValues(e.target.value);
setError('');
}}
onKeyPress={handleKeyPress}
error={Boolean(error)}
helperText={error}
size='small'
fullWidth
autoFocus
/>
<ButtonContainer>
<Button
variant='contained'
color='primary'
onClick={handleAdd}
disabled={!inputValues.trim()}
>
Add
</Button>
</ButtonContainer>
</div>
</StyledPopover>
</>
);
},
);
type Props = { type Props = {
values: string[] | undefined; values: string[] | undefined;
removeValue: (index: number) => void; removeValue: (index: number) => void;
setValues: (values: string[]) => void;
}; };
export const ValueList: FC<Props> = ({ values = [], removeValue }) => { export const ValueList: FC<Props> = ({
values = [],
removeValue,
setValues,
}) => {
const constraintElementRefs: React.MutableRefObject< const constraintElementRefs: React.MutableRefObject<
(HTMLDivElement | null)[] (HTMLDivElement | null)[]
> = useRef([]); > = useRef([]);
@ -149,6 +234,11 @@ export const ValueList: FC<Props> = ({ values = [], removeValue }) => {
} }
}; };
const handleAddValues = (newValues: string[]) => {
const combinedValues = uniqueValues([...(values || []), ...newValues]);
setValues(combinedValues);
};
return ( return (
<ValueListWrapper> <ValueListWrapper>
<StyledList> <StyledList>
@ -168,7 +258,11 @@ export const ValueList: FC<Props> = ({ values = [], removeValue }) => {
</li> </li>
))} ))}
</StyledList> </StyledList>
<AddValues ref={addValuesButtonRef} /> <AddValues ref={addValuesButtonRef} onAddValues={handleAddValues} />
</ValueListWrapper> </ValueListWrapper>
); );
}; };
const uniqueValues = <T,>(values: T[]): T[] => {
return Array.from(new Set(values));
};