mirror of
https://github.com/Unleash/unleash.git
synced 2024-12-28 00:06:53 +01:00
feat: constraints limit in a strategy UI (#7555)
This commit is contained in:
parent
7ca2ace0bc
commit
5ed4ccc981
@ -0,0 +1,61 @@
|
|||||||
|
import { screen } from '@testing-library/react';
|
||||||
|
import { render } from 'utils/testRenderer';
|
||||||
|
import { testServerRoute, testServerSetup } from 'utils/testServer';
|
||||||
|
import { FeatureStrategyConstraintAccordionList } from './FeatureStrategyConstraintAccordionList';
|
||||||
|
import type { IConstraint } from 'interfaces/strategy';
|
||||||
|
|
||||||
|
const server = testServerSetup();
|
||||||
|
|
||||||
|
const LIMIT = 5;
|
||||||
|
|
||||||
|
const setupApi = () => {
|
||||||
|
testServerRoute(server, '/api/admin/ui-config', {
|
||||||
|
flags: {
|
||||||
|
resourceLimits: true,
|
||||||
|
},
|
||||||
|
resourceLimits: {
|
||||||
|
constraints: LIMIT,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
testServerRoute(server, '/api/admin/context', [{ name: 'text' }]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const constraints = (limit: number): IConstraint[] =>
|
||||||
|
Array.from(Array(limit).keys()).map(() => ({
|
||||||
|
contextName: 'test',
|
||||||
|
operator: 'IN',
|
||||||
|
}));
|
||||||
|
|
||||||
|
test('show limit reached and disable adding new constraints', async () => {
|
||||||
|
setupApi();
|
||||||
|
render(
|
||||||
|
<FeatureStrategyConstraintAccordionList
|
||||||
|
constraints={constraints(LIMIT)}
|
||||||
|
showCreateButton={true}
|
||||||
|
setConstraints={() => {}}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
await screen.findByText(
|
||||||
|
'You have reached the limit for constraints in this strategy',
|
||||||
|
);
|
||||||
|
const button = await screen.findByText('Add constraint');
|
||||||
|
expect(button).toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('show nearing limit', async () => {
|
||||||
|
setupApi();
|
||||||
|
render(
|
||||||
|
<FeatureStrategyConstraintAccordionList
|
||||||
|
constraints={constraints(LIMIT - 1)}
|
||||||
|
showCreateButton={true}
|
||||||
|
setConstraints={() => {}}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
await screen.findByText(
|
||||||
|
'You are nearing the limit for constraints in this strategy',
|
||||||
|
);
|
||||||
|
const button = await screen.findByText('Add constraint');
|
||||||
|
expect(button).toBeEnabled();
|
||||||
|
});
|
@ -12,6 +12,9 @@ import {
|
|||||||
useConstraintAccordionList,
|
useConstraintAccordionList,
|
||||||
} from 'component/common/ConstraintAccordion/ConstraintAccordionList/ConstraintAccordionList';
|
} from 'component/common/ConstraintAccordion/ConstraintAccordionList/ConstraintAccordionList';
|
||||||
import { NewConstraintAccordionList } from 'component/common/NewConstraintAccordion/NewConstraintAccordionList/NewConstraintAccordionList';
|
import { NewConstraintAccordionList } from 'component/common/NewConstraintAccordion/NewConstraintAccordionList/NewConstraintAccordionList';
|
||||||
|
import { Limit } from 'component/common/Limit/Limit';
|
||||||
|
import { useUiFlag } from 'hooks/useUiFlag';
|
||||||
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
|
|
||||||
interface IConstraintAccordionListProps {
|
interface IConstraintAccordionListProps {
|
||||||
constraints: IConstraint[];
|
constraints: IConstraint[];
|
||||||
@ -60,6 +63,20 @@ const StyledHelpIconBox = styled(Box)(({ theme }) => ({
|
|||||||
marginBottom: theme.spacing(1),
|
marginBottom: theme.spacing(1),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const useConstraintLimit = (constraintsCount: number) => {
|
||||||
|
const resourceLimitsEnabled = useUiFlag('resourceLimits');
|
||||||
|
const { uiConfig } = useUiConfig();
|
||||||
|
const constraintsLimit = uiConfig.resourceLimits?.constraints || 30;
|
||||||
|
const limitReached =
|
||||||
|
resourceLimitsEnabled && constraintsCount >= constraintsLimit;
|
||||||
|
|
||||||
|
return {
|
||||||
|
resourceLimitsEnabled,
|
||||||
|
limit: constraintsLimit,
|
||||||
|
limitReached,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const FeatureStrategyConstraintAccordionList = forwardRef<
|
export const FeatureStrategyConstraintAccordionList = forwardRef<
|
||||||
IConstraintAccordionListRef | undefined,
|
IConstraintAccordionListRef | undefined,
|
||||||
IConstraintAccordionListProps
|
IConstraintAccordionListProps
|
||||||
@ -72,6 +89,8 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
|
|||||||
setConstraints,
|
setConstraints,
|
||||||
ref as RefObject<IConstraintAccordionListRef>,
|
ref as RefObject<IConstraintAccordionListRef>,
|
||||||
);
|
);
|
||||||
|
const { resourceLimitsEnabled, limit, limitReached } =
|
||||||
|
useConstraintLimit(constraints.length);
|
||||||
|
|
||||||
if (context.length === 0) {
|
if (context.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
@ -113,14 +132,34 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
|
|||||||
constraints={constraints}
|
constraints={constraints}
|
||||||
state={state}
|
state={state}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
sx={(theme) => ({
|
||||||
|
marginTop: theme.spacing(2),
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={resourceLimitsEnabled}
|
||||||
|
show={
|
||||||
|
<Limit
|
||||||
|
name='constraints in this strategy'
|
||||||
|
shortName='constraints'
|
||||||
|
currentValue={constraints.length}
|
||||||
|
limit={limit}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
sx={{ marginTop: '1rem' }}
|
|
||||||
type='button'
|
type='button'
|
||||||
onClick={onAdd}
|
onClick={onAdd}
|
||||||
startIcon={<Add />}
|
startIcon={<Add />}
|
||||||
variant='outlined'
|
variant='outlined'
|
||||||
color='primary'
|
color='primary'
|
||||||
data-testid='ADD_CONSTRAINT_BUTTON'
|
data-testid='ADD_CONSTRAINT_BUTTON'
|
||||||
|
disabled={Boolean(limitReached)}
|
||||||
>
|
>
|
||||||
Add constraint
|
Add constraint
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -40,6 +40,7 @@ export const defaultValue: IUiConfig = {
|
|||||||
featureEnvironmentStrategies: 30,
|
featureEnvironmentStrategies: 30,
|
||||||
environments: 50,
|
environments: 50,
|
||||||
constraintValues: 250,
|
constraintValues: 250,
|
||||||
|
constraints: 30,
|
||||||
projects: 500,
|
projects: 500,
|
||||||
segments: 300,
|
segments: 300,
|
||||||
apiTokens: 2000,
|
apiTokens: 2000,
|
||||||
|
@ -30,6 +30,8 @@ export interface ResourceLimitsSchema {
|
|||||||
environments: number;
|
environments: number;
|
||||||
/** The maximum number of values for a single constraint. */
|
/** The maximum number of values for a single constraint. */
|
||||||
constraintValues: number;
|
constraintValues: number;
|
||||||
|
/** The maximum number of constraints for a single strategy. */
|
||||||
|
constraints: number;
|
||||||
/** The maximum number of projects allowed. */
|
/** The maximum number of projects allowed. */
|
||||||
projects: number;
|
projects: number;
|
||||||
/** The maximum number of segments allowed. */
|
/** The maximum number of segments allowed. */
|
||||||
|
Loading…
Reference in New Issue
Block a user