diff --git a/frontend/src/component/segments/CreateSegmentButton/CreateSegmentButton.tsx b/frontend/src/component/segments/CreateSegmentButton/CreateSegmentButton.tsx
index 74711b6a78..4ececc5016 100644
--- a/frontend/src/component/segments/CreateSegmentButton/CreateSegmentButton.tsx
+++ b/frontend/src/component/segments/CreateSegmentButton/CreateSegmentButton.tsx
@@ -8,10 +8,7 @@ import { useNavigate } from 'react-router-dom';
import { useOptionalPathParam } from 'hooks/useOptionalPathParam';
import type { FC } from 'react';
-export const CreateSegmentButton: FC<{
- disabled: boolean;
- tooltip?: string;
-}> = ({ disabled, tooltip }) => {
+export const CreateSegmentButton: FC = () => {
const projectId = useOptionalPathParam('projectId');
const navigate = useNavigate();
@@ -26,10 +23,6 @@ export const CreateSegmentButton: FC<{
}}
permission={[CREATE_SEGMENT, UPDATE_PROJECT_SEGMENT]}
projectId={projectId}
- disabled={disabled}
- tooltipProps={{
- title: tooltip,
- }}
data-testid={NAVIGATE_TO_CREATE_SEGMENT}
>
New segment
diff --git a/frontend/src/component/segments/SegmentDocs.tsx b/frontend/src/component/segments/SegmentDocs.tsx
index 17b0aac148..03a241c8eb 100644
--- a/frontend/src/component/segments/SegmentDocs.tsx
+++ b/frontend/src/component/segments/SegmentDocs.tsx
@@ -16,7 +16,8 @@ export const SegmentDocsValuesInfo = () => {
target='_blank'
rel='noreferrer'
>
- at most {segmentValuesLimit} across all of its contraints
+ at most {segmentValuesLimit} values across all of its
+ constraints
.
diff --git a/frontend/src/component/segments/SegmentFormStepOne.test.tsx b/frontend/src/component/segments/SegmentFormStepOne.test.tsx
new file mode 100644
index 0000000000..a455bef761
--- /dev/null
+++ b/frontend/src/component/segments/SegmentFormStepOne.test.tsx
@@ -0,0 +1,75 @@
+import { render } from 'utils/testRenderer';
+import { screen, waitFor } from '@testing-library/react';
+import { testServerRoute, testServerSetup } from 'utils/testServer';
+import { SegmentFormStepOne } from './SegmentFormStepOne';
+
+const server = testServerSetup();
+
+const setupRoutes = ({
+ limit,
+ segments,
+}: { limit: number; segments: number }) => {
+ testServerRoute(server, 'api/admin/segments', {
+ segments: [...Array(segments).keys()].map((i) => ({
+ name: `segment${i}`,
+ })),
+ });
+
+ testServerRoute(server, '/api/admin/ui-config', {
+ flags: {
+ SE: true,
+ resourceLimits: true,
+ },
+ resourceLimits: {
+ segments: limit,
+ },
+ });
+};
+
+const irrelevant = () => {};
+
+test('Do not allow next step when limit reached', async () => {
+ setupRoutes({ limit: 1, segments: 1 });
+
+ render(
+ ,
+ );
+
+ await screen.findByText('You have reached the limit for segments');
+ const nextStep = await screen.findByText('Next');
+ expect(nextStep).toBeDisabled();
+});
+
+test('Allows next step when approaching limit', async () => {
+ setupRoutes({ limit: 10, segments: 9 });
+
+ render(
+ ,
+ );
+
+ await screen.findByText('You are nearing the limit for segments');
+ await waitFor(async () => {
+ const nextStep = await screen.findByText('Next');
+ expect(nextStep).toBeEnabled();
+ });
+});
diff --git a/frontend/src/component/segments/SegmentFormStepOne.tsx b/frontend/src/component/segments/SegmentFormStepOne.tsx
index 46097e0fcd..cb5a8b87ef 100644
--- a/frontend/src/component/segments/SegmentFormStepOne.tsx
+++ b/frontend/src/component/segments/SegmentFormStepOne.tsx
@@ -1,4 +1,4 @@
-import { Autocomplete, Button, styled, TextField } from '@mui/material';
+import { Autocomplete, Box, Button, styled, TextField } from '@mui/material';
import Input from 'component/common/Input/Input';
import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
@@ -20,6 +20,10 @@ 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';
interface ISegmentFormPartOneProps {
name: string;
@@ -62,6 +66,32 @@ const StyledCancelButton = styled(Button)(({ theme }) => ({
marginLeft: theme.spacing(3),
}));
+const LimitContainer = styled(Box)(({ theme }) => ({
+ flex: 1,
+ display: 'flex',
+ alignItems: 'flex-end',
+ marginTop: theme.spacing(3),
+ marginBottom: theme.spacing(3),
+}));
+
+const useSegmentLimit = () => {
+ const { segments, loading: loadingSegments } = useSegments();
+ const { uiConfig, loading: loadingConfig } = useUiConfig();
+ const segmentsLimit = uiConfig.resourceLimits.segments;
+ const segmentsCount = segments?.length || 0;
+ const resourceLimitsEnabled = useUiFlag('resourceLimits');
+ const limitReached =
+ resourceLimitsEnabled && segmentsCount >= segmentsLimit;
+
+ return {
+ limit: segmentsLimit,
+ limitReached,
+ currentCount: segmentsCount,
+ loading: loadingSegments || loadingConfig,
+ resourceLimitsEnabled,
+ };
+};
+
export const SegmentFormStepOne: React.FC = ({
name,
description,
@@ -76,6 +106,13 @@ export const SegmentFormStepOne: React.FC = ({
const projectId = useOptionalPathParam('projectId');
const navigate = useNavigate();
const { projects, loading: loadingProjects } = useProjects();
+ const {
+ limitReached,
+ limit,
+ currentCount,
+ loading: loadingSegmentLimit,
+ resourceLimitsEnabled,
+ } = useSegmentLimit();
const {
strategies,
@@ -106,7 +143,7 @@ export const SegmentFormStepOne: React.FC = ({
setSelectedProject(projects.find(({ id }) => id === project) ?? null);
}, [project, projects]);
- const loading = loadingProjects && loadingStrategies;
+ const loading = loadingProjects || loadingStrategies || loadingSegmentLimit;
return (
@@ -165,13 +202,32 @@ export const SegmentFormStepOne: React.FC = ({
}
/>
+
+
+
+ }
+ />
+
+