2022-05-02 12:52:33 +02:00
|
|
|
import {
|
|
|
|
useState,
|
|
|
|
useRef,
|
|
|
|
useEffect,
|
|
|
|
FormEventHandler,
|
|
|
|
ChangeEventHandler,
|
|
|
|
} from 'react';
|
2022-02-11 11:19:55 +01:00
|
|
|
import { Link, useHistory, useParams } from 'react-router-dom';
|
2021-08-25 13:37:22 +02:00
|
|
|
import {
|
|
|
|
Button,
|
|
|
|
TextField,
|
|
|
|
Switch,
|
|
|
|
Paper,
|
|
|
|
FormControlLabel,
|
2022-05-02 15:52:41 +02:00
|
|
|
} from '@mui/material';
|
|
|
|
import { FileCopy } from '@mui/icons-material';
|
|
|
|
import { styles as themeStyles } from 'component/common';
|
2022-05-02 12:52:33 +02:00
|
|
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
2021-08-25 13:37:22 +02:00
|
|
|
import styles from './CopyFeature.module.scss';
|
2022-03-28 10:49:59 +02:00
|
|
|
import { trim } from 'component/common/util';
|
2022-05-02 12:52:33 +02:00
|
|
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
2022-05-02 15:52:41 +02:00
|
|
|
import { Alert } from '@mui/material';
|
2022-03-28 10:49:59 +02:00
|
|
|
import { getTogglePath } from 'utils/routePathHelpers';
|
|
|
|
import useFeatureApi from 'hooks/api/actions/useFeatureApi/useFeatureApi';
|
|
|
|
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
2021-08-25 13:37:22 +02:00
|
|
|
|
2022-02-11 11:19:55 +01:00
|
|
|
export const CopyFeatureToggle = () => {
|
2021-08-25 13:37:22 +02:00
|
|
|
const [replaceGroupId, setReplaceGroupId] = useState(true);
|
|
|
|
const [apiError, setApiError] = useState('');
|
2022-05-02 12:52:33 +02:00
|
|
|
const [nameError, setNameError] = useState<string | undefined>();
|
|
|
|
const [newToggleName, setNewToggleName] = useState<string>();
|
2022-02-11 11:19:55 +01:00
|
|
|
const { cloneFeatureToggle, validateFeatureToggleName } = useFeatureApi();
|
2022-05-02 12:52:33 +02:00
|
|
|
const inputRef = useRef<HTMLInputElement>();
|
|
|
|
const { name: copyToggleName, id: projectId } = useParams<{
|
|
|
|
name: string;
|
|
|
|
id: string;
|
|
|
|
}>();
|
2021-10-07 23:04:14 +02:00
|
|
|
const { feature } = useFeature(projectId, copyToggleName);
|
2022-02-11 11:19:55 +01:00
|
|
|
const history = useHistory();
|
2021-08-25 13:37:22 +02:00
|
|
|
|
|
|
|
useEffect(() => {
|
2021-10-07 23:04:14 +02:00
|
|
|
inputRef.current?.focus();
|
|
|
|
}, []);
|
2021-08-25 13:37:22 +02:00
|
|
|
|
2022-05-02 12:52:33 +02:00
|
|
|
const setValue: ChangeEventHandler<HTMLInputElement> = event => {
|
|
|
|
const value = trim(event.target.value);
|
2021-08-25 13:37:22 +02:00
|
|
|
setNewToggleName(value);
|
|
|
|
};
|
|
|
|
|
|
|
|
const toggleReplaceGroupId = () => {
|
|
|
|
setReplaceGroupId(prev => !prev);
|
|
|
|
};
|
|
|
|
|
|
|
|
const onValidateName = async () => {
|
|
|
|
try {
|
2022-02-11 11:19:55 +01:00
|
|
|
await validateFeatureToggleName(newToggleName);
|
2021-08-25 13:37:22 +02:00
|
|
|
|
|
|
|
setNameError(undefined);
|
2022-05-02 12:52:33 +02:00
|
|
|
} catch (error) {
|
|
|
|
setNameError(formatUnknownError(error));
|
2021-08-25 13:37:22 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-05-02 12:52:33 +02:00
|
|
|
const onSubmit: FormEventHandler = async event => {
|
|
|
|
event.preventDefault();
|
2021-08-25 13:37:22 +02:00
|
|
|
|
|
|
|
if (nameError) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2022-01-14 15:50:02 +01:00
|
|
|
await cloneFeatureToggle(projectId, copyToggleName, {
|
2022-05-02 12:52:33 +02:00
|
|
|
name: newToggleName as string,
|
2022-01-14 15:50:02 +01:00
|
|
|
replaceGroupId,
|
|
|
|
});
|
2022-05-02 12:52:33 +02:00
|
|
|
history.push(getTogglePath(projectId, newToggleName as string));
|
|
|
|
} catch (error) {
|
|
|
|
setApiError(formatUnknownError(error));
|
2021-08-25 13:37:22 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-10-07 23:04:14 +02:00
|
|
|
if (!feature || !feature.name) return <span>Toggle not found</span>;
|
2021-08-25 13:37:22 +02:00
|
|
|
|
|
|
|
return (
|
|
|
|
<Paper
|
2022-05-02 15:52:41 +02:00
|
|
|
className={themeStyles.fullwidth}
|
2021-08-25 13:37:22 +02:00
|
|
|
style={{ overflow: 'visible' }}
|
|
|
|
>
|
|
|
|
<div className={styles.header}>
|
2021-10-07 23:04:14 +02:00
|
|
|
<h1>Copy {copyToggleName}</h1>
|
2021-08-25 13:37:22 +02:00
|
|
|
</div>
|
|
|
|
<ConditionallyRender
|
2022-05-02 12:52:33 +02:00
|
|
|
condition={Boolean(apiError)}
|
2021-08-25 13:37:22 +02:00
|
|
|
show={<Alert severity="error">{apiError}</Alert>}
|
|
|
|
/>
|
|
|
|
<section className={styles.content}>
|
|
|
|
<p className={styles.text}>
|
|
|
|
You are about to create a new feature toggle by cloning the
|
|
|
|
configuration of feature toggle
|
2022-02-04 10:36:08 +01:00
|
|
|
<Link to={getTogglePath(projectId, copyToggleName)}>
|
2021-10-07 23:04:14 +02:00
|
|
|
{copyToggleName}
|
2021-08-25 13:37:22 +02:00
|
|
|
</Link>
|
|
|
|
. You must give the new feature toggle a unique name before
|
|
|
|
you can proceed.
|
|
|
|
</p>
|
|
|
|
<form onSubmit={onSubmit}>
|
|
|
|
<TextField
|
|
|
|
label="Feature toggle name"
|
|
|
|
name="name"
|
|
|
|
value={newToggleName || ''}
|
|
|
|
onBlur={onValidateName}
|
|
|
|
onChange={setValue}
|
|
|
|
error={nameError !== undefined}
|
|
|
|
helperText={nameError}
|
|
|
|
variant="outlined"
|
|
|
|
size="small"
|
|
|
|
inputRef={inputRef}
|
2021-10-20 13:12:48 +02:00
|
|
|
required
|
2021-08-25 13:37:22 +02:00
|
|
|
/>
|
|
|
|
<FormControlLabel
|
|
|
|
control={
|
|
|
|
<Switch
|
|
|
|
value={replaceGroupId}
|
|
|
|
checked={replaceGroupId}
|
|
|
|
onChange={toggleReplaceGroupId}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
label="Replace groupId"
|
|
|
|
/>
|
|
|
|
|
|
|
|
<Button type="submit" color="primary" variant="contained">
|
|
|
|
<FileCopy />
|
|
|
|
Create from copy
|
|
|
|
</Button>
|
|
|
|
</form>
|
|
|
|
</section>
|
|
|
|
</Paper>
|
|
|
|
);
|
|
|
|
};
|