1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-10-22 11:18:20 +02:00

chore: get release plans from features endpoint (#10764)

This commit is contained in:
Fredrik Strand Oseberg 2025-10-09 10:12:56 +02:00 committed by GitHub
parent 4722fd4081
commit 386c7d5bc6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 60 additions and 17 deletions

View File

@ -7,7 +7,7 @@ import type {
IChangeRequestStartMilestone,
} from 'component/changeRequest/changeRequest.types';
import { useReleasePlanPreview } from 'hooks/useReleasePlanPreview';
import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePlans';
import { useFeatureReleasePlans } from 'hooks/api/getters/useFeatureReleasePlans/useFeatureReleasePlans';
import { TooltipLink } from 'component/common/TooltipLink/TooltipLink';
import { EventDiff } from 'component/events/EventDiff/EventDiff';
import { ReleasePlan } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlan';
@ -241,7 +241,7 @@ export const ReleasePlanChange: FC<{
projectId,
changeRequestState,
}) => {
const { releasePlans } = useReleasePlans(
const { releasePlans } = useFeatureReleasePlans(
projectId,
featureName,
environmentName,

View File

@ -16,7 +16,7 @@ import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useCh
import { usePendingChangeRequests } from 'hooks/api/getters/usePendingChangeRequests/usePendingChangeRequests';
import useToast from 'hooks/useToast';
import { useReleasePlansApi } from 'hooks/api/actions/useReleasePlansApi/useReleasePlansApi';
import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePlans';
import { useFeatureReleasePlans } from 'hooks/api/getters/useFeatureReleasePlans/useFeatureReleasePlans';
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
import { formatUnknownError } from 'utils/formatUnknownError';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
@ -89,7 +89,7 @@ export const FeatureStrategyMenu = ({
const { addChange } = useChangeRequestApi();
const { refetch: refetchChangeRequests } =
usePendingChangeRequests(projectId);
const { refetch, releasePlans } = useReleasePlans(
const { refetch, releasePlans } = useFeatureReleasePlans(
projectId,
featureId,
environmentId,

View File

@ -18,7 +18,7 @@ import usePagination from 'hooks/usePagination';
import type { IFeatureStrategy } from 'interfaces/strategy';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
import { useUiFlag } from 'hooks/useUiFlag';
import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePlans';
import { useFeatureReleasePlans } from 'hooks/api/getters/useFeatureReleasePlans/useFeatureReleasePlans';
import { ReleasePlan } from '../../../ReleasePlan/ReleasePlan.tsx';
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
import { ProjectEnvironmentStrategyDraggableItem } from './StrategyDraggableItem/ProjectEnvironmentStrategyDraggableItem.tsx';
@ -66,10 +66,10 @@ export const EnvironmentAccordionBody = ({
const [strategies, setStrategies] = useState(
featureEnvironment?.strategies || [],
);
const { releasePlans } = useReleasePlans(
const { releasePlans } = useFeatureReleasePlans(
projectId,
featureId,
featureEnvironment?.name,
featureEnvironment,
);
const { trackEvent } = usePlausibleTracker();

View File

@ -5,7 +5,7 @@ import { FeatureOverviewEnvironment } from './FeatureOverviewEnvironment/Feature
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import useFeatureMetrics from 'hooks/api/getters/useFeatureMetrics/useFeatureMetrics';
import { getFeatureMetrics } from 'utils/getFeatureMetrics';
import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePlans';
import { useFeatureReleasePlans } from 'hooks/api/getters/useFeatureReleasePlans/useFeatureReleasePlans';
import { useUiFlag } from 'hooks/useUiFlag';
type FeatureOverviewEnvironmentsProps = {
@ -18,10 +18,10 @@ const FeatureOverviewWithReleasePlans: FC<
> = ({ environment, ...props }) => {
const projectId = useRequiredPathParam('projectId');
const featureId = useRequiredPathParam('featureId');
const { releasePlans } = useReleasePlans(
const { releasePlans } = useFeatureReleasePlans(
projectId,
featureId,
environment?.name,
environment,
);
const envAddStrategySuggestionEnabled = useUiFlag(
'envAddStrategySuggestion',

View File

@ -13,7 +13,7 @@ import {
Button,
} from '@mui/material';
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePlans';
import { useFeatureReleasePlans } from 'hooks/api/getters/useFeatureReleasePlans/useFeatureReleasePlans';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import CloseIcon from '@mui/icons-material/Close';
@ -76,7 +76,7 @@ export const LegacyReleasePlanReviewDialog = ({
crProtected,
}: IReleasePlanAddDialogProps) => {
const { feature } = useFeature(projectId, featureName);
const { releasePlans } = useReleasePlans(
const { releasePlans } = useFeatureReleasePlans(
projectId,
featureName,
environment,

View File

@ -3,7 +3,7 @@ import { styled } from '@mui/material';
import { DELETE_FEATURE_STRATEGY } from '@server/types/permissions';
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
import { useReleasePlansApi } from 'hooks/api/actions/useReleasePlansApi/useReleasePlansApi';
import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePlans';
import { useFeatureReleasePlans } from 'hooks/api/getters/useFeatureReleasePlans/useFeatureReleasePlans';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import useToast from 'hooks/useToast';
import type {
@ -99,7 +99,11 @@ export const ReleasePlan = ({
} = plan;
const projectId = useRequiredPathParam('projectId');
const { refetch } = useReleasePlans(projectId, featureName, environment);
const { refetch } = useFeatureReleasePlans(
projectId,
featureName,
environment,
);
const { removeReleasePlanFromFeature, startReleasePlanMilestone } =
useReleasePlansApi();
const { setToastData, setToastApiError } = useToast();

View File

@ -4,7 +4,7 @@ import { ReleasePlan } from './ReleasePlan.tsx';
import { useReleasePlanPreview } from 'hooks/useReleasePlanPreview';
import { styled, Typography, Alert } from '@mui/material';
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePlans';
import { useFeatureReleasePlans } from 'hooks/api/getters/useFeatureReleasePlans/useFeatureReleasePlans';
const StyledReleasePlanContainer = styled('div')(({ theme }) => ({
margin: theme.spacing(2, 0),
@ -31,7 +31,7 @@ export const ReleasePlanAddDialog = ({
crProtected,
}: IReleasePlanAddDialogProps) => {
const { feature } = useFeature(projectId, featureName);
const { releasePlans } = useReleasePlans(
const { releasePlans } = useFeatureReleasePlans(
projectId,
featureName,
environment,

View File

@ -0,0 +1,32 @@
import { useUiFlag } from 'hooks/useUiFlag';
import { useReleasePlans } from '../useReleasePlans/useReleasePlans.js';
import { useFeature } from '../useFeature/useFeature.js';
import type { IFeatureEnvironment } from 'interfaces/featureToggle';
export const useFeatureReleasePlans = (
projectId: string,
featureId: string,
environment?: IFeatureEnvironment | string,
) => {
const featureReleasePlansEnabled = useUiFlag('featureReleasePlans');
const envName =
typeof environment === 'string' ? environment : environment?.name;
const {
releasePlans: releasePlansFromHook,
refetch: refetchReleasePlans,
...rest
} = useReleasePlans(projectId, featureId, envName);
const { refetchFeature } = useFeature(projectId, featureId);
const releasePlans = featureReleasePlansEnabled
? typeof environment === 'object'
? environment?.releasePlans || []
: []
: releasePlansFromHook;
const refetch = featureReleasePlansEnabled
? refetchFeature
: refetchReleasePlans;
return { releasePlans, refetch, ...rest };
};

View File

@ -4,6 +4,7 @@ import { formatApiPath } from 'utils/formatPath';
import handleErrorResponses from '../httpErrorResponseHandler.js';
import { useConditionalSWR } from '../useConditionalSWR/useConditionalSWR.js';
import type { IReleasePlan } from 'interfaces/releasePlans';
import { useUiFlag } from 'hooks/useUiFlag';
const DEFAULT_DATA: IReleasePlan[] = [];
@ -13,9 +14,13 @@ export const useReleasePlans = (
environment?: string,
) => {
const { isEnterprise } = useUiConfig();
const featureReleasePlansEnabled = useUiFlag('featureReleasePlans');
// When featureReleasePlans flag is enabled, release plans come embedded in the
// feature payload, so we don't need to fetch them separately from this endpoint.
// Only fetch when the flag is disabled (!featureReleasePlansEnabled).
const { data, error, mutate } = useConditionalSWR<IReleasePlan[]>(
isEnterprise() && Boolean(environment),
isEnterprise() && Boolean(environment) && !featureReleasePlansEnabled,
DEFAULT_DATA,
formatApiPath(
`api/admin/projects/${projectId}/features/${featureName}/environments/${environment}/release_plans`,

View File

@ -1,6 +1,7 @@
import type { CreateFeatureSchemaType, FeatureSchema } from 'openapi';
import type { IFeatureStrategy } from './strategy.js';
import type { ITag } from './tags.js';
import type { IReleasePlan } from './releasePlans.js';
/**
* @deprecated use FeatureSchema from openapi
@ -96,6 +97,7 @@ export interface IFeatureEnvironment {
lastSeenAt?: string;
yes?: number;
no?: number;
releasePlans?: IReleasePlan[];
}
export interface IFeatureEnvironmentWithCrEnabled extends IFeatureEnvironment {