mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	* refactor: remove unused securityLogger * refactor: port commonStyles to TS * refactor: port testIds to TS * refactor: move app.css into themes * refactor: use absolute import paths * refactor: port LayoutPicker to TS * refactor: port routes to TS * refactor: port ScrollTop to TS * refactor: update unused/missing ScrollTop exceptions * refactor: remove unused route flags field * refactor: change constants ext to TS * refactor: remove unused testData file * refactor: port styles to TS * refactor: wait before typing in auth spec
		
			
				
	
	
		
			197 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			197 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import { useEffect } from 'react';
 | |
| import PropTypes from 'prop-types';
 | |
| import { IconButton, TextField } from '@material-ui/core';
 | |
| import { Autocomplete } from '@material-ui/lab';
 | |
| import { Delete } from '@material-ui/icons';
 | |
| 
 | |
| import InputListField from 'component/common/InputListField';
 | |
| import ConditionallyRender from 'component/common/ConditionallyRender/ConditionallyRender';
 | |
| import { useCommonStyles } from 'themes/commonStyles';
 | |
| import { useStyles } from './StrategyConstraintInputField.styles';
 | |
| import { CONSTRAINT_AUTOCOMPLETE_ID } from 'utils/testIds';
 | |
| import GeneralSelect from 'component/common/GeneralSelect/GeneralSelect';
 | |
| 
 | |
| const constraintOperators = [
 | |
|     { key: 'IN', label: 'IN' },
 | |
|     { key: 'NOT_IN', label: 'NOT_IN' },
 | |
| ];
 | |
| 
 | |
