diff --git a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/EditChange.tsx b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/EditChange.tsx index c8d8b8ddd6..3aa800df6d 100644 --- a/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/EditChange.tsx +++ b/frontend/src/component/changeRequest/ChangeRequest/Changes/Change/EditChange.tsx @@ -50,10 +50,9 @@ export const EditChange = ({ ); const { segments: allSegments } = useSegments(); - const strategySegments = - allSegments?.filter(segment => { - return change.payload.segments?.includes(segment.id); - }) || []; + const strategySegments = (allSegments || []).filter(segment => { + return change.payload.segments?.includes(segment.id); + }); const [segments, setSegments] = useState(strategySegments); diff --git a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyCreate/FeatureStrategyCreate.tsx b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyCreate/FeatureStrategyCreate.tsx index 5958a9a6ff..e047b96589 100644 --- a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyCreate/FeatureStrategyCreate.tsx +++ b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyCreate/FeatureStrategyCreate.tsx @@ -30,14 +30,32 @@ import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useCh import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled'; import { usePendingChangeRequests } from 'hooks/api/getters/usePendingChangeRequests/usePendingChangeRequests'; import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; +import useQueryParams from 'hooks/useQueryParams'; +import useProject from 'hooks/api/getters/useProject/useProject'; +import { useSegments } from 'hooks/api/getters/useSegments/useSegments'; export const FeatureStrategyCreate = () => { const projectId = useRequiredPathParam('projectId'); const featureId = useRequiredPathParam('featureId'); const environmentId = useRequiredQueryParam('environmentId'); const strategyName = useRequiredQueryParam('strategyName'); + const useDefaultStrategy: boolean = JSON.parse( + useQueryParams().get('defaultStrategy') || 'false' + ); + const { project } = useProject(projectId); + + const defaultStrategy = project.environments.find( + env => env.environment === environmentId + )?.defaultStrategy; + + const { segments: allSegments } = useSegments(); + const strategySegments = (allSegments || []).filter(segment => { + return defaultStrategy?.segments?.includes(segment.id); + }); + const [strategy, setStrategy] = useState>({}); - const [segments, setSegments] = useState([]); + + const [segments, setSegments] = useState(strategySegments); const { strategyDefinition } = useStrategy(strategyName); const errors = useFormErrors(); @@ -79,10 +97,12 @@ export const FeatureStrategyCreate = () => { }, [feature.name]); useEffect(() => { - if (strategyDefinition) { + if (useDefaultStrategy) { + setStrategy((defaultStrategy as any) || {}); + } else if (strategyDefinition) { setStrategy(createFeatureStrategy(featureId, strategyDefinition)); } - }, [featureId, strategyDefinition]); + }, [featureId, strategyDefinition, useDefaultStrategy]); const onAddStrategy = async (payload: IFeatureStrategyPayload) => { await addStrategyToFeature( @@ -181,9 +201,14 @@ export const formatCreateStrategyPath = ( projectId: string, featureId: string, environmentId: string, - strategyName: string + strategyName: string, + defaultStrategy: boolean = false ): string => { - const params = new URLSearchParams({ environmentId, strategyName }); + const params = new URLSearchParams({ + environmentId, + strategyName, + defaultStrategy: String(defaultStrategy), + }); return `/projects/${projectId}/features/${featureId}/strategies/create?${params}`; }; diff --git a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenuCard/FeatureStrategyMenuCard.tsx b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenuCard/FeatureStrategyMenuCard.tsx index aae65734f5..1e3455905e 100644 --- a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenuCard/FeatureStrategyMenuCard.tsx +++ b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenuCard/FeatureStrategyMenuCard.tsx @@ -13,6 +13,7 @@ interface IFeatureStrategyMenuCardProps { featureId: string; environmentId: string; strategy: IStrategy; + defaultStrategy?: boolean; } const StyledIcon = styled('div')(({ theme }) => ({ @@ -60,6 +61,7 @@ export const FeatureStrategyMenuCard = ({ featureId, environmentId, strategy, + defaultStrategy, }: IFeatureStrategyMenuCardProps) => { const StrategyIcon = getFeatureStrategyIcon(strategy.name); const strategyName = formatStrategyName(strategy.name); @@ -68,7 +70,8 @@ export const FeatureStrategyMenuCard = ({ projectId, featureId, environmentId, - strategy.name + strategy.name, + defaultStrategy ); return ( diff --git a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenuCards/FeatureStrategyMenuCards.tsx b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenuCards/FeatureStrategyMenuCards.tsx index e58fc6d838..466935cef8 100644 --- a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenuCards/FeatureStrategyMenuCards.tsx +++ b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyMenu/FeatureStrategyMenuCards/FeatureStrategyMenuCards.tsx @@ -1,7 +1,10 @@ -import { useMemo } from 'react'; -import { List, ListItem } from '@mui/material'; +import { List, ListItem, styled, Typography } from '@mui/material'; import { useStrategies } from 'hooks/api/getters/useStrategies/useStrategies'; import { FeatureStrategyMenuCard } from '../FeatureStrategyMenuCard/FeatureStrategyMenuCard'; +import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; +import useProject from 'hooks/api/getters/useProject/useProject'; +import { IStrategy } from 'interfaces/strategy'; +import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; interface IFeatureStrategyMenuCardsProps { projectId: string; @@ -9,20 +12,70 @@ interface IFeatureStrategyMenuCardsProps { environmentId: string; } +const StyledTypography = styled(Typography)(({ theme }) => ({ + fontSize: theme.fontSizes.smallBody, + padding: theme.spacing(1, 2), +})); + export const FeatureStrategyMenuCards = ({ projectId, featureId, environmentId, }: IFeatureStrategyMenuCardsProps) => { const { strategies } = useStrategies(); + const { uiConfig } = useUiConfig(); - const availableStrategies = useMemo(() => { - return strategies.filter(strategy => !strategy.deprecated); - }, [strategies]); + const preDefinedStrategies = strategies.filter( + strategy => !strategy.deprecated && !strategy.editable + ); + const customStrategies = strategies.filter( + strategy => !strategy.deprecated && strategy.editable + ); + + const { project } = useProject(projectId); + + const strategy = project.environments.find( + env => env.environment === environmentId + )?.defaultStrategy; + + const defaultStrategy: IStrategy = { + name: 'flexibleRollout', + displayName: 'Default strategy', + description: + 'This is the default strategy defined for this environment in the project', + parameters: [], + editable: false, + deprecated: false, + }; return ( - {availableStrategies.map(strategy => ( + + + {environmentId} environment default strategy + + + + + + } + /> + + Predefined strategy types + + {preDefinedStrategies.map(strategy => ( ))} + 0} + show={ + <> + + Custom strategies + + {customStrategies.map(strategy => ( + + + + ))} + + } + /> ); };