mirror of
https://github.com/Unleash/unleash.git
synced 2025-09-01 13:47:27 +02:00
AI flag removal
This commit is contained in:
parent
6d7a344ca3
commit
dbc515a286
@ -8,9 +8,9 @@ import type {
|
|||||||
} from 'component/changeRequest/changeRequest.types';
|
} from 'component/changeRequest/changeRequest.types';
|
||||||
import { useSegment } from 'hooks/api/getters/useSegment/useSegment';
|
import { useSegment } from 'hooks/api/getters/useSegment/useSegment';
|
||||||
import { SegmentDiff, SegmentTooltipLink } from '../../SegmentTooltipLink.tsx';
|
import { SegmentDiff, SegmentTooltipLink } from '../../SegmentTooltipLink.tsx';
|
||||||
import { ConstraintAccordionList } from 'component/common/LegacyConstraintAccordion/ConstraintAccordionList/ConstraintAccordionList';
|
|
||||||
import { ViewableConstraintsList } from 'component/common/NewConstraintAccordion/ConstraintsList/ViewableConstraintsList';
|
import { ViewableConstraintsList } from 'component/common/NewConstraintAccordion/ConstraintsList/ViewableConstraintsList';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
import { ChangeOverwriteWarning } from './ChangeOverwriteWarning/ChangeOverwriteWarning.tsx';
|
import { ChangeOverwriteWarning } from './ChangeOverwriteWarning/ChangeOverwriteWarning.tsx';
|
||||||
|
|
||||||
const ChangeItemCreateEditWrapper = styled(Box)(({ theme }) => ({
|
const ChangeItemCreateEditWrapper = styled(Box)(({ theme }) => ({
|
||||||
@ -67,7 +67,6 @@ export const SegmentChangeDetails: FC<{
|
|||||||
: currentSegment?.name;
|
: currentSegment?.name;
|
||||||
const referenceSegment =
|
const referenceSegment =
|
||||||
changeRequestState === 'Applied' ? snapshotSegment : currentSegment;
|
changeRequestState === 'Applied' ? snapshotSegment : currentSegment;
|
||||||
const addEditStrategy = useUiFlag('addEditStrategy');
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SegmentContainer conflict={change.conflict}>
|
<SegmentContainer conflict={change.conflict}>
|
||||||
@ -116,16 +115,9 @@ export const SegmentChangeDetails: FC<{
|
|||||||
</ChangeItemInfo>
|
</ChangeItemInfo>
|
||||||
<div>{actions}</div>
|
<div>{actions}</div>
|
||||||
</ChangeItemCreateEditWrapper>
|
</ChangeItemCreateEditWrapper>
|
||||||
{addEditStrategy ? (
|
<ViewableConstraintsList
|
||||||
<ViewableConstraintsList
|
constraints={change.payload.constraints}
|
||||||
constraints={change.payload.constraints}
|
/>
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<ConstraintAccordionList
|
|
||||||
constraints={change.payload.constraints}
|
|
||||||
showLabel={false}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</SegmentContainer>
|
</SegmentContainer>
|
||||||
|
@ -3,8 +3,6 @@ import { Chip, styled } from '@mui/material';
|
|||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
||||||
import { ConstraintValueSearch as NewConstraintValueSearch } from 'component/feature/FeatureStrategy/FeatureStrategyConstraints/EditableConstraint/ConstraintValueSearch';
|
import { ConstraintValueSearch as NewConstraintValueSearch } from 'component/feature/FeatureStrategy/FeatureStrategyConstraints/EditableConstraint/ConstraintValueSearch';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
import { ConstraintValueSearch } from 'component/common/NewConstraintAccordion/ConstraintValueSearch/ConstraintValueSearch';
|
|
||||||
|
|
||||||
interface IMultipleValuesProps {
|
interface IMultipleValuesProps {
|
||||||
values: string[] | undefined;
|
values: string[] | undefined;
|
||||||
@ -25,7 +23,6 @@ const SearchWrapper = styled('div')(({ theme }) => ({
|
|||||||
|
|
||||||
export const MultipleValues = ({ values }: IMultipleValuesProps) => {
|
export const MultipleValues = ({ values }: IMultipleValuesProps) => {
|
||||||
const [filter, setFilter] = useState('');
|
const [filter, setFilter] = useState('');
|
||||||
const useNewSearchComponent = useUiFlag('addEditStrategy');
|
|
||||||
|
|
||||||
if (!values || values.length === 0) return null;
|
if (!values || values.length === 0) return null;
|
||||||
|
|
||||||
@ -34,19 +31,12 @@ export const MultipleValues = ({ values }: IMultipleValuesProps) => {
|
|||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={values.length > 20}
|
condition={values.length > 20}
|
||||||
show={
|
show={
|
||||||
useNewSearchComponent ? (
|
<SearchWrapper>
|
||||||
<SearchWrapper>
|
<NewConstraintValueSearch
|
||||||
<NewConstraintValueSearch
|
|
||||||
filter={filter}
|
|
||||||
setFilter={setFilter}
|
|
||||||
/>
|
|
||||||
</SearchWrapper>
|
|
||||||
) : (
|
|
||||||
<ConstraintValueSearch
|
|
||||||
filter={filter}
|
filter={filter}
|
||||||
setFilter={setFilter}
|
setFilter={setFilter}
|
||||||
/>
|
/>
|
||||||
)
|
</SearchWrapper>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{values
|
{values
|
||||||
|
@ -6,9 +6,7 @@ import produce from 'immer';
|
|||||||
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
|
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
|
||||||
import type { IUseWeakMap } from 'hooks/useWeakMap';
|
import type { IUseWeakMap } from 'hooks/useWeakMap';
|
||||||
import { constraintId } from 'component/common/LegacyConstraintAccordion/ConstraintAccordionList/createEmptyConstraint';
|
import { constraintId } from 'component/common/LegacyConstraintAccordion/ConstraintAccordionList/createEmptyConstraint';
|
||||||
import { NewConstraintAccordion } from 'component/common/NewConstraintAccordion/NewConstraintAccordion';
|
|
||||||
import { ConstraintsList } from 'component/common/ConstraintsList/ConstraintsList';
|
import { ConstraintsList } from 'component/common/ConstraintsList/ConstraintsList';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
import { ConstraintAccordionView } from 'component/common/NewConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView';
|
import { ConstraintAccordionView } from 'component/common/NewConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView';
|
||||||
import { EditableConstraint } from 'component/feature/FeatureStrategy/FeatureStrategyConstraints/EditableConstraint/EditableConstraint';
|
import { EditableConstraint } from 'component/feature/FeatureStrategy/FeatureStrategyConstraints/EditableConstraint/EditableConstraint';
|
||||||
|
|
||||||
@ -52,7 +50,6 @@ export const NewConstraintAccordionList = forwardRef<
|
|||||||
IConstraintList
|
IConstraintList
|
||||||
>(({ constraints, setConstraints, state }, ref) => {
|
>(({ constraints, setConstraints, state }, ref) => {
|
||||||
const { context } = useUnleashContext();
|
const { context } = useUnleashContext();
|
||||||
const addEditStrategy = useUiFlag('addEditStrategy');
|
|
||||||
|
|
||||||
const onEdit =
|
const onEdit =
|
||||||
setConstraints &&
|
setConstraints &&
|
||||||
@ -113,34 +110,20 @@ export const NewConstraintAccordionList = forwardRef<
|
|||||||
<StyledContainer id={constraintAccordionListId}>
|
<StyledContainer id={constraintAccordionListId}>
|
||||||
<ConstraintsList>
|
<ConstraintsList>
|
||||||
{constraints.map((constraint, index) =>
|
{constraints.map((constraint, index) =>
|
||||||
addEditStrategy ? (
|
state.get(constraint)?.editing &&
|
||||||
state.get(constraint)?.editing &&
|
Boolean(setConstraints) ? (
|
||||||
Boolean(setConstraints) ? (
|
<EditableConstraint
|
||||||
<EditableConstraint
|
key={constraint[constraintId]}
|
||||||
key={constraint[constraintId]}
|
constraint={constraint}
|
||||||
constraint={constraint}
|
// @ts-ignore todo: find a better way to do this
|
||||||
// @ts-ignore todo: find a better way to do this
|
onDelete={() => onRemove(index)}
|
||||||
onDelete={() => onRemove(index)}
|
// @ts-ignore
|
||||||
// @ts-ignore
|
onUpdate={onAutoSave(constraintId)}
|
||||||
onUpdate={onAutoSave(constraintId)}
|
/>
|
||||||
/>
|
) : (
|
||||||
) : (
|
<ConstraintAccordionView
|
||||||
<ConstraintAccordionView
|
|
||||||
key={constraint[constraintId]}
|
|
||||||
constraint={constraint}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
<NewConstraintAccordion
|
|
||||||
key={constraint[constraintId]}
|
key={constraint[constraintId]}
|
||||||
constraint={constraint}
|
constraint={constraint}
|
||||||
onEdit={onEdit?.bind(null, constraint)}
|
|
||||||
onCancel={onCancel.bind(null, index)}
|
|
||||||
onDelete={onRemove?.bind(null, index)}
|
|
||||||
onSave={onSave?.bind(null, index)}
|
|
||||||
onAutoSave={onAutoSave?.(constraint[constraintId])}
|
|
||||||
editing={Boolean(state.get(constraint)?.editing)}
|
|
||||||
compact
|
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
|
@ -10,11 +10,9 @@ import {
|
|||||||
type IConstraintAccordionListRef,
|
type IConstraintAccordionListRef,
|
||||||
useConstraintAccordionList,
|
useConstraintAccordionList,
|
||||||
} from 'component/common/LegacyConstraintAccordion/ConstraintAccordionList/ConstraintAccordionList';
|
} from 'component/common/LegacyConstraintAccordion/ConstraintAccordionList/ConstraintAccordionList';
|
||||||
import { NewConstraintAccordionList } from 'component/common/NewConstraintAccordion/NewConstraintAccordionList/NewConstraintAccordionList';
|
|
||||||
import { EditableConstraintsList } from 'component/common/NewConstraintAccordion/ConstraintsList/EditableConstraintsList';
|
import { EditableConstraintsList } from 'component/common/NewConstraintAccordion/ConstraintsList/EditableConstraintsList';
|
||||||
import { Limit } from 'component/common/Limit/Limit';
|
import { Limit } from 'component/common/Limit/Limit';
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
import { RecentlyUsedConstraints } from '../RecentlyUsedConstraints/RecentlyUsedConstraints.tsx';
|
import { RecentlyUsedConstraints } from '../RecentlyUsedConstraints/RecentlyUsedConstraints.tsx';
|
||||||
|
|
||||||
interface IConstraintAccordionListProps {
|
interface IConstraintAccordionListProps {
|
||||||
@ -58,7 +56,6 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
|
|||||||
ref as RefObject<IConstraintAccordionListRef>,
|
ref as RefObject<IConstraintAccordionListRef>,
|
||||||
);
|
);
|
||||||
const { limit, limitReached } = useConstraintLimit(constraints.length);
|
const { limit, limitReached } = useConstraintLimit(constraints.length);
|
||||||
const addEditStrategy = useUiFlag('addEditStrategy');
|
|
||||||
|
|
||||||
if (context.length === 0) {
|
if (context.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
@ -93,22 +90,13 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</StyledHelpIconBox>
|
</StyledHelpIconBox>
|
||||||
{addEditStrategy ? (
|
{setConstraints ? (
|
||||||
setConstraints ? (
|
<EditableConstraintsList
|
||||||
<EditableConstraintsList
|
|
||||||
ref={ref}
|
|
||||||
setConstraints={setConstraints}
|
|
||||||
constraints={constraints}
|
|
||||||
/>
|
|
||||||
) : null
|
|
||||||
) : (
|
|
||||||
<NewConstraintAccordionList
|
|
||||||
ref={ref}
|
ref={ref}
|
||||||
setConstraints={setConstraints}
|
setConstraints={setConstraints}
|
||||||
constraints={constraints}
|
constraints={constraints}
|
||||||
state={state}
|
|
||||||
/>
|
/>
|
||||||
)}
|
) : null}
|
||||||
<Box
|
<Box
|
||||||
sx={(theme) => ({
|
sx={(theme) => ({
|
||||||
marginTop: theme.spacing(2),
|
marginTop: theme.spacing(2),
|
||||||
@ -134,14 +122,9 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
|
|||||||
>
|
>
|
||||||
Add constraint
|
Add constraint
|
||||||
</Button>
|
</Button>
|
||||||
<ConditionallyRender
|
<RecentlyUsedConstraints
|
||||||
condition={Boolean(addEditStrategy)}
|
setConstraints={setConstraints}
|
||||||
show={
|
constraints={constraints}
|
||||||
<RecentlyUsedConstraints
|
|
||||||
setConstraints={setConstraints}
|
|
||||||
constraints={constraints}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,6 @@ export const setupUiConfigEndpoint = () => {
|
|||||||
environment: 'enterprise',
|
environment: 'enterprise',
|
||||||
flags: {
|
flags: {
|
||||||
newStrategyConfiguration: true,
|
newStrategyConfiguration: true,
|
||||||
addEditStrategy: true,
|
|
||||||
},
|
},
|
||||||
resourceLimits: {
|
resourceLimits: {
|
||||||
featureEnvironmentStrategies: 2,
|
featureEnvironmentStrategies: 2,
|
||||||
|
@ -45,10 +45,8 @@ import { FeatureStrategyEnabledDisabled } from './FeatureStrategyEnabledDisabled
|
|||||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||||
import { BuiltInStrategies, formatStrategyName } from 'utils/strategyNames';
|
import { BuiltInStrategies, formatStrategyName } from 'utils/strategyNames';
|
||||||
import { Badge } from 'component/common/Badge/Badge';
|
import { Badge } from 'component/common/Badge/Badge';
|
||||||
import EnvironmentIcon from 'component/common/EnvironmentIcon/EnvironmentIcon';
|
|
||||||
import { UpgradeChangeRequests } from '../../FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/UpgradeChangeRequests/UpgradeChangeRequests.tsx';
|
import { UpgradeChangeRequests } from '../../FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/UpgradeChangeRequests/UpgradeChangeRequests.tsx';
|
||||||
import { ConstraintSeparator } from 'component/common/ConstraintsList/ConstraintSeparator/ConstraintSeparator';
|
import { ConstraintSeparator } from 'component/common/ConstraintsList/ConstraintSeparator/ConstraintSeparator';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag.ts';
|
|
||||||
|
|
||||||
interface IFeatureStrategyFormProps {
|
interface IFeatureStrategyFormProps {
|
||||||
feature: IFeatureToggle;
|
feature: IFeatureToggle;
|
||||||
@ -211,7 +209,6 @@ export const FeatureStrategyForm = ({
|
|||||||
environmentId,
|
environmentId,
|
||||||
);
|
);
|
||||||
const { strategyDefinition } = useStrategy(strategy?.name);
|
const { strategyDefinition } = useStrategy(strategy?.name);
|
||||||
const addEditStrategy = useUiFlag('addEditStrategy');
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
trackEvent('new-strategy-form', {
|
trackEvent('new-strategy-form', {
|
||||||
@ -350,35 +347,7 @@ export const FeatureStrategyForm = ({
|
|||||||
<StyledHeaderBox>
|
<StyledHeaderBox>
|
||||||
<StyledTitle>
|
<StyledTitle>
|
||||||
{formatStrategyName(strategy.name || '')}
|
{formatStrategyName(strategy.name || '')}
|
||||||
<ConditionallyRender
|
|
||||||
condition={
|
|
||||||
!addEditStrategy &&
|
|
||||||
strategy.name === 'flexibleRollout'
|
|
||||||
}
|
|
||||||
show={
|
|
||||||
<Badge color='success' sx={{ marginLeft: '1rem' }}>
|
|
||||||
{strategy.parameters?.rollout}%
|
|
||||||
</Badge>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</StyledTitle>
|
</StyledTitle>
|
||||||
{foundEnvironment && !addEditStrategy ? (
|
|
||||||
<StyledEnvironmentBox>
|
|
||||||
<EnvironmentTypographyHeader>
|
|
||||||
Environment:
|
|
||||||
</EnvironmentTypographyHeader>
|
|
||||||
<EnvironmentIconBox>
|
|
||||||
<EnvironmentIcon
|
|
||||||
enabled={foundEnvironment.enabled}
|
|
||||||
/>{' '}
|
|
||||||
<EnvironmentTypography
|
|
||||||
enabled={foundEnvironment.enabled}
|
|
||||||
>
|
|
||||||
{foundEnvironment.name}
|
|
||||||
</EnvironmentTypography>
|
|
||||||
</EnvironmentIconBox>
|
|
||||||
</StyledEnvironmentBox>
|
|
||||||
) : null}
|
|
||||||
</StyledHeaderBox>
|
</StyledHeaderBox>
|
||||||
|
|
||||||
<StyledAlertBox>
|
<StyledAlertBox>
|
||||||
|
@ -10,7 +10,7 @@ import { SegmentDocsStrategyWarning } from 'component/segments/SegmentDocs';
|
|||||||
import { useSegmentLimits } from 'hooks/api/getters/useSegmentLimits/useSegmentLimits';
|
import { useSegmentLimits } from 'hooks/api/getters/useSegmentLimits/useSegmentLimits';
|
||||||
import { Box, styled, Typography } from '@mui/material';
|
import { Box, styled, Typography } from '@mui/material';
|
||||||
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
|
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
import { RecentlyUsedSegments } from './RecentlyUsedSegments/RecentlyUsedSegments.tsx';
|
import { RecentlyUsedSegments } from './RecentlyUsedSegments/RecentlyUsedSegments.tsx';
|
||||||
|
|
||||||
interface IFeatureStrategySegmentProps {
|
interface IFeatureStrategySegmentProps {
|
||||||
@ -31,7 +31,6 @@ export const FeatureStrategySegment = ({
|
|||||||
setSegments: setSelectedSegments,
|
setSegments: setSelectedSegments,
|
||||||
projectId,
|
projectId,
|
||||||
}: IFeatureStrategySegmentProps) => {
|
}: IFeatureStrategySegmentProps) => {
|
||||||
const addEditStrategy = useUiFlag('addEditStrategy');
|
|
||||||
const { segments: allSegments } = useSegments();
|
const { segments: allSegments } = useSegments();
|
||||||
const { strategySegmentsLimit } = useSegmentLimits();
|
const { strategySegmentsLimit } = useSegmentLimits();
|
||||||
|
|
||||||
@ -99,7 +98,7 @@ export const FeatureStrategySegment = ({
|
|||||||
options={autocompleteOptions}
|
options={autocompleteOptions}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
disabled={atStrategySegmentsLimit}
|
disabled={atStrategySegmentsLimit}
|
||||||
icon={addEditStrategy ? null : undefined}
|
icon={null}
|
||||||
width={'175px'}
|
width={'175px'}
|
||||||
/>
|
/>
|
||||||
<FeatureStrategySegmentList
|
<FeatureStrategySegmentList
|
||||||
|
@ -3,7 +3,6 @@ import { useRecentlyUsedSegments } from './useRecentlyUsedSegments.ts';
|
|||||||
import type { ISegment } from 'interfaces/segment';
|
import type { ISegment } from 'interfaces/segment';
|
||||||
import { RecentlyUsedSegmentChip } from './RecentlyUsedSegmentChip.tsx';
|
import { RecentlyUsedSegmentChip } from './RecentlyUsedSegmentChip.tsx';
|
||||||
import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
|
import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
type RecentlyUsedSegmentsProps = {
|
type RecentlyUsedSegmentsProps = {
|
||||||
setSegments?: React.Dispatch<React.SetStateAction<ISegment[]>>;
|
setSegments?: React.Dispatch<React.SetStateAction<ISegment[]>>;
|
||||||
@ -32,14 +31,7 @@ export const RecentlyUsedSegments = ({
|
|||||||
}: RecentlyUsedSegmentsProps) => {
|
}: RecentlyUsedSegmentsProps) => {
|
||||||
const { items: recentlyUsedSegmentIds } = useRecentlyUsedSegments();
|
const { items: recentlyUsedSegmentIds } = useRecentlyUsedSegments();
|
||||||
const { segments: allSegments } = useSegments();
|
const { segments: allSegments } = useSegments();
|
||||||
const addEditStrategyEnabled = useUiFlag('addEditStrategy');
|
if (recentlyUsedSegmentIds.length === 0 || !setSegments || !allSegments) {
|
||||||
|
|
||||||
if (
|
|
||||||
!addEditStrategyEnabled ||
|
|
||||||
recentlyUsedSegmentIds.length === 0 ||
|
|
||||||
!setSegments ||
|
|
||||||
!allSegments
|
|
||||||
) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import RolloutSlider from './RolloutSlider.tsx';
|
import RolloutSlider from './RolloutSlider.tsx';
|
||||||
import LegacyRolloutSlider from './LegacyRolloutSlider.tsx';
|
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
interface IRolloutSliderProps {
|
interface IRolloutSliderProps {
|
||||||
name: string;
|
name: string;
|
||||||
@ -12,13 +10,7 @@ interface IRolloutSliderProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ConditionalRolloutSlider = (props: IRolloutSliderProps) => {
|
const ConditionalRolloutSlider = (props: IRolloutSliderProps) => {
|
||||||
const addEditStrategy = useUiFlag('addEditStrategy');
|
return <RolloutSlider {...props} />;
|
||||||
|
|
||||||
if (addEditStrategy) {
|
|
||||||
return <RolloutSlider {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <LegacyRolloutSlider {...props} />;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ConditionalRolloutSlider;
|
export default ConditionalRolloutSlider;
|
||||||
|
@ -1,162 +0,0 @@
|
|||||||
import { makeStyles, withStyles } from 'tss-react/mui';
|
|
||||||
import { Slider, Typography, Box, styled } from '@mui/material';
|
|
||||||
import { ROLLOUT_SLIDER_ID } from 'utils/testIds';
|
|
||||||
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
|
|
||||||
|
|
||||||
const StyledSlider = withStyles(Slider, (theme) => ({
|
|
||||||
root: {
|
|
||||||
height: 8,
|
|
||||||
},
|
|
||||||
thumb: {
|
|
||||||
height: 24,
|
|
||||||
width: 24,
|
|
||||||
backgroundColor: theme.palette.background.paper,
|
|
||||||
border: '2px solid currentColor',
|
|
||||||
},
|
|
||||||
active: {},
|
|
||||||
valueLabel: {},
|
|
||||||
track: {
|
|
||||||
height: 8,
|
|
||||||
borderRadius: theme.shape.borderRadius,
|
|
||||||
},
|
|
||||||
rail: {
|
|
||||||
height: 8,
|
|
||||||
borderRadius: theme.shape.borderRadius,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
const StyledHeader = styled(Typography)(({ theme }) => ({
|
|
||||||
marginBottom: theme.spacing(1),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const StyledSubheader = styled(Typography)(({ theme }) => ({
|
|
||||||
marginBottom: theme.spacing(1),
|
|
||||||
marginTop: theme.spacing(1),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const StyledBox = styled(Box)(({ theme }) => ({
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginBottom: theme.spacing(1),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const useStyles = makeStyles()((theme) => ({
|
|
||||||
slider: {
|
|
||||||
width: '100%',
|
|
||||||
maxWidth: '100%',
|
|
||||||
},
|
|
||||||
margin: {
|
|
||||||
height: theme.spacing(3),
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
const marks = [
|
|
||||||
{
|
|
||||||
value: 0,
|
|
||||||
label: '0%',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 25,
|
|
||||||
label: '25%',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 50,
|
|
||||||
label: '50%',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 75,
|
|
||||||
label: '75%',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 100,
|
|
||||||
label: '100%',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
interface IRolloutSliderProps {
|
|
||||||
name: string;
|
|
||||||
minLabel?: string;
|
|
||||||
maxLabel?: string;
|
|
||||||
value: number;
|
|
||||||
onChange: (e: Event, newValue: number | number[]) => void;
|
|
||||||
disabled?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const LegacyRolloutSlider = ({
|
|
||||||
name,
|
|
||||||
value,
|
|
||||||
onChange,
|
|
||||||
disabled = false,
|
|
||||||
}: IRolloutSliderProps) => {
|
|
||||||
const { classes } = useStyles();
|
|
||||||
|
|
||||||
const valuetext = (value: number) => `${value}%`;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={classes.slider}>
|
|
||||||
<StyledBox>
|
|
||||||
<Typography id='discrete-slider-always'>{name}</Typography>
|
|
||||||
<HelpIcon
|
|
||||||
htmlTooltip
|
|
||||||
tooltip={
|
|
||||||
<Box>
|
|
||||||
<StyledHeader variant='h3'>
|
|
||||||
Rollout percentage
|
|
||||||
</StyledHeader>
|
|
||||||
<Typography variant='body2'>
|
|
||||||
The rollout percentage determines the proportion
|
|
||||||
of users exposed to a feature. It's based on the
|
|
||||||
MurmurHash of a user's unique identifier,
|
|
||||||
normalized to a number between 1 and 100. If the
|
|
||||||
normalized hash is less than or equal to the
|
|
||||||
rollout percentage, the user sees the feature.
|
|
||||||
This ensures a consistent, random distribution
|
|
||||||
of the feature among users.
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<StyledSubheader variant='h3'>
|
|
||||||
Stickiness
|
|
||||||
</StyledSubheader>
|
|
||||||
<Typography variant='body2'>
|
|
||||||
Stickiness refers to the value used for hashing
|
|
||||||
to ensure a consistent user experience. It
|
|
||||||
determines the input for the MurmurHash,
|
|
||||||
ensuring that a user's feature exposure remains
|
|
||||||
consistent across sessions.
|
|
||||||
<br />
|
|
||||||
By default Unleash will use the first value
|
|
||||||
present in the context in the order of{' '}
|
|
||||||
<b>userId, sessionId and random</b>.
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<StyledSubheader variant='h3'>
|
|
||||||
GroupId
|
|
||||||
</StyledSubheader>
|
|
||||||
<Typography variant='body2'>
|
|
||||||
The groupId is used as a seed for the hash
|
|
||||||
function, ensuring consistent feature exposure
|
|
||||||
across different feature flags for a uniform
|
|
||||||
user experience.
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</StyledBox>
|
|
||||||
<StyledSlider
|
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
value={value}
|
|
||||||
getAriaValueText={valuetext}
|
|
||||||
aria-labelledby='discrete-slider-always'
|
|
||||||
step={1}
|
|
||||||
data-testid={ROLLOUT_SLIDER_ID}
|
|
||||||
marks={marks}
|
|
||||||
onChange={onChange}
|
|
||||||
valueLabelDisplay='on'
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default LegacyRolloutSlider;
|
|
@ -9,7 +9,6 @@ import {
|
|||||||
type IAutocompleteBoxOption,
|
type IAutocompleteBoxOption,
|
||||||
} from 'component/common/AutocompleteBox/AutocompleteBox';
|
} from 'component/common/AutocompleteBox/AutocompleteBox';
|
||||||
import { MilestoneStrategySegmentList } from './MilestoneStrategySegmentList.tsx';
|
import { MilestoneStrategySegmentList } from './MilestoneStrategySegmentList.tsx';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
const StyledHelpIconBox = styled(Box)(({ theme }) => ({
|
const StyledHelpIconBox = styled(Box)(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -27,7 +26,6 @@ export const MilestoneStrategySegment = ({
|
|||||||
segments: selectedSegments,
|
segments: selectedSegments,
|
||||||
setSegments: setSelectedSegments,
|
setSegments: setSelectedSegments,
|
||||||
}: IMilestoneStrategySegmentProps) => {
|
}: IMilestoneStrategySegmentProps) => {
|
||||||
const addEditStrategy = useUiFlag('addEditStrategy');
|
|
||||||
const { segments: allSegments } = useSegments();
|
const { segments: allSegments } = useSegments();
|
||||||
const { strategySegmentsLimit } = useSegmentLimits();
|
const { strategySegmentsLimit } = useSegmentLimits();
|
||||||
|
|
||||||
@ -90,7 +88,7 @@ export const MilestoneStrategySegment = ({
|
|||||||
options={autocompleteOptions}
|
options={autocompleteOptions}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
disabled={atStrategySegmentsLimit}
|
disabled={atStrategySegmentsLimit}
|
||||||
icon={addEditStrategy ? null : undefined}
|
icon={null}
|
||||||
width={'175px'}
|
width={'175px'}
|
||||||
/>
|
/>
|
||||||
<MilestoneStrategySegmentList
|
<MilestoneStrategySegmentList
|
||||||
|
@ -20,9 +20,7 @@ const setupRoutes = () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
testServerRoute(server, '/api/admin/ui-config', {
|
testServerRoute(server, '/api/admin/ui-config', {
|
||||||
flags: {
|
flags: {},
|
||||||
addEditStrategy: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ import {
|
|||||||
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
|
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
|
||||||
import type { IConstraint } from 'interfaces/strategy';
|
import type { IConstraint } from 'interfaces/strategy';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { ConstraintAccordionList } from 'component/common/LegacyConstraintAccordion/ConstraintAccordionList/ConstraintAccordionList';
|
|
||||||
import { EditableConstraintsList } from 'component/common/NewConstraintAccordion/ConstraintsList/EditableConstraintsList';
|
import { EditableConstraintsList } from 'component/common/NewConstraintAccordion/ConstraintsList/EditableConstraintsList';
|
||||||
import type { IEditableConstraintsListRef } from 'component/common/NewConstraintAccordion/ConstraintsList/EditableConstraintsList';
|
import type { IEditableConstraintsListRef } from 'component/common/NewConstraintAccordion/ConstraintsList/EditableConstraintsList';
|
||||||
import type { SegmentFormStep, SegmentFormMode } from './SegmentForm.tsx';
|
import type { SegmentFormStep, SegmentFormMode } from './SegmentForm.tsx';
|
||||||
@ -31,7 +30,6 @@ import { useSegmentValuesCount } from 'component/segments/hooks/useSegmentValues
|
|||||||
import AccessContext from 'contexts/AccessContext';
|
import AccessContext from 'contexts/AccessContext';
|
||||||
import { useSegmentLimits } from 'hooks/api/getters/useSegmentLimits/useSegmentLimits';
|
import { useSegmentLimits } from 'hooks/api/getters/useSegmentLimits/useSegmentLimits';
|
||||||
import { GO_BACK } from 'constants/navigate';
|
import { GO_BACK } from 'constants/navigate';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
interface ISegmentFormPartTwoProps {
|
interface ISegmentFormPartTwoProps {
|
||||||
project?: string;
|
project?: string;
|
||||||
@ -122,7 +120,6 @@ export const SegmentFormStepTwo: React.FC<ISegmentFormPartTwoProps> = ({
|
|||||||
? [CREATE_SEGMENT, UPDATE_PROJECT_SEGMENT]
|
? [CREATE_SEGMENT, UPDATE_PROJECT_SEGMENT]
|
||||||
: [UPDATE_SEGMENT, UPDATE_PROJECT_SEGMENT];
|
: [UPDATE_SEGMENT, UPDATE_PROJECT_SEGMENT];
|
||||||
const { segmentValuesLimit } = useSegmentLimits();
|
const { segmentValuesLimit } = useSegmentLimits();
|
||||||
const addEditStrategy = useUiFlag('addEditStrategy');
|
|
||||||
|
|
||||||
const overSegmentValuesLimit: boolean = Boolean(
|
const overSegmentValuesLimit: boolean = Boolean(
|
||||||
segmentValuesLimit && segmentValuesCount > segmentValuesLimit,
|
segmentValuesLimit && segmentValuesCount > segmentValuesLimit,
|
||||||
@ -202,25 +199,13 @@ export const SegmentFormStepTwo: React.FC<ISegmentFormPartTwoProps> = ({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<StyledConstraintContainer>
|
<StyledConstraintContainer>
|
||||||
{addEditStrategy ? (
|
{hasAccess(modePermission, project) && setConstraints ? (
|
||||||
hasAccess(modePermission, project) && setConstraints ? (
|
<EditableConstraintsList
|
||||||
<EditableConstraintsList
|
|
||||||
ref={constraintsAccordionListRef}
|
|
||||||
constraints={constraints}
|
|
||||||
setConstraints={setConstraints}
|
|
||||||
/>
|
|
||||||
) : null
|
|
||||||
) : (
|
|
||||||
<ConstraintAccordionList
|
|
||||||
ref={constraintsAccordionListRef}
|
ref={constraintsAccordionListRef}
|
||||||
constraints={constraints}
|
constraints={constraints}
|
||||||
setConstraints={
|
setConstraints={setConstraints}
|
||||||
hasAccess(modePermission, project)
|
|
||||||
? setConstraints
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
)}
|
) : null}
|
||||||
</StyledConstraintContainer>
|
</StyledConstraintContainer>
|
||||||
</StyledForm>
|
</StyledForm>
|
||||||
<StyledButtonContainer>
|
<StyledButtonContainer>
|
||||||
|
@ -6,7 +6,6 @@ import type {
|
|||||||
import useAPI from '../useApi/useApi.js';
|
import useAPI from '../useApi/useApi.js';
|
||||||
import { useRecentlyUsedConstraints } from 'component/feature/FeatureStrategy/FeatureStrategyConstraints/RecentlyUsedConstraints/useRecentlyUsedConstraints';
|
import { useRecentlyUsedConstraints } from 'component/feature/FeatureStrategy/FeatureStrategyConstraints/RecentlyUsedConstraints/useRecentlyUsedConstraints';
|
||||||
import { useRecentlyUsedSegments } from 'component/feature/FeatureStrategy/FeatureStrategySegment/RecentlyUsedSegments/useRecentlyUsedSegments';
|
import { useRecentlyUsedSegments } from 'component/feature/FeatureStrategy/FeatureStrategySegment/RecentlyUsedSegments/useRecentlyUsedSegments';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
const useFeatureStrategyApi = () => {
|
const useFeatureStrategyApi = () => {
|
||||||
const { makeRequest, createRequest, errors, loading } = useAPI({
|
const { makeRequest, createRequest, errors, loading } = useAPI({
|
||||||
@ -16,7 +15,6 @@ const useFeatureStrategyApi = () => {
|
|||||||
const { addItem: addToRecentlyUsedConstraints } =
|
const { addItem: addToRecentlyUsedConstraints } =
|
||||||
useRecentlyUsedConstraints();
|
useRecentlyUsedConstraints();
|
||||||
const { addItem: addToRecentlyUsedSegments } = useRecentlyUsedSegments();
|
const { addItem: addToRecentlyUsedSegments } = useRecentlyUsedSegments();
|
||||||
const addEditStrategyEnabled = useUiFlag('addEditStrategy');
|
|
||||||
|
|
||||||
const addStrategyToFeature = async (
|
const addStrategyToFeature = async (
|
||||||
projectId: string,
|
projectId: string,
|
||||||
@ -24,14 +22,12 @@ const useFeatureStrategyApi = () => {
|
|||||||
environmentId: string,
|
environmentId: string,
|
||||||
payload: IFeatureStrategyPayload,
|
payload: IFeatureStrategyPayload,
|
||||||
): Promise<IFeatureStrategy> => {
|
): Promise<IFeatureStrategy> => {
|
||||||
if (addEditStrategyEnabled) {
|
if (payload.constraints && payload.constraints.length > 0) {
|
||||||
if (payload.constraints && payload.constraints.length > 0) {
|
addToRecentlyUsedConstraints(payload.constraints);
|
||||||
addToRecentlyUsedConstraints(payload.constraints);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (payload.segments && payload.segments.length > 0) {
|
if (payload.segments && payload.segments.length > 0) {
|
||||||
addToRecentlyUsedSegments(payload.segments);
|
addToRecentlyUsedSegments(payload.segments);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const path = `api/admin/projects/${projectId}/features/${featureId}/environments/${environmentId}/strategies`;
|
const path = `api/admin/projects/${projectId}/features/${featureId}/environments/${environmentId}/strategies`;
|
||||||
@ -67,14 +63,12 @@ const useFeatureStrategyApi = () => {
|
|||||||
strategyId: string,
|
strategyId: string,
|
||||||
payload: IFeatureStrategyPayload,
|
payload: IFeatureStrategyPayload,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
if (addEditStrategyEnabled) {
|
if (payload.constraints && payload.constraints.length > 0) {
|
||||||
if (payload.constraints && payload.constraints.length > 0) {
|
addToRecentlyUsedConstraints(payload.constraints);
|
||||||
addToRecentlyUsedConstraints(payload.constraints);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (payload.segments && payload.segments.length > 0) {
|
if (payload.segments && payload.segments.length > 0) {
|
||||||
addToRecentlyUsedSegments(payload.segments);
|
addToRecentlyUsedSegments(payload.segments);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const path = `api/admin/projects/${projectId}/features/${featureId}/environments/${environmentId}/strategies/${strategyId}`;
|
const path = `api/admin/projects/${projectId}/features/${featureId}/environments/${environmentId}/strategies/${strategyId}`;
|
||||||
|
@ -86,7 +86,6 @@ export type UiFlags = {
|
|||||||
showUserDeviceCount?: boolean;
|
showUserDeviceCount?: boolean;
|
||||||
consumptionModel?: boolean;
|
consumptionModel?: boolean;
|
||||||
edgeObservability?: boolean;
|
edgeObservability?: boolean;
|
||||||
addEditStrategy?: boolean;
|
|
||||||
registerFrontendClient?: boolean;
|
registerFrontendClient?: boolean;
|
||||||
customMetrics?: boolean;
|
customMetrics?: boolean;
|
||||||
lifecycleMetrics?: boolean;
|
lifecycleMetrics?: boolean;
|
||||||
|
@ -56,7 +56,6 @@ export type IFlagKey =
|
|||||||
| 'uniqueSdkTracking'
|
| 'uniqueSdkTracking'
|
||||||
| 'consumptionModel'
|
| 'consumptionModel'
|
||||||
| 'edgeObservability'
|
| 'edgeObservability'
|
||||||
| 'addEditStrategy'
|
|
||||||
| 'registerFrontendClient'
|
| 'registerFrontendClient'
|
||||||
| 'reportUnknownFlags'
|
| 'reportUnknownFlags'
|
||||||
| 'lastSeenBulkQuery'
|
| 'lastSeenBulkQuery'
|
||||||
@ -269,10 +268,6 @@ const flags: IFlags = {
|
|||||||
process.env.EXPERIMENTAL_EDGE_OBSERVABILITY,
|
process.env.EXPERIMENTAL_EDGE_OBSERVABILITY,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
addEditStrategy: parseEnvVarBoolean(
|
|
||||||
process.env.UNLEASH_EXPERIMENTAL_ADD_EDIT_STRATEGY,
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
registerFrontendClient: parseEnvVarBoolean(
|
registerFrontendClient: parseEnvVarBoolean(
|
||||||
process.env.UNLEASH_EXPERIMENTAL_REGISTER_FRONTEND_CLIENT,
|
process.env.UNLEASH_EXPERIMENTAL_REGISTER_FRONTEND_CLIENT,
|
||||||
false,
|
false,
|
||||||
|
@ -50,7 +50,6 @@ process.nextTick(async () => {
|
|||||||
showUserDeviceCount: true,
|
showUserDeviceCount: true,
|
||||||
deltaApi: true,
|
deltaApi: true,
|
||||||
uniqueSdkTracking: true,
|
uniqueSdkTracking: true,
|
||||||
addEditStrategy: true,
|
|
||||||
strictSchemaValidation: true,
|
strictSchemaValidation: true,
|
||||||
registerFrontendClient: true,
|
registerFrontendClient: true,
|
||||||
reportUnknownFlags: true,
|
reportUnknownFlags: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user