{
style={{ overflow: 'visible' }}
>
-
Copy {copyToggle.name}
+ Copy {copyToggleName}
{
You are about to create a new feature toggle by cloning the
configuration of feature toggle
- {copyToggle.name}
+ {copyToggleName}
. You must give the new feature toggle a unique name before
you can proceed.
@@ -157,10 +139,7 @@ const CopyFeature = props => {
};
CopyFeature.propTypes = {
- copyToggle: PropTypes.object,
history: PropTypes.object.isRequired,
- createFeatureToggle: PropTypes.func.isRequired,
- fetchFeatureToggles: PropTypes.func.isRequired,
validateName: PropTypes.func.isRequired,
};
diff --git a/frontend/src/component/feature/create/CopyFeature/index.jsx b/frontend/src/component/feature/create/CopyFeature/index.jsx
index 427bec1b56..a1e07db14d 100644
--- a/frontend/src/component/feature/create/CopyFeature/index.jsx
+++ b/frontend/src/component/feature/create/CopyFeature/index.jsx
@@ -1,24 +1,15 @@
import { connect } from 'react-redux';
import CopyFeatureComponent from './CopyFeature';
import {
- createFeatureToggles,
- validateName,
- fetchFeatureToggles,
+ validateName
} from '../../../../store/feature-toggle/actions';
const mapStateToProps = (state, props) => ({
history: props.history,
- features: state.features.toJS(),
- copyToggle: state.features
- .toJS()
- .find(toggle => toggle.name === props.copyToggleName),
});
const mapDispatchToProps = dispatch => ({
validateName,
- createFeatureToggle: featureToggle =>
- createFeatureToggles(featureToggle)(dispatch),
- fetchFeatureToggles: () => fetchFeatureToggles()(dispatch),
});
const FormAddContainer = connect(
diff --git a/frontend/src/hooks/api/actions/useFeatureApi/useFeatureApi.ts b/frontend/src/hooks/api/actions/useFeatureApi/useFeatureApi.ts
index 55822a5b7e..87fa316087 100644
--- a/frontend/src/hooks/api/actions/useFeatureApi/useFeatureApi.ts
+++ b/frontend/src/hooks/api/actions/useFeatureApi/useFeatureApi.ts
@@ -143,6 +143,26 @@ const useFeatureApi = () => {
}
};
+ const cloneFeatureToggle = async (
+ projectId: string,
+ featureId: string,
+ payload: {name: string, replaceGroupId: boolean}
+ ) => {
+ const path = `api/admin/projects/${projectId}/features/${featureId}/clone`;
+ const req = createRequest(
+ path,
+ { method: 'POST', body: JSON.stringify(payload) },
+ );
+
+ try {
+ const res = await makeRequest(req.caller, req.id);
+
+ return res;
+ } catch (e) {
+ throw e;
+ }
+ };
+
return {
changeFeatureProject,
errors,
@@ -152,6 +172,7 @@ const useFeatureApi = () => {
deleteTagFromFeature,
archiveFeatureToggle,
patchFeatureToggle,
+ cloneFeatureToggle
};
};
diff --git a/frontend/src/hooks/api/getters/useFeature/useFeature.ts b/frontend/src/hooks/api/getters/useFeature/useFeature.ts
index de83e101f8..8c96c83938 100644
--- a/frontend/src/hooks/api/getters/useFeature/useFeature.ts
+++ b/frontend/src/hooks/api/getters/useFeature/useFeature.ts
@@ -17,13 +17,29 @@ const useFeature = (
id: string,
options: IUseFeatureOptions = {}
) => {
- const fetcher = () => {
+ const fetcher = async () => {
const path = formatApiPath(
`api/admin/projects/${projectId}/features/${id}`
);
- return fetch(path, {
+
+ const res = await fetch(path, {
method: 'GET',
- }).then(res => res.json());
+ });
+
+
+ // If the status code is not in the range 200-299,
+ // we still try to parse and throw it.
+ if (!res.ok) {
+ const error = new Error('An error occurred while fetching the data.')
+ // Attach extra info to the error object.
+ // @ts-ignore
+ error.info = await res.json();
+ // @ts-ignore
+ error.status = res.status;
+ throw error;
+ }
+
+ return res.json()
};
const FEATURE_CACHE_KEY = `api/admin/projects/${projectId}/features/${id}`;