diff --git a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyEdit/FeatureStrategyEdit.tsx b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyEdit/FeatureStrategyEdit.tsx
index 97346c5b80..43036006f2 100644
--- a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyEdit/FeatureStrategyEdit.tsx
+++ b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyEdit/FeatureStrategyEdit.tsx
@@ -242,6 +242,7 @@ export const createStrategyPayload = (
title: strategy.title,
constraints: strategy.constraints ?? [],
parameters: strategy.parameters ?? {},
+ variants: strategy.variants ?? [],
segments: segments.map(segment => segment.id),
disabled: strategy.disabled ?? false,
});
diff --git a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyForm/FeatureStrategyForm.tsx b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyForm/FeatureStrategyForm.tsx
index c8f518b2f0..cba83a9ece 100644
--- a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyForm/FeatureStrategyForm.tsx
+++ b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyForm/FeatureStrategyForm.tsx
@@ -31,6 +31,7 @@ import { usePendingChangeRequests } from 'hooks/api/getters/usePendingChangeRequ
import { useHasProjectEnvironmentAccess } from 'hooks/useHasAccess';
import { FeatureStrategyTitle } from './FeatureStrategyTitle/FeatureStrategyTitle';
import { FeatureStrategyEnabledDisabled } from './FeatureStrategyEnabledDisabled/FeatureStrategyEnabledDisabled';
+import { StrategyVariants } from 'component/feature/StrategyTypes/StrategyVariants';
interface IFeatureStrategyFormProps {
feature: IFeatureToggle;
@@ -246,6 +247,16 @@ export const FeatureStrategyForm = ({
hasAccess={access}
/>
+
+ }
+ />
+
diff --git a/frontend/src/component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/EnvironmentVariantsModal.tsx b/frontend/src/component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/EnvironmentVariantsModal.tsx
index 8d80af481b..63802b697a 100644
--- a/frontend/src/component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/EnvironmentVariantsModal.tsx
+++ b/frontend/src/component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/EnvironmentVariantsModal.tsx
@@ -390,7 +390,6 @@ export const EnvironmentVariantsModal = ({
)
)
}
- projectId={projectId}
apiPayload={apiPayload}
/>
))}
diff --git a/frontend/src/component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/VariantForm/VariantForm.tsx b/frontend/src/component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/VariantForm/VariantForm.tsx
index 969c541ecb..1e5ac5880e 100644
--- a/frontend/src/component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/VariantForm/VariantForm.tsx
+++ b/frontend/src/component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/VariantForm/VariantForm.tsx
@@ -150,7 +150,6 @@ interface IVariantFormProps {
variants: IFeatureVariantEdit[];
updateVariant: (updatedVariant: IFeatureVariantEdit) => void;
removeVariant: (variantId: string) => void;
- projectId: string;
apiPayload: {
patch: Operation[];
error?: string;
diff --git a/frontend/src/component/feature/StrategyTypes/FlexibleStrategy/FlexibleStrategy.tsx b/frontend/src/component/feature/StrategyTypes/FlexibleStrategy/FlexibleStrategy.tsx
index d4fead7c3f..43659c5ce5 100644
--- a/frontend/src/component/feature/StrategyTypes/FlexibleStrategy/FlexibleStrategy.tsx
+++ b/frontend/src/component/feature/StrategyTypes/FlexibleStrategy/FlexibleStrategy.tsx
@@ -17,8 +17,6 @@ import Loader from '../../../common/Loader/Loader';
import { useEffect, useMemo } from 'react';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { useLocation } from 'react-router';
-import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
-import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
interface IFlexibleStrategyProps {
parameters: IFeatureStrategyParameters;
@@ -35,7 +33,6 @@ const FlexibleStrategy = ({
const projectId = useRequiredPathParam('projectId');
const { defaultStickiness, loading } = useDefaultProjectSettings(projectId);
const { pathname } = useLocation();
- const { uiConfig } = useUiConfig();
const isDefaultStrategyEdit = pathname.includes('default-strategy');
const onUpdate = (field: string) => (newValue: string) => {
@@ -126,34 +123,6 @@ const FlexibleStrategy = ({
onChange={e => onUpdate('groupId')(e.target.value)}
data-testid={FLEXIBLE_STRATEGY_GROUP_ID}
/>
-
-
-
- Variant
-
-
- onUpdate('variant')(e.target.value)
- }
- />
- >
- }
- />
);
diff --git a/frontend/src/component/feature/StrategyTypes/StrategyVariants.tsx b/frontend/src/component/feature/StrategyTypes/StrategyVariants.tsx
new file mode 100644
index 0000000000..29900efdef
--- /dev/null
+++ b/frontend/src/component/feature/StrategyTypes/StrategyVariants.tsx
@@ -0,0 +1,125 @@
+import { VariantForm } from '../FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/VariantForm/VariantForm';
+import { updateWeightEdit } from '../../common/util';
+import React, { FC, useEffect, useState } from 'react';
+import { IFeatureVariantEdit } from '../FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/EnvironmentVariantsModal';
+import PermissionButton from '../../common/PermissionButton/PermissionButton';
+import { UPDATE_FEATURE_ENVIRONMENT_VARIANTS } from '../../providers/AccessProvider/permissions';
+import { v4 as uuidv4 } from 'uuid';
+import { WeightType } from '../../../constants/variantTypes';
+import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
+import { useDefaultProjectSettings } from 'hooks/useDefaultProjectSettings';
+import { styled } from '@mui/material';
+import { useRequiredQueryParam } from 'hooks/useRequiredQueryParam';
+import { IFeatureStrategy } from 'interfaces/strategy';
+
+const StyledVariantForms = styled('div')({
+ display: 'flex',
+ flexDirection: 'column',
+});
+
+export const StrategyVariants: FC<{
+ setStrategy: React.Dispatch<
+ React.SetStateAction>
+ >;
+ strategy: Partial;
+}> = ({ strategy, setStrategy }) => {
+ const projectId = useRequiredPathParam('projectId');
+ const environment = useRequiredQueryParam('environmentId');
+ const [variantsEdit, setVariantsEdit] = useState([]);
+ const [newVariant, setNewVariant] = useState();
+ const { defaultStickiness, loading } = useDefaultProjectSettings(projectId);
+
+ useEffect(() => {
+ setVariantsEdit(
+ (strategy.variants || []).map(variant => ({
+ ...variant,
+ new: false,
+ isValid: true,
+ id: uuidv4(),
+ overrides: [],
+ }))
+ );
+ }, []);
+
+ useEffect(() => {
+ setStrategy(prev => ({
+ ...prev,
+ variants: variantsEdit.map(variant => ({
+ name: variant.name,
+ weight: variant.weight,
+ stickiness: variant.stickiness,
+ payload: variant.payload,
+ weightType: variant.weightType,
+ })),
+ }));
+ }, [JSON.stringify(variantsEdit)]);
+
+ const updateVariant = (updatedVariant: IFeatureVariantEdit, id: string) => {
+ setVariantsEdit(prevVariants =>
+ updateWeightEdit(
+ prevVariants.map(prevVariant =>
+ prevVariant.id === id ? updatedVariant : prevVariant
+ ),
+ 1000
+ )
+ );
+ };
+
+ const addVariant = () => {
+ const id = uuidv4();
+ setVariantsEdit(variantsEdit => [
+ ...variantsEdit,
+ {
+ name: '',
+ weightType: WeightType.VARIABLE,
+ weight: 0,
+ overrides: [],
+ stickiness:
+ variantsEdit?.length > 0
+ ? variantsEdit[0].stickiness
+ : defaultStickiness,
+ new: true,
+ isValid: false,
+ id,
+ },
+ ]);
+ setNewVariant(id);
+ };
+
+ return (
+ <>
+
+ {variantsEdit.map(variant => (
+
+ updateVariant(updatedVariant, variant.id)
+ }
+ removeVariant={() =>
+ setVariantsEdit(variantsEdit =>
+ updateWeightEdit(
+ variantsEdit.filter(
+ v => v.id !== variant.id
+ ),
+ 1000
+ )
+ )
+ }
+ apiPayload={{ patch: [] }}
+ />
+ ))}
+
+
+ Add variant
+
+ >
+ );
+};
diff --git a/frontend/src/interfaces/featureToggle.ts b/frontend/src/interfaces/featureToggle.ts
index affb40cfbd..e38f54ff0e 100644
--- a/frontend/src/interfaces/featureToggle.ts
+++ b/frontend/src/interfaces/featureToggle.ts
@@ -57,6 +57,14 @@ export interface IFeatureVariant {
payload?: IPayload;
}
+export interface IFeatureStrategyVariant {
+ name: string;
+ stickiness: string;
+ weight: number;
+ weightType: string;
+ payload?: IPayload;
+}
+
export interface IOverride {
contextName: string;
values: string[];
diff --git a/frontend/src/interfaces/strategy.ts b/frontend/src/interfaces/strategy.ts
index 3109783efe..67915af1f7 100644
--- a/frontend/src/interfaces/strategy.ts
+++ b/frontend/src/interfaces/strategy.ts
@@ -1,4 +1,5 @@
import { Operator } from 'constants/operators';
+import { IFeatureStrategyVariant } from './featureToggle';
export interface IFeatureStrategy {
id: string;
@@ -7,6 +8,7 @@ export interface IFeatureStrategy {
title?: string;
constraints: IConstraint[];
parameters: IFeatureStrategyParameters;
+ variants?: IFeatureStrategyVariant[];
featureName?: string;
projectId?: string;
environment?: string;
@@ -24,6 +26,7 @@ export interface IFeatureStrategyPayload {
title?: string;
constraints: IConstraint[];
parameters: IFeatureStrategyParameters;
+ variants?: IFeatureStrategyVariant[];
segments?: number[];
disabled?: boolean;
}