mirror of
https://github.com/Unleash/unleash.git
synced 2025-08-27 13:49:10 +02:00
Chore(1-3807)/remove flag add edit strategy take2 (#10108)
Removes all usages of flag addEditStrategy and refactors code where necessary. This is only the first step of the cleanup. After this, there's still lots of code to be removed. I've got a different PR that removes ~5k lines of code (https://github.com/Unleash/unleash/pull/10105) that I want to reach in pieces to make sure that everythnig works on the way there.
This commit is contained in:
parent
2d228eea76
commit
7e61e0dd09
@ -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>
|
||||||
|
@ -33,7 +33,6 @@ export const ConstraintsList: FC<{ children: ReactNode }> = ({ children }) => {
|
|||||||
result.push(
|
result.push(
|
||||||
<StyledListItem key={index}>
|
<StyledListItem key={index}>
|
||||||
{index > 0 ? (
|
{index > 0 ? (
|
||||||
// todo (addEditStrategy): change divider for edit screen (probably a new component or a prop)
|
|
||||||
<ConstraintSeparator key={`${index}-divider`} />
|
<ConstraintSeparator key={`${index}-divider`} />
|
||||||
) : null}
|
) : null}
|
||||||
{child}
|
{child}
|
||||||
|
@ -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}
|
filter={filter}
|
||||||
setFilter={setFilter}
|
setFilter={setFilter}
|
||||||
/>
|
/>
|
||||||
</SearchWrapper>
|
</SearchWrapper>
|
||||||
) : (
|
|
||||||
<ConstraintValueSearch
|
|
||||||
filter={filter}
|
|
||||||
setFilter={setFilter}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{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,7 +110,6 @@ 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
|
||||||
@ -129,19 +125,6 @@ export const NewConstraintAccordionList = forwardRef<
|
|||||||
key={constraint[constraintId]}
|
key={constraint[constraintId]}
|
||||||
constraint={constraint}
|
constraint={constraint}
|
||||||
/>
|
/>
|
||||||
)
|
|
||||||
) : (
|
|
||||||
<NewConstraintAccordion
|
|
||||||
key={constraint[constraintId]}
|
|
||||||
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
|
|
||||||
/>
|
|
||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
</ConstraintsList>
|
</ConstraintsList>
|
||||||
|
@ -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}
|
ref={ref}
|
||||||
setConstraints={setConstraints}
|
setConstraints={setConstraints}
|
||||||
constraints={constraints}
|
constraints={constraints}
|
||||||
/>
|
/>
|
||||||
) : null
|
) : null}
|
||||||
) : (
|
|
||||||
<NewConstraintAccordionList
|
|
||||||
ref={ref}
|
|
||||||
setConstraints={setConstraints}
|
|
||||||
constraints={constraints}
|
|
||||||
state={state}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Box
|
<Box
|
||||||
sx={(theme) => ({
|
sx={(theme) => ({
|
||||||
marginTop: theme.spacing(2),
|
marginTop: theme.spacing(2),
|
||||||
@ -134,15 +122,10 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
|
|||||||
>
|
>
|
||||||
Add constraint
|
Add constraint
|
||||||
</Button>
|
</Button>
|
||||||
<ConditionallyRender
|
|
||||||
condition={Boolean(addEditStrategy)}
|
|
||||||
show={
|
|
||||||
<RecentlyUsedConstraints
|
<RecentlyUsedConstraints
|
||||||
setConstraints={setConstraints}
|
setConstraints={setConstraints}
|
||||||
constraints={constraints}
|
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');
|
|
||||||
|
|
||||||
if (addEditStrategy) {
|
|
||||||
return <RolloutSlider {...props} />;
|
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;
|
|
@ -49,7 +49,7 @@ const StyledActionsSmallScreen = styled('div')(({ theme }) => ({
|
|||||||
|
|
||||||
export const InsightsHeader: VFC<DashboardHeaderProps> = ({ actions }) => {
|
export const InsightsHeader: VFC<DashboardHeaderProps> = ({ actions }) => {
|
||||||
const showInactiveUsers = useUiFlag('showInactiveUsers');
|
const showInactiveUsers = useUiFlag('showInactiveUsers');
|
||||||
const pageName = useUiFlag('sideMenuCleanup') ? 'Analytics' : 'Insights';
|
const pageName = 'Analytics';
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
|
|
||||||
|
@ -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}
|
ref={constraintsAccordionListRef}
|
||||||
constraints={constraints}
|
constraints={constraints}
|
||||||
setConstraints={setConstraints}
|
setConstraints={setConstraints}
|
||||||
/>
|
/>
|
||||||
) : null
|
) : null}
|
||||||
) : (
|
|
||||||
<ConstraintAccordionList
|
|
||||||
ref={constraintsAccordionListRef}
|
|
||||||
constraints={constraints}
|
|
||||||
setConstraints={
|
|
||||||
hasAccess(modePermission, project)
|
|
||||||
? setConstraints
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</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,7 +22,6 @@ 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);
|
||||||
}
|
}
|
||||||
@ -32,7 +29,6 @@ const useFeatureStrategyApi = () => {
|
|||||||
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`;
|
||||||
const req = createRequest(
|
const req = createRequest(
|
||||||
@ -67,7 +63,6 @@ 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);
|
||||||
}
|
}
|
||||||
@ -75,7 +70,6 @@ const useFeatureStrategyApi = () => {
|
|||||||
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}`;
|
||||||
const req = createRequest(
|
const req = createRequest(
|
||||||
|
@ -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'
|
||||||
@ -268,10 +267,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