diff --git a/frontend/src/component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/VariantForm/VariantForm.tsx b/frontend/src/component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/VariantForm/VariantForm.tsx index 236d0e6d66..fea165e547 100644 --- a/frontend/src/component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/VariantForm/VariantForm.tsx +++ b/frontend/src/component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/VariantForm/VariantForm.tsx @@ -19,6 +19,7 @@ import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashCon import { WeightType } from 'constants/variantTypes'; import { IFeatureVariantEdit } from '../EnvironmentVariantsModal'; import { Delete } from '@mui/icons-material'; +import { useUiFlag } from 'hooks/useUiFlag'; const StyledVariantForm = styled('div')(({ theme }) => ({ position: 'relative', @@ -195,6 +196,14 @@ export const VariantForm = ({ const [errors, setErrors] = useState({}); + const variantTypeNumber = useUiFlag('variantTypeNumber'); + + useEffect(() => { + if (variantTypeNumber) { + payloadOptions.push({ key: 'number', label: 'number' }); + } + }, [variantTypeNumber]); + const clearError = (field: ErrorField) => { setErrors(errors => ({ ...errors, [field]: undefined })); }; @@ -283,6 +292,9 @@ export const VariantForm = ({ if (payload.type === 'json') { JSON.parse(payload.value); } + if (variantTypeNumber && payload.type === 'number') { + Number(payload.value); + } return true; } catch (e: unknown) { return false; @@ -428,7 +440,12 @@ export const VariantForm = ({ name="variant-payload-value" label="Value" multiline={payload.type !== 'string'} - rows={payload.type === 'string' ? 1 : 4} + rows={ + payload.type === 'string' || + payload.type === 'number' + ? 1 + : 4 + } value={payload.value} onChange={e => { clearError(ErrorField.PAYLOAD); diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts index 91772b67f4..cdc94ecfa6 100644 --- a/frontend/src/interfaces/uiConfig.ts +++ b/frontend/src/interfaces/uiConfig.ts @@ -64,6 +64,7 @@ export type UiFlags = { multipleRoles?: boolean; featureNamingPattern?: boolean; doraMetrics?: boolean; + variantTypeNumber?: boolean; [key: string]: boolean | Variant | undefined; }; diff --git a/src/lib/__snapshots__/create-config.test.ts.snap b/src/lib/__snapshots__/create-config.test.ts.snap index 152ce1a640..c2bd0150a9 100644 --- a/src/lib/__snapshots__/create-config.test.ts.snap +++ b/src/lib/__snapshots__/create-config.test.ts.snap @@ -99,6 +99,7 @@ exports[`should create default config 1`] = ` "responseTimeWithAppNameKillSwitch": false, "slackAppAddon": false, "strictSchemaValidation": false, + "variantTypeNumber": false, }, }, "flagResolver": FlagResolver { @@ -134,6 +135,7 @@ exports[`should create default config 1`] = ` "responseTimeWithAppNameKillSwitch": false, "slackAppAddon": false, "strictSchemaValidation": false, + "variantTypeNumber": false, }, "externalResolver": { "getVariant": [Function], diff --git a/src/lib/features/playground/feature-evaluator/variant.ts b/src/lib/features/playground/feature-evaluator/variant.ts index 4448ff2635..6784836b2e 100644 --- a/src/lib/features/playground/feature-evaluator/variant.ts +++ b/src/lib/features/playground/feature-evaluator/variant.ts @@ -10,7 +10,7 @@ interface Override { } export interface Payload { - type: 'string' | 'csv' | 'json'; + type: 'string' | 'csv' | 'json' | 'number'; value: string; } diff --git a/src/lib/openapi/spec/__snapshots__/feature-schema.test.ts.snap b/src/lib/openapi/spec/__snapshots__/feature-schema.test.ts.snap index 90169d38ac..be88a656bf 100644 --- a/src/lib/openapi/spec/__snapshots__/feature-schema.test.ts.snap +++ b/src/lib/openapi/spec/__snapshots__/feature-schema.test.ts.snap @@ -29,6 +29,7 @@ exports[`featureSchema variant override values must be an array 1`] = ` "json", "csv", "string", + "number", ], }, "schemaPath": "#/properties/payload/properties/type/enum", diff --git a/src/lib/openapi/spec/create-strategy-variant-schema.ts b/src/lib/openapi/spec/create-strategy-variant-schema.ts index ec8532f9a7..0520cb8dfe 100644 --- a/src/lib/openapi/spec/create-strategy-variant-schema.ts +++ b/src/lib/openapi/spec/create-strategy-variant-schema.ts @@ -40,9 +40,9 @@ export const createStrategyVariantSchema = { properties: { type: { description: - 'The type of the value. Commonly used types are string, json and csv.', + 'The type of the value. Commonly used types are string, number, json and csv.', type: 'string', - enum: ['json', 'csv', 'string'], + enum: ['json', 'csv', 'string', 'number'], }, value: { description: 'The actual value of payload', diff --git a/src/lib/openapi/spec/playground-strategy-schema.ts b/src/lib/openapi/spec/playground-strategy-schema.ts index 3b94cd97b8..c039766a85 100644 --- a/src/lib/openapi/spec/playground-strategy-schema.ts +++ b/src/lib/openapi/spec/playground-strategy-schema.ts @@ -83,7 +83,7 @@ export const strategyEvaluationResults = { type: { description: 'The format of the payload.', type: 'string', - enum: ['json', 'csv', 'string'], + enum: ['json', 'csv', 'string', 'number'], }, value: { type: 'string', diff --git a/src/lib/openapi/spec/variant-schema.ts b/src/lib/openapi/spec/variant-schema.ts index c455fb3d18..c8920a44b8 100644 --- a/src/lib/openapi/spec/variant-schema.ts +++ b/src/lib/openapi/spec/variant-schema.ts @@ -42,9 +42,9 @@ export const variantSchema = { properties: { type: { description: - 'The type of the value. Commonly used types are string, json and csv.', + 'The type of the value. Commonly used types are string, number, json and csv.', type: 'string', - enum: ['json', 'csv', 'string'], + enum: ['json', 'csv', 'string', 'number'], }, value: { description: 'The actual value of payload', diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts index 76c1f63d05..b38fd6f8d7 100644 --- a/src/lib/types/experimental.ts +++ b/src/lib/types/experimental.ts @@ -27,7 +27,8 @@ export type IFlagKey = | 'integrationsRework' | 'multipleRoles' | 'featureNamingPattern' - | 'doraMetrics'; + | 'doraMetrics' + | 'variantTypeNumber'; export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>; @@ -127,6 +128,10 @@ const flags: IFlags = { process.env.UNLEASH_EXPERIMENTAL_DORA_METRICS, false, ), + variantTypeNumber: parseEnvVarBoolean( + process.env.UNLEASH_EXPERIMENTAL_VARIANT_TYPE_NUMBER, + false, + ), }; export const defaultExperimentalOptions: IExperimentalOptions = { diff --git a/src/lib/types/model.ts b/src/lib/types/model.ts index d15f65d13e..986ce07add 100644 --- a/src/lib/types/model.ts +++ b/src/lib/types/model.ts @@ -123,7 +123,7 @@ export interface IVariant { weight: number; weightType: 'variable' | 'fix'; payload?: { - type: 'json' | 'csv' | 'string'; + type: 'json' | 'csv' | 'string' | 'number'; value: string; }; stickiness: string; diff --git a/src/server-dev.ts b/src/server-dev.ts index 0ebe247baa..a757ccda05 100644 --- a/src/server-dev.ts +++ b/src/server-dev.ts @@ -42,6 +42,7 @@ process.nextTick(async () => { integrationsRework: true, featureNamingPattern: true, doraMetrics: true, + variantTypeNumber: true, }, }, authentication: {