diff --git a/frontend/src/component/feature/FeatureStrategy/FeatureStrategySegment/FeatureStrategySegment.tsx b/frontend/src/component/feature/FeatureStrategy/FeatureStrategySegment/FeatureStrategySegment.tsx
index 6a8f2ebfd0..e84110f346 100644
--- a/frontend/src/component/feature/FeatureStrategy/FeatureStrategySegment/FeatureStrategySegment.tsx
+++ b/frontend/src/component/feature/FeatureStrategy/FeatureStrategySegment/FeatureStrategySegment.tsx
@@ -8,7 +8,7 @@ import {
import { FeatureStrategySegmentList } from 'component/feature/FeatureStrategy/FeatureStrategySegment/FeatureStrategySegmentList';
import { useStyles } from 'component/feature/FeatureStrategy/FeatureStrategySegment/FeatureStrategySegment.styles';
import { SegmentDocsStrategyWarning } from 'component/segments/SegmentDocs/SegmentDocs';
-import { STRATEGY_SEGMENTS_LIMIT } from 'utils/segmentLimits';
+import { useSegmentLimits } from 'hooks/api/getters/useSegmentLimits/useSegmentLimits';
interface IFeatureStrategySegmentProps {
segments: ISegment[];
@@ -19,9 +19,14 @@ export const FeatureStrategySegment = ({
segments: selectedSegments,
setSegments: setSelectedSegments,
}: IFeatureStrategySegmentProps) => {
- const atSegmentsLimit = selectedSegments.length >= STRATEGY_SEGMENTS_LIMIT;
const { segments: allSegments } = useSegments();
const { classes: styles } = useStyles();
+ const { strategySegmentsLimit } = useSegmentLimits();
+
+ const atStrategySegmentsLimit: boolean = Boolean(
+ strategySegmentsLimit &&
+ selectedSegments.length >= strategySegmentsLimit
+ );
if (!allSegments || allSegments.length === 0) {
return null;
@@ -48,13 +53,13 @@ export const FeatureStrategySegment = ({
return (
<>
Segmentation
- {atSegmentsLimit && }
+ {atStrategySegmentsLimit && }
Add a predefined segment to constrain this feature toggle:
;
diff --git a/frontend/src/component/segments/CreateSegment/CreateSegment.tsx b/frontend/src/component/segments/CreateSegment/CreateSegment.tsx
index d53224c917..29dd893f27 100644
--- a/frontend/src/component/segments/CreateSegment/CreateSegment.tsx
+++ b/frontend/src/component/segments/CreateSegment/CreateSegment.tsx
@@ -14,8 +14,8 @@ import { SegmentForm } from '../SegmentForm/SegmentForm';
import { feedbackCESContext } from 'component/feedback/FeedbackCESContext/FeedbackCESContext';
import { segmentsDocsLink } from 'component/segments/SegmentDocs/SegmentDocs';
import { useSegmentValuesCount } from 'component/segments/hooks/useSegmentValuesCount';
-import { SEGMENT_VALUES_LIMIT } from 'utils/segmentLimits';
import { SEGMENT_CREATE_BTN_ID } from 'utils/testIds';
+import { useSegmentLimits } from 'hooks/api/getters/useSegmentLimits/useSegmentLimits';
export const CreateSegment = () => {
const { uiConfig } = useUiConfig();
@@ -38,8 +38,12 @@ export const CreateSegment = () => {
} = useSegmentForm();
const hasValidConstraints = useConstraintsValidation(constraints);
+ const { segmentValuesLimit } = useSegmentLimits();
const segmentValuesCount = useSegmentValuesCount(constraints);
- const atSegmentValuesLimit = segmentValuesCount >= SEGMENT_VALUES_LIMIT;
+
+ const overSegmentValuesLimit: boolean = Boolean(
+ segmentValuesLimit && segmentValuesCount > segmentValuesLimit
+ );
const formatApiCode = () => {
return `curl --location --request POST '${
@@ -96,7 +100,7 @@ export const CreateSegment = () => {
diff --git a/frontend/src/component/segments/EditSegment/EditSegment.tsx b/frontend/src/component/segments/EditSegment/EditSegment.tsx
index 7757d30bcf..2a7ba360a4 100644
--- a/frontend/src/component/segments/EditSegment/EditSegment.tsx
+++ b/frontend/src/component/segments/EditSegment/EditSegment.tsx
@@ -16,8 +16,8 @@ import { segmentsFormDescription } from 'component/segments/CreateSegment/Create
import { UpdateButton } from 'component/common/UpdateButton/UpdateButton';
import { segmentsDocsLink } from 'component/segments/SegmentDocs/SegmentDocs';
import { useSegmentValuesCount } from 'component/segments/hooks/useSegmentValuesCount';
-import { SEGMENT_VALUES_LIMIT } from 'utils/segmentLimits';
import { SEGMENT_SAVE_BTN_ID } from 'utils/testIds';
+import { useSegmentLimits } from 'hooks/api/getters/useSegmentLimits/useSegmentLimits';
export const EditSegment = () => {
const segmentId = useRequiredPathParam('segmentId');
@@ -46,7 +46,11 @@ export const EditSegment = () => {
const hasValidConstraints = useConstraintsValidation(constraints);
const segmentValuesCount = useSegmentValuesCount(constraints);
- const atSegmentValuesLimit = segmentValuesCount >= SEGMENT_VALUES_LIMIT;
+ const { segmentValuesLimit } = useSegmentLimits();
+
+ const overSegmentValuesLimit: boolean = Boolean(
+ segmentValuesLimit && segmentValuesCount > segmentValuesLimit
+ );
const formatApiCode = () => {
return `curl --location --request PUT '${
@@ -98,7 +102,7 @@ export const EditSegment = () => {
>
diff --git a/frontend/src/component/segments/SegmentDocs/SegmentDocs.tsx b/frontend/src/component/segments/SegmentDocs/SegmentDocs.tsx
index 211a301907..1bb3b503b5 100644
--- a/frontend/src/component/segments/SegmentDocs/SegmentDocs.tsx
+++ b/frontend/src/component/segments/SegmentDocs/SegmentDocs.tsx
@@ -1,9 +1,6 @@
import { Alert } from '@mui/material';
import { useStyles } from 'component/segments/SegmentDocs/SegmentDocs.styles';
-import {
- STRATEGY_SEGMENTS_LIMIT,
- SEGMENT_VALUES_LIMIT,
-} from 'utils/segmentLimits';
+import { useSegmentLimits } from 'hooks/api/getters/useSegmentLimits/useSegmentLimits';
export const SegmentDocsWarning = () => {
const { classes: styles } = useStyles();
@@ -25,19 +22,31 @@ export const SegmentDocsWarning = () => {
};
export const SegmentDocsValuesWarning = () => {
+ const { segmentValuesLimit } = useSegmentLimits();
+
+ if (typeof segmentValuesLimit === 'undefined') {
+ return null;
+ }
+
return (
Segments is an experimental feature available to select users.
- Currently, segments are limited to at most {SEGMENT_VALUES_LIMIT}{' '}
+ Currently, segments are limited to at most {segmentValuesLimit}{' '}
values.
);
};
export const SegmentDocsValuesError = (props: { values: number }) => {
+ const { segmentValuesLimit } = useSegmentLimits();
+
+ if (typeof segmentValuesLimit === 'undefined') {
+ return null;
+ }
+
return (
- Segments are limited to at most {SEGMENT_VALUES_LIMIT} values. This
+ Segments are limited to at most {segmentValuesLimit} values. This
segment currently has {props.values}{' '}
{props.values === 1 ? 'value' : 'values'}.
@@ -45,9 +54,15 @@ export const SegmentDocsValuesError = (props: { values: number }) => {
};
export const SegmentDocsStrategyWarning = () => {
+ const { strategySegmentsLimit } = useSegmentLimits();
+
+ if (typeof strategySegmentsLimit === 'undefined') {
+ return null;
+ }
+
return (
- Strategies are limited to {STRATEGY_SEGMENTS_LIMIT} segments.{' '}
+ Strategies are limited to {strategySegmentsLimit} segments.{' '}
);
diff --git a/frontend/src/component/segments/SegmentFormStepTwo/SegmentFormStepTwo.tsx b/frontend/src/component/segments/SegmentFormStepTwo/SegmentFormStepTwo.tsx
index 6a6274e20d..0799f330f2 100644
--- a/frontend/src/component/segments/SegmentFormStepTwo/SegmentFormStepTwo.tsx
+++ b/frontend/src/component/segments/SegmentFormStepTwo/SegmentFormStepTwo.tsx
@@ -28,8 +28,8 @@ import {
SegmentDocsValuesError,
} from 'component/segments/SegmentDocs/SegmentDocs';
import { useSegmentValuesCount } from 'component/segments/hooks/useSegmentValuesCount';
-import { SEGMENT_VALUES_LIMIT } from 'utils/segmentLimits';
import AccessContext from 'contexts/AccessContext';
+import { useSegmentLimits } from 'hooks/api/getters/useSegmentLimits/useSegmentLimits';
interface ISegmentFormPartTwoProps {
constraints: IConstraint[];
@@ -52,8 +52,12 @@ export const SegmentFormStepTwo: React.FC = ({
const { context = [] } = useUnleashContext();
const [open, setOpen] = useState(false);
const segmentValuesCount = useSegmentValuesCount(constraints);
- const overSegmentValuesLimit = segmentValuesCount > SEGMENT_VALUES_LIMIT;
const modePermission = mode === 'create' ? CREATE_SEGMENT : UPDATE_SEGMENT;
+ const { segmentValuesLimit } = useSegmentLimits();
+
+ const overSegmentValuesLimit: boolean = Boolean(
+ segmentValuesLimit && segmentValuesCount > segmentValuesLimit
+ );
const autocompleteOptions = context.map(c => ({
value: c.name,
diff --git a/frontend/src/hooks/api/getters/useSegmentLimits/useSegmentLimits.ts b/frontend/src/hooks/api/getters/useSegmentLimits/useSegmentLimits.ts
new file mode 100644
index 0000000000..dd07e6fb55
--- /dev/null
+++ b/frontend/src/hooks/api/getters/useSegmentLimits/useSegmentLimits.ts
@@ -0,0 +1,16 @@
+import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
+import { IUiConfig } from 'interfaces/uiConfig';
+
+type IUseSegmentLimits = Pick<
+ IUiConfig,
+ 'segmentValuesLimit' | 'strategySegmentsLimit'
+>;
+
+export const useSegmentLimits = (): IUseSegmentLimits => {
+ const { uiConfig } = useUiConfig();
+
+ return {
+ segmentValuesLimit: uiConfig.segmentValuesLimit,
+ strategySegmentsLimit: uiConfig.strategySegmentsLimit,
+ };
+};
diff --git a/frontend/src/hooks/api/getters/useUiConfig/defaultValue.ts b/frontend/src/hooks/api/getters/useUiConfig/defaultValue.ts
index 1ad5b11b71..51d90d5dff 100644
--- a/frontend/src/hooks/api/getters/useUiConfig/defaultValue.ts
+++ b/frontend/src/hooks/api/getters/useUiConfig/defaultValue.ts
@@ -1,9 +1,9 @@
import { LibraryBooks } from '@mui/icons-material';
+import { IUiConfig } from 'interfaces/uiConfig';
-export const defaultValue = {
+export const defaultValue: IUiConfig = {
name: 'Unleash',
version: '3.x',
- environment: '',
slogan: 'The enterprise ready feature toggle service.',
flags: {
P: false,
diff --git a/frontend/src/hooks/api/getters/useUiConfig/useUiConfig.ts b/frontend/src/hooks/api/getters/useUiConfig/useUiConfig.ts
index e5fa78c01c..9ab1725009 100644
--- a/frontend/src/hooks/api/getters/useUiConfig/useUiConfig.ts
+++ b/frontend/src/hooks/api/getters/useUiConfig/useUiConfig.ts
@@ -1,40 +1,27 @@
-import useSWR, { mutate, SWRConfiguration } from 'swr';
+import useSWR from 'swr';
import { formatApiPath } from 'utils/formatPath';
import { defaultValue } from './defaultValue';
import { IUiConfig } from 'interfaces/uiConfig';
import handleErrorResponses from '../httpErrorResponseHandler';
-import { useMemo } from 'react';
+import { useMemo, useCallback } from 'react';
-const REQUEST_KEY = 'api/admin/ui-config';
+interface IUseUIConfigOutput {
+ uiConfig: IUiConfig;
+ loading: boolean;
+ error?: Error;
+ refetch: () => void;
+ isOss: () => boolean;
+}
-const useUiConfig = (options: SWRConfiguration = {}) => {
- const fetcher = () => {
- const path = formatApiPath(`api/admin/ui-config`);
+const useUiConfig = (): IUseUIConfigOutput => {
+ const path = formatApiPath(`api/admin/ui-config`);
+ const { data, error, mutate } = useSWR(path, fetcher);
- return fetch(path, {
- method: 'GET',
- credentials: 'include',
- })
- .then(handleErrorResponses('configuration'))
- .then(res => res.json());
- };
+ const isOss = useCallback(() => {
+ return !data?.versionInfo?.current?.enterprise;
+ }, [data]);
- const { data, error } = useSWR(REQUEST_KEY, fetcher, options);
-
- const refetch = () => {
- mutate(REQUEST_KEY);
- };
-
- const isOss = () => {
- if (data?.versionInfo?.current?.enterprise) {
- return false;
- } else if (!data || !data.versionInfo) {
- return false;
- }
- return true;
- };
-
- const uiConfig = useMemo(() => {
+ const uiConfig: IUiConfig = useMemo(() => {
return { ...defaultValue, ...data };
}, [data]);
@@ -42,9 +29,15 @@ const useUiConfig = (options: SWRConfiguration = {}) => {
uiConfig,
loading: !error && !data,
error,
- refetch,
+ refetch: mutate,
isOss,
};
};
+const fetcher = (path: string) => {
+ return fetch(path)
+ .then(handleErrorResponses('configuration'))
+ .then(res => res.json());
+};
+
export default useUiConfig;
diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts
index ea28afda0d..4ca783a355 100644
--- a/frontend/src/interfaces/uiConfig.ts
+++ b/frontend/src/interfaces/uiConfig.ts
@@ -1,15 +1,20 @@
+import { ReactNode } from 'react';
+
export interface IUiConfig {
- authenticationType: string;
- baseUriPath: string;
+ authenticationType?: string;
+ baseUriPath?: string;
flags: IFlags;
name: string;
slogan: string;
- unleashUrl: string;
+ environment?: string;
+ unleashUrl?: string;
version: string;
- versionInfo: IVersionInfo;
+ versionInfo?: IVersionInfo;
links: ILinks[];
disablePasswordAuth?: boolean;
toast?: IProclamationToast;
+ segmentValuesLimit?: number;
+ strategySegmentsLimit?: number;
}
export interface IProclamationToast {
@@ -46,7 +51,7 @@ export interface IVersion {
export interface ILinks {
value: string;
- icon: string;
+ icon: ReactNode;
href: string;
title: string;
}
diff --git a/frontend/src/utils/segmentLimits.ts b/frontend/src/utils/segmentLimits.ts
deleted file mode 100644
index 9837119c2a..0000000000
--- a/frontend/src/utils/segmentLimits.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export const SEGMENT_VALUES_LIMIT = 100;
-export const STRATEGY_SEGMENTS_LIMIT = 5;