mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-08 01:15:49 +02:00
Change request - edit strategy (#2334)
* feat: request change - add strategy * refactor: use change request is-enabled hook * feat: edit strategy * fix: prettier formatting * fix: refetch change request draft after adding
This commit is contained in:
parent
d2000f2848
commit
4b281d9513
@ -19,7 +19,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
formatStrategyName,
|
formatStrategyName,
|
||||||
GetFeatureStrategyIcon,
|
GetFeatureStrategyIcon,
|
||||||
} from '../../../utils/strategyNames';
|
} from 'utils/strategyNames';
|
||||||
import { IChangeRequestEnabled } from '../changeRequest.types';
|
import { IChangeRequestEnabled } from '../changeRequest.types';
|
||||||
|
|
||||||
interface IChangeRequestProps {
|
interface IChangeRequestProps {
|
||||||
|
@ -29,6 +29,7 @@ import { IFeatureToggle } from 'interfaces/featureToggle';
|
|||||||
import { comparisonModerator } from '../featureStrategy.utils';
|
import { comparisonModerator } from '../featureStrategy.utils';
|
||||||
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
||||||
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
||||||
|
import { useChangeRequestOpen } from 'hooks/api/getters/useChangeRequestOpen/useChangeRequestOpen';
|
||||||
|
|
||||||
export const FeatureStrategyCreate = () => {
|
export const FeatureStrategyCreate = () => {
|
||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
@ -51,6 +52,7 @@ export const FeatureStrategyCreate = () => {
|
|||||||
const { feature, refetchFeature } = useFeature(projectId, featureId);
|
const { feature, refetchFeature } = useFeature(projectId, featureId);
|
||||||
const ref = useRef<IFeatureToggle>(feature);
|
const ref = useRef<IFeatureToggle>(feature);
|
||||||
const isChangeRequestEnabled = useChangeRequestsEnabled();
|
const isChangeRequestEnabled = useChangeRequestsEnabled();
|
||||||
|
const { refetch: refetchChangeRequests } = useChangeRequestOpen(projectId);
|
||||||
|
|
||||||
const isChangeRequest =
|
const isChangeRequest =
|
||||||
isChangeRequestEnabled && environmentId === 'production'; // FIXME: get from API - is it enabled
|
isChangeRequestEnabled && environmentId === 'production'; // FIXME: get from API - is it enabled
|
||||||
@ -106,20 +108,19 @@ export const FeatureStrategyCreate = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAddStrategySuggestion = async (
|
const onStrategyRequestAdd = async (payload: IFeatureStrategyPayload) => {
|
||||||
payload: IFeatureStrategyPayload
|
|
||||||
) => {
|
|
||||||
await addChangeRequest(projectId, environmentId, {
|
await addChangeRequest(projectId, environmentId, {
|
||||||
action: 'addStrategy',
|
action: 'addStrategy',
|
||||||
feature: featureId,
|
feature: featureId,
|
||||||
payload,
|
payload,
|
||||||
});
|
});
|
||||||
// TODO: segments in change requests
|
// FIXME: segments in change requests
|
||||||
setToastData({
|
setToastData({
|
||||||
title: 'Strategy added to draft',
|
title: 'Strategy added to draft',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
confetti: true,
|
confetti: true,
|
||||||
});
|
});
|
||||||
|
refetchChangeRequests();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
@ -127,7 +128,7 @@ export const FeatureStrategyCreate = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (isChangeRequest) {
|
if (isChangeRequest) {
|
||||||
await onAddStrategySuggestion(payload);
|
await onStrategyRequestAdd(payload);
|
||||||
} else {
|
} else {
|
||||||
await onAddStrategy(payload);
|
await onAddStrategy(payload);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { FeatureStrategyForm } from 'component/feature/FeatureStrategy/FeatureStrategyForm/FeatureStrategyForm';
|
import { FeatureStrategyForm } from 'component/feature/FeatureStrategy/FeatureStrategyForm/FeatureStrategyForm';
|
||||||
import FormTemplate from 'component/common/FormTemplate/FormTemplate';
|
import FormTemplate from 'component/common/FormTemplate/FormTemplate';
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
@ -25,6 +25,9 @@ import { useCollaborateData } from 'hooks/useCollaborateData';
|
|||||||
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
||||||
import { IFeatureToggle } from 'interfaces/featureToggle';
|
import { IFeatureToggle } from 'interfaces/featureToggle';
|
||||||
import { comparisonModerator } from '../featureStrategy.utils';
|
import { comparisonModerator } from '../featureStrategy.utils';
|
||||||
|
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
||||||
|
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
||||||
|
import { useChangeRequestOpen } from 'hooks/api/getters/useChangeRequestOpen/useChangeRequestOpen';
|
||||||
|
|
||||||
export const FeatureStrategyEdit = () => {
|
export const FeatureStrategyEdit = () => {
|
||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
@ -42,6 +45,12 @@ export const FeatureStrategyEdit = () => {
|
|||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
const { unleashUrl } = uiConfig;
|
const { unleashUrl } = uiConfig;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { addChangeRequest } = useChangeRequestApi();
|
||||||
|
const isChangeRequestEnabled = useChangeRequestsEnabled();
|
||||||
|
const { refetch: refetchChangeRequests } = useChangeRequestOpen(projectId);
|
||||||
|
|
||||||
|
const isChangeRequest =
|
||||||
|
isChangeRequestEnabled && environmentId === 'production'; // FIXME: get from API - is it enabled
|
||||||
|
|
||||||
const { feature, refetchFeature } = useFeature(projectId, featureId);
|
const { feature, refetchFeature } = useFeature(projectId, featureId);
|
||||||
|
|
||||||
@ -87,29 +96,54 @@ export const FeatureStrategyEdit = () => {
|
|||||||
savedStrategySegments && setSegments(savedStrategySegments);
|
savedStrategySegments && setSegments(savedStrategySegments);
|
||||||
}, [savedStrategySegments]);
|
}, [savedStrategySegments]);
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const onStrategyEdit = async (payload: IFeatureStrategyPayload) => {
|
||||||
try {
|
await updateStrategyOnFeature(
|
||||||
await updateStrategyOnFeature(
|
projectId,
|
||||||
projectId,
|
featureId,
|
||||||
featureId,
|
environmentId,
|
||||||
|
strategyId,
|
||||||
|
payload
|
||||||
|
);
|
||||||
|
if (uiConfig.flags.SE) {
|
||||||
|
await setStrategySegments({
|
||||||
environmentId,
|
environmentId,
|
||||||
|
projectId,
|
||||||
strategyId,
|
strategyId,
|
||||||
createStrategyPayload(strategy)
|
segmentIds: segments.map(s => s.id),
|
||||||
);
|
|
||||||
if (uiConfig.flags.SE) {
|
|
||||||
await setStrategySegments({
|
|
||||||
environmentId,
|
|
||||||
projectId,
|
|
||||||
strategyId,
|
|
||||||
segmentIds: segments.map(s => s.id),
|
|
||||||
});
|
|
||||||
await refetchSavedStrategySegments();
|
|
||||||
}
|
|
||||||
setToastData({
|
|
||||||
title: 'Strategy updated',
|
|
||||||
type: 'success',
|
|
||||||
confetti: true,
|
|
||||||
});
|
});
|
||||||
|
await refetchSavedStrategySegments();
|
||||||
|
}
|
||||||
|
setToastData({
|
||||||
|
title: 'Strategy updated',
|
||||||
|
type: 'success',
|
||||||
|
confetti: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onStrategyRequestEdit = async (payload: IFeatureStrategyPayload) => {
|
||||||
|
await addChangeRequest(projectId, environmentId, {
|
||||||
|
action: 'updateStrategy',
|
||||||
|
feature: featureId,
|
||||||
|
payload: { ...payload, id: strategyId },
|
||||||
|
});
|
||||||
|
// FIXME: segments in change requests
|
||||||
|
setToastData({
|
||||||
|
title: 'Change added to draft',
|
||||||
|
type: 'success',
|
||||||
|
confetti: true,
|
||||||
|
});
|
||||||
|
refetchChangeRequests();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = async () => {
|
||||||
|
const payload = createStrategyPayload(strategy);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (isChangeRequest) {
|
||||||
|
await onStrategyRequestEdit(payload);
|
||||||
|
} else {
|
||||||
|
await onStrategyEdit(payload);
|
||||||
|
}
|
||||||
refetchFeature();
|
refetchFeature();
|
||||||
navigate(formatFeaturePath(projectId, featureId));
|
navigate(formatFeaturePath(projectId, featureId));
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
@ -152,6 +186,7 @@ export const FeatureStrategyEdit = () => {
|
|||||||
loading={loading}
|
loading={loading}
|
||||||
permission={UPDATE_FEATURE_STRATEGY}
|
permission={UPDATE_FEATURE_STRATEGY}
|
||||||
errors={errors}
|
errors={errors}
|
||||||
|
isChangeRequest={isChangeRequest}
|
||||||
/>
|
/>
|
||||||
{staleDataNotification}
|
{staleDataNotification}
|
||||||
</FormTemplate>
|
</FormTemplate>
|
||||||
@ -160,13 +195,11 @@ export const FeatureStrategyEdit = () => {
|
|||||||
|
|
||||||
export const createStrategyPayload = (
|
export const createStrategyPayload = (
|
||||||
strategy: Partial<IFeatureStrategy>
|
strategy: Partial<IFeatureStrategy>
|
||||||
): IFeatureStrategyPayload => {
|
): IFeatureStrategyPayload => ({
|
||||||
return {
|
name: strategy.name,
|
||||||
name: strategy.name,
|
constraints: strategy.constraints ?? [],
|
||||||
constraints: strategy.constraints ?? [],
|
parameters: strategy.parameters ?? {},
|
||||||
parameters: strategy.parameters ?? {},
|
});
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const formatFeaturePath = (
|
export const formatFeaturePath = (
|
||||||
projectId: string,
|
projectId: string,
|
||||||
|
@ -9,9 +9,9 @@ export const FeatureStrategyChangeRequestAlert: VFC<
|
|||||||
IFeatureStrategyChangeRequestAlertProps
|
IFeatureStrategyChangeRequestAlertProps
|
||||||
> = ({ environment }) => (
|
> = ({ environment }) => (
|
||||||
<Alert severity="info">
|
<Alert severity="info">
|
||||||
Change requests are enabled{environment ? ` for ${environment}` : ''}.
|
<strong>Change requests</strong> are enabled
|
||||||
Your changes needs to be approved before they will be live. All the
|
{environment ? ` for ${environment}` : ''}. Your changes needs to be
|
||||||
changes you do now will be added into a draft that you can submit for
|
approved before they will be live. All the changes you do now will be
|
||||||
review.
|
added into a draft that you can submit for review.
|
||||||
</Alert>
|
</Alert>
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import React, { useState, useContext } from 'react';
|
import React, { useState, useContext } from 'react';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import { Button } from '@mui/material';
|
||||||
import {
|
import {
|
||||||
IFeatureStrategy,
|
IFeatureStrategy,
|
||||||
IFeatureStrategyParameters,
|
IFeatureStrategyParameters,
|
||||||
@ -7,15 +9,8 @@ import {
|
|||||||
import { FeatureStrategyType } from '../FeatureStrategyType/FeatureStrategyType';
|
import { FeatureStrategyType } from '../FeatureStrategyType/FeatureStrategyType';
|
||||||
import { FeatureStrategyEnabled } from './FeatureStrategyEnabled/FeatureStrategyEnabled';
|
import { FeatureStrategyEnabled } from './FeatureStrategyEnabled/FeatureStrategyEnabled';
|
||||||
import { FeatureStrategyConstraints } from '../FeatureStrategyConstraints/FeatureStrategyConstraints';
|
import { FeatureStrategyConstraints } from '../FeatureStrategyConstraints/FeatureStrategyConstraints';
|
||||||
import { Button } from '@mui/material';
|
|
||||||
import {
|
|
||||||
FeatureStrategyProdGuard,
|
|
||||||
useFeatureStrategyProdGuard,
|
|
||||||
} from '../FeatureStrategyProdGuard/FeatureStrategyProdGuard';
|
|
||||||
import { IFeatureToggle } from 'interfaces/featureToggle';
|
import { IFeatureToggle } from 'interfaces/featureToggle';
|
||||||
import { useStyles } from './FeatureStrategyForm.styles';
|
import { useStyles } from './FeatureStrategyForm.styles';
|
||||||
import { formatFeaturePath } from '../FeatureStrategyEdit/FeatureStrategyEdit';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { STRATEGY_FORM_SUBMIT_ID } from 'utils/testIds';
|
import { STRATEGY_FORM_SUBMIT_ID } from 'utils/testIds';
|
||||||
@ -28,6 +23,11 @@ import { IFormErrors } from 'hooks/useFormErrors';
|
|||||||
import { validateParameterValue } from 'utils/validateParameterValue';
|
import { validateParameterValue } from 'utils/validateParameterValue';
|
||||||
import { useStrategy } from 'hooks/api/getters/useStrategy/useStrategy';
|
import { useStrategy } from 'hooks/api/getters/useStrategy/useStrategy';
|
||||||
import { FeatureStrategyChangeRequestAlert } from './FeatureStrategyChangeRequestAlert/FeatureStrategyChangeRequestAlert';
|
import { FeatureStrategyChangeRequestAlert } from './FeatureStrategyChangeRequestAlert/FeatureStrategyChangeRequestAlert';
|
||||||
|
import {
|
||||||
|
FeatureStrategyProdGuard,
|
||||||
|
useFeatureStrategyProdGuard,
|
||||||
|
} from '../FeatureStrategyProdGuard/FeatureStrategyProdGuard';
|
||||||
|
import { formatFeaturePath } from '../FeatureStrategyEdit/FeatureStrategyEdit';
|
||||||
|
|
||||||
interface IFeatureStrategyFormProps {
|
interface IFeatureStrategyFormProps {
|
||||||
feature: IFeatureToggle;
|
feature: IFeatureToggle;
|
||||||
@ -129,23 +129,19 @@ export const FeatureStrategyForm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<form className={styles.form} onSubmit={onSubmitWithValidation}>
|
<form className={styles.form} onSubmit={onSubmitWithValidation}>
|
||||||
<div>
|
<ConditionallyRender
|
||||||
<ConditionallyRender
|
condition={Boolean(isChangeRequest)}
|
||||||
condition={Boolean(isChangeRequest)}
|
show={
|
||||||
show={
|
<FeatureStrategyChangeRequestAlert
|
||||||
<FeatureStrategyChangeRequestAlert
|
environment={environmentId}
|
||||||
environment={environmentId}
|
/>
|
||||||
/>
|
}
|
||||||
}
|
/>
|
||||||
elseShow={
|
<FeatureStrategyEnabled
|
||||||
<FeatureStrategyEnabled
|
projectId={feature.project}
|
||||||
projectId={feature.project}
|
featureId={feature.name}
|
||||||
featureId={feature.name}
|
environmentId={environmentId}
|
||||||
environmentId={environmentId}
|
/>
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<hr className={styles.hr} />
|
<hr className={styles.hr} />
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(uiConfig.flags.SE)}
|
condition={Boolean(uiConfig.flags.SE)}
|
||||||
|
Loading…
Reference in New Issue
Block a user