1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-25 00:07:47 +01: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) => {
testServerRoute(server, '/api/admin/ui-config', {
flags: {
resourceLimits: true,
},
resourceLimits: {
apiTokens: 1,
},

View File

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

View File

@ -11,12 +11,7 @@ const setupApi = ({
apiTokenLimit,
}: { apiTokenCount: number; apiTokenLimit: number }) => {
testServerRoute(server, '/api/admin/ui-config', {
flags: {
resourceLimits: true,
},
resourceLimits: {
apiTokens: apiTokenLimit,
},
resourceLimits: { apiTokens: apiTokenLimit },
});
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 Add from '@mui/icons-material/Add';
import { useApiTokens } from 'hooks/api/getters/useApiTokens/useApiTokens';
import { useUiFlag } from 'hooks/useUiFlag';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
interface ICreateApiTokenButton {
path: string;
@ -12,9 +11,7 @@ interface ICreateApiTokenButton {
}
const useApiTokenLimit = (apiTokenLimit: number, apiTokenCount: number) => {
const resourceLimitsEnabled = useUiFlag('resourceLimits');
const limitReached =
resourceLimitsEnabled && apiTokenCount >= apiTokenLimit;
const limitReached = apiTokenCount >= apiTokenLimit;
return {
limitReached,

View File

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

View File

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

View File

@ -7,14 +7,10 @@ import { ADMIN } from '../../providers/AccessProvider/permissions';
const server = testServerSetup();
const setupApi = ({
resourceLimits,
limit,
environments,
}: { resourceLimits: boolean; limit: number; environments: number }) => {
}: { limit: number; environments: number }) => {
testServerRoute(server, '/api/admin/ui-config', {
flags: {
resourceLimits,
},
resourceLimits: {
environments: limit,
},
@ -28,7 +24,7 @@ const setupApi = ({
};
test('show limit reached info', async () => {
setupApi({ environments: 1, limit: 1, resourceLimits: true });
setupApi({ environments: 1, limit: 1 });
render(<CreateEnvironment />, { permissions: [{ permission: ADMIN }] });
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 () => {
setupApi({ environments: 9, limit: 10, resourceLimits: true });
setupApi({ environments: 9, limit: 10 });
render(<CreateEnvironment />, { permissions: [{ permission: ADMIN }] });
await screen.findByText('You are nearing the limit for environments');
@ -48,10 +44,3 @@ test('show approaching limit info', async () => {
});
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 EnvironmentForm from '../EnvironmentForm/EnvironmentForm';
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 useEnvironmentApi from 'hooks/api/actions/useEnvironmentApi/useEnvironmentApi';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import useToast from 'hooks/useToast';
import { useEnvironments } from 'hooks/api/getters/useEnvironments/useEnvironments';
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 { PageHeader } from 'component/common/PageHeader/PageHeader';
import { formatUnknownError } from 'utils/formatUnknownError';
import { GO_BACK } from 'constants/navigate';
import { Limit } from 'component/common/Limit/Limit';
import { useUiFlag } from 'hooks/useUiFlag';
const CreateEnvironment = () => {
const { setToastApiError, setToastData } = useToast();
const { uiConfig } = useUiConfig();
const resourceLimitsEnabled = useUiFlag('resourceLimits');
const environmentLimit = uiConfig.resourceLimits.environments;
const navigate = useNavigate();
const { environments } = useEnvironments();
@ -73,13 +66,10 @@ const CreateEnvironment = () => {
};
return (
<ConditionallyRender
condition={resourceLimitsEnabled || canCreateMoreEnvs}
show={
<FormTemplate
loading={loading}
title='Create environment'
description='Environments allow you to manage your
<FormTemplate
loading={loading}
title='Create environment'
description='Environments allow you to manage your
product lifecycle from local development
through production. Your projects and
feature flags are accessible in all your
@ -89,66 +79,36 @@ const CreateEnvironment = () => {
development or test environment without
enabling the feature flag in the
production environment.'
documentationLink='https://docs.getunleash.io/reference/environments'
documentationLinkLabel='Environments documentation'
formatApiCode={formatApiCode}
>
<EnvironmentForm
errors={errors}
handleSubmit={handleSubmit}
handleCancel={handleCancel}
validateEnvironmentName={validateEnvironmentName}
name={name}
type={type}
setName={setName}
setType={setType}
mode='Create'
clearErrors={clearErrors}
Limit={
<ConditionallyRender
condition={resourceLimitsEnabled}
show={
<Limit
name='environments'
limit={environmentLimit}
currentValue={environments.length}
/>
}
/>
}
>
<CreateButton
name='environment'
permission={ADMIN}
disabled={!canCreateMoreEnvs}
/>
</EnvironmentForm>
</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>
</>
}
/>
documentationLink='https://docs.getunleash.io/reference/environments'
documentationLinkLabel='Environments documentation'
formatApiCode={formatApiCode}
>
<EnvironmentForm
errors={errors}
handleSubmit={handleSubmit}
handleCancel={handleCancel}
validateEnvironmentName={validateEnvironmentName}
name={name}
type={type}
setName={setName}
setType={setType}
mode='Create'
clearErrors={clearErrors}
Limit={
<Limit
name='environments'
limit={environmentLimit}
currentValue={environments.length}
/>
}
>
<CreateButton
name='environment'
permission={ADMIN}
disabled={!canCreateMoreEnvs}
/>
</EnvironmentForm>
</FormTemplate>
);
};

View File

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

View File

@ -1,8 +1,7 @@
import type React 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 HelpOutline from '@mui/icons-material/HelpOutline';
import type { IConstraint } from 'interfaces/strategy';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
@ -13,7 +12,6 @@ import {
} 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 {
@ -32,30 +30,6 @@ const StyledContainer = styled('div')({
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 }) => ({
display: 'flex',
alignItems: 'center',
@ -64,14 +38,11 @@ const StyledHelpIconBox = styled(Box)(({ theme }) => ({
}));
const useConstraintLimit = (constraintsCount: number) => {
const resourceLimitsEnabled = useUiFlag('resourceLimits');
const { uiConfig } = useUiConfig();
const constraintsLimit = uiConfig.resourceLimits?.constraints || 30;
const limitReached =
resourceLimitsEnabled && constraintsCount >= constraintsLimit;
const limitReached = constraintsCount >= constraintsLimit;
return {
resourceLimitsEnabled,
limit: constraintsLimit,
limitReached,
};
@ -80,93 +51,81 @@ const useConstraintLimit = (constraintsCount: number) => {
export const FeatureStrategyConstraintAccordionList = forwardRef<
IConstraintAccordionListRef | undefined,
IConstraintAccordionListProps
>(
(
{ constraints, setConstraints, showCreateButton, showLabel = true },
ref,
) => {
const { onAdd, state, context } = useConstraintAccordionList(
setConstraints,
ref as RefObject<IConstraintAccordionListRef>,
);
const { resourceLimitsEnabled, limit, limitReached } =
useConstraintLimit(constraints.length);
>(({ constraints, setConstraints, showCreateButton }, ref) => {
const { onAdd, state, context } = useConstraintAccordionList(
setConstraints,
ref as RefObject<IConstraintAccordionListRef>,
);
const { limit, limitReached } = useConstraintLimit(constraints.length);
if (context.length === 0) {
return null;
}
if (context.length === 0) {
return null;
}
return (
<StyledContainer id={constraintAccordionListId}>
<ConditionallyRender
condition={Boolean(showCreateButton && onAdd)}
show={
<div>
<StyledHelpIconBox>
<Typography>Constraints</Typography>
<HelpIcon
htmlTooltip
tooltip={
<Box>
<Typography variant='body2'>
Constraints are advanced
targeting rules that you can use
to enable a feature flag for a
subset of your users. Read more
about constraints{' '}
<a
href='https://docs.getunleash.io/reference/strategy-constraints'
target='_blank'
rel='noopener noreferrer'
>
here
</a>
</Typography>
</Box>
}
/>
</StyledHelpIconBox>
<NewConstraintAccordionList
ref={ref}
setConstraints={setConstraints}
constraints={constraints}
state={state}
return (
<StyledContainer id={constraintAccordionListId}>
<ConditionallyRender
condition={Boolean(showCreateButton && onAdd)}
show={
<div>
<StyledHelpIconBox>
<Typography>Constraints</Typography>
<HelpIcon
htmlTooltip
tooltip={
<Box>
<Typography variant='body2'>
Constraints are advanced targeting
rules that you can use to enable a
feature flag for a subset of your
users. Read more about constraints{' '}
<a
href='https://docs.getunleash.io/reference/strategy-constraints'
target='_blank'
rel='noopener noreferrer'
>
here
</a>
</Typography>
</Box>
}
/>
</StyledHelpIconBox>
<NewConstraintAccordionList
ref={ref}
setConstraints={setConstraints}
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>
<Box
sx={(theme) => ({
marginTop: theme.spacing(2),
marginBottom: theme.spacing(2),
})}
>
<Limit
name='constraints in this strategy'
shortName='constraints'
currentValue={constraints.length}
limit={limit}
/>
</Box>
<Button
type='button'
onClick={onAdd}
startIcon={<Add />}
variant='outlined'
color='primary'
data-testid='ADD_CONSTRAINT_BUTTON'
disabled={Boolean(limitReached)}
>
Add constraint
</Button>
</div>
}
/>
</StyledContainer>
);
},
);
<Button
type='button'
onClick={onAdd}
startIcon={<Add />}
variant='outlined'
color='primary'
data-testid='ADD_CONSTRAINT_BUTTON'
disabled={Boolean(limitReached)}
>
Add constraint
</Button>
</div>
}
/>
</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 { FeatureStrategyForm } from '../FeatureStrategyForm/FeatureStrategyForm';
import { NewStrategyVariants } from 'component/feature/StrategyTypes/NewStrategyVariants';
import { useUiFlag } from 'hooks/useUiFlag';
import { Limit } from 'component/common/Limit/Limit';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
const useStrategyLimit = (strategyCount: number) => {
const resourceLimitsEnabled = useUiFlag('resourceLimits');
const { uiConfig } = useUiConfig();
const featureEnvironmentStrategiesLimit =
uiConfig.resourceLimits?.featureEnvironmentStrategies || 100;
const limitReached =
resourceLimitsEnabled &&
strategyCount >= featureEnvironmentStrategiesLimit;
const limitReached = strategyCount >= featureEnvironmentStrategiesLimit;
return {
resourceLimitsEnabled,
limit: featureEnvironmentStrategiesLimit,
limitReached,
};
@ -93,8 +87,7 @@ export const FeatureStrategyCreate = () => {
(featureEnvironment) => featureEnvironment.name === environmentId,
);
const strategyCount = featureEnvironment?.strategies.length || 0;
const { limit, limitReached, resourceLimitsEnabled } =
useStrategyLimit(strategyCount);
const { limit, limitReached } = useStrategyLimit(strategyCount);
const ref = useRef<IFeatureToggle>(feature);
const { isChangeRequestConfigured } = useChangeRequestsEnabled(projectId);
const { refetch: refetchChangeRequests } =
@ -247,16 +240,11 @@ export const FeatureStrategyCreate = () => {
/>
}
Limit={
<ConditionallyRender
condition={resourceLimitsEnabled}
show={
<Limit
name='strategies in this environment'
shortName='strategies'
currentValue={strategyCount}
limit={limit}
/>
}
<Limit
name='strategies in this environment'
shortName='strategies'
currentValue={strategyCount}
limit={limit}
/>
}
disabled={limitReached}

View File

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

View File

@ -8,12 +8,7 @@ const server = testServerSetup();
const setupApi = (existingProjectsCount: number) => {
testServerRoute(server, '/api/admin/ui-config', {
flags: {
resourceLimits: true,
},
resourceLimits: {
projects: 1,
},
resourceLimits: { projects: 1 },
versionInfo: {
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 { useNavigate } from 'react-router-dom';
import { Dialog, styled } from '@mui/material';
import { useUiFlag } from 'hooks/useUiFlag';
import useProjects from 'hooks/api/getters/useProjects/useProjects';
import { Limit } from 'component/common/Limit/Limit';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
@ -96,15 +95,12 @@ const configButtonData = {
};
const useProjectLimit = () => {
const resourceLimitsEnabled = useUiFlag('resourceLimits');
const { projects, loading: loadingProjects } = useProjects();
const { uiConfig, loading: loadingConfig } = useUiConfig();
const projectsLimit = uiConfig.resourceLimits?.projects;
const limitReached =
resourceLimitsEnabled && projects.length >= projectsLimit;
const limitReached = projects.length >= projectsLimit;
return {
resourceLimitsEnabled,
limit: projectsLimit,
currentValue: projects.length,
limitReached,
@ -201,7 +197,6 @@ export const CreateProjectDialog = ({
};
const {
resourceLimitsEnabled,
limit,
currentValue,
limitReached,
@ -251,15 +246,10 @@ export const CreateProjectDialog = ({
creatingProject || limitReached || loadingLimit,
}}
Limit={
<ConditionallyRender
condition={resourceLimitsEnabled}
show={
<Limit
name='projects'
limit={limit}
currentValue={currentValue}
/>
}
<Limit
name='projects'
limit={limit}
currentValue={currentValue}
/>
}
handleSubmit={handleSubmit}

View File

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

View File

@ -1,5 +1,3 @@
import { useUiFlag } from 'hooks/useUiFlag';
type FlagLimitsProps = {
global: { 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 resourceLimitsEnabled = useUiFlag('resourceLimits');
const limitReached = resourceLimitsEnabled && flagCount >= flagLimit;
const limitReached = flagCount >= flagLimit;
return {
limitReached,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -308,15 +308,13 @@ export class ApiTokenService {
}
private async validateApiTokenLimit() {
if (this.flagResolver.isEnabled('resourceLimits')) {
const currentTokenCount = await this.store.count();
const limit = this.resourceLimits.apiTokens;
if (currentTokenCount >= limit) {
throwExceedsLimitError(this.eventBus, {
resource: 'api token',
limit,
});
}
const currentTokenCount = await this.store.count();
const limit = this.resourceLimits.apiTokens;
if (currentTokenCount >= limit) {
throwExceedsLimitError(this.eventBus, {
resource: 'api token',
limit,
});
}
}

View File

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

View File

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