1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-06-09 01:17:06 +02:00

chore: remove new strategy configuration flag (#6335)

This commit is contained in:
Mateusz Kwasniewski 2024-02-27 11:23:49 +01:00 committed by GitHub
parent e9603f866b
commit c049374a25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 166 additions and 478 deletions

View File

@ -1,9 +1,9 @@
import React, { FC, useState } from 'react'; import React, { FC, useState } from 'react';
import { import {
ChangeRequestType, ChangeRequestType,
IChange,
IChangeRequestAddStrategy, IChangeRequestAddStrategy,
IChangeRequestUpdateStrategy, IChangeRequestUpdateStrategy,
IChange,
} from 'component/changeRequest/changeRequest.types'; } from 'component/changeRequest/changeRequest.types';
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi'; import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
import useToast from 'hooks/useToast'; import useToast from 'hooks/useToast';
@ -24,8 +24,6 @@ import {
Typography, Typography,
} from '@mui/material'; } from '@mui/material';
import { Delete, Edit, MoreVert } from '@mui/icons-material'; import { Delete, Edit, MoreVert } from '@mui/icons-material';
import { EditChange } from './EditChange';
import { useUiFlag } from 'hooks/useUiFlag';
import { NewEditChange } from './NewEditChange'; import { NewEditChange } from './NewEditChange';
const useShowActions = (changeRequest: ChangeRequestType, change: IChange) => { const useShowActions = (changeRequest: ChangeRequestType, change: IChange) => {
@ -68,7 +66,6 @@ export const ChangeActions: FC<{
const { showDiscard, showEdit } = useShowActions(changeRequest, change); const { showDiscard, showEdit } = useShowActions(changeRequest, change);
const { discardChange } = useChangeRequestApi(); const { discardChange } = useChangeRequestApi();
const { setToastData, setToastApiError } = useToast(); const { setToastData, setToastApiError } = useToast();
const newStrategyConfiguration = useUiFlag('newStrategyConfiguration');
const [editOpen, setEditOpen] = useState(false); const [editOpen, setEditOpen] = useState(false);
@ -152,56 +149,25 @@ export const ChangeActions: FC<{
Edit change Edit change
</Typography> </Typography>
</ListItemText> </ListItemText>
<ConditionallyRender <NewEditChange
condition={newStrategyConfiguration} changeRequestId={changeRequest.id}
show={ featureId={feature}
<NewEditChange change={
changeRequestId={ change as
changeRequest.id | IChangeRequestAddStrategy
} | IChangeRequestUpdateStrategy
featureId={feature}
change={
change as
| IChangeRequestAddStrategy
| IChangeRequestUpdateStrategy
}
environment={
changeRequest.environment
}
open={editOpen}
onSubmit={() => {
setEditOpen(false);
onRefetch?.();
}}
onClose={() => {
setEditOpen(false);
}}
/>
} }
elseShow={ environment={
<EditChange changeRequest.environment
changeRequestId={
changeRequest.id
}
featureId={feature}
change={
change as
| IChangeRequestAddStrategy
| IChangeRequestUpdateStrategy
}
environment={
changeRequest.environment
}
open={editOpen}
onSubmit={() => {
setEditOpen(false);
onRefetch?.();
}}
onClose={() => {
setEditOpen(false);
}}
/>
} }
open={editOpen}
onSubmit={() => {
setEditOpen(false);
onRefetch?.();
}}
onClose={() => {
setEditOpen(false);
}}
/> />
</MenuItem> </MenuItem>
} }

View File

@ -1,5 +1,4 @@
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { FeatureStrategyForm } from 'component/feature/FeatureStrategy/FeatureStrategyForm/FeatureStrategyForm';
import FormTemplate from 'component/common/FormTemplate/FormTemplate'; import FormTemplate from 'component/common/FormTemplate/FormTemplate';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
@ -22,8 +21,6 @@ import {
} from 'component/changeRequest/changeRequest.types'; } from 'component/changeRequest/changeRequest.types';
import { SidebarModal } from 'component/common/SidebarModal/SidebarModal'; import { SidebarModal } from 'component/common/SidebarModal/SidebarModal';
import { useSegments } from 'hooks/api/getters/useSegments/useSegments'; import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
import { useUiFlag } from 'hooks/useUiFlag';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { NewFeatureStrategyForm } from 'component/feature/FeatureStrategy/FeatureStrategyForm/NewFeatureStrategyForm'; import { NewFeatureStrategyForm } from 'component/feature/FeatureStrategy/FeatureStrategyForm/NewFeatureStrategyForm';
import { StrategyVariants } from 'component/feature/StrategyTypes/StrategyVariants'; import { StrategyVariants } from 'component/feature/StrategyTypes/StrategyVariants';
@ -49,7 +46,6 @@ export const EditChange = ({
const projectId = useRequiredPathParam('projectId'); const projectId = useRequiredPathParam('projectId');
const { editChange } = useChangeRequestApi(); const { editChange } = useChangeRequestApi();
const [tab, setTab] = useState(0); const [tab, setTab] = useState(0);
const newStrategyConfiguration = useUiFlag('newStrategyConfiguration');
const [strategy, setStrategy] = useState<Partial<IFeatureStrategy>>( const [strategy, setStrategy] = useState<Partial<IFeatureStrategy>>(
change.payload, change.payload,
@ -152,54 +148,28 @@ export const EditChange = ({
) )
} }
> >
<ConditionallyRender <NewFeatureStrategyForm
condition={newStrategyConfiguration} projectId={projectId}
show={ feature={data}
<NewFeatureStrategyForm strategy={strategy}
projectId={projectId} setStrategy={setStrategy}
feature={data} segments={segments}
setSegments={setSegments}
environmentId={environment}
onSubmit={onInternalSubmit}
onCancel={onClose}
loading={false}
permission={UPDATE_FEATURE_STRATEGY}
errors={errors}
isChangeRequest={isChangeRequestConfigured(environment)}
tab={tab}
setTab={setTab}
StrategyVariants={
<StrategyVariants
strategy={strategy} strategy={strategy}
setStrategy={setStrategy} setStrategy={setStrategy}
segments={segments} environment={environment}
setSegments={setSegments}
environmentId={environment}
onSubmit={onInternalSubmit}
onCancel={onClose}
loading={false}
permission={UPDATE_FEATURE_STRATEGY}
errors={errors}
isChangeRequest={isChangeRequestConfigured(
environment,
)}
tab={tab}
setTab={setTab}
StrategyVariants={
<StrategyVariants
strategy={strategy}
setStrategy={setStrategy}
environment={environment}
projectId={projectId}
/>
}
/>
}
elseShow={
<FeatureStrategyForm
projectId={projectId} projectId={projectId}
feature={data}
strategy={strategy}
setStrategy={setStrategy}
segments={segments}
setSegments={setSegments}
environmentId={environment}
onSubmit={onInternalSubmit}
onCancel={onClose}
loading={false}
permission={UPDATE_FEATURE_STRATEGY}
errors={errors}
isChangeRequest={isChangeRequestConfigured(
environment,
)}
/> />
} }
/> />

View File

@ -1,5 +1,4 @@
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { FeatureStrategyForm } from 'component/feature/FeatureStrategy/FeatureStrategyForm/FeatureStrategyForm';
import FormTemplate from 'component/common/FormTemplate/FormTemplate'; import FormTemplate from 'component/common/FormTemplate/FormTemplate';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
@ -23,8 +22,6 @@ import {
} from 'component/changeRequest/changeRequest.types'; } from 'component/changeRequest/changeRequest.types';
import { SidebarModal } from 'component/common/SidebarModal/SidebarModal'; import { SidebarModal } from 'component/common/SidebarModal/SidebarModal';
import { useSegments } from 'hooks/api/getters/useSegments/useSegments'; import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
import { useUiFlag } from 'hooks/useUiFlag';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { NewFeatureStrategyForm } from 'component/feature/FeatureStrategy/FeatureStrategyForm/NewFeatureStrategyForm'; import { NewFeatureStrategyForm } from 'component/feature/FeatureStrategy/FeatureStrategyForm/NewFeatureStrategyForm';
import { NewStrategyVariants } from 'component/feature/StrategyTypes/NewStrategyVariants'; import { NewStrategyVariants } from 'component/feature/StrategyTypes/NewStrategyVariants';
import { constraintId } from 'component/common/ConstraintAccordion/ConstraintAccordionList/createEmptyConstraint'; import { constraintId } from 'component/common/ConstraintAccordion/ConstraintAccordionList/createEmptyConstraint';
@ -62,7 +59,6 @@ export const NewEditChange = ({
const projectId = useRequiredPathParam('projectId'); const projectId = useRequiredPathParam('projectId');
const { editChange } = useChangeRequestApi(); const { editChange } = useChangeRequestApi();
const [tab, setTab] = useState(0); const [tab, setTab] = useState(0);
const newStrategyConfiguration = useUiFlag('newStrategyConfiguration');
const constraintsWithId = addIdSymbolToConstraints(change.payload); const constraintsWithId = addIdSymbolToConstraints(change.payload);
@ -168,54 +164,28 @@ export const NewEditChange = ({
) )
} }
> >
<ConditionallyRender <NewFeatureStrategyForm
condition={newStrategyConfiguration} projectId={projectId}
show={ feature={data}
<NewFeatureStrategyForm strategy={strategy}
projectId={projectId} setStrategy={setStrategy}
feature={data} segments={segments}
setSegments={setSegments}
environmentId={environment}
onSubmit={onInternalSubmit}
onCancel={onClose}
loading={false}
permission={UPDATE_FEATURE_STRATEGY}
errors={errors}
isChangeRequest={isChangeRequestConfigured(environment)}
tab={tab}
setTab={setTab}
StrategyVariants={
<NewStrategyVariants
strategy={strategy} strategy={strategy}
setStrategy={setStrategy} setStrategy={setStrategy}
segments={segments} environment={environment}
setSegments={setSegments}
environmentId={environment}
onSubmit={onInternalSubmit}
onCancel={onClose}
loading={false}
permission={UPDATE_FEATURE_STRATEGY}
errors={errors}
isChangeRequest={isChangeRequestConfigured(
environment,
)}
tab={tab}
setTab={setTab}
StrategyVariants={
<NewStrategyVariants
strategy={strategy}
setStrategy={setStrategy}
environment={environment}
projectId={projectId}
/>
}
/>
}
elseShow={
<FeatureStrategyForm
projectId={projectId} projectId={projectId}
feature={data}
strategy={strategy}
setStrategy={setStrategy}
segments={segments}
setSegments={setSegments}
environmentId={environment}
onSubmit={onInternalSubmit}
onCancel={onClose}
loading={false}
permission={UPDATE_FEATURE_STRATEGY}
errors={errors}
isChangeRequest={isChangeRequestConfigured(
environment,
)}
/> />
} }
/> />

View File

@ -1,9 +1,13 @@
import { useStyles } from 'component/common/AutocompleteBox/AutocompleteBox.styles'; import { useStyles } from 'component/common/AutocompleteBox/AutocompleteBox.styles';
import { Search, ArrowDropDown, Add } from '@mui/icons-material'; import { Add } from '@mui/icons-material';
import { Autocomplete, styled, InputAdornment, useTheme } from '@mui/material'; import {
Autocomplete,
InputAdornment,
styled,
TextField,
useTheme,
} from '@mui/material';
import { AutocompleteRenderInputParams } from '@mui/material/Autocomplete'; import { AutocompleteRenderInputParams } from '@mui/material/Autocomplete';
import { TextField } from '@mui/material';
import { useUiFlag } from 'hooks/useUiFlag';
import { useState } from 'react'; import { useState } from 'react';
interface IAutocompleteBoxProps { interface IAutocompleteBoxProps {
@ -60,8 +64,6 @@ export const AutocompleteBox = ({
const { classes: styles } = useStyles(); const { classes: styles } = useStyles();
const theme = useTheme(); const theme = useTheme();
const newStrategyConfiguration = useUiFlag('newStrategyConfiguration');
const renderInput = (params: AutocompleteRenderInputParams) => { const renderInput = (params: AutocompleteRenderInputParams) => {
return <TextField {...params} variant='outlined' label={label} />; return <TextField {...params} variant='outlined' label={label} />;
}; };
@ -113,35 +115,13 @@ export const AutocompleteBox = ({
/> />
); );
}; };
if (newStrategyConfiguration) {
return (
<StyledContainer>
<StyledAutocomplete
options={options}
value={value}
onChange={(event, value) => onChange(value || [])}
renderInput={renderCustomInput}
getOptionLabel={(value) => value.label}
disabled={disabled}
size='small'
multiple
/>
</StyledContainer>
);
}
return ( return (
<StyledContainer> <StyledContainer>
<StyledIcon $disabled={Boolean(disabled)} aria-hidden>
<Search />
</StyledIcon>
<StyledAutocomplete <StyledAutocomplete
classes={{ inputRoot: styles.inputRoot }}
options={options} options={options}
value={value} value={value}
popupIcon={<ArrowDropDown titleAccess='Toggle' />}
onChange={(event, value) => onChange(value || [])} onChange={(event, value) => onChange(value || [])}
renderInput={renderInput} renderInput={renderCustomInput}
getOptionLabel={(value) => value.label} getOptionLabel={(value) => value.label}
disabled={disabled} disabled={disabled}
size='small' size='small'

View File

@ -4,11 +4,8 @@ import { Add, HelpOutline } from '@mui/icons-material';
import { IConstraint } from 'interfaces/strategy'; import { IConstraint } from 'interfaces/strategy';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { useUiFlag } from 'hooks/useUiFlag';
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon'; import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
import { import {
ConstraintList,
IConstraintAccordionListRef, IConstraintAccordionListRef,
useConstraintAccordionList, useConstraintAccordionList,
} from 'component/common/ConstraintAccordion/ConstraintAccordionList/ConstraintAccordionList'; } from 'component/common/ConstraintAccordion/ConstraintAccordionList/ConstraintAccordionList';
@ -21,6 +18,7 @@ interface IConstraintAccordionListProps {
/* Add "constraints" title on the top - default `true` */ /* Add "constraints" title on the top - default `true` */
showLabel?: boolean; showLabel?: boolean;
} }
export const constraintAccordionListId = 'constraintAccordionListId'; export const constraintAccordionListId = 'constraintAccordionListId';
const StyledContainer = styled('div')({ const StyledContainer = styled('div')({
@ -72,110 +70,52 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
setConstraints, setConstraints,
ref as RefObject<IConstraintAccordionListRef>, ref as RefObject<IConstraintAccordionListRef>,
); );
const newStrategyConfiguration = useUiFlag('newStrategyConfiguration');
if (context.length === 0) { if (context.length === 0) {
return null; return null;
} }
if (newStrategyConfiguration) {
return (
<StyledContainer id={constraintAccordionListId}>
<ConditionallyRender
condition={Boolean(showCreateButton && onAdd)}
show={
<div>
<StyledHelpIconBox>
<Typography>Constraints</Typography>
<HelpIcon
htmlTooltip
tooltip={
<Box>
<Typography variant='body2'>
Constraints are advanced
targeting rules that you can
use to enable a feature
toggle for a subset of your
users. Read more about
constraints{' '}
<a
href='https://docs.getunleash.io/reference/strategy-constraints'
target='_blank'
rel='noopener noreferrer'
>
here
</a>
</Typography>
</Box>
}
/>
</StyledHelpIconBox>
<NewConstraintAccordionList
ref={ref}
setConstraints={setConstraints}
constraints={constraints}
state={state}
/>
<Button
sx={{ marginTop: '1rem' }}
type='button'
onClick={onAdd}
startIcon={<Add />}
variant='outlined'
color='primary'
data-testid='ADD_CONSTRAINT_BUTTON'
>
Add constraint
</Button>
</div>
}
/>
</StyledContainer>
);
}
return ( return (
<StyledContainer id={constraintAccordionListId}> <StyledContainer id={constraintAccordionListId}>
<ConditionallyRender
condition={
constraints && constraints.length > 0 && showLabel
}
show={
<StyledConstraintLabel>
Constraints
</StyledConstraintLabel>
}
/>
<ConstraintList
ref={ref}
setConstraints={setConstraints}
constraints={constraints}
state={state}
/>
<ConditionallyRender <ConditionallyRender
condition={Boolean(showCreateButton && onAdd)} condition={Boolean(showCreateButton && onAdd)}
show={ show={
<div> <div>
<StyledAddCustomLabel> <StyledHelpIconBox>
<p>Add any number of constraints</p> <Typography>Constraints</Typography>
<StyledHelpWrapper <HelpIcon
title='View constraints documentation' htmlTooltip
arrow tooltip={
> <Box>
<a <Typography variant='body2'>
href={ Constraints are advanced
'https://docs.getunleash.io/reference/strategy-constraints' targeting rules that you can use
} to enable a feature toggle for a
target='_blank' subset of your users. Read more
rel='noopener noreferrer' about constraints{' '}
> <a
<StyledHelp /> href='https://docs.getunleash.io/reference/strategy-constraints'
</a> target='_blank'
</StyledHelpWrapper> rel='noopener noreferrer'
</StyledAddCustomLabel> >
here
</a>
</Typography>
</Box>
}
/>
</StyledHelpIconBox>
<NewConstraintAccordionList
ref={ref}
setConstraints={setConstraints}
constraints={constraints}
state={state}
/>
<Button <Button
sx={{ marginTop: '1rem' }}
type='button' type='button'
onClick={onAdd} onClick={onAdd}
startIcon={<Add />}
variant='outlined' variant='outlined'
color='primary' color='primary'
data-testid='ADD_CONSTRAINT_BUTTON' data-testid='ADD_CONSTRAINT_BUTTON'

View File

@ -1,11 +1,10 @@
import { import {
Box, Box,
FormControlLabel, FormControlLabel,
styled,
Switch, Switch,
Typography, Typography,
styled,
} from '@mui/material'; } from '@mui/material';
import { useUiFlag } from 'hooks/useUiFlag';
import { VFC } from 'react'; import { VFC } from 'react';
interface IFeatureStrategyEnabledDisabledProps { interface IFeatureStrategyEnabledDisabledProps {
@ -25,36 +24,19 @@ const StyledBox = styled(Box)(({ theme }) => ({
export const FeatureStrategyEnabledDisabled: VFC< export const FeatureStrategyEnabledDisabled: VFC<
IFeatureStrategyEnabledDisabledProps IFeatureStrategyEnabledDisabledProps
> = ({ enabled, onToggleEnabled }) => { > = ({ enabled, onToggleEnabled }) => {
const strategyConfigurationEnabled = useUiFlag('newStrategyConfiguration');
if (strategyConfigurationEnabled) {
return (
<StyledBox>
<Typography>Strategy Status</Typography>
<FormControlLabel
control={
<Switch
name='enabled'
onChange={onToggleEnabled}
checked={enabled}
/>
}
label='Enabled'
/>
</StyledBox>
);
}
return ( return (
<FormControlLabel <StyledBox>
control={ <Typography>Strategy Status</Typography>
<Switch <FormControlLabel
name='enabled' control={
onChange={onToggleEnabled} <Switch
checked={enabled} name='enabled'
/> onChange={onToggleEnabled}
} checked={enabled}
label='Enabled &ndash; This strategy will be used when evaluating feature toggles.' />
/> }
label='Enabled'
/>
</StyledBox>
); );
}; };

View File

@ -9,7 +9,6 @@ import { FeatureStrategySegmentList } from 'component/feature/FeatureStrategy/Fe
import { SegmentDocsStrategyWarning } from 'component/segments/SegmentDocs'; import { SegmentDocsStrategyWarning } from 'component/segments/SegmentDocs';
import { useSegmentLimits } from 'hooks/api/getters/useSegmentLimits/useSegmentLimits'; import { useSegmentLimits } from 'hooks/api/getters/useSegmentLimits/useSegmentLimits';
import { Box, Divider, styled, Typography } from '@mui/material'; import { Box, Divider, styled, Typography } from '@mui/material';
import { useUiFlag } from 'hooks/useUiFlag';
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon'; import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
interface IFeatureStrategySegmentProps { interface IFeatureStrategySegmentProps {
@ -37,8 +36,6 @@ export const FeatureStrategySegment = ({
const { segments: allSegments } = useSegments(); const { segments: allSegments } = useSegments();
const { strategySegmentsLimit } = useSegmentLimits(); const { strategySegmentsLimit } = useSegmentLimits();
const newStrategyConfiguration = useUiFlag('newStrategyConfiguration');
const atStrategySegmentsLimit: boolean = Boolean( const atStrategySegmentsLimit: boolean = Boolean(
strategySegmentsLimit && strategySegmentsLimit &&
selectedSegments.length >= strategySegmentsLimit, selectedSegments.length >= strategySegmentsLimit,
@ -70,56 +67,34 @@ export const FeatureStrategySegment = ({
} }
}; };
if (newStrategyConfiguration) {
return (
<>
<StyledHelpIconBox>
<Typography>Segments</Typography>
<HelpIcon
htmlTooltip
tooltip={
<Box>
<Typography variant='body2'>
Segments are reusable sets of constraints
that can be defined once and reused across
feature toggle configurations. You can
create a segment on the global or the
project level. Read more about segments{' '}
<a
href='https://docs.getunleash.io/reference/segments'
target='_blank'
rel='noopener noreferrer'
>
here
</a>
</Typography>
</Box>
}
/>
</StyledHelpIconBox>
{atStrategySegmentsLimit && <SegmentDocsStrategyWarning />}
<AutocompleteBox
label='Select segments'
options={autocompleteOptions}
onChange={onChange}
disabled={atStrategySegmentsLimit}
/>
<FeatureStrategySegmentList
segments={selectedSegments}
setSegments={setSelectedSegments}
/>
</>
);
}
return ( return (
<> <>
<Typography component='h3' sx={{ m: 0 }} variant='h3'> <StyledHelpIconBox>
Segmentation <Typography>Segments</Typography>
</Typography> <HelpIcon
htmlTooltip
tooltip={
<Box>
<Typography variant='body2'>
Segments are reusable sets of constraints that
can be defined once and reused across feature
toggle configurations. You can create a segment
on the global or the project level. Read more
about segments{' '}
<a
href='https://docs.getunleash.io/reference/segments'
target='_blank'
rel='noopener noreferrer'
>
here
</a>
</Typography>
</Box>
}
/>
</StyledHelpIconBox>
{atStrategySegmentsLimit && <SegmentDocsStrategyWarning />} {atStrategySegmentsLimit && <SegmentDocsStrategyWarning />}
<p>Add a predefined segment to constrain this feature toggle:</p>
<AutocompleteBox <AutocompleteBox
label='Select segments' label='Select segments'
options={autocompleteOptions} options={autocompleteOptions}
@ -130,8 +105,6 @@ export const FeatureStrategySegment = ({
segments={selectedSegments} segments={selectedSegments}
setSegments={setSelectedSegments} setSegments={setSelectedSegments}
/> />
<StyledDivider />
</> </>
); );
}; };

View File

@ -3,16 +3,12 @@ import FeatureOverviewEnvironments from './FeatureOverviewEnvironments/FeatureOv
import { Route, Routes, useNavigate } from 'react-router-dom'; import { Route, Routes, useNavigate } from 'react-router-dom';
import { FeatureStrategyCreate } from 'component/feature/FeatureStrategy/FeatureStrategyCreate/FeatureStrategyCreate'; import { FeatureStrategyCreate } from 'component/feature/FeatureStrategy/FeatureStrategyCreate/FeatureStrategyCreate';
import { SidebarModal } from 'component/common/SidebarModal/SidebarModal'; import { SidebarModal } from 'component/common/SidebarModal/SidebarModal';
import { import { formatFeaturePath } from 'component/feature/FeatureStrategy/FeatureStrategyEdit/FeatureStrategyEdit';
FeatureStrategyEdit,
formatFeaturePath,
} from 'component/feature/FeatureStrategy/FeatureStrategyEdit/FeatureStrategyEdit';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { usePageTitle } from 'hooks/usePageTitle'; import { usePageTitle } from 'hooks/usePageTitle';
import { FeatureOverviewSidePanel } from 'component/feature/FeatureView/FeatureOverview/FeatureOverviewSidePanel/FeatureOverviewSidePanel'; import { FeatureOverviewSidePanel } from 'component/feature/FeatureView/FeatureOverview/FeatureOverviewSidePanel/FeatureOverviewSidePanel';
import { useHiddenEnvironments } from 'hooks/useHiddenEnvironments'; import { useHiddenEnvironments } from 'hooks/useHiddenEnvironments';
import { styled } from '@mui/material'; import { styled } from '@mui/material';
import { useUiFlag } from 'hooks/useUiFlag';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { NewFeatureStrategyCreate } from 'component/feature/FeatureStrategy/NewFeatureStrategyCreate/NewFeatureStrategyCreate'; import { NewFeatureStrategyCreate } from 'component/feature/FeatureStrategy/NewFeatureStrategyCreate/NewFeatureStrategyCreate';
import { NewFeatureStrategyEdit } from 'component/feature/FeatureStrategy/NewFeatureStrategyEdit/NewFeatureStrategyEdit'; import { NewFeatureStrategyEdit } from 'component/feature/FeatureStrategy/NewFeatureStrategyEdit/NewFeatureStrategyEdit';
@ -44,8 +40,6 @@ const FeatureOverview = () => {
const onSidebarClose = () => navigate(featurePath); const onSidebarClose = () => navigate(featurePath);
usePageTitle(featureId); usePageTitle(featureId);
const newStrategyConfiguration = useUiFlag('newStrategyConfiguration');
return ( return (
<StyledContainer> <StyledContainer>
<div> <div>
@ -67,11 +61,7 @@ const FeatureOverview = () => {
onClose={onSidebarClose} onClose={onSidebarClose}
open open
> >
<ConditionallyRender <NewFeatureStrategyCreate />
condition={newStrategyConfiguration}
show={<NewFeatureStrategyCreate />}
elseShow={<FeatureStrategyCreate />}
/>
</SidebarModal> </SidebarModal>
} }
/> />
@ -83,11 +73,7 @@ const FeatureOverview = () => {
onClose={onSidebarClose} onClose={onSidebarClose}
open open
> >
<ConditionallyRender <NewFeatureStrategyEdit />
condition={newStrategyConfiguration}
show={<NewFeatureStrategyEdit />}
elseShow={<FeatureStrategyEdit />}
/>
</SidebarModal> </SidebarModal>
} }
/> />

View File

@ -1,4 +1,4 @@
import { Box, Typography, styled } from '@mui/material'; import { Box, styled } from '@mui/material';
import { IFeatureStrategyParameters } from 'interfaces/strategy'; import { IFeatureStrategyParameters } from 'interfaces/strategy';
import RolloutSlider from '../RolloutSlider/RolloutSlider'; import RolloutSlider from '../RolloutSlider/RolloutSlider';
import Input from 'component/common/Input/Input'; import Input from 'component/common/Input/Input';
@ -6,7 +6,6 @@ import {
FLEXIBLE_STRATEGY_GROUP_ID, FLEXIBLE_STRATEGY_GROUP_ID,
FLEXIBLE_STRATEGY_STICKINESS_ID, FLEXIBLE_STRATEGY_STICKINESS_ID,
} from 'utils/testIds'; } from 'utils/testIds';
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
import { import {
parseParameterNumber, parseParameterNumber,
parseParameterString, parseParameterString,
@ -17,7 +16,6 @@ import Loader from '../../../common/Loader/Loader';
import { useEffect, useMemo } from 'react'; import { useEffect, useMemo } from 'react';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { useLocation } from 'react-router'; import { useLocation } from 'react-router';
import { useUiFlag } from 'hooks/useUiFlag';
interface IFlexibleStrategyProps { interface IFlexibleStrategyProps {
parameters: IFeatureStrategyParameters; parameters: IFeatureStrategyParameters;
@ -60,8 +58,6 @@ const FlexibleStrategy = ({
const { defaultStickiness, loading } = useDefaultProjectSettings(projectId); const { defaultStickiness, loading } = useDefaultProjectSettings(projectId);
const { pathname } = useLocation(); const { pathname } = useLocation();
const newStrategyConfiguration = useUiFlag('newStrategyConfiguration');
const isDefaultStrategyEdit = pathname.includes('default-strategy'); const isDefaultStrategyEdit = pathname.includes('default-strategy');
const onUpdate = (field: string) => (newValue: string) => { const onUpdate = (field: string) => (newValue: string) => {
updateParameter(field, newValue); updateParameter(field, newValue);
@ -98,100 +94,37 @@ const FlexibleStrategy = ({
return <Loader />; return <Loader />;
} }
if (newStrategyConfiguration) {
return (
<StyledBox>
<RolloutSlider
name='Rollout'
value={rollout}
disabled={!editable}
onChange={updateRollout}
/>
<StyledOuterBox>
<StyledInnerBox1>
<StickinessSelect
label='Stickiness'
value={stickiness}
editable={editable}
dataTestId={FLEXIBLE_STRATEGY_STICKINESS_ID}
onChange={(e) =>
onUpdate('stickiness')(e.target.value)
}
/>
</StyledInnerBox1>
<StyledInnerBox2>
<Input
label='groupId'
sx={{ width: '100%' }}
id='groupId-input'
value={parseParameterString(parameters.groupId)}
disabled={!editable}
onChange={(e) =>
onUpdate('groupId')(e.target.value)
}
data-testid={FLEXIBLE_STRATEGY_GROUP_ID}
/>
</StyledInnerBox2>
</StyledOuterBox>
</StyledBox>
);
}
return ( return (
<div> <StyledBox>
<RolloutSlider <RolloutSlider
name='Rollout' name='Rollout'
value={rollout} value={rollout}
disabled={!editable} disabled={!editable}
onChange={updateRollout} onChange={updateRollout}
/> />
<StyledOuterBox>
<br /> <StyledInnerBox1>
<div> <StickinessSelect
<Typography label='Stickiness'
variant='subtitle2' value={stickiness}
style={{ editable={editable}
marginBottom: '1rem', dataTestId={FLEXIBLE_STRATEGY_STICKINESS_ID}
display: 'flex', onChange={(e) => onUpdate('stickiness')(e.target.value)}
gap: '1ch', />
}} </StyledInnerBox1>
component='h2' <StyledInnerBox2>
> <Input
Stickiness label='groupId'
<HelpIcon tooltip='Stickiness defines what parameter should be used to ensure that your users get consistency in features. By default unleash will use the first value present in the context in the order of userId, sessionId and random.' /> sx={{ width: '100%' }}
</Typography> id='groupId-input'
<StickinessSelect value={parseParameterString(parameters.groupId)}
label='Stickiness' disabled={!editable}
value={stickiness} onChange={(e) => onUpdate('groupId')(e.target.value)}
editable={editable} data-testid={FLEXIBLE_STRATEGY_GROUP_ID}
dataTestId={FLEXIBLE_STRATEGY_STICKINESS_ID} />
onChange={(e) => onUpdate('stickiness')(e.target.value)} </StyledInnerBox2>
/> </StyledOuterBox>
&nbsp; </StyledBox>
<br />
<br />
<Typography
variant='subtitle2'
style={{
marginBottom: '1rem',
display: 'flex',
gap: '1ch',
}}
component='h2'
>
GroupId
<HelpIcon tooltip='GroupId is used to ensure that different toggles will hash differently for the same user. The groupId defaults to feature toggle name, but you can override it to correlate rollout of multiple feature toggles.' />
</Typography>
<Input
label='groupId'
id='groupId-input'
value={parseParameterString(parameters.groupId)}
disabled={!editable}
onChange={(e) => onUpdate('groupId')(e.target.value)}
data-testid={FLEXIBLE_STRATEGY_GROUP_ID}
/>
</div>
</div>
); );
}; };

View File

@ -1,7 +1,6 @@
import Select from 'component/common/select'; import Select from 'component/common/select';
import { SelectChangeEvent, useTheme } from '@mui/material'; import { SelectChangeEvent, useTheme } from '@mui/material';
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext'; import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
import { useUiFlag } from 'hooks/useUiFlag';
type OptionType = { key: string; label: string }; type OptionType = { key: string; label: string };
@ -23,7 +22,6 @@ export const StickinessSelect = ({
dataTestId, dataTestId,
}: IStickinessSelectProps) => { }: IStickinessSelectProps) => {
const { context } = useUnleashContext(); const { context } = useUnleashContext();
const newStrategyConfiguration = useUiFlag('newStrategyConfiguration');
const theme = useTheme(); const theme = useTheme();
const resolveStickinessOptions = () => { const resolveStickinessOptions = () => {
@ -53,9 +51,6 @@ export const StickinessSelect = ({
return options; return options;
}; };
// newStrategyConfiguration - Temporary check for backwards compatibility
const formControlStyles = newStrategyConfiguration ? { width: '100%' } : {};
const stickinessOptions = resolveStickinessOptions(); const stickinessOptions = resolveStickinessOptions();
return ( return (
<Select <Select
@ -71,7 +66,7 @@ export const StickinessSelect = ({
minWidth: '100%', minWidth: '100%',
marginBottom: theme.spacing(2), marginBottom: theme.spacing(2),
}} }}
formControlStyles={formControlStyles} formControlStyles={{ width: '100%' }}
/> />
); );
}; };

View File

@ -129,7 +129,6 @@ exports[`should create default config 1`] = `
}, },
}, },
"migrationLock": true, "migrationLock": true,
"newStrategyConfiguration": false,
"newStrategyConfigurationFeedback": false, "newStrategyConfigurationFeedback": false,
"personalAccessTokensKillSwitch": false, "personalAccessTokensKillSwitch": false,
"proPlanAutoCharge": false, "proPlanAutoCharge": false,

View File

@ -28,7 +28,6 @@ export type IFlagKey =
| 'disableMetrics' | 'disableMetrics'
| 'scheduledConfigurationChanges' | 'scheduledConfigurationChanges'
| 'stripClientHeadersOn304' | 'stripClientHeadersOn304'
| 'newStrategyConfiguration'
| 'stripHeadersOnAPI' | 'stripHeadersOnAPI'
| 'incomingWebhooks' | 'incomingWebhooks'
| 'automatedActions' | 'automatedActions'
@ -139,10 +138,6 @@ const flags: IFlags = {
.UNLEASH_EXPERIMENTAL_DETECT_SEGMENT_USAGE_IN_CHANGE_REQUESTS, .UNLEASH_EXPERIMENTAL_DETECT_SEGMENT_USAGE_IN_CHANGE_REQUESTS,
false, false,
), ),
newStrategyConfiguration: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_NEW_STRATEGY_CONFIGURATION,
false,
),
incomingWebhooks: parseEnvVarBoolean( incomingWebhooks: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_INCOMING_WEBHOOKS, process.env.UNLEASH_EXPERIMENTAL_INCOMING_WEBHOOKS,
false, false,

View File

@ -41,7 +41,6 @@ process.nextTick(async () => {
anonymiseEventLog: false, anonymiseEventLog: false,
responseTimeWithAppNameKillSwitch: false, responseTimeWithAppNameKillSwitch: false,
stripClientHeadersOn304: true, stripClientHeadersOn304: true,
newStrategyConfiguration: true,
stripHeadersOnAPI: true, stripHeadersOnAPI: true,
celebrateUnleash: true, celebrateUnleash: true,
increaseUnleashWidth: true, increaseUnleashWidth: true,