1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-01 01:18:10 +02:00

[Gitar] Cleaning up stale flag: resourceLimits with value true (#7964)

[![Gitar](https://raw.githubusercontent.com/gitarcode/.github/main/assets/gitar-banner.svg)](https://gitar.co)
  
  ---
This automated PR was generated by [Gitar](https://gitar.co). View
[docs](https://gitar.co/docs).

---------

Co-authored-by: Gitar <noreply@gitar.co>
Co-authored-by: Thomas Heartman <thomas@getunleash.io>
This commit is contained in:
gitar-bot[bot] 2024-08-22 13:20:53 +02:00 committed by GitHub
parent b0541a0af2
commit 4615ff40ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 177 additions and 392 deletions

View File

@ -18,9 +18,6 @@ const server = testServerSetup();
const setupApi = (existingTokensCount: number) => { const setupApi = (existingTokensCount: number) => {
testServerRoute(server, '/api/admin/ui-config', { testServerRoute(server, '/api/admin/ui-config', {
flags: {
resourceLimits: true,
},
resourceLimits: { resourceLimits: {
apiTokens: 1, apiTokens: 1,
}, },

View File

@ -1,8 +1,6 @@
import { useState } from 'react'; import { useState } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { styled } from '@mui/material'; import { styled } from '@mui/material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { useUiFlag } from 'hooks/useUiFlag';
import FormTemplate from 'component/common/FormTemplate/FormTemplate'; import FormTemplate from 'component/common/FormTemplate/FormTemplate';
import ApiTokenForm from '../ApiTokenForm/ApiTokenForm'; import ApiTokenForm from '../ApiTokenForm/ApiTokenForm';
import { CreateButton } from 'component/common/CreateButton/CreateButton'; import { CreateButton } from 'component/common/CreateButton/CreateButton';
@ -37,16 +35,14 @@ const StyledLimit = styled(Limit)(({ theme }) => ({
})); }));
const useApiTokenLimit = () => { const useApiTokenLimit = () => {
const resourceLimitsEnabled = useUiFlag('resourceLimits');
const { tokens, loading: loadingTokens } = useApiTokens(); const { tokens, loading: loadingTokens } = useApiTokens();
const { uiConfig, loading: loadingConfig } = useUiConfig(); const { uiConfig, loading: loadingConfig } = useUiConfig();
const apiTokensLimit = uiConfig.resourceLimits.apiTokens; const apiTokensLimit = uiConfig.resourceLimits.apiTokens;
return { return {
resourceLimitsEnabled,
limit: apiTokensLimit, limit: apiTokensLimit,
currentValue: tokens.length, currentValue: tokens.length,
limitReached: resourceLimitsEnabled && tokens.length >= apiTokensLimit, limitReached: tokens.length >= apiTokensLimit,
loading: loadingConfig || loadingTokens, loading: loadingConfig || loadingTokens,
}; };
}; };
@ -58,7 +54,6 @@ export const CreateApiToken = ({ modal = false }: ICreateApiTokenProps) => {
const [showConfirm, setShowConfirm] = useState(false); const [showConfirm, setShowConfirm] = useState(false);
const [token, setToken] = useState(''); const [token, setToken] = useState('');
const { const {
resourceLimitsEnabled,
limit, limit,
currentValue, currentValue,
limitReached, limitReached,
@ -176,17 +171,12 @@ export const CreateApiToken = ({ modal = false }: ICreateApiTokenProps) => {
environment={environment} environment={environment}
setEnvironment={setEnvironment} setEnvironment={setEnvironment}
/> />
<ConditionallyRender
condition={resourceLimitsEnabled}
show={
<StyledLimit <StyledLimit
name='API tokens' name='API tokens'
shortName='tokens' shortName='tokens'
currentValue={currentValue} currentValue={currentValue}
limit={limit} limit={limit}
/> />
}
/>
</ApiTokenForm> </ApiTokenForm>
<ConfirmToken <ConfirmToken
open={showConfirm} open={showConfirm}

View File

@ -11,12 +11,7 @@ const setupApi = ({
apiTokenLimit, apiTokenLimit,
}: { apiTokenCount: number; apiTokenLimit: number }) => { }: { apiTokenCount: number; apiTokenLimit: number }) => {
testServerRoute(server, '/api/admin/ui-config', { testServerRoute(server, '/api/admin/ui-config', {
flags: { resourceLimits: { apiTokens: apiTokenLimit },
resourceLimits: true,
},
resourceLimits: {
apiTokens: apiTokenLimit,
},
}); });
testServerRoute(server, '/api/admin/api-tokens', { testServerRoute(server, '/api/admin/api-tokens', {

View File

@ -3,7 +3,6 @@ import { CREATE_API_TOKEN_BUTTON } from 'utils/testIds';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import Add from '@mui/icons-material/Add'; import Add from '@mui/icons-material/Add';
import { useApiTokens } from 'hooks/api/getters/useApiTokens/useApiTokens'; import { useApiTokens } from 'hooks/api/getters/useApiTokens/useApiTokens';
import { useUiFlag } from 'hooks/useUiFlag';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
interface ICreateApiTokenButton { interface ICreateApiTokenButton {
path: string; path: string;
@ -12,9 +11,7 @@ interface ICreateApiTokenButton {
} }
const useApiTokenLimit = (apiTokenLimit: number, apiTokenCount: number) => { const useApiTokenLimit = (apiTokenLimit: number, apiTokenCount: number) => {
const resourceLimitsEnabled = useUiFlag('resourceLimits'); const limitReached = apiTokenCount >= apiTokenLimit;
const limitReached =
resourceLimitsEnabled && apiTokenCount >= apiTokenLimit;
return { return {
limitReached, limitReached,

View File

@ -6,15 +6,9 @@ import { FreeTextInput } from './FreeTextInput';
const server = testServerSetup(); const server = testServerSetup();
const LIMIT = 3; const LIMIT = 3;
const setupApi = () => { const setupApi = () => {
testServerRoute(server, '/api/admin/ui-config', { testServerRoute(server, '/api/admin/ui-config', {
flags: { resourceLimits: { constraintValues: LIMIT },
resourceLimits: true,
},
resourceLimits: {
constraintValues: LIMIT,
},
}); });
}; };
@ -126,8 +120,8 @@ test('should show limit reached indicator', async () => {
<FreeTextInput <FreeTextInput
error='' error=''
values={['1', '2', '3']} values={['1', '2', '3']}
setValues={(newValues) => {}} setValues={() => {}}
setError={(newError: string) => {}} setError={() => {}}
removeValue={() => {}} removeValue={() => {}}
/>, />,
); );

View File

@ -6,9 +6,7 @@ import type React from 'react';
import { useState } from 'react'; import { useState } from 'react';
import { ConstraintFormHeader } from '../ConstraintFormHeader/ConstraintFormHeader'; import { ConstraintFormHeader } from '../ConstraintFormHeader/ConstraintFormHeader';
import { parseParameterStrings } from 'utils/parseParameter'; import { parseParameterStrings } from 'utils/parseParameter';
import { useUiFlag } from 'hooks/useUiFlag';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { Limit } from 'component/common/Limit/Limit'; import { Limit } from 'component/common/Limit/Limit';
interface IFreeTextInputProps { interface IFreeTextInputProps {
@ -72,7 +70,6 @@ export const FreeTextInput = ({
}: IFreeTextInputProps) => { }: IFreeTextInputProps) => {
const [inputValues, setInputValues] = useState(''); const [inputValues, setInputValues] = useState('');
const { classes: styles } = useStyles(); const { classes: styles } = useStyles();
const resourceLimitsEnabled = useUiFlag('resourceLimits');
const { uiConfig, loading } = useUiConfig(); const { uiConfig, loading } = useUiConfig();
const constraintValuesLimit = uiConfig.resourceLimits.constraintValues; const constraintValuesLimit = uiConfig.resourceLimits.constraintValues;
@ -88,9 +85,7 @@ export const FreeTextInput = ({
...values, ...values,
...parseParameterStrings(inputValues), ...parseParameterStrings(inputValues),
]); ]);
const limitReached = Boolean( const limitReached = Boolean(newValues.length > constraintValuesLimit);
resourceLimitsEnabled && newValues.length > constraintValuesLimit,
);
if (limitReached) { if (limitReached) {
setError( setError(
@ -148,17 +143,12 @@ export const FreeTextInput = ({
/> />
</div> </div>
<LimitContainer> <LimitContainer>
<ConditionallyRender
condition={resourceLimitsEnabled}
show={
<Limit <Limit
name='single constraint values' name='single constraint values'
shortName='values' shortName='values'
currentValue={values.length} currentValue={values.length}
limit={constraintValuesLimit} limit={constraintValuesLimit}
/> />
}
/>
</LimitContainer> </LimitContainer>
</> </>
); );

View File

@ -7,14 +7,10 @@ import { ADMIN } from '../../providers/AccessProvider/permissions';
const server = testServerSetup(); const server = testServerSetup();
const setupApi = ({ const setupApi = ({
resourceLimits,
limit, limit,
environments, environments,
}: { resourceLimits: boolean; limit: number; environments: number }) => { }: { limit: number; environments: number }) => {
testServerRoute(server, '/api/admin/ui-config', { testServerRoute(server, '/api/admin/ui-config', {
flags: {
resourceLimits,
},
resourceLimits: { resourceLimits: {
environments: limit, environments: limit,
}, },
@ -28,7 +24,7 @@ const setupApi = ({
}; };
test('show limit reached info', async () => { test('show limit reached info', async () => {
setupApi({ environments: 1, limit: 1, resourceLimits: true }); setupApi({ environments: 1, limit: 1 });
render(<CreateEnvironment />, { permissions: [{ permission: ADMIN }] }); render(<CreateEnvironment />, { permissions: [{ permission: ADMIN }] });
await screen.findByText('You have reached the limit for environments'); await screen.findByText('You have reached the limit for environments');
@ -39,7 +35,7 @@ test('show limit reached info', async () => {
}); });
test('show approaching limit info', async () => { test('show approaching limit info', async () => {
setupApi({ environments: 9, limit: 10, resourceLimits: true }); setupApi({ environments: 9, limit: 10 });
render(<CreateEnvironment />, { permissions: [{ permission: ADMIN }] }); render(<CreateEnvironment />, { permissions: [{ permission: ADMIN }] });
await screen.findByText('You are nearing the limit for environments'); await screen.findByText('You are nearing the limit for environments');
@ -48,10 +44,3 @@ test('show approaching limit info', async () => {
}); });
expect(createButton).toBeEnabled(); expect(createButton).toBeEnabled();
}); });
test('show limit reached info - no resource limits component', async () => {
setupApi({ environments: 1, limit: 1, resourceLimits: false });
render(<CreateEnvironment />);
await screen.findByText('Go back');
});

View File

@ -2,27 +2,20 @@ import { useNavigate } from 'react-router-dom';
import useEnvironmentForm from '../hooks/useEnvironmentForm'; import useEnvironmentForm from '../hooks/useEnvironmentForm';
import EnvironmentForm from '../EnvironmentForm/EnvironmentForm'; import EnvironmentForm from '../EnvironmentForm/EnvironmentForm';
import FormTemplate from 'component/common/FormTemplate/FormTemplate'; import FormTemplate from 'component/common/FormTemplate/FormTemplate';
import { Alert } from '@mui/material';
import { Button } from '@mui/material';
import { CreateButton } from 'component/common/CreateButton/CreateButton'; import { CreateButton } from 'component/common/CreateButton/CreateButton';
import useEnvironmentApi from 'hooks/api/actions/useEnvironmentApi/useEnvironmentApi'; import useEnvironmentApi from 'hooks/api/actions/useEnvironmentApi/useEnvironmentApi';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import useToast from 'hooks/useToast'; import useToast from 'hooks/useToast';
import { useEnvironments } from 'hooks/api/getters/useEnvironments/useEnvironments'; import { useEnvironments } from 'hooks/api/getters/useEnvironments/useEnvironments';
import usePermissions from 'hooks/api/getters/usePermissions/usePermissions'; import usePermissions from 'hooks/api/getters/usePermissions/usePermissions';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { PageContent } from 'component/common/PageContent/PageContent';
import { ADMIN } from 'component/providers/AccessProvider/permissions'; import { ADMIN } from 'component/providers/AccessProvider/permissions';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
import { formatUnknownError } from 'utils/formatUnknownError'; import { formatUnknownError } from 'utils/formatUnknownError';
import { GO_BACK } from 'constants/navigate'; import { GO_BACK } from 'constants/navigate';
import { Limit } from 'component/common/Limit/Limit'; import { Limit } from 'component/common/Limit/Limit';
import { useUiFlag } from 'hooks/useUiFlag';
const CreateEnvironment = () => { const CreateEnvironment = () => {
const { setToastApiError, setToastData } = useToast(); const { setToastApiError, setToastData } = useToast();
const { uiConfig } = useUiConfig(); const { uiConfig } = useUiConfig();
const resourceLimitsEnabled = useUiFlag('resourceLimits');
const environmentLimit = uiConfig.resourceLimits.environments; const environmentLimit = uiConfig.resourceLimits.environments;
const navigate = useNavigate(); const navigate = useNavigate();
const { environments } = useEnvironments(); const { environments } = useEnvironments();
@ -73,9 +66,6 @@ const CreateEnvironment = () => {
}; };
return ( return (
<ConditionallyRender
condition={resourceLimitsEnabled || canCreateMoreEnvs}
show={
<FormTemplate <FormTemplate
loading={loading} loading={loading}
title='Create environment' title='Create environment'
@ -105,17 +95,12 @@ const CreateEnvironment = () => {
mode='Create' mode='Create'
clearErrors={clearErrors} clearErrors={clearErrors}
Limit={ Limit={
<ConditionallyRender
condition={resourceLimitsEnabled}
show={
<Limit <Limit
name='environments' name='environments'
limit={environmentLimit} limit={environmentLimit}
currentValue={environments.length} currentValue={environments.length}
/> />
} }
/>
}
> >
<CreateButton <CreateButton
name='environment' name='environment'
@ -124,31 +109,6 @@ const CreateEnvironment = () => {
/> />
</EnvironmentForm> </EnvironmentForm>
</FormTemplate> </FormTemplate>
}
elseShow={
<>
<PageContent
header={<PageHeader title='Create environment' />}
>
<Alert severity='error'>
<p>
Currently Unleash does not support more than{' '}
{environmentLimit} environments. If you need
more please reach out.
</p>
</Alert>
<br />
<Button
onClick={handleCancel}
variant='contained'
color='primary'
>
Go back
</Button>
</PageContent>
</>
}
/>
); );
}; };

View File

@ -10,9 +10,6 @@ const LIMIT = 5;
const setupApi = () => { const setupApi = () => {
testServerRoute(server, '/api/admin/ui-config', { testServerRoute(server, '/api/admin/ui-config', {
flags: {
resourceLimits: true,
},
resourceLimits: { resourceLimits: {
constraints: LIMIT, constraints: LIMIT,
}, },

View File

@ -1,8 +1,7 @@
import type React from 'react'; import type React from 'react';
import { forwardRef, type RefObject } from 'react'; import { forwardRef, type RefObject } from 'react';
import { Box, Button, styled, Tooltip, Typography } from '@mui/material'; import { Box, Button, styled, Typography } from '@mui/material';
import Add from '@mui/icons-material/Add'; import Add from '@mui/icons-material/Add';
import HelpOutline from '@mui/icons-material/HelpOutline';
import type { IConstraint } from 'interfaces/strategy'; import type { IConstraint } from 'interfaces/strategy';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
@ -13,7 +12,6 @@ import {
} 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 { Limit } from 'component/common/Limit/Limit';
import { useUiFlag } from 'hooks/useUiFlag';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
interface IConstraintAccordionListProps { interface IConstraintAccordionListProps {
@ -32,30 +30,6 @@ const StyledContainer = styled('div')({
flexDirection: 'column', flexDirection: 'column',
}); });
const StyledHelpWrapper = styled(Tooltip)(({ theme }) => ({
marginLeft: theme.spacing(0.75),
height: theme.spacing(1.5),
}));
const StyledHelp = styled(HelpOutline)(({ theme }) => ({
fill: theme.palette.action.active,
[theme.breakpoints.down(860)]: {
display: 'none',
},
}));
const StyledConstraintLabel = styled('p')(({ theme }) => ({
marginBottom: theme.spacing(1),
color: theme.palette.text.secondary,
}));
const StyledAddCustomLabel = styled('div')(({ theme }) => ({
marginTop: theme.spacing(1),
marginBottom: theme.spacing(1),
color: theme.palette.text.primary,
display: 'flex',
}));
const StyledHelpIconBox = styled(Box)(({ theme }) => ({ const StyledHelpIconBox = styled(Box)(({ theme }) => ({
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
@ -64,14 +38,11 @@ const StyledHelpIconBox = styled(Box)(({ theme }) => ({
})); }));
const useConstraintLimit = (constraintsCount: number) => { const useConstraintLimit = (constraintsCount: number) => {
const resourceLimitsEnabled = useUiFlag('resourceLimits');
const { uiConfig } = useUiConfig(); const { uiConfig } = useUiConfig();
const constraintsLimit = uiConfig.resourceLimits?.constraints || 30; const constraintsLimit = uiConfig.resourceLimits?.constraints || 30;
const limitReached = const limitReached = constraintsCount >= constraintsLimit;
resourceLimitsEnabled && constraintsCount >= constraintsLimit;
return { return {
resourceLimitsEnabled,
limit: constraintsLimit, limit: constraintsLimit,
limitReached, limitReached,
}; };
@ -80,17 +51,12 @@ const useConstraintLimit = (constraintsCount: number) => {
export const FeatureStrategyConstraintAccordionList = forwardRef< export const FeatureStrategyConstraintAccordionList = forwardRef<
IConstraintAccordionListRef | undefined, IConstraintAccordionListRef | undefined,
IConstraintAccordionListProps IConstraintAccordionListProps
>( >(({ constraints, setConstraints, showCreateButton }, ref) => {
(
{ constraints, setConstraints, showCreateButton, showLabel = true },
ref,
) => {
const { onAdd, state, context } = useConstraintAccordionList( const { onAdd, state, context } = useConstraintAccordionList(
setConstraints, setConstraints,
ref as RefObject<IConstraintAccordionListRef>, ref as RefObject<IConstraintAccordionListRef>,
); );
const { resourceLimitsEnabled, limit, limitReached } = const { limit, limitReached } = useConstraintLimit(constraints.length);
useConstraintLimit(constraints.length);
if (context.length === 0) { if (context.length === 0) {
return null; return null;
@ -109,11 +75,10 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
tooltip={ tooltip={
<Box> <Box>
<Typography variant='body2'> <Typography variant='body2'>
Constraints are advanced Constraints are advanced targeting
targeting rules that you can use rules that you can use to enable a
to enable a feature flag for a feature flag for a subset of your
subset of your users. Read more users. Read more about constraints{' '}
about constraints{' '}
<a <a
href='https://docs.getunleash.io/reference/strategy-constraints' href='https://docs.getunleash.io/reference/strategy-constraints'
target='_blank' target='_blank'
@ -139,17 +104,12 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
marginBottom: theme.spacing(2), marginBottom: theme.spacing(2),
})} })}
> >
<ConditionallyRender
condition={resourceLimitsEnabled}
show={
<Limit <Limit
name='constraints in this strategy' name='constraints in this strategy'
shortName='constraints' shortName='constraints'
currentValue={constraints.length} currentValue={constraints.length}
limit={limit} limit={limit}
/> />
}
/>
</Box> </Box>
<Button <Button
@ -168,5 +128,4 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
/> />
</StyledContainer> </StyledContainer>
); );
}, });
);

View File

@ -36,21 +36,15 @@ import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
import { useDefaultStrategy } from '../../../project/Project/ProjectSettings/ProjectDefaultStrategySettings/ProjectEnvironment/ProjectEnvironmentDefaultStrategy/EditDefaultStrategy'; import { useDefaultStrategy } from '../../../project/Project/ProjectSettings/ProjectDefaultStrategySettings/ProjectEnvironment/ProjectEnvironmentDefaultStrategy/EditDefaultStrategy';
import { FeatureStrategyForm } from '../FeatureStrategyForm/FeatureStrategyForm'; import { FeatureStrategyForm } from '../FeatureStrategyForm/FeatureStrategyForm';
import { NewStrategyVariants } from 'component/feature/StrategyTypes/NewStrategyVariants'; import { NewStrategyVariants } from 'component/feature/StrategyTypes/NewStrategyVariants';
import { useUiFlag } from 'hooks/useUiFlag';
import { Limit } from 'component/common/Limit/Limit'; import { Limit } from 'component/common/Limit/Limit';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
const useStrategyLimit = (strategyCount: number) => { const useStrategyLimit = (strategyCount: number) => {
const resourceLimitsEnabled = useUiFlag('resourceLimits');
const { uiConfig } = useUiConfig(); const { uiConfig } = useUiConfig();
const featureEnvironmentStrategiesLimit = const featureEnvironmentStrategiesLimit =
uiConfig.resourceLimits?.featureEnvironmentStrategies || 100; uiConfig.resourceLimits?.featureEnvironmentStrategies || 100;
const limitReached = const limitReached = strategyCount >= featureEnvironmentStrategiesLimit;
resourceLimitsEnabled &&
strategyCount >= featureEnvironmentStrategiesLimit;
return { return {
resourceLimitsEnabled,
limit: featureEnvironmentStrategiesLimit, limit: featureEnvironmentStrategiesLimit,
limitReached, limitReached,
}; };
@ -93,8 +87,7 @@ export const FeatureStrategyCreate = () => {
(featureEnvironment) => featureEnvironment.name === environmentId, (featureEnvironment) => featureEnvironment.name === environmentId,
); );
const strategyCount = featureEnvironment?.strategies.length || 0; const strategyCount = featureEnvironment?.strategies.length || 0;
const { limit, limitReached, resourceLimitsEnabled } = const { limit, limitReached } = useStrategyLimit(strategyCount);
useStrategyLimit(strategyCount);
const ref = useRef<IFeatureToggle>(feature); const ref = useRef<IFeatureToggle>(feature);
const { isChangeRequestConfigured } = useChangeRequestsEnabled(projectId); const { isChangeRequestConfigured } = useChangeRequestsEnabled(projectId);
const { refetch: refetchChangeRequests } = const { refetch: refetchChangeRequests } =
@ -247,9 +240,6 @@ export const FeatureStrategyCreate = () => {
/> />
} }
Limit={ Limit={
<ConditionallyRender
condition={resourceLimitsEnabled}
show={
<Limit <Limit
name='strategies in this environment' name='strategies in this environment'
shortName='strategies' shortName='strategies'
@ -257,8 +247,6 @@ export const FeatureStrategyCreate = () => {
limit={limit} limit={limit}
/> />
} }
/>
}
disabled={limitReached} disabled={limitReached}
/> />
{staleDataNotification} {staleDataNotification}

View File

@ -86,7 +86,6 @@ export const setupUiConfigEndpoint = () => {
environment: 'enterprise', environment: 'enterprise',
flags: { flags: {
newStrategyConfiguration: true, newStrategyConfiguration: true,
resourceLimits: true,
}, },
resourceLimits: { resourceLimits: {
featureEnvironmentStrategies: 2, featureEnvironmentStrategies: 2,

View File

@ -8,12 +8,7 @@ const server = testServerSetup();
const setupApi = (existingProjectsCount: number) => { const setupApi = (existingProjectsCount: number) => {
testServerRoute(server, '/api/admin/ui-config', { testServerRoute(server, '/api/admin/ui-config', {
flags: { resourceLimits: { projects: 1 },
resourceLimits: true,
},
resourceLimits: {
projects: 1,
},
versionInfo: { versionInfo: {
current: { enterprise: 'version' }, current: { enterprise: 'version' },
}, },

View File

@ -16,7 +16,6 @@ import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { Dialog, styled } from '@mui/material'; import { Dialog, styled } from '@mui/material';
import { useUiFlag } from 'hooks/useUiFlag';
import useProjects from 'hooks/api/getters/useProjects/useProjects'; import useProjects from 'hooks/api/getters/useProjects/useProjects';
import { Limit } from 'component/common/Limit/Limit'; import { Limit } from 'component/common/Limit/Limit';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
@ -96,15 +95,12 @@ const configButtonData = {
}; };
const useProjectLimit = () => { const useProjectLimit = () => {
const resourceLimitsEnabled = useUiFlag('resourceLimits');
const { projects, loading: loadingProjects } = useProjects(); const { projects, loading: loadingProjects } = useProjects();
const { uiConfig, loading: loadingConfig } = useUiConfig(); const { uiConfig, loading: loadingConfig } = useUiConfig();
const projectsLimit = uiConfig.resourceLimits?.projects; const projectsLimit = uiConfig.resourceLimits?.projects;
const limitReached = const limitReached = projects.length >= projectsLimit;
resourceLimitsEnabled && projects.length >= projectsLimit;
return { return {
resourceLimitsEnabled,
limit: projectsLimit, limit: projectsLimit,
currentValue: projects.length, currentValue: projects.length,
limitReached, limitReached,
@ -201,7 +197,6 @@ export const CreateProjectDialog = ({
}; };
const { const {
resourceLimitsEnabled,
limit, limit,
currentValue, currentValue,
limitReached, limitReached,
@ -251,17 +246,12 @@ export const CreateProjectDialog = ({
creatingProject || limitReached || loadingLimit, creatingProject || limitReached || loadingLimit,
}} }}
Limit={ Limit={
<ConditionallyRender
condition={resourceLimitsEnabled}
show={
<Limit <Limit
name='projects' name='projects'
limit={limit} limit={limit}
currentValue={currentValue} currentValue={currentValue}
/> />
} }
/>
}
handleSubmit={handleSubmit} handleSubmit={handleSubmit}
name={projectName} name={projectName}
setName={setProjectName} setName={setProjectName}

View File

@ -12,7 +12,6 @@ import {
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { Dialog, styled } from '@mui/material'; import { Dialog, styled } from '@mui/material';
import { useUiFlag } from 'hooks/useUiFlag';
import useProjects from 'hooks/api/getters/useProjects/useProjects'; import useProjects from 'hooks/api/getters/useProjects/useProjects';
import { Limit } from 'component/common/Limit/Limit'; import { Limit } from 'component/common/Limit/Limit';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
@ -174,8 +173,6 @@ const CreateFeatureDialogContent = ({
const { project: projectInfo } = useProjectOverview(project); const { project: projectInfo } = useProjectOverview(project);
const { tags: allTags } = useAllTags(); const { tags: allTags } = useAllTags();
const resourceLimitsEnabled = useUiFlag('resourceLimits');
const { globalFlagLimitReached, projectFlagLimitReached, limitMessage } = const { globalFlagLimitReached, projectFlagLimitReached, limitMessage } =
useFlagLimits({ useFlagLimits({
global: { global: {
@ -233,17 +230,12 @@ const CreateFeatureDialogContent = ({
Icon={<FlagIcon />} Icon={<FlagIcon />}
validateName={validateToggleName} validateName={validateToggleName}
Limit={ Limit={
<ConditionallyRender
condition={resourceLimitsEnabled}
show={
<Limit <Limit
name='feature flags' name='feature flags'
limit={uiConfig.resourceLimits.featureFlags} limit={uiConfig.resourceLimits.featureFlags}
currentValue={totalFlags ?? 0} currentValue={totalFlags ?? 0}
/> />
} }
/>
}
name={name} name={name}
onClose={onClose} onClose={onClose}
resource={'feature flag'} resource={'feature flag'}

View File

@ -1,5 +1,3 @@
import { useUiFlag } from 'hooks/useUiFlag';
type FlagLimitsProps = { type FlagLimitsProps = {
global: { limit: number; count: number }; global: { limit: number; count: number };
project: { limit?: number; count: number }; project: { limit?: number; count: number };
@ -30,8 +28,7 @@ export const useFlagLimits = ({ global, project }: FlagLimitsProps) => {
}; };
const useGlobalFlagLimit = (flagLimit: number, flagCount: number) => { const useGlobalFlagLimit = (flagLimit: number, flagCount: number) => {
const resourceLimitsEnabled = useUiFlag('resourceLimits'); const limitReached = flagCount >= flagLimit;
const limitReached = resourceLimitsEnabled && flagCount >= flagLimit;
return { return {
limitReached, limitReached,

View File

@ -8,12 +8,7 @@ const server = testServerSetup();
const setupApi = () => { const setupApi = () => {
testServerRoute(server, '/api/admin/ui-config', { testServerRoute(server, '/api/admin/ui-config', {
flags: { resourceLimits: { projects: 1 },
resourceLimits: true,
},
resourceLimits: {
projects: 1,
},
versionInfo: { versionInfo: {
current: { enterprise: 'version' }, current: { enterprise: 'version' },
}, },

View File

@ -18,7 +18,6 @@ const setupRoutes = ({
testServerRoute(server, '/api/admin/ui-config', { testServerRoute(server, '/api/admin/ui-config', {
flags: { flags: {
SE: true, SE: true,
resourceLimits: true,
}, },
resourceLimits: { resourceLimits: {
segments: limit, segments: limit,

View File

@ -20,7 +20,6 @@ import {
import { SegmentProjectAlert } from './SegmentProjectAlert'; import { SegmentProjectAlert } from './SegmentProjectAlert';
import { sortStrategiesByFeature } from './SegmentDelete/SegmentDeleteUsedSegment/sort-strategies'; import { sortStrategiesByFeature } from './SegmentDelete/SegmentDeleteUsedSegment/sort-strategies';
import type { IFeatureStrategy } from 'interfaces/strategy'; import type { IFeatureStrategy } from 'interfaces/strategy';
import { useUiFlag } from 'hooks/useUiFlag';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { useSegments } from 'hooks/api/getters/useSegments/useSegments'; import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
import { Limit } from '../common/Limit/Limit'; import { Limit } from '../common/Limit/Limit';
@ -37,15 +36,15 @@ interface ISegmentFormPartOneProps {
setCurrentStep: React.Dispatch<React.SetStateAction<SegmentFormStep>>; setCurrentStep: React.Dispatch<React.SetStateAction<SegmentFormStep>>;
} }
const StyledForm = styled('div')(({ theme }) => ({ const StyledForm = styled('div')({
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
height: '100%', height: '100%',
})); });
const StyledContainer = styled('div')(({ theme }) => ({ const StyledContainer = styled('div')({
maxWidth: '400px', maxWidth: '400px',
})); });
const StyledInputDescription = styled('p')(({ theme }) => ({ const StyledInputDescription = styled('p')(({ theme }) => ({
marginBottom: theme.spacing(1), marginBottom: theme.spacing(1),
@ -56,11 +55,11 @@ const StyledInput = styled(Input)(({ theme }) => ({
marginBottom: theme.spacing(2), marginBottom: theme.spacing(2),
})); }));
const StyledButtonContainer = styled('div')(({ theme }) => ({ const StyledButtonContainer = styled('div')({
marginTop: 'auto', marginTop: 'auto',
display: 'flex', display: 'flex',
justifyContent: 'flex-end', justifyContent: 'flex-end',
})); });
const StyledCancelButton = styled(Button)(({ theme }) => ({ const StyledCancelButton = styled(Button)(({ theme }) => ({
marginLeft: theme.spacing(3), marginLeft: theme.spacing(3),
@ -79,16 +78,13 @@ const useSegmentLimit = () => {
const { uiConfig, loading: loadingConfig } = useUiConfig(); const { uiConfig, loading: loadingConfig } = useUiConfig();
const segmentsLimit = uiConfig.resourceLimits.segments; const segmentsLimit = uiConfig.resourceLimits.segments;
const segmentsCount = segments?.length || 0; const segmentsCount = segments?.length || 0;
const resourceLimitsEnabled = useUiFlag('resourceLimits'); const limitReached = segmentsCount >= segmentsLimit;
const limitReached =
resourceLimitsEnabled && segmentsCount >= segmentsLimit;
return { return {
limit: segmentsLimit, limit: segmentsLimit,
limitReached, limitReached,
currentCount: segmentsCount, currentCount: segmentsCount,
loading: loadingSegments || loadingConfig, loading: loadingSegments || loadingConfig,
resourceLimitsEnabled,
}; };
}; };
@ -111,7 +107,6 @@ export const SegmentFormStepOne: React.FC<ISegmentFormPartOneProps> = ({
limit, limit,
currentCount, currentCount,
loading: loadingSegmentLimit, loading: loadingSegmentLimit,
resourceLimitsEnabled,
} = useSegmentLimit(); } = useSegmentLimit();
const { const {
@ -204,16 +199,11 @@ export const SegmentFormStepOne: React.FC<ISegmentFormPartOneProps> = ({
</StyledContainer> </StyledContainer>
<LimitContainer> <LimitContainer>
<ConditionallyRender
condition={resourceLimitsEnabled}
show={
<Limit <Limit
name='segments' name='segments'
limit={limit} limit={limit}
currentValue={currentCount} currentValue={currentCount}
/> />
}
/>
</LimitContainer> </LimitContainer>
<StyledButtonContainer> <StyledButtonContainer>

View File

@ -88,7 +88,6 @@ export type UiFlags = {
enableLegacyVariants?: boolean; enableLegacyVariants?: boolean;
navigationSidebar?: boolean; navigationSidebar?: boolean;
flagCreator?: boolean; flagCreator?: boolean;
resourceLimits?: boolean;
newEventSearch?: boolean; newEventSearch?: boolean;
archiveProjects?: boolean; archiveProjects?: boolean;
projectListImprovements?: boolean; projectListImprovements?: boolean;

View File

@ -142,7 +142,6 @@ exports[`should create default config 1`] = `
"projectOverviewRefactorFeedback": false, "projectOverviewRefactorFeedback": false,
"queryMissingTokens": false, "queryMissingTokens": false,
"removeUnsafeInlineStyleSrc": false, "removeUnsafeInlineStyleSrc": false,
"resourceLimits": false,
"responseTimeMetricsFix": false, "responseTimeMetricsFix": false,
"responseTimeWithAppNameKillSwitch": false, "responseTimeWithAppNameKillSwitch": false,
"showInactiveUsers": false, "showInactiveUsers": false,

View File

@ -378,8 +378,6 @@ class FeatureToggleService {
environment: string; environment: string;
featureName: string; featureName: string;
}) { }) {
if (!this.flagResolver.isEnabled('resourceLimits')) return;
const limit = this.resourceLimits.featureEnvironmentStrategies; const limit = this.resourceLimits.featureEnvironmentStrategies;
const existingCount = ( const existingCount = (
await this.featureStrategiesStore.getStrategiesForFeatureEnv( await this.featureStrategiesStore.getStrategiesForFeatureEnv(
@ -400,8 +398,6 @@ class FeatureToggleService {
updated: IConstraint[]; updated: IConstraint[];
existing: IConstraint[]; existing: IConstraint[];
}) { }) {
if (!this.flagResolver.isEnabled('resourceLimits')) return;
const { const {
constraints: constraintsLimit, constraints: constraintsLimit,
constraintValues: constraintValuesLimit, constraintValues: constraintValuesLimit,
@ -1223,7 +1219,6 @@ class FeatureToggleService {
} }
private async validateFeatureFlagLimit() { private async validateFeatureFlagLimit() {
if (this.flagResolver.isEnabled('resourceLimits')) {
const currentFlagCount = await this.featureToggleStore.count(); const currentFlagCount = await this.featureToggleStore.count();
const limit = this.resourceLimits.featureFlags; const limit = this.resourceLimits.featureFlags;
if (currentFlagCount >= limit) { if (currentFlagCount >= limit) {
@ -1233,7 +1228,6 @@ class FeatureToggleService {
}); });
} }
} }
}
private async validateActiveProject(projectId: string) { private async validateActiveProject(projectId: string) {
if (this.flagResolver.isEnabled('archiveProjects')) { if (this.flagResolver.isEnabled('archiveProjects')) {

View File

@ -14,9 +14,7 @@ test('Should not allow to exceed project limit on create', async () => {
const projectService = createFakeProjectService({ const projectService = createFakeProjectService({
...createTestConfig(), ...createTestConfig(),
flagResolver: alwaysOnFlagResolver, flagResolver: alwaysOnFlagResolver,
resourceLimits: { resourceLimits: { projects: LIMIT },
projects: LIMIT,
},
eventBus: { eventBus: {
emit: () => {}, emit: () => {},
}, },
@ -37,9 +35,7 @@ test('Should not allow to exceed project limit on revive', async () => {
const projectService = createFakeProjectService({ const projectService = createFakeProjectService({
...createTestConfig(), ...createTestConfig(),
flagResolver: alwaysOnFlagResolver, flagResolver: alwaysOnFlagResolver,
resourceLimits: { resourceLimits: { projects: LIMIT },
projects: LIMIT,
},
eventBus: { eventBus: {
emit: () => {}, emit: () => {},
}, },

View File

@ -325,8 +325,6 @@ export default class ProjectService {
} }
async validateProjectLimit() { async validateProjectLimit() {
if (!this.flagResolver.isEnabled('resourceLimits')) return;
const limit = Math.max(this.resourceLimits.projects, 1); const limit = Math.max(this.resourceLimits.projects, 1);
const projectCount = await this.projectStore.count(); const projectCount = await this.projectStore.count();

View File

@ -13,9 +13,7 @@ test('Should not allow to exceed segment limit', async () => {
const segmentService = createFakeSegmentService({ const segmentService = createFakeSegmentService({
getLogger, getLogger,
flagResolver: alwaysOnFlagResolver, flagResolver: alwaysOnFlagResolver,
resourceLimits: { resourceLimits: { segments: LIMIT },
segments: LIMIT,
},
eventBus: { eventBus: {
emit: () => {}, emit: () => {},
}, },

View File

@ -129,8 +129,6 @@ export class SegmentService implements ISegmentService {
} }
async validateSegmentLimit() { async validateSegmentLimit() {
if (!this.flagResolver.isEnabled('resourceLimits')) return;
const limit = this.resourceLimits.segments; const limit = this.resourceLimits.segments;
const segmentCount = await this.segmentStore.count(); const segmentCount = await this.segmentStore.count();

View File

@ -7,9 +7,7 @@ import { createFakeApiTokenService } from '../features/api-tokens/createApiToken
const createServiceWithLimit = (limit: number) => { const createServiceWithLimit = (limit: number) => {
const config: IUnleashConfig = createTestConfig({ const config: IUnleashConfig = createTestConfig({
experimental: { experimental: {
flags: { flags: {},
resourceLimits: true,
},
}, },
}); });
config.resourceLimits.apiTokens = limit; config.resourceLimits.apiTokens = limit;

View File

@ -308,7 +308,6 @@ export class ApiTokenService {
} }
private async validateApiTokenLimit() { private async validateApiTokenLimit() {
if (this.flagResolver.isEnabled('resourceLimits')) {
const currentTokenCount = await this.store.count(); const currentTokenCount = await this.store.count();
const limit = this.resourceLimits.apiTokens; const limit = this.resourceLimits.apiTokens;
if (currentTokenCount >= limit) { if (currentTokenCount >= limit) {
@ -318,7 +317,6 @@ export class ApiTokenService {
}); });
} }
} }
}
// TODO: Remove this service method after embedded proxy has been released in // TODO: Remove this service method after embedded proxy has been released in
// 4.16.0 // 4.16.0

View File

@ -56,7 +56,6 @@ export type IFlagKey =
| 'enableLegacyVariants' | 'enableLegacyVariants'
| 'navigationSidebar' | 'navigationSidebar'
| 'anonymizeProjectOwners' | 'anonymizeProjectOwners'
| 'resourceLimits'
| 'extendedMetrics' | 'extendedMetrics'
| 'removeUnsafeInlineStyleSrc' | 'removeUnsafeInlineStyleSrc'
| 'originMiddleware' | 'originMiddleware'
@ -278,10 +277,6 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_ANONYMIZE_PROJECT_OWNERS, process.env.UNLEASH_EXPERIMENTAL_ANONYMIZE_PROJECT_OWNERS,
false, false,
), ),
resourceLimits: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_RESOURCE_LIMITS,
false,
),
extendedMetrics: parseEnvVarBoolean( extendedMetrics: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_EXTENDED_METRICS, process.env.UNLEASH_EXPERIMENTAL_EXTENDED_METRICS,
false, false,

View File

@ -50,7 +50,6 @@ process.nextTick(async () => {
projectOverviewRefactorFeedback: true, projectOverviewRefactorFeedback: true,
manyStrategiesPagination: true, manyStrategiesPagination: true,
enableLegacyVariants: false, enableLegacyVariants: false,
resourceLimits: true,
extendedMetrics: true, extendedMetrics: true,
originMiddleware: true, originMiddleware: true,
newEventSearch: true, newEventSearch: true,