| const StrategyConstraintInputField = ({
 | |
|     constraint,
 | |
|     updateConstraint,
 | |
|     removeConstraint,
 | |
|     contextFields,
 | |
|     id,
 | |
|     constraintError,
 | |
|     setConstraintError,
 | |
| }) => {
 | |
|     useEffect(() => {
 | |
|         return () => {
 | |
|             resetError();
 | |
|         };
 | |
|         /*eslint-disable-next-line */
 | |
|     }, []);
 | |
| 
 | |
|     const checkError = () => {
 | |
|         const values = constraint.values;
 | |
|         const filtered = values.filter(v => v).map(v => v.trim());
 | |
|         if (filtered.length !== values.length) {
 | |
|             updateConstraint(filtered, 'values');
 | |
|         }
 | |
|         if (filtered.length === 0) {
 | |
|             setConstraintError(prev => ({
 | |
|                 ...prev,
 | |
|                 [id]: 'You need to specify at least one value',
 | |
|             }));
 | |
|         } else {
 | |
|             resetError();
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     const resetError = () =>
 | |
|         setConstraintError(prev => ({ ...prev, [id]: undefined }));
 | |
| 
 | |
|     const commonStyles = useCommonStyles();
 | |
|     const styles = useStyles();
 | |
|     const onBlur = evt => {
 | |
|         evt.preventDefault();
 | |
|         checkError();
 | |
|     };
 | |
| 
 | |
|     const handleChangeValue = selectedOptions => {
 | |
|         const values = selectedOptions ? selectedOptions.map(o => o.value) : [];
 | |
|         updateConstraint(values, 'values');
 | |
|         checkError();
 | |
|     };
 | |
| 
 | |
|     const constraintContextNames = contextFields.map(f => ({
 | |
|         key: f.name,
 | |
|         label: f.name,
 | |
|     }));
 | |
|     const constraintDef = contextFields.find(
 | |
|         c => c.name === constraint.contextName
 | |
|     );
 | |
| 
 | |
|     const options =
 | |
|         constraintDef &&
 | |
|         constraintDef.legalValues &&
 | |
|         constraintDef.legalValues.length > 0
 | |
|             ? constraintDef.legalValues.map(l => ({ value: l, label: l }))
 | |
|             : undefined;
 | |
|     const values = constraint.values.map(v => ({ value: v, label: v }));
 | |
| 
 | |
|     const error = constraintError[id];
 | |
| 
 | |
|     return (
 | |
|         <tr className={commonStyles.contentSpacingY}>
 | |
|             <td className={styles.tableCell}>
 | |
|                 <GeneralSelect
 | |
|                     name="contextName"
 | |
|                     label="Context Field"
 | |
|                     options={constraintContextNames}
 | |
|                     value={constraint.contextName || ''}
 | |
|                     onChange={evt =>
 | |
|                         updateConstraint(evt.target.value, 'contextName')
 | |
|                     }
 | |
|                     className={styles.contextField}
 | |
|                 />
 | |
|             </td>
 | |
|             <td className={styles.tableCell}>
 | |
|                 <GeneralSelect
 | |
|                     name="operator"
 | |
|                     label="Operator"
 | |
|                     options={constraintOperators}
 | |
|                     value={constraint.operator}
 | |
|                     onChange={evt =>
 | |
|                         updateConstraint(evt.target.value, 'operator')
 | |
|                     }
 | |
|                     className={styles.operator}
 | |
|                 />
 | |
|             </td>
 | |
|             <td className={styles.tableCell} style={{ width: '100%' }}>
 | |
|                 <ConditionallyRender
 | |
|                     condition={options}
 | |
|                     show={
 | |
|                         <div className={styles.inputContainer}>
 | |
|                             <Autocomplete
 | |
|                                 multiple
 | |
|                                 size="small"
 | |
|                                 options={options}
 | |
|                                 data-test={CONSTRAINT_AUTOCOMPLETE_ID}
 | |
|                                 value={values || []}
 | |
|                                 getOptionLabel={option => option.label}
 | |
|                                 onBlur={onBlur}
 | |
|                                 onFocus={() => resetError()}
 | |
|                                 getOptionSelected={(option, value) =>
 | |
|                                     option.value === value.value
 | |
|                                 }
 | |
|                                 filterSelectedOptions
 | |
|                                 filterOptions={options =>
 | |
|                                     options.filter(
 | |
|                                         o =>
 | |
|                                             !values.some(
 | |
|                                                 v => v.value === o.value
 | |
|                                             )
 | |
|                                     )
 | |
|                                 }
 | |
|                                 onChange={(evt, values) =>
 | |
|                                     handleChangeValue(values)
 | |
|                                 }
 | |
|                                 renderInput={params => (
 | |
|                                     <TextField
 | |
|                                         {...params}
 | |
|                                         variant="outlined"
 | |
|                                         label={'Values'}
 | |
|                                         error={Boolean(error)}
 | |
|                                         helperText={error}
 | |
|                                         FormHelperTextProps={{
 | |
|                                             classes: {
 | |
|                                                 root: styles.helperText,
 | |
|                                             },
 | |
|                                         }}
 | |
|                                     />
 | |
|                                 )}
 | |
|                             />
 | |
|                         </div>
 | |
|                     }
 | |
|                     elseShow={
 | |
|                         <div className={styles.inputContainer}>
 | |
|                             <InputListField
 | |
|                                 name="values"
 | |
|                                 error={Boolean(error)}
 | |
|                                 errorText={error}
 | |
|                                 onBlur={onBlur}
 | |
|                                 values={constraint.values}
 | |
|                                 label="Values (v1, v2, v3)"
 | |
|                                 updateValues={values =>
 | |
|                                     updateConstraint(values, 'values')
 | |
|                                 }
 | |
|                                 helperText={error}
 | |
|                                 FormHelperTextProps={{
 | |
|                                     classes: {
 | |
|                                         root: styles.helperText,
 | |
|                                     },
 | |
|                                 }}
 | |
|                             />
 | |
|                         </div>
 | |
|                     }
 | |
|                 />
 | |
|             </td>
 | |
|             <td className={styles.tableCell}>
 | |
|                 <IconButton onClick={removeConstraint}>
 | |
|                     <Delete />
 | |
|                 </IconButton>
 | |
|             </td>
 | |
|         </tr>
 | |
|     );
 | |
| };
 | |
| StrategyConstraintInputField.propTypes = {
 | |
|     id: PropTypes.string.isRequired,
 | |
|     constraint: PropTypes.object.isRequired,
 | |
|     updateConstraint: PropTypes.func.isRequired,
 | |
|     removeConstraint: PropTypes.func.isRequired,
 | |
|     contextFields: PropTypes.array.isRequired,
 | |
| };
 | |
| 
 | |
| export default StrategyConstraintInputField;
 |