diff --git a/frontend/src/component/admin/roles/RoleForm/RolePermissionCategories/RolePermissionCategories.tsx b/frontend/src/component/admin/roles/RoleForm/RolePermissionCategories/RolePermissionCategories.tsx index b1b7078ce0..401e0db753 100644 --- a/frontend/src/component/admin/roles/RoleForm/RolePermissionCategories/RolePermissionCategories.tsx +++ b/frontend/src/component/admin/roles/RoleForm/RolePermissionCategories/RolePermissionCategories.tsx @@ -18,7 +18,6 @@ import { } from 'utils/permissions'; import { RolePermissionEnvironment } from './RolePermissionEnvironment.tsx'; import { useMemo } from 'react'; -import { useUiFlag } from 'hooks/useUiFlag'; import { RolePermissionProject } from './RolePermissionProject.tsx'; import { RolePermissionCategoryAccordion } from './RolePermissionCategoryAccordion.tsx'; @@ -43,8 +42,6 @@ export const RolePermissionCategories = ({ revalidateOnFocus: false, }); - const releasePlansEnabled = useUiFlag('releasePlans'); - const isProjectRole = PROJECT_ROLE_TYPES.includes(type); const categories = useMemo( @@ -81,51 +78,42 @@ export const RolePermissionCategories = ({ return useMemo( () => ( <> - {categories - .filter( - ({ label }) => - releasePlansEnabled || - label !== 'Release plan templates', - ) - .map(({ label, type, permissions }) => ( - - ) : type === ENVIRONMENT_PERMISSION_TYPE ? ( - - ) : ( - - ) - } - permissions={permissions} - checkedPermissions={checkedPermissions} - onCheckAll={() => onCheckAll(permissions)} - > - {type === 'project' ? ( - ( + + ) : type === ENVIRONMENT_PERMISSION_TYPE ? ( + ) : ( - - )} - - ))} + + ) + } + permissions={permissions} + checkedPermissions={checkedPermissions} + onCheckAll={() => onCheckAll(permissions)} + > + {type === 'project' ? ( + + ) : ( + + )} + + ))} ), [categories, checkedPermissions], diff --git a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenu.tsx b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenu.tsx index e59c5726fa..ff2ecba811 100644 --- a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenu.tsx +++ b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenu.tsx @@ -77,10 +77,8 @@ export const FeatureStrategyMenu = ({ const { addReleasePlanToFeature } = useReleasePlansApi(); const { isEnterprise } = useUiConfig(); const addConfigurationEnabled = useUiFlag('addConfiguration'); - const releasePlansEnabled = useUiFlag('releasePlans'); - const displayReleasePlanButton = isEnterprise() && releasePlansEnabled; - const crProtected = - releasePlansEnabled && isChangeRequestConfigured(environmentId); + const displayReleasePlanButton = isEnterprise(); + const crProtected = isChangeRequestConfigured(environmentId); const onClose = () => { setIsStrategyMenuDialogOpen(false); diff --git a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenuCards/FeatureStrategyMenuCards.tsx b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenuCards/FeatureStrategyMenuCards.tsx index 37a3f4bdd4..b66e3504d7 100644 --- a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenuCards/FeatureStrategyMenuCards.tsx +++ b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenuCards/FeatureStrategyMenuCards.tsx @@ -8,7 +8,6 @@ import { useNavigate } from 'react-router-dom'; import CloseIcon from '@mui/icons-material/Close'; import FactCheckOutlinedIcon from '@mui/icons-material/FactCheckOutlined'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig.ts'; -import { useUiFlag } from 'hooks/useUiFlag.ts'; import { HelpIcon } from 'component/common/HelpIcon/HelpIcon.tsx'; interface IFeatureStrategyMenuCardsProps { @@ -124,7 +123,6 @@ export const FeatureStrategyMenuCards = ({ onClose, }: IFeatureStrategyMenuCardsProps) => { const { isEnterprise } = useUiConfig(); - const releasePlansEnabled = useUiFlag('releasePlans'); const { strategies } = useStrategies(); const { templates } = useReleasePlanTemplates(); @@ -150,7 +148,7 @@ export const FeatureStrategyMenuCards = ({ }; const renderReleasePlanTemplates = () => { - if (!isEnterprise() || !releasePlansEnabled) { + if (!isEnterprise()) { return null; } diff --git a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/ReleaseTemplatesFeedback/ReleaseTemplatesFeedback.tsx b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/ReleaseTemplatesFeedback/ReleaseTemplatesFeedback.tsx index 712cc58f13..6444b65e52 100644 --- a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/ReleaseTemplatesFeedback/ReleaseTemplatesFeedback.tsx +++ b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/ReleaseTemplatesFeedback/ReleaseTemplatesFeedback.tsx @@ -2,7 +2,6 @@ import type { FC } from 'react'; import { styled, Link } from '@mui/material'; import type { Link as RouterLink } from 'react-router-dom'; import { RELEASE_TEMPLATE_FEEDBACK } from 'constants/links'; -import { useUiFlag } from 'hooks/useUiFlag'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; const StyledLink = styled(Link)(({ theme }) => ({ @@ -17,9 +16,8 @@ const StyledLink = styled(Link)(({ theme }) => ({ export const ReleaseTemplatesFeedback: FC = () => { const { isEnterprise } = useUiConfig(); - const releaseTemplatesEnabled = useUiFlag('releasePlans'); - if (!isEnterprise() || !releaseTemplatesEnabled) { + if (!isEnterprise()) { return null; } diff --git a/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlan.tsx b/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlan.tsx index 8ad1f12c75..64bea62bde 100644 --- a/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlan.tsx +++ b/frontend/src/component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlan.tsx @@ -16,7 +16,6 @@ import { ReleasePlanRemoveDialog } from './ReleasePlanRemoveDialog.tsx'; import { ReleasePlanMilestone } from './ReleasePlanMilestone/ReleasePlanMilestone.tsx'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled'; -import { useUiFlag } from 'hooks/useUiFlag'; import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi'; import { usePendingChangeRequests } from 'hooks/api/getters/usePendingChangeRequests/usePendingChangeRequests'; import { RemoveReleasePlanChangeRequestDialog } from './ChangeRequest/RemoveReleasePlanChangeRequestDialog.tsx'; @@ -120,8 +119,6 @@ export const ReleasePlan = ({ const { refetch: refetchChangeRequests } = usePendingChangeRequests(projectId); - const releasePlansEnabled = useUiFlag('releasePlans'); - const onAddRemovePlanChangesConfirm = async () => { await addChange(projectId, environment, { feature: featureName, @@ -162,7 +159,7 @@ export const ReleasePlan = ({ }; const confirmRemoveReleasePlan = () => { - if (releasePlansEnabled && isChangeRequestConfigured(environment)) { + if (isChangeRequestConfigured(environment)) { setChangeRequestDialogRemoveOpen(true); } else { setRemoveOpen(true); @@ -197,7 +194,7 @@ export const ReleasePlan = ({ }; const onStartMilestone = async (milestone: IReleasePlanMilestone) => { - if (releasePlansEnabled && isChangeRequestConfigured(environment)) { + if (isChangeRequestConfigured(environment)) { setMilestoneForChangeRequestDialog(milestone); setChangeRequestDialogStartMilestoneOpen(true); } else { diff --git a/frontend/src/component/layout/MainLayout/NavigationSidebar/NewInUnleash/NewInUnleash.tsx b/frontend/src/component/layout/MainLayout/NavigationSidebar/NewInUnleash/NewInUnleash.tsx index c5f3832bc2..2886eefc32 100644 --- a/frontend/src/component/layout/MainLayout/NavigationSidebar/NewInUnleash/NewInUnleash.tsx +++ b/frontend/src/component/layout/MainLayout/NavigationSidebar/NewInUnleash/NewInUnleash.tsx @@ -1,4 +1,4 @@ -import { useUiFlag } from 'hooks/useUiFlag'; +import { useUiFlag } from 'hooks/useUiFlag.ts'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import { useLocalStorageState } from 'hooks/useLocalStorageState'; import { @@ -102,7 +102,6 @@ export const NewInUnleash = ({ ); const { isEnterprise } = useUiConfig(); const signalsEnabled = useUiFlag('signals'); - const releasePlansEnabled = useUiFlag('releasePlans'); const items: NewInUnleashItemDetails[] = [ { @@ -175,7 +174,7 @@ export const NewInUnleash = ({ ), onCheckItOut: () => navigate('/release-templates'), docsLink: 'https://docs.getunleash.io/reference/release-templates', - show: isEnterprise() && releasePlansEnabled, + show: isEnterprise(), beta: false, popout: true, }, diff --git a/frontend/src/component/layout/MainLayout/NavigationSidebar/__snapshots__/NavigationSidebar.test.tsx.snap b/frontend/src/component/layout/MainLayout/NavigationSidebar/__snapshots__/NavigationSidebar.test.tsx.snap index 43c893f11d..76d8dfeae1 100644 --- a/frontend/src/component/layout/MainLayout/NavigationSidebar/__snapshots__/NavigationSidebar.test.tsx.snap +++ b/frontend/src/component/layout/MainLayout/NavigationSidebar/__snapshots__/NavigationSidebar.test.tsx.snap @@ -46,6 +46,10 @@ exports[`order of items in navigation > menu for enterprise plan 1`] = ` "icon": "StopRoundedIcon", "text": "Environments", }, + { + "icon": "StopRoundedIcon", + "text": "Release templates", + }, { "icon": "StopRoundedIcon", "text": "Tag types", @@ -168,6 +172,10 @@ exports[`order of items in navigation > menu for pro plan 1`] = ` "icon": "StopRoundedIcon", "text": "Environments", }, + { + "icon": "StopRoundedIcon", + "text": "Release templates", + }, { "icon": "StopRoundedIcon", "text": "Tag types", diff --git a/frontend/src/component/menu/__tests__/__snapshots__/routes.test.tsx.snap b/frontend/src/component/menu/__tests__/__snapshots__/routes.test.tsx.snap index 0e353125b6..2ab1f09d71 100644 --- a/frontend/src/component/menu/__tests__/__snapshots__/routes.test.tsx.snap +++ b/frontend/src/component/menu/__tests__/__snapshots__/routes.test.tsx.snap @@ -282,7 +282,6 @@ exports[`returns all baseRoutes 1`] = ` }, { "component": [Function], - "flag": "releasePlans", "menu": { "main": true, "mode": [ @@ -296,7 +295,6 @@ exports[`returns all baseRoutes 1`] = ` { "component": [Function], "enterprise": true, - "flag": "releasePlans", "menu": { "mode": [ "enterprise", @@ -310,7 +308,6 @@ exports[`returns all baseRoutes 1`] = ` { "component": [Function], "enterprise": true, - "flag": "releasePlans", "menu": { "mode": [ "enterprise", diff --git a/frontend/src/component/menu/routes.ts b/frontend/src/component/menu/routes.ts index c66eb80b1d..c7450a6d35 100644 --- a/frontend/src/component/menu/routes.ts +++ b/frontend/src/component/menu/routes.ts @@ -304,7 +304,6 @@ export const routes: IRoute[] = [ component: ReleaseManagement, type: 'protected', menu: { main: true, mode: ['enterprise'] }, - flag: 'releasePlans', }, { path: '/release-templates/create-template', @@ -313,7 +312,6 @@ export const routes: IRoute[] = [ component: CreateReleasePlanTemplate, type: 'protected', menu: { mode: ['enterprise'] }, - flag: 'releasePlans', enterprise: true, }, { @@ -323,7 +321,6 @@ export const routes: IRoute[] = [ component: EditReleasePlanTemplate, type: 'protected', menu: { mode: ['enterprise'] }, - flag: 'releasePlans', enterprise: true, }, diff --git a/frontend/src/component/releases/ReleaseManagement/ReleaseManagement.tsx b/frontend/src/component/releases/ReleaseManagement/ReleaseManagement.tsx index fec6e412ba..8bb3b738bd 100644 --- a/frontend/src/component/releases/ReleaseManagement/ReleaseManagement.tsx +++ b/frontend/src/component/releases/ReleaseManagement/ReleaseManagement.tsx @@ -9,7 +9,6 @@ import { useNavigate } from 'react-router-dom'; import { useReleasePlanTemplates } from 'hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplates'; import { EmptyTemplatesListMessage } from './EmptyTemplatesListMessage.tsx'; import { ReleasePlanTemplateList } from './ReleasePlanTemplateList.tsx'; -import { useUiFlag } from 'hooks/useUiFlag'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature'; import { RELEASE_PLAN_TEMPLATE_CREATE } from '@server/types/permissions'; @@ -57,11 +56,6 @@ export const ReleaseManagement = () => { const data = useReleasePlanTemplates(); const { isEnterprise } = useUiConfig(); - const releasePlansEnabled = useUiFlag('releasePlans'); - if (!releasePlansEnabled) { - return null; - } - if (!isEnterprise()) { return ; } diff --git a/frontend/src/component/releases/ReleasePlanTemplate/CreateReleasePlanTemplate.tsx b/frontend/src/component/releases/ReleasePlanTemplate/CreateReleasePlanTemplate.tsx index 706279666d..702a5ae8e8 100644 --- a/frontend/src/component/releases/ReleasePlanTemplate/CreateReleasePlanTemplate.tsx +++ b/frontend/src/component/releases/ReleasePlanTemplate/CreateReleasePlanTemplate.tsx @@ -10,7 +10,6 @@ import useReleasePlanTemplatesApi from 'hooks/api/actions/useReleasePlanTemplate import { scrollToTop } from 'component/common/util'; import useToast from 'hooks/useToast'; import { formatUnknownError } from 'utils/formatUnknownError'; -import { useUiFlag } from 'hooks/useUiFlag'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; import { Limit } from 'component/common/Limit/Limit.tsx'; @@ -28,7 +27,6 @@ const StyledCancelButton = styled(Button)(({ theme }) => ({ export const CreateReleasePlanTemplate = () => { const { uiConfig, isEnterprise } = useUiConfig(); - const releasePlansEnabled = useUiFlag('releasePlans'); const { setToastApiError, setToastData } = useToast(); const navigate = useNavigate(); const { createReleasePlanTemplate } = useReleasePlanTemplatesApi(); @@ -92,7 +90,7 @@ export const CreateReleasePlanTemplate = () => { --header 'Content-Type: application/json' \\ --data-raw '${JSON.stringify(getTemplatePayload(), undefined, 2)}'`; - if (!releasePlansEnabled || !isEnterprise()) { + if (!isEnterprise()) { return null; } diff --git a/frontend/src/component/releases/ReleasePlanTemplate/EditReleasePlanTemplate.tsx b/frontend/src/component/releases/ReleasePlanTemplate/EditReleasePlanTemplate.tsx index 483e55279f..b314b97f3a 100644 --- a/frontend/src/component/releases/ReleasePlanTemplate/EditReleasePlanTemplate.tsx +++ b/frontend/src/component/releases/ReleasePlanTemplate/EditReleasePlanTemplate.tsx @@ -1,4 +1,3 @@ -import { useUiFlag } from 'hooks/useUiFlag'; import { usePageTitle } from 'hooks/usePageTitle'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { useReleasePlanTemplate } from 'hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplate'; @@ -26,7 +25,6 @@ const StyledCancelButton = styled(Button)(({ theme }) => ({ export const EditReleasePlanTemplate = () => { const { uiConfig, isEnterprise } = useUiConfig(); - const releasePlansEnabled = useUiFlag('releasePlans'); const templateId = useRequiredPathParam('templateId'); const { template, loading, error, refetch } = useReleasePlanTemplate(templateId); @@ -92,7 +90,7 @@ export const EditReleasePlanTemplate = () => { --header 'Content-Type: application/json' \\ --data-raw '${JSON.stringify(getTemplatePayload(), undefined, 2)}'`; - if (!releasePlansEnabled || !isEnterprise()) { + if (!isEnterprise()) { return null; } diff --git a/frontend/src/hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplate.ts b/frontend/src/hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplate.ts index f3bda9c114..6cddec476a 100644 --- a/frontend/src/hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplate.ts +++ b/frontend/src/hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplate.ts @@ -3,7 +3,6 @@ import useUiConfig from '../useUiConfig/useUiConfig.js'; import { formatApiPath } from 'utils/formatPath'; import handleErrorResponses from '../httpErrorResponseHandler.js'; import { useConditionalSWR } from '../useConditionalSWR/useConditionalSWR.js'; -import { useUiFlag } from 'hooks/useUiFlag'; import type { IReleasePlanTemplate } from 'interfaces/releasePlans'; const path = (templateId: string) => @@ -20,10 +19,9 @@ const DEFAULT_DATA: IReleasePlanTemplate = { export const useReleasePlanTemplate = (templateId: string) => { const { isEnterprise } = useUiConfig(); - const releasePlansEnabled = useUiFlag('releasePlans'); const { data, error, mutate } = useConditionalSWR( - isEnterprise() && releasePlansEnabled, + isEnterprise(), DEFAULT_DATA, formatApiPath(path(templateId)), fetcher, diff --git a/frontend/src/hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplates.ts b/frontend/src/hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplates.ts index 13959e70e6..0e03efa0be 100644 --- a/frontend/src/hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplates.ts +++ b/frontend/src/hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplates.ts @@ -3,7 +3,6 @@ import useUiConfig from '../useUiConfig/useUiConfig.js'; import { formatApiPath } from 'utils/formatPath'; import handleErrorResponses from '../httpErrorResponseHandler.js'; import { useConditionalSWR } from '../useConditionalSWR/useConditionalSWR.js'; -import { useUiFlag } from 'hooks/useUiFlag'; import type { IReleasePlanTemplate } from 'interfaces/releasePlans'; const ENDPOINT = 'api/admin/release-plan-templates'; @@ -12,10 +11,9 @@ const DEFAULT_DATA: IReleasePlanTemplate[] = []; export const useReleasePlanTemplates = () => { const { isEnterprise } = useUiConfig(); - const releasePlansEnabled = useUiFlag('releasePlans'); const { data, error, mutate } = useConditionalSWR( - isEnterprise() && releasePlansEnabled, + isEnterprise(), DEFAULT_DATA, formatApiPath(ENDPOINT), fetcher, diff --git a/frontend/src/hooks/api/getters/useReleasePlans/useReleasePlans.ts b/frontend/src/hooks/api/getters/useReleasePlans/useReleasePlans.ts index af71b768ae..c5e38d7f57 100644 --- a/frontend/src/hooks/api/getters/useReleasePlans/useReleasePlans.ts +++ b/frontend/src/hooks/api/getters/useReleasePlans/useReleasePlans.ts @@ -3,7 +3,6 @@ import useUiConfig from '../useUiConfig/useUiConfig.js'; import { formatApiPath } from 'utils/formatPath'; import handleErrorResponses from '../httpErrorResponseHandler.js'; import { useConditionalSWR } from '../useConditionalSWR/useConditionalSWR.js'; -import { useUiFlag } from 'hooks/useUiFlag'; import type { IReleasePlan } from 'interfaces/releasePlans'; const DEFAULT_DATA: IReleasePlan[] = []; @@ -14,10 +13,9 @@ export const useReleasePlans = ( environment?: string, ) => { const { isEnterprise } = useUiConfig(); - const releasePlansEnabled = useUiFlag('releasePlans'); const { data, error, mutate } = useConditionalSWR( - isEnterprise() && releasePlansEnabled && Boolean(environment), + isEnterprise() && Boolean(environment), DEFAULT_DATA, formatApiPath( `api/admin/projects/${projectId}/features/${featureName}/environments/${environment}/release_plans`, diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts index fad9a1f7f0..db53b93cc2 100644 --- a/frontend/src/interfaces/uiConfig.ts +++ b/frontend/src/interfaces/uiConfig.ts @@ -79,7 +79,6 @@ export type UiFlags = { manyStrategiesPagination?: boolean; enableLegacyVariants?: boolean; flagCreator?: boolean; - releasePlans?: boolean; productivityReportEmail?: boolean; showUserDeviceCount?: boolean; consumptionModel?: boolean; diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts index c106de9df8..134196a3de 100644 --- a/src/lib/types/experimental.ts +++ b/src/lib/types/experimental.ts @@ -41,7 +41,6 @@ export type IFlagKey = | 'projectRoleAssignment' | 'originMiddlewareRequestLogging' | 'webhookDomainLogging' - | 'releasePlans' | 'productivityReportEmail' | 'productivityReportUnsubscribers' | 'showUserDeviceCount' @@ -209,10 +208,6 @@ const flags: IFlags = { process.env.UNLEASH_EXPERIMENT_WEBHOOK_DOMAIN_LOGGING, false, ), - releasePlans: parseEnvVarBoolean( - process.env.UNLEASH_EXPERIMENTAL_RELEASE_PLANS, - false, - ), productivityReportEmail: parseEnvVarBoolean( process.env.UNLEASH_EXPERIMENTAL_PRODUCTIVITY_REPORT_EMAIL, false, diff --git a/src/server-dev.ts b/src/server-dev.ts index 7fc9690898..85354c7307 100644 --- a/src/server-dev.ts +++ b/src/server-dev.ts @@ -46,7 +46,6 @@ process.nextTick(async () => { extendedMetrics: true, originMiddlewareRequestLogging: true, webhookDomainLogging: true, - releasePlans: false, showUserDeviceCount: true, deltaApi: true, uniqueSdkTracking: true,