mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-26 13:48:33 +02:00
feat: show Changes scheduled in feature variants even when CR are dis… (#5613)
show Changes scheduled in feature variants even when CR are disabled Modifies existing hook to call the new `change-requests/scheduled` endpoint that returns the relevant scheduled change requests even when change requests are disabled Rename the ChangeRequestIdentityData to ScheduledChangeRequestViewModel for consistency (finalised schemas will replace the BE and FE types in a follow up PR) Closes # [1-1746](https://linear.app/unleash/issue/1-1746/show-change-scheduled-badge-in-feature-environment-variants-even-if) <img width="1486" alt="Screenshot 2023-12-12 at 14 24 44" src="https://github.com/Unleash/unleash/assets/104830839/7c4e92ef-81d8-423e-8b78-9015ede59952"> --------- Signed-off-by: andreas-unleash <andreas@getunleash.ai>
This commit is contained in:
parent
bc62a98f51
commit
4376697250
@ -11,10 +11,8 @@ import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
|
||||
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
||||
import { usePendingChangeRequests } from 'hooks/api/getters/usePendingChangeRequests/usePendingChangeRequests';
|
||||
import { useHighestPermissionChangeRequestEnvironment } from 'hooks/useHighestPermissionChangeRequestEnvironment';
|
||||
import {
|
||||
ChangeRequestIdentityData,
|
||||
useScheduledChangeRequestsWithFlags,
|
||||
} from 'hooks/api/getters/useScheduledChangeRequestsWithFlags/useScheduledChangeRequestsWithFlags';
|
||||
import { useScheduledChangeRequestsWithFlags } from 'hooks/api/getters/useScheduledChangeRequestsWithFlags/useScheduledChangeRequestsWithFlags';
|
||||
import { ScheduledChangeRequestViewModel } from 'hooks/api/getters/useScheduledChangeRequestsWithStrategy/useScheduledChangeRequestsWithStrategy';
|
||||
|
||||
interface IFeatureArchiveDialogProps {
|
||||
isOpen: boolean;
|
||||
@ -128,7 +126,7 @@ const ArchiveParentError = ({
|
||||
};
|
||||
|
||||
const ScheduledChangeRequestAlert: VFC<{
|
||||
changeRequests?: ChangeRequestIdentityData[];
|
||||
changeRequests?: ScheduledChangeRequestViewModel[];
|
||||
projectId: string;
|
||||
}> = ({ changeRequests, projectId }) => {
|
||||
if (changeRequests && changeRequests.length > 0) {
|
||||
|
@ -14,7 +14,7 @@ import { ChangesScheduledBadge } from 'component/changeRequest/ModifiedInChangeR
|
||||
import { IFeatureChange } from 'component/changeRequest/changeRequest.types';
|
||||
import { Badge } from 'component/common/Badge/Badge';
|
||||
import {
|
||||
ChangeRequestIdentityData,
|
||||
ScheduledChangeRequestViewModel,
|
||||
useScheduledChangeRequestsWithStrategy,
|
||||
} from 'hooks/api/getters/useScheduledChangeRequestsWithStrategy/useScheduledChangeRequestsWithStrategy';
|
||||
|
||||
@ -114,7 +114,7 @@ const ChangeRequestStatusBadge = ({
|
||||
|
||||
const renderHeaderChildren = (
|
||||
changes?: UseStrategyChangeFromRequestResult,
|
||||
scheduledChanges?: ChangeRequestIdentityData[],
|
||||
scheduledChanges?: ScheduledChangeRequestViewModel[],
|
||||
): JSX.Element[] => {
|
||||
const badges: JSX.Element[] = [];
|
||||
if (changes?.length === 0 && scheduledChanges?.length === 0) {
|
||||
|
@ -136,6 +136,25 @@ const changeRequestConfig = () =>
|
||||
'get',
|
||||
);
|
||||
|
||||
const disableChangeRequests = () =>
|
||||
testServerRoute(
|
||||
server,
|
||||
'/api/admin/projects/default/change-requests/config',
|
||||
[
|
||||
{
|
||||
environment: 'development',
|
||||
type: 'development',
|
||||
changeRequestEnabled: false,
|
||||
},
|
||||
{
|
||||
environment: 'production',
|
||||
type: 'production',
|
||||
changeRequestEnabled: false,
|
||||
},
|
||||
],
|
||||
'get',
|
||||
);
|
||||
|
||||
const feature = () => {
|
||||
testServerRoute(server, '/api/admin/projects/default/features/feature1', {
|
||||
environments: [
|
||||
@ -246,7 +265,28 @@ describe('Change request badges for variants', () => {
|
||||
|
||||
testServerRoute(
|
||||
server,
|
||||
'/api/admin/projects/default/change-requests/pending/feature1',
|
||||
'/api/admin/projects/default/change-requests/scheduled',
|
||||
[changeRequest],
|
||||
);
|
||||
|
||||
render(<Component />, {
|
||||
route: '/projects/default/features/feature1/variants',
|
||||
permissions: [
|
||||
{
|
||||
permission: ADMIN,
|
||||
},
|
||||
],
|
||||
});
|
||||
await screen.findByText('Changes Scheduled');
|
||||
});
|
||||
|
||||
test('should render the badge when scheduled request with "patchVariant" action when change requests are disabled', async () => {
|
||||
disableChangeRequests();
|
||||
const changeRequest = scheduledRequest('patchVariant', 1);
|
||||
|
||||
testServerRoute(
|
||||
server,
|
||||
'/api/admin/projects/default/change-requests/scheduled',
|
||||
[changeRequest],
|
||||
);
|
||||
|
||||
|
@ -1,39 +1,25 @@
|
||||
import { usePendingChangeRequestsForFeature } from 'hooks/api/getters/usePendingChangeRequestsForFeature/usePendingChangeRequestsForFeature';
|
||||
import { useScheduledChangeRequestsWithVariant } from 'hooks/api/getters/useScheduledChangeRequestsWithVariants/useScheduledChangeRequestsWithVariant';
|
||||
|
||||
export const useVariantsFromScheduledRequests = (
|
||||
projectId: string,
|
||||
featureId: string,
|
||||
environment: string,
|
||||
): number[] => {
|
||||
const { changeRequests } = usePendingChangeRequestsForFeature(
|
||||
const { changeRequests } = useScheduledChangeRequestsWithVariant(
|
||||
projectId,
|
||||
featureId,
|
||||
);
|
||||
|
||||
const scheduledEnvironmentRequests =
|
||||
changeRequests?.filter(
|
||||
(request) =>
|
||||
request.environment === environment &&
|
||||
request.state === 'Scheduled',
|
||||
) || [];
|
||||
const filtered = changeRequests?.filter(
|
||||
(changeRequestIdentity) =>
|
||||
changeRequestIdentity.environment === environment,
|
||||
);
|
||||
|
||||
const result: number[] = [];
|
||||
if (scheduledEnvironmentRequests.length === 0) {
|
||||
return result;
|
||||
if (filtered) {
|
||||
return filtered.map(
|
||||
(changeRequestIdentity) => changeRequestIdentity.id,
|
||||
);
|
||||
}
|
||||
|
||||
scheduledEnvironmentRequests.forEach((scheduledRequest) => {
|
||||
const feature = scheduledRequest?.features.find(
|
||||
(feature) => feature.name === featureId,
|
||||
);
|
||||
const change = feature?.changes.find((change) => {
|
||||
return change.action === 'patchVariant';
|
||||
});
|
||||
|
||||
if (change) {
|
||||
result.push(scheduledRequest.id);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
return [];
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { formatApiPath } from 'utils/formatPath';
|
||||
import handleErrorResponses from '../httpErrorResponseHandler';
|
||||
import { useEnterpriseSWR } from '../useEnterpriseSWR/useEnterpriseSWR';
|
||||
import { ScheduledChangeRequestViewModel } from '../useScheduledChangeRequestsWithStrategy/useScheduledChangeRequestsWithStrategy';
|
||||
|
||||
const fetcher = (path: string) => {
|
||||
return fetch(path)
|
||||
@ -8,11 +9,6 @@ const fetcher = (path: string) => {
|
||||
.then((res) => res.json());
|
||||
};
|
||||
|
||||
export type ChangeRequestIdentityData = {
|
||||
id: number;
|
||||
title?: string;
|
||||
};
|
||||
|
||||
export const useScheduledChangeRequestsWithFlags = (
|
||||
project: string,
|
||||
flags: string[],
|
||||
@ -20,7 +16,7 @@ export const useScheduledChangeRequestsWithFlags = (
|
||||
const queryString = flags.map((flag) => `feature=${flag}`).join('&');
|
||||
|
||||
const { data, error, mutate } = useEnterpriseSWR<
|
||||
ChangeRequestIdentityData[]
|
||||
ScheduledChangeRequestViewModel[]
|
||||
>(
|
||||
[],
|
||||
formatApiPath(
|
||||
|
@ -8,8 +8,9 @@ const fetcher = (path: string) => {
|
||||
.then((res) => res.json());
|
||||
};
|
||||
|
||||
export type ChangeRequestIdentityData = {
|
||||
export type ScheduledChangeRequestViewModel = {
|
||||
id: number;
|
||||
environment: string;
|
||||
title?: string;
|
||||
};
|
||||
|
||||
@ -18,7 +19,7 @@ export const useScheduledChangeRequestsWithStrategy = (
|
||||
strategyId: string,
|
||||
) => {
|
||||
const { data, error, mutate } = useEnterpriseSWR<
|
||||
ChangeRequestIdentityData[]
|
||||
ScheduledChangeRequestViewModel[]
|
||||
>(
|
||||
[],
|
||||
formatApiPath(
|
||||
|
@ -0,0 +1,32 @@
|
||||
import { formatApiPath } from 'utils/formatPath';
|
||||
import handleErrorResponses from '../httpErrorResponseHandler';
|
||||
import { useEnterpriseSWR } from '../useEnterpriseSWR/useEnterpriseSWR';
|
||||
import { ScheduledChangeRequestViewModel } from '../useScheduledChangeRequestsWithStrategy/useScheduledChangeRequestsWithStrategy';
|
||||
|
||||
const fetcher = (path: string) => {
|
||||
return fetch(path)
|
||||
.then(handleErrorResponses('ChangeRequest'))
|
||||
.then((res) => res.json());
|
||||
};
|
||||
|
||||
export const useScheduledChangeRequestsWithVariant = (
|
||||
project: string,
|
||||
feature: string,
|
||||
) => {
|
||||
const { data, error, mutate } = useEnterpriseSWR<
|
||||
ScheduledChangeRequestViewModel[]
|
||||
>(
|
||||
[],
|
||||
formatApiPath(
|
||||
`api/admin/projects/${project}/change-requests/scheduled?variantForFlag=${feature}`,
|
||||
),
|
||||
fetcher,
|
||||
);
|
||||
|
||||
return {
|
||||
changeRequests: data,
|
||||
loading: !error && !data,
|
||||
refetch: mutate,
|
||||
error,
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue
Block a user