1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-22 19:07:54 +01:00

feat: constraints limit in a strategy UI (#7555)

This commit is contained in:
Mateusz Kwasniewski 2024-07-08 13:10:00 +02:00 committed by GitHub
parent 7ca2ace0bc
commit 5ed4ccc981
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 104 additions and 1 deletions

View File

@ -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();
});

View File

@ -12,6 +12,9 @@ import {
useConstraintAccordionList,
} from 'component/common/ConstraintAccordion/ConstraintAccordionList/ConstraintAccordionList';
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 {
constraints: IConstraint[];
@ -60,6 +63,20 @@ const StyledHelpIconBox = styled(Box)(({ theme }) => ({
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<
IConstraintAccordionListRef | undefined,
IConstraintAccordionListProps
@ -72,6 +89,8 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
setConstraints,
ref as RefObject<IConstraintAccordionListRef>,
);
const { resourceLimitsEnabled, limit, limitReached } =
useConstraintLimit(constraints.length);
if (context.length === 0) {
return null;
@ -113,14 +132,34 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
constraints={constraints}
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
sx={{ marginTop: '1rem' }}
type='button'
onClick={onAdd}
startIcon={<Add />}
variant='outlined'
color='primary'
data-testid='ADD_CONSTRAINT_BUTTON'
disabled={Boolean(limitReached)}
>
Add constraint
</Button>

View File

@ -40,6 +40,7 @@ export const defaultValue: IUiConfig = {
featureEnvironmentStrategies: 30,
environments: 50,
constraintValues: 250,
constraints: 30,
projects: 500,
segments: 300,
apiTokens: 2000,

View File

@ -30,6 +30,8 @@ export interface ResourceLimitsSchema {
environments: number;
/** The maximum number of values for a single constraint. */
constraintValues: number;
/** The maximum number of constraints for a single strategy. */
constraints: number;
/** The maximum number of projects allowed. */
projects: number;
/** The maximum number of segments allowed. */