mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-04 01:18:20 +02:00
feat: stop change project on change request enabled (#3391)
This commit is contained in:
parent
585df244e5
commit
3b311f74c0
@ -8,6 +8,7 @@ import { Alert, List, ListItem, styled } from '@mui/material';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { IChangeRequest } from 'component/changeRequest/changeRequest.types';
|
import { IChangeRequest } from 'component/changeRequest/changeRequest.types';
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
|
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
||||||
|
|
||||||
const StyledContainer = styled('div')(({ theme }) => ({
|
const StyledContainer = styled('div')(({ theme }) => ({
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
@ -42,6 +43,10 @@ const FeatureSettingsProjectConfirm = ({
|
|||||||
const currentProjectId = useRequiredPathParam('projectId');
|
const currentProjectId = useRequiredPathParam('projectId');
|
||||||
const { project } = useProject(projectId);
|
const { project } = useProject(projectId);
|
||||||
|
|
||||||
|
const { isChangeRequestConfiguredInAnyEnv } =
|
||||||
|
useChangeRequestsEnabled(projectId);
|
||||||
|
const targetProjectHasChangeRequestsEnabled =
|
||||||
|
isChangeRequestConfiguredInAnyEnv();
|
||||||
const hasSameEnvironments: boolean = useMemo(() => {
|
const hasSameEnvironments: boolean = useMemo(() => {
|
||||||
return arraysHaveSameItems(
|
return arraysHaveSameItems(
|
||||||
feature.environments.map(env => env.name),
|
feature.environments.map(env => env.name),
|
||||||
@ -55,7 +60,11 @@ const FeatureSettingsProjectConfirm = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={hasSameEnvironments && !hasPendingChangeRequests}
|
condition={
|
||||||
|
hasSameEnvironments &&
|
||||||
|
!hasPendingChangeRequests &&
|
||||||
|
!targetProjectHasChangeRequestsEnabled
|
||||||
|
}
|
||||||
show={
|
show={
|
||||||
<Dialogue
|
<Dialogue
|
||||||
open={open}
|
open={open}
|
||||||
@ -82,26 +91,32 @@ const FeatureSettingsProjectConfirm = ({
|
|||||||
open={open}
|
open={open}
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
title="Confirm change project"
|
title="Confirm change project"
|
||||||
primaryButtonText="OK"
|
primaryButtonText="Close"
|
||||||
>
|
>
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<StyledAlert severity="warning">
|
<StyledAlert severity="warning">
|
||||||
Incompatible project environments
|
Cannot proceed with the move
|
||||||
</StyledAlert>
|
</StyledAlert>
|
||||||
<p>
|
|
||||||
In order to move a feature toggle between two
|
<ConditionallyRender
|
||||||
projects, both projects must have the exact same
|
condition={!hasSameEnvironments}
|
||||||
environments enabled.
|
show={
|
||||||
</p>
|
<p>
|
||||||
|
In order to move a feature toggle between
|
||||||
|
two projects, both projects must have the
|
||||||
|
exact same environments enabled.
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={hasPendingChangeRequests}
|
condition={hasPendingChangeRequests}
|
||||||
show={
|
show={
|
||||||
<>
|
<>
|
||||||
<p>
|
<p>
|
||||||
In addition the feature toggle must not
|
The feature toggle must not have any
|
||||||
have any pending change requests. This
|
pending change requests. This feature
|
||||||
feature toggle is currently referenced
|
toggle is currently referenced in the
|
||||||
in the following change requests:
|
following change requests:
|
||||||
</p>
|
</p>
|
||||||
<StyledList>
|
<StyledList>
|
||||||
{changeRequests?.map(changeRequest => {
|
{changeRequests?.map(changeRequest => {
|
||||||
@ -122,6 +137,21 @@ const FeatureSettingsProjectConfirm = ({
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={targetProjectHasChangeRequestsEnabled}
|
||||||
|
show={
|
||||||
|
<p>
|
||||||
|
You're not allowed to move the feature to
|
||||||
|
project{' '}
|
||||||
|
<Link
|
||||||
|
to={`/projects/${projectId}/settings/change-requests`}
|
||||||
|
>
|
||||||
|
{projectId}
|
||||||
|
</Link>
|
||||||
|
. This project has change requests enabled.
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
</Dialogue>
|
</Dialogue>
|
||||||
}
|
}
|
||||||
|
@ -1350,6 +1350,15 @@ class FeatureToggleService {
|
|||||||
newProject: string,
|
newProject: string,
|
||||||
createdBy: string,
|
createdBy: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const changeRequestEnabled =
|
||||||
|
await this.changeRequestAccessReadModel.isChangeRequestsEnabledForProject(
|
||||||
|
newProject,
|
||||||
|
);
|
||||||
|
if (changeRequestEnabled) {
|
||||||
|
throw new NoAccessError(
|
||||||
|
`Changing project not allowed. Project ${newProject} has change requests enabled.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
const feature = await this.featureToggleStore.get(featureName);
|
const feature = await this.featureToggleStore.get(featureName);
|
||||||
const oldProject = feature.project;
|
const oldProject = feature.project;
|
||||||
feature.project = newProject;
|
feature.project = newProject;
|
||||||
|
@ -354,6 +354,20 @@ test('cloning a feature toggle not allowed for change requests enabled', async (
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('changing to a project with change requests enabled should not be allowed', async () => {
|
||||||
|
await db.rawDatabase('change_request_settings').insert({
|
||||||
|
project: 'default',
|
||||||
|
environment: 'default',
|
||||||
|
});
|
||||||
|
await expect(
|
||||||
|
service.changeProject('newToggleName', 'default', 'user'),
|
||||||
|
).rejects.toEqual(
|
||||||
|
new NoAccessError(
|
||||||
|
`Changing project not allowed. Project default has change requests enabled.`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('Cloning a feature toggle also clones segments correctly', async () => {
|
test('Cloning a feature toggle also clones segments correctly', async () => {
|
||||||
const featureName = 'ToggleWithSegments';
|
const featureName = 'ToggleWithSegments';
|
||||||
const clonedFeatureName = 'AWholeNewFeatureToggle';
|
const clonedFeatureName = 'AWholeNewFeatureToggle';
|
||||||
|
Loading…
Reference in New Issue
Block a user