diff --git a/frontend/src/component/segments/CreateSegmentButton/CreateSegmentButton.tsx b/frontend/src/component/segments/CreateSegmentButton/CreateSegmentButton.tsx
index 7ca62fe951bb..74711b6a7880 100644
--- a/frontend/src/component/segments/CreateSegmentButton/CreateSegmentButton.tsx
+++ b/frontend/src/component/segments/CreateSegmentButton/CreateSegmentButton.tsx
@@ -6,8 +6,12 @@ import PermissionButton from 'component/common/PermissionButton/PermissionButton
import { NAVIGATE_TO_CREATE_SEGMENT } from 'utils/testIds';
import { useNavigate } from 'react-router-dom';
import { useOptionalPathParam } from 'hooks/useOptionalPathParam';
+import type { FC } from 'react';
-export const CreateSegmentButton = () => {
+export const CreateSegmentButton: FC<{
+ disabled: boolean;
+ tooltip?: string;
+}> = ({ disabled, tooltip }) => {
const projectId = useOptionalPathParam('projectId');
const navigate = useNavigate();
@@ -22,6 +26,10 @@ export const CreateSegmentButton = () => {
}}
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/SegmentTable/SegmentTable.test.tsx b/frontend/src/component/segments/SegmentTable/SegmentTable.test.tsx
index 8c4d4ba65be6..87b66b05d8a2 100644
--- a/frontend/src/component/segments/SegmentTable/SegmentTable.test.tsx
+++ b/frontend/src/component/segments/SegmentTable/SegmentTable.test.tsx
@@ -2,6 +2,7 @@ import { render } from 'utils/testRenderer';
import { screen } from '@testing-library/react';
import { SegmentTable } from './SegmentTable';
import { testServerRoute, testServerSetup } from 'utils/testServer';
+import { CREATE_SEGMENT } from '../../providers/AccessProvider/permissions';
const server = testServerSetup();
@@ -23,6 +24,10 @@ const setupRoutes = () => {
testServerRoute(server, '/api/admin/ui-config', {
flags: {
SE: true,
+ resourceLimits: true,
+ },
+ resourceLimits: {
+ segments: 2,
},
});
};
@@ -30,8 +35,14 @@ const setupRoutes = () => {
test('should show the count of projects and features used in', async () => {
setupRoutes();
- render();
+ render(, { permissions: [{ permission: CREATE_SEGMENT }] });
+
+ const loadingSegment = await screen.findByText('New segment');
+ expect(loadingSegment).toBeDisabled();
await screen.findByText('2 feature flags');
await screen.findByText('3 projects');
+
+ const segment = await screen.findByText('New segment');
+ expect(segment).not.toBeDisabled();
});
diff --git a/frontend/src/component/segments/SegmentTable/SegmentTable.tsx b/frontend/src/component/segments/SegmentTable/SegmentTable.tsx
index c0d33139688e..c10d98446394 100644
--- a/frontend/src/component/segments/SegmentTable/SegmentTable.tsx
+++ b/frontend/src/component/segments/SegmentTable/SegmentTable.tsx
@@ -29,15 +29,41 @@ import { useConditionallyHiddenColumns } from 'hooks/useConditionallyHiddenColum
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
import { useOptionalPathParam } from 'hooks/useOptionalPathParam';
import { UsedInCell } from 'component/context/ContextList/UsedInCell';
+import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
+import { useUiFlag } from 'hooks/useUiFlag';
+
+const useSegmentLimit = (segmentsLimit: number, segmentsCount: number) => {
+ const resourceLimitsEnabled = useUiFlag('resourceLimits');
+ const limitReached =
+ resourceLimitsEnabled && segmentsCount >= segmentsLimit;
+
+ return {
+ limitReached,
+ limitMessage: limitReached
+ ? `Limit of ${segmentsCount} segments reached`
+ : undefined,
+ };
+};
export const SegmentTable = () => {
const projectId = useOptionalPathParam('projectId');
- const { segments, loading } = useSegments();
+ const { segments, loading: loadingSegments } = useSegments();
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
const [initialState] = useState({
sortBy: [{ id: 'createdAt' }],
hiddenColumns: ['description'],
});
+ const { uiConfig, loading: loadingConfig } = useUiConfig();
+ const segmentLimit = uiConfig.resourceLimits.segments;
+ const segmentCount = segments?.length || 0;
+
+ const { limitReached, limitMessage } = useSegmentLimit(
+ segmentLimit,
+ segmentCount,
+ );
+
+ const createSegmentDisabled =
+ loadingSegments || loadingConfig || limitReached;
const data = useMemo(() => {
if (!segments) {
@@ -112,15 +138,18 @@ export const SegmentTable = () => {
onChange={setGlobalFilter}
/>
-
+
>
}
/>
}
- isLoading={loading}
+ isLoading={loadingSegments}
>
diff --git a/frontend/src/hooks/api/getters/useUiConfig/defaultValue.tsx b/frontend/src/hooks/api/getters/useUiConfig/defaultValue.tsx
index 033faefd9149..b81dcbd045e8 100644
--- a/frontend/src/hooks/api/getters/useUiConfig/defaultValue.tsx
+++ b/frontend/src/hooks/api/getters/useUiConfig/defaultValue.tsx
@@ -41,5 +41,6 @@ export const defaultValue: IUiConfig = {
environments: 50,
constraintValues: 250,
projects: 500,
+ segments: 300,
},
};
diff --git a/frontend/src/openapi/models/resourceLimitsSchema.ts b/frontend/src/openapi/models/resourceLimitsSchema.ts
index f04845a529a4..5a5770852def 100644
--- a/frontend/src/openapi/models/resourceLimitsSchema.ts
+++ b/frontend/src/openapi/models/resourceLimitsSchema.ts
@@ -32,4 +32,6 @@ export interface ResourceLimitsSchema {
constraintValues: number;
/** The maximum number of projects allowed. */
projects: number;
+ /** The maximum number of segment allowed. */
+ segments: number;
}