1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-10-18 20:09:08 +02:00
unleash.unleash/frontend/src/component/context/ContextForm/ContextForm.tsx

198 lines
6.7 KiB
TypeScript
Raw Normal View History

import Input from '../../common/Input/Input';
import { TextField, Button, Switch, Chip, Typography } from '@material-ui/core';
import { useStyles } from './ContextForm.styles';
import React, { useState } from 'react';
import { Add } from '@material-ui/icons';
import { trim } from '../../common/util';
interface IContextForm {
contextName: string;
contextDesc: string;
legalValues: Array<string>;
stickiness: boolean;
setContextName: React.Dispatch<React.SetStateAction<string>>;
setContextDesc: React.Dispatch<React.SetStateAction<string>>;
setStickiness: React.Dispatch<React.SetStateAction<boolean>>;
setLegalValues: React.Dispatch<React.SetStateAction<string[]>>;
handleSubmit: (e: any) => void;
handleCancel: () => void;
errors: { [key: string]: string };
mode: string;
clearErrors: () => void;
validateNameUniqueness: () => void;
setErrors: React.Dispatch<React.SetStateAction<Object>>;
}
const ENTER = 'Enter';
const ContextForm: React.FC<IContextForm> = ({
children,
handleSubmit,
handleCancel,
contextName,
contextDesc,
legalValues,
stickiness,
setContextName,
setContextDesc,
setLegalValues,
setStickiness,
errors,
mode,
validateNameUniqueness,
setErrors,
clearErrors,
}) => {
const styles = useStyles();
const [value, setValue] = useState('');
const [focused, setFocused] = useState(false);
const submit = (event: React.SyntheticEvent) => {
event.preventDefault();
if (focused) return;
handleSubmit(event);
};
const handleKeyDown = (event: React.KeyboardEvent) => {
if (event.key === ENTER && focused) {
addLegalValue();
return;
} else if (event.key === ENTER) {
handleSubmit(event);
}
};
const sortIgnoreCase = (a: string, b: string) => {
a = a.toLowerCase();
b = b.toLowerCase();
if (a === b) return 0;
if (a > b) return 1;
return -1;
};
const addLegalValue = () => {
clearErrors();
if (!value) {
return;
}
if (legalValues.indexOf(value) !== -1) {
setErrors(prev => ({
...prev,
tag: 'Duplicate legal value',
}));
return;
}
setLegalValues(prev => [...prev, trim(value)].sort(sortIgnoreCase));
setValue('');
};
const removeLegalValue = (index: number) => {
const filteredValues = legalValues.filter((_, i) => i !== index);
setLegalValues([...filteredValues]);
};
return (
<form onSubmit={submit} className={styles.form}>
<h3 className={styles.formHeader}>Context information</h3>
<div className={styles.container}>
<p className={styles.inputDescription}>
What is your context name?
</p>
<Input
className={styles.input}
label="Context name"
value={contextName}
disabled={mode === 'Edit'}
onChange={e => setContextName(e.target.value)}
error={Boolean(errors.name)}
errorText={errors.name}
onFocus={() => clearErrors()}
onBlur={validateNameUniqueness}
/>
<p className={styles.inputDescription}>
What is this context for?
</p>
<TextField
className={styles.input}
label="Context description"
variant="outlined"
multiline
maxRows={4}
value={contextDesc}
onChange={e => setContextDesc(e.target.value)}
/>
<p className={styles.inputDescription}>
Which values do you want to allow?
</p>
{legalValues.map((value, index) => {
return (
<Chip
key={index + value}
label={value}
className={styles.tagValue}
onDelete={() => removeLegalValue(index)}
title="Remove value"
/>
);
})}
<div className={styles.tagContainer}>
<TextField
label="Value"
name="value"
className={styles.tagInput}
value={value}
error={Boolean(errors.tag)}
helperText={errors.tag}
variant="outlined"
size="small"
onChange={e => setValue(trim(e.target.value))}
onKeyPress={e => handleKeyDown(e)}
onBlur={e => setFocused(false)}
onFocus={e => setFocused(true)}
/>
<Button
startIcon={<Add />}
onClick={addLegalValue}
variant="contained"
color="primary"
>
Add
</Button>
</div>
<p className={styles.inputHeader}>Custom stickiness (beta)</p>
<p>
By enabling stickiness on this context field you can use it
together with the flexible-rollout strategy. This will
guarantee a consistent behavior for specific values of this
context field. PS! Not all client SDK's support this feature
yet!{' '}
<a
href="https://docs.getunleash.io/advanced/stickiness"
target="_blank"
rel="noreferrer"
>
Read more
</a>
</p>
<div className={styles.switchContainer}>
<Switch
checked={stickiness}
value={stickiness}
onChange={() => setStickiness(!stickiness)}
/>
<Typography>{stickiness ? 'On' : 'Off'}</Typography>
</div>
</div>
<div className={styles.buttonContainer}>
<Button onClick={handleCancel} className={styles.cancelButton}>
Cancel
</Button>
{children}
</div>
</form>
);
};
export default ContextForm;