mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	refactor: clean up strategy parameter types (#944)
* refactor: fix splash page button background color * refactor: regenerate OpenAPI client * refactor: clean up strategy parameter types * refactor: remove index signature from IConstraint * refactor: fix never-seen status in features list
This commit is contained in:
		
							parent
							
								
									7b60ef2aa6
								
							
						
					
					
						commit
						35262e404b
					
				@ -118,7 +118,7 @@ describe('feature', () => {
 | 
			
		||||
                expect(req.body.name).to.equal('flexibleRollout');
 | 
			
		||||
                expect(req.body.parameters.groupId).to.equal(featureToggleName);
 | 
			
		||||
                expect(req.body.parameters.stickiness).to.equal('default');
 | 
			
		||||
                expect(req.body.parameters.rollout).to.equal(100);
 | 
			
		||||
                expect(req.body.parameters.rollout).to.equal('100');
 | 
			
		||||
 | 
			
		||||
                if (ENTERPRISE) {
 | 
			
		||||
                    expect(req.body.constraints.length).to.equal(1);
 | 
			
		||||
@ -159,7 +159,7 @@ describe('feature', () => {
 | 
			
		||||
            req => {
 | 
			
		||||
                expect(req.body.parameters.groupId).to.equal('new-group-id');
 | 
			
		||||
                expect(req.body.parameters.stickiness).to.equal('sessionId');
 | 
			
		||||
                expect(req.body.parameters.rollout).to.equal(100);
 | 
			
		||||
                expect(req.body.parameters.rollout).to.equal('100');
 | 
			
		||||
 | 
			
		||||
                if (ENTERPRISE) {
 | 
			
		||||
                    expect(req.body.constraints.length).to.equal(1);
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@ import Input from 'component/common/Input/Input';
 | 
			
		||||
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
 | 
			
		||||
import React, { useState } from 'react';
 | 
			
		||||
import { ConstraintFormHeader } from '../ConstraintFormHeader/ConstraintFormHeader';
 | 
			
		||||
import { parseParameterStrings } from 'utils/parseParameter';
 | 
			
		||||
 | 
			
		||||
interface IFreeTextInputProps {
 | 
			
		||||
    values: string[];
 | 
			
		||||
@ -74,17 +75,9 @@ export const FreeTextInput = ({
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        setError('');
 | 
			
		||||
 | 
			
		||||
        if (inputValues.includes(',')) {
 | 
			
		||||
            const newValues = inputValues
 | 
			
		||||
                .split(',')
 | 
			
		||||
                .filter(values => values)
 | 
			
		||||
                .map(value => value.trim());
 | 
			
		||||
            setValues(uniqueValues([...values, ...newValues]));
 | 
			
		||||
        } else {
 | 
			
		||||
            setValues(uniqueValues([...values, inputValues.trim()]));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        setValues(
 | 
			
		||||
            uniqueValues([...values, ...parseParameterStrings(inputValues)])
 | 
			
		||||
        );
 | 
			
		||||
        setInputValues('');
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@ import useFeatureStrategyApi from 'hooks/api/actions/useFeatureStrategyApi/useFe
 | 
			
		||||
import { formatUnknownError } from 'utils/formatUnknownError';
 | 
			
		||||
import { useHistory } from 'react-router-dom';
 | 
			
		||||
import useToast from 'hooks/useToast';
 | 
			
		||||
import { IFeatureStrategy, IStrategyPayload } from 'interfaces/strategy';
 | 
			
		||||
import { IFeatureStrategy, IFeatureStrategyPayload } from 'interfaces/strategy';
 | 
			
		||||
import { UPDATE_FEATURE_STRATEGY } from 'component/providers/AccessProvider/permissions';
 | 
			
		||||
import { ISegment } from 'interfaces/segment';
 | 
			
		||||
import { useSegmentsApi } from 'hooks/api/actions/useSegmentsApi/useSegmentsApi';
 | 
			
		||||
@ -122,7 +122,7 @@ export const FeatureStrategyEdit = () => {
 | 
			
		||||
 | 
			
		||||
export const createStrategyPayload = (
 | 
			
		||||
    strategy: Partial<IFeatureStrategy>
 | 
			
		||||
): IStrategyPayload => {
 | 
			
		||||
): IFeatureStrategyPayload => {
 | 
			
		||||
    return {
 | 
			
		||||
        name: strategy.name,
 | 
			
		||||
        constraints: strategy.constraints ?? [],
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,7 @@ export const FeatureStrategyType = ({
 | 
			
		||||
        return definition.name === strategy.name;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const updateParameter = (field: string, value: unknown) => {
 | 
			
		||||
    const updateParameter = (field: string, value: string) => {
 | 
			
		||||
        setStrategy(
 | 
			
		||||
            produce(draft => {
 | 
			
		||||
                draft.parameters = draft.parameters ?? {};
 | 
			
		||||
@ -48,7 +48,7 @@ export const FeatureStrategyType = ({
 | 
			
		||||
            return (
 | 
			
		||||
                <FlexibleStrategy
 | 
			
		||||
                    context={context}
 | 
			
		||||
                    parameters={strategy.parameters ?? []}
 | 
			
		||||
                    parameters={strategy.parameters ?? {}}
 | 
			
		||||
                    updateParameter={updateParameter}
 | 
			
		||||
                    editable={hasAccess}
 | 
			
		||||
                />
 | 
			
		||||
@ -56,7 +56,7 @@ export const FeatureStrategyType = ({
 | 
			
		||||
        case 'userWithId':
 | 
			
		||||
            return (
 | 
			
		||||
                <UserWithIdStrategy
 | 
			
		||||
                    parameters={strategy.parameters ?? []}
 | 
			
		||||
                    parameters={strategy.parameters ?? {}}
 | 
			
		||||
                    updateParameter={updateParameter}
 | 
			
		||||
                    editable={hasAccess}
 | 
			
		||||
                />
 | 
			
		||||
@ -65,7 +65,7 @@ export const FeatureStrategyType = ({
 | 
			
		||||
            return (
 | 
			
		||||
                <GeneralStrategy
 | 
			
		||||
                    strategyDefinition={strategyDefinition}
 | 
			
		||||
                    parameters={strategy.parameters ?? []}
 | 
			
		||||
                    parameters={strategy.parameters ?? {}}
 | 
			
		||||
                    updateParameter={updateParameter}
 | 
			
		||||
                    editable={hasAccess}
 | 
			
		||||
                />
 | 
			
		||||
 | 
			
		||||
@ -72,14 +72,9 @@ export const FeatureToggleListItem = memo<IFeatureToggleListItemProps>(
 | 
			
		||||
                className={classnames(styles.listItem, className)}
 | 
			
		||||
            >
 | 
			
		||||
                <span className={styles.listItemMetric}>
 | 
			
		||||
                    <ConditionallyRender
 | 
			
		||||
                        condition={Boolean(lastSeenAt)}
 | 
			
		||||
                        show={() => (
 | 
			
		||||
                            <FeatureStatus
 | 
			
		||||
                                lastSeenAt={lastSeenAt as Date}
 | 
			
		||||
                                tooltipPlacement="left"
 | 
			
		||||
                            />
 | 
			
		||||
                        )}
 | 
			
		||||
                    <FeatureStatus
 | 
			
		||||
                        lastSeenAt={lastSeenAt}
 | 
			
		||||
                        tooltipPlacement="left"
 | 
			
		||||
                    />
 | 
			
		||||
                </span>
 | 
			
		||||
                <span
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,9 @@
 | 
			
		||||
import { Fragment } from 'react';
 | 
			
		||||
import { IConstraint, IFeatureStrategy, IParameter } from 'interfaces/strategy';
 | 
			
		||||
import {
 | 
			
		||||
    IFeatureStrategy,
 | 
			
		||||
    IFeatureStrategyParameters,
 | 
			
		||||
    IConstraint,
 | 
			
		||||
} from 'interfaces/strategy';
 | 
			
		||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
			
		||||
import PercentageCircle from 'component/common/PercentageCircle/PercentageCircle';
 | 
			
		||||
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
 | 
			
		||||
@ -10,9 +14,14 @@ import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
			
		||||
import { FeatureOverviewSegment } from 'component/feature/FeatureView/FeatureOverview/FeatureOverviewSegment/FeatureOverviewSegment';
 | 
			
		||||
import { ConstraintAccordionList } from 'component/common/ConstraintAccordion/ConstraintAccordionList/ConstraintAccordionList';
 | 
			
		||||
import { useStyles } from 'component/feature/FeatureView/FeatureOverview/FeatureOverviewExecution/FeatureOverviewExecution.styles';
 | 
			
		||||
import {
 | 
			
		||||
    parseParameterString,
 | 
			
		||||
    parseParameterNumber,
 | 
			
		||||
    parseParameterStrings,
 | 
			
		||||
} from 'utils/parseParameter';
 | 
			
		||||
 | 
			
		||||
interface IFeatureOverviewExecutionProps {
 | 
			
		||||
    parameters: IParameter;
 | 
			
		||||
    parameters: IFeatureStrategyParameters;
 | 
			
		||||
    constraints?: IConstraint[];
 | 
			
		||||
    strategy: IFeatureStrategy;
 | 
			
		||||
    percentageFill?: string;
 | 
			
		||||
@ -52,15 +61,16 @@ const FeatureOverviewExecution = ({
 | 
			
		||||
                                is included.
 | 
			
		||||
                            </p>
 | 
			
		||||
 | 
			
		||||
                            <PercentageCircle percentage={parameters[key]} />
 | 
			
		||||
                            <PercentageCircle
 | 
			
		||||
                                percentage={parseParameterNumber(
 | 
			
		||||
                                    parameters[key]
 | 
			
		||||
                                )}
 | 
			
		||||
                            />
 | 
			
		||||
                        </Fragment>
 | 
			
		||||
                    );
 | 
			
		||||
                case 'userIds':
 | 
			
		||||
                case 'UserIds':
 | 
			
		||||
                    const users = parameters[key]
 | 
			
		||||
                        .split(',')
 | 
			
		||||
                        .filter((userId: string) => userId);
 | 
			
		||||
 | 
			
		||||
                    const users = parseParameterStrings(parameters[key]);
 | 
			
		||||
                    return (
 | 
			
		||||
                        <FeatureOverviewExecutionChips
 | 
			
		||||
                            key={key}
 | 
			
		||||
@ -70,10 +80,7 @@ const FeatureOverviewExecution = ({
 | 
			
		||||
                    );
 | 
			
		||||
                case 'hostNames':
 | 
			
		||||
                case 'HostNames':
 | 
			
		||||
                    const hosts = parameters[key]
 | 
			
		||||
                        .split(',')
 | 
			
		||||
                        .filter((hosts: string) => hosts);
 | 
			
		||||
 | 
			
		||||
                    const hosts = parseParameterStrings(parameters[key]);
 | 
			
		||||
                    return (
 | 
			
		||||
                        <FeatureOverviewExecutionChips
 | 
			
		||||
                            key={key}
 | 
			
		||||
@ -82,10 +89,7 @@ const FeatureOverviewExecution = ({
 | 
			
		||||
                        />
 | 
			
		||||
                    );
 | 
			
		||||
                case 'IPs':
 | 
			
		||||
                    const IPs = parameters[key]
 | 
			
		||||
                        .split(',')
 | 
			
		||||
                        .filter((hosts: string) => hosts);
 | 
			
		||||
 | 
			
		||||
                    const IPs = parseParameterStrings(parameters[key]);
 | 
			
		||||
                    return (
 | 
			
		||||
                        <FeatureOverviewExecutionChips
 | 
			
		||||
                            key={key}
 | 
			
		||||
@ -108,10 +112,9 @@ const FeatureOverviewExecution = ({
 | 
			
		||||
            const notLastItem = index !== definition?.parameters?.length - 1;
 | 
			
		||||
            switch (param?.type) {
 | 
			
		||||
                case 'list':
 | 
			
		||||
                    const values = strategy?.parameters[param.name]
 | 
			
		||||
                        .split(',')
 | 
			
		||||
                        .filter((val: string) => val);
 | 
			
		||||
 | 
			
		||||
                    const values = parseParameterStrings(
 | 
			
		||||
                        strategy?.parameters[param.name]
 | 
			
		||||
                    );
 | 
			
		||||
                    return (
 | 
			
		||||
                        <Fragment key={param?.name}>
 | 
			
		||||
                            <FeatureOverviewExecutionChips
 | 
			
		||||
@ -134,9 +137,10 @@ const FeatureOverviewExecution = ({
 | 
			
		||||
                                    : ''}{' '}
 | 
			
		||||
                                is included.
 | 
			
		||||
                            </p>
 | 
			
		||||
 | 
			
		||||
                            <PercentageCircle
 | 
			
		||||
                                percentage={strategy.parameters[param.name]}
 | 
			
		||||
                                percentage={parseParameterNumber(
 | 
			
		||||
                                    strategy.parameters[param.name]
 | 
			
		||||
                                )}
 | 
			
		||||
                            />
 | 
			
		||||
                            <ConditionallyRender
 | 
			
		||||
                                condition={notLastItem}
 | 
			
		||||
@ -156,7 +160,10 @@ const FeatureOverviewExecution = ({
 | 
			
		||||
                                {strategy.parameters[param.name]}
 | 
			
		||||
                            </p>
 | 
			
		||||
                            <ConditionallyRender
 | 
			
		||||
                                condition={strategy.parameters[param.name]}
 | 
			
		||||
                                condition={
 | 
			
		||||
                                    typeof strategy.parameters[param.name] !==
 | 
			
		||||
                                    'undefined'
 | 
			
		||||
                                }
 | 
			
		||||
                                show={
 | 
			
		||||
                                    <ConditionallyRender
 | 
			
		||||
                                        condition={notLastItem}
 | 
			
		||||
@ -167,10 +174,15 @@ const FeatureOverviewExecution = ({
 | 
			
		||||
                        </Fragment>
 | 
			
		||||
                    );
 | 
			
		||||
                case 'string':
 | 
			
		||||
                    const value = strategy.parameters[param.name];
 | 
			
		||||
                    const value = parseParameterString(
 | 
			
		||||
                        strategy.parameters[param.name]
 | 
			
		||||
                    );
 | 
			
		||||
                    return (
 | 
			
		||||
                        <ConditionallyRender
 | 
			
		||||
                            condition={value !== undefined}
 | 
			
		||||
                            condition={
 | 
			
		||||
                                typeof strategy.parameters[param.name] !==
 | 
			
		||||
                                'undefined'
 | 
			
		||||
                            }
 | 
			
		||||
                            key={param.name}
 | 
			
		||||
                            show={
 | 
			
		||||
                                <>
 | 
			
		||||
@ -198,7 +210,9 @@ const FeatureOverviewExecution = ({
 | 
			
		||||
                        />
 | 
			
		||||
                    );
 | 
			
		||||
                case 'number':
 | 
			
		||||
                    const number = strategy.parameters[param.name];
 | 
			
		||||
                    const number = parseParameterNumber(
 | 
			
		||||
                        strategy.parameters[param.name]
 | 
			
		||||
                    );
 | 
			
		||||
                    return (
 | 
			
		||||
                        <ConditionallyRender
 | 
			
		||||
                            condition={number !== undefined}
 | 
			
		||||
 | 
			
		||||
@ -47,7 +47,7 @@ function getColor(unit?: string): string {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface IFeatureStatusProps {
 | 
			
		||||
    lastSeenAt?: string | Date;
 | 
			
		||||
    lastSeenAt?: string | Date | null;
 | 
			
		||||
    tooltipPlacement?: TooltipProps['placement'];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -75,7 +75,7 @@ const FeatureStatus = ({
 | 
			
		||||
    return (
 | 
			
		||||
        <ConditionallyRender
 | 
			
		||||
            condition={Boolean(lastSeenAt)}
 | 
			
		||||
            show={
 | 
			
		||||
            show={() => (
 | 
			
		||||
                <TimeAgo
 | 
			
		||||
                    date={lastSeenAt!}
 | 
			
		||||
                    title=""
 | 
			
		||||
@ -98,7 +98,7 @@ const FeatureStatus = ({
 | 
			
		||||
                        );
 | 
			
		||||
                    }}
 | 
			
		||||
                />
 | 
			
		||||
            }
 | 
			
		||||
            )}
 | 
			
		||||
            elseShow={
 | 
			
		||||
                <Wrapper
 | 
			
		||||
                    toolTip="No usage reported from connected applications"
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
import { Typography } from '@mui/material';
 | 
			
		||||
import { IParameter } from 'interfaces/strategy';
 | 
			
		||||
import { IFeatureStrategyParameters } from 'interfaces/strategy';
 | 
			
		||||
import RolloutSlider from '../RolloutSlider/RolloutSlider';
 | 
			
		||||
import Select from 'component/common/select';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
@ -9,6 +9,10 @@ import {
 | 
			
		||||
    FLEXIBLE_STRATEGY_STICKINESS_ID,
 | 
			
		||||
} from 'utils/testIds';
 | 
			
		||||
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
 | 
			
		||||
import {
 | 
			
		||||
    parseParameterNumber,
 | 
			
		||||
    parseParameterString,
 | 
			
		||||
} from 'utils/parseParameter';
 | 
			
		||||
 | 
			
		||||
const builtInStickinessOptions = [
 | 
			
		||||
    { key: 'default', label: 'default' },
 | 
			
		||||
@ -18,8 +22,8 @@ const builtInStickinessOptions = [
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
interface IFlexibleStrategyProps {
 | 
			
		||||
    parameters: IParameter;
 | 
			
		||||
    updateParameter: (field: string, value: any) => void;
 | 
			
		||||
    parameters: IFeatureStrategyParameters;
 | 
			
		||||
    updateParameter: (field: string, value: string) => void;
 | 
			
		||||
    context: any;
 | 
			
		||||
    editable: boolean;
 | 
			
		||||
}
 | 
			
		||||
@ -54,15 +58,15 @@ const FlexibleStrategy = ({
 | 
			
		||||
    const stickinessOptions = resolveStickiness();
 | 
			
		||||
 | 
			
		||||
    const rollout =
 | 
			
		||||
        parameters.rollout !== undefined ? parameters.rollout : '100';
 | 
			
		||||
    const stickiness = parameters.stickiness;
 | 
			
		||||
    const groupId = parameters.groupId;
 | 
			
		||||
        parameters.rollout !== undefined
 | 
			
		||||
            ? parseParameterNumber(parameters.rollout)
 | 
			
		||||
            : 100;
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div>
 | 
			
		||||
            <RolloutSlider
 | 
			
		||||
                name="Rollout"
 | 
			
		||||
                value={parseInt(rollout)}
 | 
			
		||||
                value={rollout}
 | 
			
		||||
                disabled={!editable}
 | 
			
		||||
                onChange={updateRollout}
 | 
			
		||||
            />
 | 
			
		||||
@ -86,7 +90,7 @@ const FlexibleStrategy = ({
 | 
			
		||||
                    name="stickiness"
 | 
			
		||||
                    label="Stickiness"
 | 
			
		||||
                    options={stickinessOptions}
 | 
			
		||||
                    value={stickiness}
 | 
			
		||||
                    value={parseParameterString(parameters.stickiness)}
 | 
			
		||||
                    disabled={!editable}
 | 
			
		||||
                    data-testid={FLEXIBLE_STRATEGY_STICKINESS_ID}
 | 
			
		||||
                    onChange={e => onUpdate('stickiness')(e.target.value)}
 | 
			
		||||
@ -109,7 +113,7 @@ const FlexibleStrategy = ({
 | 
			
		||||
                <Input
 | 
			
		||||
                    label="groupId"
 | 
			
		||||
                    id="groupId-input"
 | 
			
		||||
                    value={groupId || ''}
 | 
			
		||||
                    value={parseParameterString(parameters.groupId)}
 | 
			
		||||
                    disabled={!editable}
 | 
			
		||||
                    onChange={e => onUpdate('groupId')(e.target.value)}
 | 
			
		||||
                    data-testid={FLEXIBLE_STRATEGY_GROUP_ID}
 | 
			
		||||
 | 
			
		||||
@ -2,13 +2,18 @@ import React from 'react';
 | 
			
		||||
import { FormControlLabel, Switch, TextField, Tooltip } from '@mui/material';
 | 
			
		||||
import StrategyInputList from '../StrategyInputList/StrategyInputList';
 | 
			
		||||
import RolloutSlider from '../RolloutSlider/RolloutSlider';
 | 
			
		||||
import { IParameter, IStrategy } from 'interfaces/strategy';
 | 
			
		||||
import { IStrategy, IFeatureStrategyParameters } from 'interfaces/strategy';
 | 
			
		||||
import { useStyles } from './GeneralStrategy.styles';
 | 
			
		||||
import {
 | 
			
		||||
    parseParameterNumber,
 | 
			
		||||
    parseParameterStrings,
 | 
			
		||||
    parseParameterString,
 | 
			
		||||
} from 'utils/parseParameter';
 | 
			
		||||
 | 
			
		||||
interface IGeneralStrategyProps {
 | 
			
		||||
    parameters: IParameter;
 | 
			
		||||
    parameters: IFeatureStrategyParameters;
 | 
			
		||||
    strategyDefinition: IStrategy;
 | 
			
		||||
    updateParameter: (field: string, value: any) => void;
 | 
			
		||||
    updateParameter: (field: string, value: string) => void;
 | 
			
		||||
    editable: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -29,9 +34,13 @@ const GeneralStrategy = ({
 | 
			
		||||
        updateParameter(field, value);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const onChangePercentage = (field: string, evt: Event, newValue: any) => {
 | 
			
		||||
    const onChangePercentage = (
 | 
			
		||||
        field: string,
 | 
			
		||||
        evt: Event,
 | 
			
		||||
        newValue: number | number[]
 | 
			
		||||
    ) => {
 | 
			
		||||
        evt.preventDefault();
 | 
			
		||||
        updateParameter(field, newValue);
 | 
			
		||||
        updateParameter(field, newValue.toString());
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const handleSwitchChange = (field: string, currentValue: any) => {
 | 
			
		||||
@ -47,15 +56,8 @@ const GeneralStrategy = ({
 | 
			
		||||
        <>
 | 
			
		||||
            {strategyDefinition.parameters.map(
 | 
			
		||||
                ({ name, type, description, required }) => {
 | 
			
		||||
                    let value = parameters[name];
 | 
			
		||||
 | 
			
		||||
                    if (type === 'percentage') {
 | 
			
		||||
                        if (
 | 
			
		||||
                            value == null ||
 | 
			
		||||
                            (typeof value === 'string' && value === '')
 | 
			
		||||
                        ) {
 | 
			
		||||
                            value = 0;
 | 
			
		||||
                        }
 | 
			
		||||
                        const value = parseParameterNumber(parameters[name]);
 | 
			
		||||
                        return (
 | 
			
		||||
                            <div key={name}>
 | 
			
		||||
                                <br />
 | 
			
		||||
@ -66,7 +68,7 @@ const GeneralStrategy = ({
 | 
			
		||||
                                        name
 | 
			
		||||
                                    )}
 | 
			
		||||
                                    disabled={!editable}
 | 
			
		||||
                                    value={1 * value}
 | 
			
		||||
                                    value={value}
 | 
			
		||||
                                    minLabel="off"
 | 
			
		||||
                                    maxLabel="on"
 | 
			
		||||
                                />
 | 
			
		||||
@ -78,15 +80,12 @@ const GeneralStrategy = ({
 | 
			
		||||
                            </div>
 | 
			
		||||
                        );
 | 
			
		||||
                    } else if (type === 'list') {
 | 
			
		||||
                        let list: string[] = [];
 | 
			
		||||
                        if (typeof value === 'string') {
 | 
			
		||||
                            list = value.trim().split(',').filter(Boolean);
 | 
			
		||||
                        }
 | 
			
		||||
                        const values = parseParameterStrings(parameters[name]);
 | 
			
		||||
                        return (
 | 
			
		||||
                            <div key={name}>
 | 
			
		||||
                                <StrategyInputList
 | 
			
		||||
                                    name={name}
 | 
			
		||||
                                    list={list}
 | 
			
		||||
                                    list={values}
 | 
			
		||||
                                    disabled={!editable}
 | 
			
		||||
                                    setConfig={updateParameter}
 | 
			
		||||
                                />
 | 
			
		||||
@ -99,8 +98,9 @@ const GeneralStrategy = ({
 | 
			
		||||
                        );
 | 
			
		||||
                    } else if (type === 'number') {
 | 
			
		||||
                        const regex = new RegExp('^\\d+$');
 | 
			
		||||
                        const value = parseParameterString(parameters[name]);
 | 
			
		||||
                        const error =
 | 
			
		||||
                            value?.length > 0 ? !regex.test(value) : false;
 | 
			
		||||
                            value.length > 0 ? !regex.test(value) : false;
 | 
			
		||||
 | 
			
		||||
                        return (
 | 
			
		||||
                            <div key={name} className={styles.generalSection}>
 | 
			
		||||
@ -130,6 +130,7 @@ const GeneralStrategy = ({
 | 
			
		||||
                            </div>
 | 
			
		||||
                        );
 | 
			
		||||
                    } else if (type === 'boolean') {
 | 
			
		||||
                        const value = parseParameterString(parameters[name]);
 | 
			
		||||
                        return (
 | 
			
		||||
                            <div key={name} style={{ padding: '20px 0' }}>
 | 
			
		||||
                                <Tooltip
 | 
			
		||||
@ -154,6 +155,7 @@ const GeneralStrategy = ({
 | 
			
		||||
                            </div>
 | 
			
		||||
                        );
 | 
			
		||||
                    } else {
 | 
			
		||||
                        const value = parseParameterString(parameters[name]);
 | 
			
		||||
                        return (
 | 
			
		||||
                            <div key={name} className={styles.generalSection}>
 | 
			
		||||
                                <TextField
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,9 @@
 | 
			
		||||
import { IParameter } from 'interfaces/strategy';
 | 
			
		||||
import { IFeatureStrategyParameters } from 'interfaces/strategy';
 | 
			
		||||
import StrategyInputList from '../StrategyInputList/StrategyInputList';
 | 
			
		||||
import { parseParameterStrings } from 'utils/parseParameter';
 | 
			
		||||
 | 
			
		||||
interface IUserWithIdStrategyProps {
 | 
			
		||||
    parameters: IParameter;
 | 
			
		||||
    parameters: IFeatureStrategyParameters;
 | 
			
		||||
    updateParameter: (field: string, value: string) => void;
 | 
			
		||||
    editable: boolean;
 | 
			
		||||
}
 | 
			
		||||
@ -12,18 +13,11 @@ const UserWithIdStrategy = ({
 | 
			
		||||
    parameters,
 | 
			
		||||
    updateParameter,
 | 
			
		||||
}: IUserWithIdStrategyProps) => {
 | 
			
		||||
    const value = parameters.userIds;
 | 
			
		||||
 | 
			
		||||
    let list: string[] = [];
 | 
			
		||||
    if (typeof value === 'string') {
 | 
			
		||||
        list = value.trim().split(',').filter(Boolean);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div>
 | 
			
		||||
            <StrategyInputList
 | 
			
		||||
                name="userIds"
 | 
			
		||||
                list={list}
 | 
			
		||||
                list={parseParameterStrings(parameters.userIds)}
 | 
			
		||||
                disabled={!editable}
 | 
			
		||||
                setConfig={updateParameter}
 | 
			
		||||
            />
 | 
			
		||||
 | 
			
		||||
@ -72,7 +72,7 @@ export const useStyles = makeStyles()(theme => ({
 | 
			
		||||
        color: 'inherit',
 | 
			
		||||
    },
 | 
			
		||||
    button: {
 | 
			
		||||
        background: 'white',
 | 
			
		||||
        background: 'white !important',
 | 
			
		||||
        color: theme.palette.primary.main,
 | 
			
		||||
    },
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
@ -36,7 +36,7 @@ import { useStrategies } from 'hooks/api/getters/useStrategies/useStrategies';
 | 
			
		||||
import useStrategiesApi from 'hooks/api/actions/useStrategiesApi/useStrategiesApi';
 | 
			
		||||
import useToast from 'hooks/useToast';
 | 
			
		||||
import { formatUnknownError } from 'utils/formatUnknownError';
 | 
			
		||||
import { ICustomStrategy } from 'interfaces/strategy';
 | 
			
		||||
import { IStrategy } from 'interfaces/strategy';
 | 
			
		||||
 | 
			
		||||
interface IDialogueMetaData {
 | 
			
		||||
    show: boolean;
 | 
			
		||||
@ -102,7 +102,7 @@ export const StrategiesList = () => {
 | 
			
		||||
        </Link>
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const onReactivateStrategy = (strategy: ICustomStrategy) => {
 | 
			
		||||
    const onReactivateStrategy = (strategy: IStrategy) => {
 | 
			
		||||
        setDialogueMetaData({
 | 
			
		||||
            show: true,
 | 
			
		||||
            title: 'Really reactivate strategy?',
 | 
			
		||||
@ -122,7 +122,7 @@ export const StrategiesList = () => {
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const onDeprecateStrategy = (strategy: ICustomStrategy) => {
 | 
			
		||||
    const onDeprecateStrategy = (strategy: IStrategy) => {
 | 
			
		||||
        setDialogueMetaData({
 | 
			
		||||
            show: true,
 | 
			
		||||
            title: 'Really deprecate strategy?',
 | 
			
		||||
@ -142,7 +142,7 @@ export const StrategiesList = () => {
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const onDeleteStrategy = (strategy: ICustomStrategy) => {
 | 
			
		||||
    const onDeleteStrategy = (strategy: IStrategy) => {
 | 
			
		||||
        setDialogueMetaData({
 | 
			
		||||
            show: true,
 | 
			
		||||
            title: 'Really delete strategy?',
 | 
			
		||||
@ -162,7 +162,7 @@ export const StrategiesList = () => {
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const reactivateButton = (strategy: ICustomStrategy) => (
 | 
			
		||||
    const reactivateButton = (strategy: IStrategy) => (
 | 
			
		||||
        <PermissionIconButton
 | 
			
		||||
            onClick={() => onReactivateStrategy(strategy)}
 | 
			
		||||
            permission={UPDATE_STRATEGY}
 | 
			
		||||
@ -172,7 +172,7 @@ export const StrategiesList = () => {
 | 
			
		||||
        </PermissionIconButton>
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const deprecateButton = (strategy: ICustomStrategy) => (
 | 
			
		||||
    const deprecateButton = (strategy: IStrategy) => (
 | 
			
		||||
        <ConditionallyRender
 | 
			
		||||
            condition={strategy.name === 'default'}
 | 
			
		||||
            show={
 | 
			
		||||
@ -198,7 +198,7 @@ export const StrategiesList = () => {
 | 
			
		||||
        />
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const editButton = (strategy: ICustomStrategy) => (
 | 
			
		||||
    const editButton = (strategy: IStrategy) => (
 | 
			
		||||
        <ConditionallyRender
 | 
			
		||||
            condition={strategy?.editable}
 | 
			
		||||
            show={
 | 
			
		||||
@ -224,7 +224,7 @@ export const StrategiesList = () => {
 | 
			
		||||
        />
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const deleteButton = (strategy: ICustomStrategy) => (
 | 
			
		||||
    const deleteButton = (strategy: IStrategy) => (
 | 
			
		||||
        <ConditionallyRender
 | 
			
		||||
            condition={strategy?.editable}
 | 
			
		||||
            show={
 | 
			
		||||
 | 
			
		||||
@ -4,16 +4,16 @@ import { useStyles } from './StrategyForm.styles';
 | 
			
		||||
import { Add } from '@mui/icons-material';
 | 
			
		||||
import { trim } from 'component/common/util';
 | 
			
		||||
import { StrategyParameters } from './StrategyParameters/StrategyParameters';
 | 
			
		||||
import { ICustomStrategyParameter } from 'interfaces/strategy';
 | 
			
		||||
import { IStrategyParameter } from 'interfaces/strategy';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
 | 
			
		||||
interface IStrategyFormProps {
 | 
			
		||||
    strategyName: string;
 | 
			
		||||
    strategyDesc: string;
 | 
			
		||||
    params: ICustomStrategyParameter[];
 | 
			
		||||
    params: IStrategyParameter[];
 | 
			
		||||
    setStrategyName: React.Dispatch<React.SetStateAction<string>>;
 | 
			
		||||
    setStrategyDesc: React.Dispatch<React.SetStateAction<string>>;
 | 
			
		||||
    setParams: React.Dispatch<React.SetStateAction<ICustomStrategyParameter[]>>;
 | 
			
		||||
    setParams: React.Dispatch<React.SetStateAction<IStrategyParameter[]>>;
 | 
			
		||||
    handleSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
 | 
			
		||||
    handleCancel: () => void;
 | 
			
		||||
    errors: { [key: string]: string };
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@ import GeneralSelect from 'component/common/GeneralSelect/GeneralSelect';
 | 
			
		||||
import Input from 'component/common/Input/Input';
 | 
			
		||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { ICustomStrategyParameter } from 'interfaces/strategy';
 | 
			
		||||
import { IStrategyParameter } from 'interfaces/strategy';
 | 
			
		||||
 | 
			
		||||
const paramTypesOptions = [
 | 
			
		||||
    {
 | 
			
		||||
@ -41,10 +41,10 @@ const paramTypesOptions = [
 | 
			
		||||
 | 
			
		||||
interface IStrategyParameterProps {
 | 
			
		||||
    set: React.Dispatch<React.SetStateAction<object>>;
 | 
			
		||||
    input: ICustomStrategyParameter;
 | 
			
		||||
    input: IStrategyParameter;
 | 
			
		||||
    index: number;
 | 
			
		||||
    params: ICustomStrategyParameter[];
 | 
			
		||||
    setParams: React.Dispatch<React.SetStateAction<ICustomStrategyParameter[]>>;
 | 
			
		||||
    params: IStrategyParameter[];
 | 
			
		||||
    setParams: React.Dispatch<React.SetStateAction<IStrategyParameter[]>>;
 | 
			
		||||
    errors: { [key: string]: string };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,11 @@
 | 
			
		||||
import { StrategyParameter } from './StrategyParameter/StrategyParameter';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { ICustomStrategyParameter } from 'interfaces/strategy';
 | 
			
		||||
import { IStrategyParameter } from 'interfaces/strategy';
 | 
			
		||||
 | 
			
		||||
interface IStrategyParametersProps {
 | 
			
		||||
    input: ICustomStrategyParameter[];
 | 
			
		||||
    input: IStrategyParameter[];
 | 
			
		||||
    updateParameter: (index: number, updated: object) => void;
 | 
			
		||||
    setParams: React.Dispatch<React.SetStateAction<ICustomStrategyParameter[]>>;
 | 
			
		||||
    setParams: React.Dispatch<React.SetStateAction<IStrategyParameter[]>>;
 | 
			
		||||
    errors: { [key: string]: string };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ import { AppsLinkList } from 'component/common';
 | 
			
		||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
			
		||||
import styles from '../../strategies.module.scss';
 | 
			
		||||
import { TogglesLinkList } from 'component/strategies/TogglesLinkList/TogglesLinkList';
 | 
			
		||||
import { IParameter, IStrategy } from 'interfaces/strategy';
 | 
			
		||||
import { IStrategy, IStrategyParameter } from 'interfaces/strategy';
 | 
			
		||||
import { IApplication } from 'interfaces/application';
 | 
			
		||||
import { FeatureSchema } from 'openapi';
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,7 @@ export const StrategyDetails = ({
 | 
			
		||||
    toggles,
 | 
			
		||||
}: IStrategyDetailsProps) => {
 | 
			
		||||
    const { parameters = [] } = strategy;
 | 
			
		||||
    const renderParameters = (params: IParameter[]) => {
 | 
			
		||||
    const renderParameters = (params: IStrategyParameter[]) => {
 | 
			
		||||
        if (params.length > 0) {
 | 
			
		||||
            return params.map(({ name, type, description, required }, i) => (
 | 
			
		||||
                <ListItem key={`${name}-${i}`}>
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,11 @@
 | 
			
		||||
import { ICustomStrategyParameter } from 'interfaces/strategy';
 | 
			
		||||
import { IStrategyParameter } from 'interfaces/strategy';
 | 
			
		||||
import { useEffect, useState } from 'react';
 | 
			
		||||
import { useStrategies } from 'hooks/api/getters/useStrategies/useStrategies';
 | 
			
		||||
 | 
			
		||||
export const useStrategyForm = (
 | 
			
		||||
    initialStrategyName: string = '',
 | 
			
		||||
    initialStrategyDesc: string = '',
 | 
			
		||||
    initialParams: ICustomStrategyParameter[] = []
 | 
			
		||||
    initialParams: IStrategyParameter[] = []
 | 
			
		||||
) => {
 | 
			
		||||
    const [strategyName, setStrategyName] = useState(initialStrategyName);
 | 
			
		||||
    const [strategyDesc, setStrategyDesc] = useState(initialStrategyDesc);
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,9 @@
 | 
			
		||||
import { ITag } from 'interfaces/tags';
 | 
			
		||||
import useAPI from '../useApi/useApi';
 | 
			
		||||
import { Operation } from 'fast-json-patch';
 | 
			
		||||
import { IConstraint } from 'interfaces/strategy';
 | 
			
		||||
import { CreateFeatureSchema } from 'openapi';
 | 
			
		||||
import { openApiAdmin } from 'utils/openapiClient';
 | 
			
		||||
import { IConstraint } from 'interfaces/strategy';
 | 
			
		||||
 | 
			
		||||
const useFeatureApi = () => {
 | 
			
		||||
    const { makeRequest, createRequest, errors, loading } = useAPI({
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
import { IStrategyPayload, IFeatureStrategy } from 'interfaces/strategy';
 | 
			
		||||
import { IFeatureStrategyPayload, IFeatureStrategy } from 'interfaces/strategy';
 | 
			
		||||
import useAPI from '../useApi/useApi';
 | 
			
		||||
 | 
			
		||||
const useFeatureStrategyApi = () => {
 | 
			
		||||
@ -10,7 +10,7 @@ const useFeatureStrategyApi = () => {
 | 
			
		||||
        projectId: string,
 | 
			
		||||
        featureId: string,
 | 
			
		||||
        environmentId: string,
 | 
			
		||||
        payload: IStrategyPayload
 | 
			
		||||
        payload: IFeatureStrategyPayload
 | 
			
		||||
    ): Promise<IFeatureStrategy> => {
 | 
			
		||||
        const path = `api/admin/projects/${projectId}/features/${featureId}/environments/${environmentId}/strategies`;
 | 
			
		||||
        const req = createRequest(
 | 
			
		||||
@ -41,7 +41,7 @@ const useFeatureStrategyApi = () => {
 | 
			
		||||
        featureId: string,
 | 
			
		||||
        environmentId: string,
 | 
			
		||||
        strategyId: string,
 | 
			
		||||
        payload: IStrategyPayload
 | 
			
		||||
        payload: IFeatureStrategyPayload
 | 
			
		||||
    ): Promise<void> => {
 | 
			
		||||
        const path = `api/admin/projects/${projectId}/features/${featureId}/environments/${environmentId}/strategies/${strategyId}`;
 | 
			
		||||
        const req = createRequest(
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
import { ICustomStrategyPayload } from 'interfaces/strategy';
 | 
			
		||||
import { IStrategyPayload } from 'interfaces/strategy';
 | 
			
		||||
import useAPI from '../useApi/useApi';
 | 
			
		||||
 | 
			
		||||
const useStrategiesApi = () => {
 | 
			
		||||
@ -7,7 +7,7 @@ const useStrategiesApi = () => {
 | 
			
		||||
    });
 | 
			
		||||
    const URI = 'api/admin/strategies';
 | 
			
		||||
 | 
			
		||||
    const createStrategy = async (strategy: ICustomStrategyPayload) => {
 | 
			
		||||
    const createStrategy = async (strategy: IStrategyPayload) => {
 | 
			
		||||
        const req = createRequest(URI, {
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            body: JSON.stringify(strategy),
 | 
			
		||||
@ -22,7 +22,7 @@ const useStrategiesApi = () => {
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const updateStrategy = async (strategy: ICustomStrategyPayload) => {
 | 
			
		||||
    const updateStrategy = async (strategy: IStrategyPayload) => {
 | 
			
		||||
        const path = `${URI}/${strategy.name}`;
 | 
			
		||||
        const req = createRequest(path, {
 | 
			
		||||
            method: 'PUT',
 | 
			
		||||
@ -38,7 +38,7 @@ const useStrategiesApi = () => {
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const removeStrategy = async (strategy: ICustomStrategyPayload) => {
 | 
			
		||||
    const removeStrategy = async (strategy: IStrategyPayload) => {
 | 
			
		||||
        const path = `${URI}/${strategy.name}`;
 | 
			
		||||
        const req = createRequest(path, { method: 'DELETE' });
 | 
			
		||||
 | 
			
		||||
@ -51,7 +51,7 @@ const useStrategiesApi = () => {
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const deprecateStrategy = async (strategy: ICustomStrategyPayload) => {
 | 
			
		||||
    const deprecateStrategy = async (strategy: IStrategyPayload) => {
 | 
			
		||||
        const path = `${URI}/${strategy.name}/deprecate`;
 | 
			
		||||
        const req = createRequest(path, {
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
@ -66,7 +66,7 @@ const useStrategiesApi = () => {
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const reactivateStrategy = async (strategy: ICustomStrategyPayload) => {
 | 
			
		||||
    const reactivateStrategy = async (strategy: IStrategyPayload) => {
 | 
			
		||||
        const path = `${URI}/${strategy.name}/reactivate`;
 | 
			
		||||
        const req = createRequest(path, { method: 'POST' });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
import { renderHook, act } from '@testing-library/react-hooks';
 | 
			
		||||
import { useFeaturesFilter } from 'hooks/useFeaturesFilter';
 | 
			
		||||
import { IConstraint, IFeatureStrategy } from 'interfaces/strategy';
 | 
			
		||||
import { FeatureSchema } from 'openapi';
 | 
			
		||||
import { FeatureSchema, FeatureSchemaStrategies } from 'openapi';
 | 
			
		||||
import parseISO from 'date-fns/parseISO';
 | 
			
		||||
import { IConstraint } from 'interfaces/strategy';
 | 
			
		||||
 | 
			
		||||
test('useFeaturesFilter empty', () => {
 | 
			
		||||
    const { result } = renderHook(() => useFeaturesFilter([]));
 | 
			
		||||
@ -108,8 +108,8 @@ const mockFeatureToggle = (
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const mockFeatureStrategy = (
 | 
			
		||||
    overrides?: Partial<IFeatureStrategy>
 | 
			
		||||
): IFeatureStrategy => {
 | 
			
		||||
    overrides?: Partial<FeatureSchemaStrategies>
 | 
			
		||||
): FeatureSchemaStrategies => {
 | 
			
		||||
    return {
 | 
			
		||||
        id: '1',
 | 
			
		||||
        name: '1',
 | 
			
		||||
 | 
			
		||||
@ -5,19 +5,42 @@ export interface IFeatureStrategy {
 | 
			
		||||
    strategyName?: string;
 | 
			
		||||
    name: string;
 | 
			
		||||
    constraints: IConstraint[];
 | 
			
		||||
    parameters: IParameter;
 | 
			
		||||
    parameters: IFeatureStrategyParameters;
 | 
			
		||||
    featureName?: string;
 | 
			
		||||
    projectId?: string;
 | 
			
		||||
    environment?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IFeatureStrategyParameters {
 | 
			
		||||
    [key: string]: string | number | undefined;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IFeatureStrategyPayload {
 | 
			
		||||
    name?: string;
 | 
			
		||||
    constraints: IConstraint[];
 | 
			
		||||
    parameters: IFeatureStrategyParameters;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IStrategy {
 | 
			
		||||
    name: string;
 | 
			
		||||
    displayName: string;
 | 
			
		||||
    editable: boolean;
 | 
			
		||||
    deprecated: boolean;
 | 
			
		||||
    description: string;
 | 
			
		||||
    parameters: IParameter[];
 | 
			
		||||
    parameters: IStrategyParameter[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IStrategyParameter {
 | 
			
		||||
    name: string;
 | 
			
		||||
    description: string;
 | 
			
		||||
    required: boolean;
 | 
			
		||||
    type: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IStrategyPayload {
 | 
			
		||||
    name: string;
 | 
			
		||||
    description: string;
 | 
			
		||||
    parameters: IStrategyParameter[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IConstraint {
 | 
			
		||||
@ -27,38 +50,4 @@ export interface IConstraint {
 | 
			
		||||
    caseInsensitive?: boolean;
 | 
			
		||||
    operator: Operator;
 | 
			
		||||
    contextName: string;
 | 
			
		||||
    [index: string]: unknown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IParameter {
 | 
			
		||||
    groupId?: string;
 | 
			
		||||
    rollout?: string;
 | 
			
		||||
    stickiness?: string;
 | 
			
		||||
 | 
			
		||||
    [index: string]: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IStrategyPayload {
 | 
			
		||||
    name?: string;
 | 
			
		||||
    constraints: IConstraint[];
 | 
			
		||||
    parameters: IParameter;
 | 
			
		||||
}
 | 
			
		||||
export interface ICustomStrategyParameter {
 | 
			
		||||
    name: string;
 | 
			
		||||
    description: string;
 | 
			
		||||
    required: boolean;
 | 
			
		||||
    type: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ICustomStrategyPayload {
 | 
			
		||||
    name: string;
 | 
			
		||||
    description: string;
 | 
			
		||||
    parameters: IParameter[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ICustomStrategy {
 | 
			
		||||
    name: string;
 | 
			
		||||
    description: string;
 | 
			
		||||
    parameters: IParameter[];
 | 
			
		||||
    editable: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -15,21 +15,51 @@
 | 
			
		||||
 | 
			
		||||
import * as runtime from '../runtime';
 | 
			
		||||
import {
 | 
			
		||||
    ChangeProjectSchema,
 | 
			
		||||
    ChangeProjectSchemaFromJSON,
 | 
			
		||||
    ChangeProjectSchemaToJSON,
 | 
			
		||||
    CreateFeatureSchema,
 | 
			
		||||
    CreateFeatureSchemaFromJSON,
 | 
			
		||||
    CreateFeatureSchemaToJSON,
 | 
			
		||||
    CreateStrategySchema,
 | 
			
		||||
    CreateStrategySchemaFromJSON,
 | 
			
		||||
    CreateStrategySchemaToJSON,
 | 
			
		||||
    FeatureSchema,
 | 
			
		||||
    FeatureSchemaFromJSON,
 | 
			
		||||
    FeatureSchemaToJSON,
 | 
			
		||||
    FeaturesSchema,
 | 
			
		||||
    FeaturesSchemaFromJSON,
 | 
			
		||||
    FeaturesSchemaToJSON,
 | 
			
		||||
    StrategySchema,
 | 
			
		||||
    StrategySchemaFromJSON,
 | 
			
		||||
    StrategySchemaToJSON,
 | 
			
		||||
} from '../models';
 | 
			
		||||
 | 
			
		||||
export interface ApiAdminArchiveFeaturesProjectIdGetRequest {
 | 
			
		||||
    projectId: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ApiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRequest {
 | 
			
		||||
    projectId: string;
 | 
			
		||||
    featureName: string;
 | 
			
		||||
    changeProjectSchema: ChangeProjectSchema;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ApiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesPostRequest {
 | 
			
		||||
    projectId: string;
 | 
			
		||||
    featureName: string;
 | 
			
		||||
    environment: string;
 | 
			
		||||
    createStrategySchema: CreateStrategySchema;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ApiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesStrategyIdPutRequest {
 | 
			
		||||
    projectId: string;
 | 
			
		||||
    featureName: string;
 | 
			
		||||
    environment: string;
 | 
			
		||||
    strategyId: string;
 | 
			
		||||
    createStrategySchema: CreateStrategySchema;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ApiAdminProjectsProjectIdFeaturesFeatureNameGetRequest {
 | 
			
		||||
    projectId: string;
 | 
			
		||||
    featureName: string;
 | 
			
		||||
@ -137,6 +167,146 @@ export class AdminApi extends runtime.BaseAPI {
 | 
			
		||||
        return await response.value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRaw(requestParameters: ApiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<void>> {
 | 
			
		||||
        if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPost.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (requestParameters.featureName === null || requestParameters.featureName === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('featureName','Required parameter requestParameters.featureName was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPost.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (requestParameters.changeProjectSchema === null || requestParameters.changeProjectSchema === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('changeProjectSchema','Required parameter requestParameters.changeProjectSchema was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPost.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const queryParameters: any = {};
 | 
			
		||||
 | 
			
		||||
        const headerParameters: runtime.HTTPHeaders = {};
 | 
			
		||||
 | 
			
		||||
        headerParameters['Content-Type'] = 'application/json';
 | 
			
		||||
 | 
			
		||||
        if (this.configuration && this.configuration.apiKey) {
 | 
			
		||||
            headerParameters["Authorization"] = this.configuration.apiKey("Authorization"); // apiKey authentication
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const response = await this.request({
 | 
			
		||||
            path: `/api/admin/projects/{projectId}/features/{featureName}/changeProject`.replace(`{${"projectId"}}`, encodeURIComponent(String(requestParameters.projectId))).replace(`{${"featureName"}}`, encodeURIComponent(String(requestParameters.featureName))),
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            headers: headerParameters,
 | 
			
		||||
            query: queryParameters,
 | 
			
		||||
            body: ChangeProjectSchemaToJSON(requestParameters.changeProjectSchema),
 | 
			
		||||
        }, initOverrides);
 | 
			
		||||
 | 
			
		||||
        return new runtime.VoidApiResponse(response);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPost(requestParameters: ApiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRequest, initOverrides?: RequestInit): Promise<void> {
 | 
			
		||||
        await this.apiAdminProjectsProjectIdFeaturesFeatureNameChangeProjectPostRaw(requestParameters, initOverrides);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesPostRaw(requestParameters: ApiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesPostRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<StrategySchema>> {
 | 
			
		||||
        if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesPost.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (requestParameters.featureName === null || requestParameters.featureName === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('featureName','Required parameter requestParameters.featureName was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesPost.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (requestParameters.environment === null || requestParameters.environment === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('environment','Required parameter requestParameters.environment was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesPost.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (requestParameters.createStrategySchema === null || requestParameters.createStrategySchema === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('createStrategySchema','Required parameter requestParameters.createStrategySchema was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesPost.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const queryParameters: any = {};
 | 
			
		||||
 | 
			
		||||
        const headerParameters: runtime.HTTPHeaders = {};
 | 
			
		||||
 | 
			
		||||
        headerParameters['Content-Type'] = 'application/json';
 | 
			
		||||
 | 
			
		||||
        if (this.configuration && this.configuration.apiKey) {
 | 
			
		||||
            headerParameters["Authorization"] = this.configuration.apiKey("Authorization"); // apiKey authentication
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const response = await this.request({
 | 
			
		||||
            path: `/api/admin/projects/{projectId}/features/{featureName}/environments/{environment}/strategies`.replace(`{${"projectId"}}`, encodeURIComponent(String(requestParameters.projectId))).replace(`{${"featureName"}}`, encodeURIComponent(String(requestParameters.featureName))).replace(`{${"environment"}}`, encodeURIComponent(String(requestParameters.environment))),
 | 
			
		||||
            method: 'POST',
 | 
			
		||||
            headers: headerParameters,
 | 
			
		||||
            query: queryParameters,
 | 
			
		||||
            body: CreateStrategySchemaToJSON(requestParameters.createStrategySchema),
 | 
			
		||||
        }, initOverrides);
 | 
			
		||||
 | 
			
		||||
        return new runtime.JSONApiResponse(response, (jsonValue) => StrategySchemaFromJSON(jsonValue));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesPost(requestParameters: ApiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesPostRequest, initOverrides?: RequestInit): Promise<StrategySchema> {
 | 
			
		||||
        const response = await this.apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesPostRaw(requestParameters, initOverrides);
 | 
			
		||||
        return await response.value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesStrategyIdPutRaw(requestParameters: ApiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesStrategyIdPutRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<StrategySchema>> {
 | 
			
		||||
        if (requestParameters.projectId === null || requestParameters.projectId === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('projectId','Required parameter requestParameters.projectId was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesStrategyIdPut.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (requestParameters.featureName === null || requestParameters.featureName === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('featureName','Required parameter requestParameters.featureName was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesStrategyIdPut.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (requestParameters.environment === null || requestParameters.environment === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('environment','Required parameter requestParameters.environment was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesStrategyIdPut.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (requestParameters.strategyId === null || requestParameters.strategyId === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('strategyId','Required parameter requestParameters.strategyId was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesStrategyIdPut.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (requestParameters.createStrategySchema === null || requestParameters.createStrategySchema === undefined) {
 | 
			
		||||
            throw new runtime.RequiredError('createStrategySchema','Required parameter requestParameters.createStrategySchema was null or undefined when calling apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesStrategyIdPut.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const queryParameters: any = {};
 | 
			
		||||
 | 
			
		||||
        const headerParameters: runtime.HTTPHeaders = {};
 | 
			
		||||
 | 
			
		||||
        headerParameters['Content-Type'] = 'application/json';
 | 
			
		||||
 | 
			
		||||
        if (this.configuration && this.configuration.apiKey) {
 | 
			
		||||
            headerParameters["Authorization"] = this.configuration.apiKey("Authorization"); // apiKey authentication
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const response = await this.request({
 | 
			
		||||
            path: `/api/admin/projects/{projectId}/features/{featureName}/environments/{environment}/strategies/{strategyId}`.replace(`{${"projectId"}}`, encodeURIComponent(String(requestParameters.projectId))).replace(`{${"featureName"}}`, encodeURIComponent(String(requestParameters.featureName))).replace(`{${"environment"}}`, encodeURIComponent(String(requestParameters.environment))).replace(`{${"strategyId"}}`, encodeURIComponent(String(requestParameters.strategyId))),
 | 
			
		||||
            method: 'PUT',
 | 
			
		||||
            headers: headerParameters,
 | 
			
		||||
            query: queryParameters,
 | 
			
		||||
            body: CreateStrategySchemaToJSON(requestParameters.createStrategySchema),
 | 
			
		||||
        }, initOverrides);
 | 
			
		||||
 | 
			
		||||
        return new runtime.JSONApiResponse(response, (jsonValue) => StrategySchemaFromJSON(jsonValue));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesStrategyIdPut(requestParameters: ApiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesStrategyIdPutRequest, initOverrides?: RequestInit): Promise<StrategySchema> {
 | 
			
		||||
        const response = await this.apiAdminProjectsProjectIdFeaturesFeatureNameEnvironmentsEnvironmentStrategiesStrategyIdPutRaw(requestParameters, initOverrides);
 | 
			
		||||
        return await response.value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     */
 | 
			
		||||
    async apiAdminProjectsProjectIdFeaturesFeatureNameGetRaw(requestParameters: ApiAdminProjectsProjectIdFeaturesFeatureNameGetRequest, initOverrides?: RequestInit): Promise<runtime.ApiResponse<FeatureSchema>> {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										56
									
								
								frontend/src/openapi/models/ChangeProjectSchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								frontend/src/openapi/models/ChangeProjectSchema.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface ChangeProjectSchema
 | 
			
		||||
 */
 | 
			
		||||
export interface ChangeProjectSchema {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof ChangeProjectSchema
 | 
			
		||||
     */
 | 
			
		||||
    newProjectId: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function ChangeProjectSchemaFromJSON(json: any): ChangeProjectSchema {
 | 
			
		||||
    return ChangeProjectSchemaFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function ChangeProjectSchemaFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChangeProjectSchema {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'newProjectId': json['newProjectId'],
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function ChangeProjectSchemaToJSON(value?: ChangeProjectSchema | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'newProjectId': value.newProjectId,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -31,12 +31,30 @@ export interface ConstraintSchema {
 | 
			
		||||
     * @memberof ConstraintSchema
 | 
			
		||||
     */
 | 
			
		||||
    operator: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {boolean}
 | 
			
		||||
     * @memberof ConstraintSchema
 | 
			
		||||
     */
 | 
			
		||||
    caseInsensitive?: boolean;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {boolean}
 | 
			
		||||
     * @memberof ConstraintSchema
 | 
			
		||||
     */
 | 
			
		||||
    inverted?: boolean;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<string>}
 | 
			
		||||
     * @memberof ConstraintSchema
 | 
			
		||||
     */
 | 
			
		||||
    values?: Array<string>;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof ConstraintSchema
 | 
			
		||||
     */
 | 
			
		||||
    value?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function ConstraintSchemaFromJSON(json: any): ConstraintSchema {
 | 
			
		||||
@ -51,7 +69,10 @@ export function ConstraintSchemaFromJSONTyped(json: any, ignoreDiscriminator: bo
 | 
			
		||||
        
 | 
			
		||||
        'contextName': json['contextName'],
 | 
			
		||||
        'operator': json['operator'],
 | 
			
		||||
        'caseInsensitive': !exists(json, 'caseInsensitive') ? undefined : json['caseInsensitive'],
 | 
			
		||||
        'inverted': !exists(json, 'inverted') ? undefined : json['inverted'],
 | 
			
		||||
        'values': !exists(json, 'values') ? undefined : json['values'],
 | 
			
		||||
        'value': !exists(json, 'value') ? undefined : json['value'],
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -66,7 +87,10 @@ export function ConstraintSchemaToJSON(value?: ConstraintSchema | null): any {
 | 
			
		||||
        
 | 
			
		||||
        'contextName': value.contextName,
 | 
			
		||||
        'operator': value.operator,
 | 
			
		||||
        'caseInsensitive': value.caseInsensitive,
 | 
			
		||||
        'inverted': value.inverted,
 | 
			
		||||
        'values': value.values,
 | 
			
		||||
        'value': value.value,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										87
									
								
								frontend/src/openapi/models/CreateStrategySchema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								frontend/src/openapi/models/CreateStrategySchema.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,87 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
import {
 | 
			
		||||
    CreateStrategySchemaConstraints,
 | 
			
		||||
    CreateStrategySchemaConstraintsFromJSON,
 | 
			
		||||
    CreateStrategySchemaConstraintsFromJSONTyped,
 | 
			
		||||
    CreateStrategySchemaConstraintsToJSON,
 | 
			
		||||
} from './CreateStrategySchemaConstraints';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface CreateStrategySchema
 | 
			
		||||
 */
 | 
			
		||||
export interface CreateStrategySchema {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof CreateStrategySchema
 | 
			
		||||
     */
 | 
			
		||||
    name?: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {number}
 | 
			
		||||
     * @memberof CreateStrategySchema
 | 
			
		||||
     */
 | 
			
		||||
    sortOrder?: number;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<CreateStrategySchemaConstraints>}
 | 
			
		||||
     * @memberof CreateStrategySchema
 | 
			
		||||
     */
 | 
			
		||||
    constraints?: Array<CreateStrategySchemaConstraints>;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {{ [key: string]: string; }}
 | 
			
		||||
     * @memberof CreateStrategySchema
 | 
			
		||||
     */
 | 
			
		||||
    parameters?: { [key: string]: string; };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function CreateStrategySchemaFromJSON(json: any): CreateStrategySchema {
 | 
			
		||||
    return CreateStrategySchemaFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function CreateStrategySchemaFromJSONTyped(json: any, ignoreDiscriminator: boolean): CreateStrategySchema {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'name': !exists(json, 'name') ? undefined : json['name'],
 | 
			
		||||
        'sortOrder': !exists(json, 'sortOrder') ? undefined : json['sortOrder'],
 | 
			
		||||
        'constraints': !exists(json, 'constraints') ? undefined : ((json['constraints'] as Array<any>).map(CreateStrategySchemaConstraintsFromJSON)),
 | 
			
		||||
        'parameters': !exists(json, 'parameters') ? undefined : json['parameters'],
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function CreateStrategySchemaToJSON(value?: CreateStrategySchema | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'name': value.name,
 | 
			
		||||
        'sortOrder': value.sortOrder,
 | 
			
		||||
        'constraints': value.constraints === undefined ? undefined : ((value.constraints as Array<any>).map(CreateStrategySchemaConstraintsToJSON)),
 | 
			
		||||
        'parameters': value.parameters,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,96 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface CreateStrategySchemaConstraints
 | 
			
		||||
 */
 | 
			
		||||
export interface CreateStrategySchemaConstraints {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof CreateStrategySchemaConstraints
 | 
			
		||||
     */
 | 
			
		||||
    contextName: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof CreateStrategySchemaConstraints
 | 
			
		||||
     */
 | 
			
		||||
    operator: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {boolean}
 | 
			
		||||
     * @memberof CreateStrategySchemaConstraints
 | 
			
		||||
     */
 | 
			
		||||
    caseInsensitive?: boolean;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {boolean}
 | 
			
		||||
     * @memberof CreateStrategySchemaConstraints
 | 
			
		||||
     */
 | 
			
		||||
    inverted?: boolean;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<string>}
 | 
			
		||||
     * @memberof CreateStrategySchemaConstraints
 | 
			
		||||
     */
 | 
			
		||||
    values?: Array<string>;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof CreateStrategySchemaConstraints
 | 
			
		||||
     */
 | 
			
		||||
    value?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function CreateStrategySchemaConstraintsFromJSON(json: any): CreateStrategySchemaConstraints {
 | 
			
		||||
    return CreateStrategySchemaConstraintsFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function CreateStrategySchemaConstraintsFromJSONTyped(json: any, ignoreDiscriminator: boolean): CreateStrategySchemaConstraints {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'contextName': json['contextName'],
 | 
			
		||||
        'operator': json['operator'],
 | 
			
		||||
        'caseInsensitive': !exists(json, 'caseInsensitive') ? undefined : json['caseInsensitive'],
 | 
			
		||||
        'inverted': !exists(json, 'inverted') ? undefined : json['inverted'],
 | 
			
		||||
        'values': !exists(json, 'values') ? undefined : json['values'],
 | 
			
		||||
        'value': !exists(json, 'value') ? undefined : json['value'],
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function CreateStrategySchemaConstraintsToJSON(value?: CreateStrategySchemaConstraints | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'contextName': value.contextName,
 | 
			
		||||
        'operator': value.operator,
 | 
			
		||||
        'caseInsensitive': value.caseInsensitive,
 | 
			
		||||
        'inverted': value.inverted,
 | 
			
		||||
        'values': value.values,
 | 
			
		||||
        'value': value.value,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -14,17 +14,17 @@
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
import {
 | 
			
		||||
    StrategySchema,
 | 
			
		||||
    StrategySchemaFromJSON,
 | 
			
		||||
    StrategySchemaFromJSONTyped,
 | 
			
		||||
    StrategySchemaToJSON,
 | 
			
		||||
} from './StrategySchema';
 | 
			
		||||
    FeatureSchemaStrategies,
 | 
			
		||||
    FeatureSchemaStrategiesFromJSON,
 | 
			
		||||
    FeatureSchemaStrategiesFromJSONTyped,
 | 
			
		||||
    FeatureSchemaStrategiesToJSON,
 | 
			
		||||
} from './FeatureSchemaStrategies';
 | 
			
		||||
import {
 | 
			
		||||
    VariantSchema,
 | 
			
		||||
    VariantSchemaFromJSON,
 | 
			
		||||
    VariantSchemaFromJSONTyped,
 | 
			
		||||
    VariantSchemaToJSON,
 | 
			
		||||
} from './VariantSchema';
 | 
			
		||||
    FeatureSchemaVariants,
 | 
			
		||||
    FeatureSchemaVariantsFromJSON,
 | 
			
		||||
    FeatureSchemaVariantsFromJSONTyped,
 | 
			
		||||
    FeatureSchemaVariantsToJSON,
 | 
			
		||||
} from './FeatureSchemaVariants';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
@ -88,16 +88,16 @@ export interface FeatureSchema {
 | 
			
		||||
    lastSeenAt?: Date | null;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<StrategySchema>}
 | 
			
		||||
     * @type {Array<FeatureSchemaStrategies>}
 | 
			
		||||
     * @memberof FeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    strategies?: Array<StrategySchema>;
 | 
			
		||||
    strategies?: Array<FeatureSchemaStrategies>;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<VariantSchema>}
 | 
			
		||||
     * @type {Array<FeatureSchemaVariants>}
 | 
			
		||||
     * @memberof FeatureSchema
 | 
			
		||||
     */
 | 
			
		||||
    variants?: Array<VariantSchema>;
 | 
			
		||||
    variants?: Array<FeatureSchemaVariants>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeatureSchemaFromJSON(json: any): FeatureSchema {
 | 
			
		||||
@ -119,8 +119,8 @@ export function FeatureSchemaFromJSONTyped(json: any, ignoreDiscriminator: boole
 | 
			
		||||
        'impressionData': !exists(json, 'impressionData') ? undefined : json['impressionData'],
 | 
			
		||||
        'createdAt': !exists(json, 'createdAt') ? undefined : (json['createdAt'] === null ? null : new Date(json['createdAt'])),
 | 
			
		||||
        'lastSeenAt': !exists(json, 'lastSeenAt') ? undefined : (json['lastSeenAt'] === null ? null : new Date(json['lastSeenAt'])),
 | 
			
		||||
        'strategies': !exists(json, 'strategies') ? undefined : ((json['strategies'] as Array<any>).map(StrategySchemaFromJSON)),
 | 
			
		||||
        'variants': !exists(json, 'variants') ? undefined : ((json['variants'] as Array<any>).map(VariantSchemaFromJSON)),
 | 
			
		||||
        'strategies': !exists(json, 'strategies') ? undefined : ((json['strategies'] as Array<any>).map(FeatureSchemaStrategiesFromJSON)),
 | 
			
		||||
        'variants': !exists(json, 'variants') ? undefined : ((json['variants'] as Array<any>).map(FeatureSchemaVariantsFromJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -142,8 +142,8 @@ export function FeatureSchemaToJSON(value?: FeatureSchema | null): any {
 | 
			
		||||
        'impressionData': value.impressionData,
 | 
			
		||||
        'createdAt': value.createdAt === undefined ? undefined : (value.createdAt === null ? null : value.createdAt.toISOString().substr(0,10)),
 | 
			
		||||
        'lastSeenAt': value.lastSeenAt === undefined ? undefined : (value.lastSeenAt === null ? null : value.lastSeenAt.toISOString().substr(0,10)),
 | 
			
		||||
        'strategies': value.strategies === undefined ? undefined : ((value.strategies as Array<any>).map(StrategySchemaToJSON)),
 | 
			
		||||
        'variants': value.variants === undefined ? undefined : ((value.variants as Array<any>).map(VariantSchemaToJSON)),
 | 
			
		||||
        'strategies': value.strategies === undefined ? undefined : ((value.strategies as Array<any>).map(FeatureSchemaStrategiesToJSON)),
 | 
			
		||||
        'variants': value.variants === undefined ? undefined : ((value.variants as Array<any>).map(FeatureSchemaVariantsToJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										64
									
								
								frontend/src/openapi/models/FeatureSchemaOverrides.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								frontend/src/openapi/models/FeatureSchemaOverrides.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,64 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface FeatureSchemaOverrides
 | 
			
		||||
 */
 | 
			
		||||
export interface FeatureSchemaOverrides {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof FeatureSchemaOverrides
 | 
			
		||||
     */
 | 
			
		||||
    contextName: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<string>}
 | 
			
		||||
     * @memberof FeatureSchemaOverrides
 | 
			
		||||
     */
 | 
			
		||||
    values: Array<string>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeatureSchemaOverridesFromJSON(json: any): FeatureSchemaOverrides {
 | 
			
		||||
    return FeatureSchemaOverridesFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeatureSchemaOverridesFromJSONTyped(json: any, ignoreDiscriminator: boolean): FeatureSchemaOverrides {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'contextName': json['contextName'],
 | 
			
		||||
        'values': json['values'],
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeatureSchemaOverridesToJSON(value?: FeatureSchemaOverrides | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'contextName': value.contextName,
 | 
			
		||||
        'values': value.values,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										87
									
								
								frontend/src/openapi/models/FeatureSchemaStrategies.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								frontend/src/openapi/models/FeatureSchemaStrategies.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,87 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
import {
 | 
			
		||||
    CreateStrategySchemaConstraints,
 | 
			
		||||
    CreateStrategySchemaConstraintsFromJSON,
 | 
			
		||||
    CreateStrategySchemaConstraintsFromJSONTyped,
 | 
			
		||||
    CreateStrategySchemaConstraintsToJSON,
 | 
			
		||||
} from './CreateStrategySchemaConstraints';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface FeatureSchemaStrategies
 | 
			
		||||
 */
 | 
			
		||||
export interface FeatureSchemaStrategies {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof FeatureSchemaStrategies
 | 
			
		||||
     */
 | 
			
		||||
    id: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof FeatureSchemaStrategies
 | 
			
		||||
     */
 | 
			
		||||
    name: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<CreateStrategySchemaConstraints>}
 | 
			
		||||
     * @memberof FeatureSchemaStrategies
 | 
			
		||||
     */
 | 
			
		||||
    constraints: Array<CreateStrategySchemaConstraints>;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {{ [key: string]: string; }}
 | 
			
		||||
     * @memberof FeatureSchemaStrategies
 | 
			
		||||
     */
 | 
			
		||||
    parameters: { [key: string]: string; };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeatureSchemaStrategiesFromJSON(json: any): FeatureSchemaStrategies {
 | 
			
		||||
    return FeatureSchemaStrategiesFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeatureSchemaStrategiesFromJSONTyped(json: any, ignoreDiscriminator: boolean): FeatureSchemaStrategies {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'id': json['id'],
 | 
			
		||||
        'name': json['name'],
 | 
			
		||||
        'constraints': ((json['constraints'] as Array<any>).map(CreateStrategySchemaConstraintsFromJSON)),
 | 
			
		||||
        'parameters': json['parameters'],
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeatureSchemaStrategiesToJSON(value?: FeatureSchemaStrategies | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'id': value.id,
 | 
			
		||||
        'name': value.name,
 | 
			
		||||
        'constraints': ((value.constraints as Array<any>).map(CreateStrategySchemaConstraintsToJSON)),
 | 
			
		||||
        'parameters': value.parameters,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										103
									
								
								frontend/src/openapi/models/FeatureSchemaVariants.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								frontend/src/openapi/models/FeatureSchemaVariants.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,103 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
import {
 | 
			
		||||
    FeatureSchemaOverrides,
 | 
			
		||||
    FeatureSchemaOverridesFromJSON,
 | 
			
		||||
    FeatureSchemaOverridesFromJSONTyped,
 | 
			
		||||
    FeatureSchemaOverridesToJSON,
 | 
			
		||||
} from './FeatureSchemaOverrides';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface FeatureSchemaVariants
 | 
			
		||||
 */
 | 
			
		||||
export interface FeatureSchemaVariants {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof FeatureSchemaVariants
 | 
			
		||||
     */
 | 
			
		||||
    name: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {number}
 | 
			
		||||
     * @memberof FeatureSchemaVariants
 | 
			
		||||
     */
 | 
			
		||||
    weight: number;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof FeatureSchemaVariants
 | 
			
		||||
     */
 | 
			
		||||
    weightType: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof FeatureSchemaVariants
 | 
			
		||||
     */
 | 
			
		||||
    stickiness: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {object}
 | 
			
		||||
     * @memberof FeatureSchemaVariants
 | 
			
		||||
     */
 | 
			
		||||
    payload?: object;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<FeatureSchemaOverrides>}
 | 
			
		||||
     * @memberof FeatureSchemaVariants
 | 
			
		||||
     */
 | 
			
		||||
    overrides?: Array<FeatureSchemaOverrides>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeatureSchemaVariantsFromJSON(json: any): FeatureSchemaVariants {
 | 
			
		||||
    return FeatureSchemaVariantsFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeatureSchemaVariantsFromJSONTyped(json: any, ignoreDiscriminator: boolean): FeatureSchemaVariants {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'name': json['name'],
 | 
			
		||||
        'weight': json['weight'],
 | 
			
		||||
        'weightType': json['weightType'],
 | 
			
		||||
        'stickiness': json['stickiness'],
 | 
			
		||||
        'payload': !exists(json, 'payload') ? undefined : json['payload'],
 | 
			
		||||
        'overrides': !exists(json, 'overrides') ? undefined : ((json['overrides'] as Array<any>).map(FeatureSchemaOverridesFromJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeatureSchemaVariantsToJSON(value?: FeatureSchemaVariants | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'name': value.name,
 | 
			
		||||
        'weight': value.weight,
 | 
			
		||||
        'weightType': value.weightType,
 | 
			
		||||
        'stickiness': value.stickiness,
 | 
			
		||||
        'payload': value.payload,
 | 
			
		||||
        'overrides': value.overrides === undefined ? undefined : ((value.overrides as Array<any>).map(FeatureSchemaOverridesToJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -14,11 +14,11 @@
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
import {
 | 
			
		||||
    FeatureSchema,
 | 
			
		||||
    FeatureSchemaFromJSON,
 | 
			
		||||
    FeatureSchemaFromJSONTyped,
 | 
			
		||||
    FeatureSchemaToJSON,
 | 
			
		||||
} from './FeatureSchema';
 | 
			
		||||
    FeaturesSchemaFeatures,
 | 
			
		||||
    FeaturesSchemaFeaturesFromJSON,
 | 
			
		||||
    FeaturesSchemaFeaturesFromJSONTyped,
 | 
			
		||||
    FeaturesSchemaFeaturesToJSON,
 | 
			
		||||
} from './FeaturesSchemaFeatures';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
@ -34,10 +34,10 @@ export interface FeaturesSchema {
 | 
			
		||||
    version: number;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<FeatureSchema>}
 | 
			
		||||
     * @type {Array<FeaturesSchemaFeatures>}
 | 
			
		||||
     * @memberof FeaturesSchema
 | 
			
		||||
     */
 | 
			
		||||
    features: Array<FeatureSchema>;
 | 
			
		||||
    features: Array<FeaturesSchemaFeatures>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeaturesSchemaFromJSON(json: any): FeaturesSchema {
 | 
			
		||||
@ -51,7 +51,7 @@ export function FeaturesSchemaFromJSONTyped(json: any, ignoreDiscriminator: bool
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'version': json['version'],
 | 
			
		||||
        'features': ((json['features'] as Array<any>).map(FeatureSchemaFromJSON)),
 | 
			
		||||
        'features': ((json['features'] as Array<any>).map(FeaturesSchemaFeaturesFromJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -65,7 +65,7 @@ export function FeaturesSchemaToJSON(value?: FeaturesSchema | null): any {
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'version': value.version,
 | 
			
		||||
        'features': ((value.features as Array<any>).map(FeatureSchemaToJSON)),
 | 
			
		||||
        'features': ((value.features as Array<any>).map(FeaturesSchemaFeaturesToJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										149
									
								
								frontend/src/openapi/models/FeaturesSchemaFeatures.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								frontend/src/openapi/models/FeaturesSchemaFeatures.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,149 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/**
 | 
			
		||||
 * Unleash API
 | 
			
		||||
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 | 
			
		||||
 *
 | 
			
		||||
 * The version of the OpenAPI document: 4.10.0
 | 
			
		||||
 * 
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 | 
			
		||||
 * https://openapi-generator.tech
 | 
			
		||||
 * Do not edit the class manually.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
import {
 | 
			
		||||
    FeatureSchemaStrategies,
 | 
			
		||||
    FeatureSchemaStrategiesFromJSON,
 | 
			
		||||
    FeatureSchemaStrategiesFromJSONTyped,
 | 
			
		||||
    FeatureSchemaStrategiesToJSON,
 | 
			
		||||
} from './FeatureSchemaStrategies';
 | 
			
		||||
import {
 | 
			
		||||
    FeatureSchemaVariants,
 | 
			
		||||
    FeatureSchemaVariantsFromJSON,
 | 
			
		||||
    FeatureSchemaVariantsFromJSONTyped,
 | 
			
		||||
    FeatureSchemaVariantsToJSON,
 | 
			
		||||
} from './FeatureSchemaVariants';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @export
 | 
			
		||||
 * @interface FeaturesSchemaFeatures
 | 
			
		||||
 */
 | 
			
		||||
export interface FeaturesSchemaFeatures {
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof FeaturesSchemaFeatures
 | 
			
		||||
     */
 | 
			
		||||
    name: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof FeaturesSchemaFeatures
 | 
			
		||||
     */
 | 
			
		||||
    type?: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof FeaturesSchemaFeatures
 | 
			
		||||
     */
 | 
			
		||||
    description?: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     * @memberof FeaturesSchemaFeatures
 | 
			
		||||
     */
 | 
			
		||||
    project: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {boolean}
 | 
			
		||||
     * @memberof FeaturesSchemaFeatures
 | 
			
		||||
     */
 | 
			
		||||
    enabled?: boolean;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {boolean}
 | 
			
		||||
     * @memberof FeaturesSchemaFeatures
 | 
			
		||||
     */
 | 
			
		||||
    stale?: boolean;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {boolean}
 | 
			
		||||
     * @memberof FeaturesSchemaFeatures
 | 
			
		||||
     */
 | 
			
		||||
    impressionData?: boolean;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Date}
 | 
			
		||||
     * @memberof FeaturesSchemaFeatures
 | 
			
		||||
     */
 | 
			
		||||
    createdAt?: Date | null;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Date}
 | 
			
		||||
     * @memberof FeaturesSchemaFeatures
 | 
			
		||||
     */
 | 
			
		||||
    lastSeenAt?: Date | null;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<FeatureSchemaStrategies>}
 | 
			
		||||
     * @memberof FeaturesSchemaFeatures
 | 
			
		||||
     */
 | 
			
		||||
    strategies?: Array<FeatureSchemaStrategies>;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<FeatureSchemaVariants>}
 | 
			
		||||
     * @memberof FeaturesSchemaFeatures
 | 
			
		||||
     */
 | 
			
		||||
    variants?: Array<FeatureSchemaVariants>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeaturesSchemaFeaturesFromJSON(json: any): FeaturesSchemaFeatures {
 | 
			
		||||
    return FeaturesSchemaFeaturesFromJSONTyped(json, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeaturesSchemaFeaturesFromJSONTyped(json: any, ignoreDiscriminator: boolean): FeaturesSchemaFeatures {
 | 
			
		||||
    if ((json === undefined) || (json === null)) {
 | 
			
		||||
        return json;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'name': json['name'],
 | 
			
		||||
        'type': !exists(json, 'type') ? undefined : json['type'],
 | 
			
		||||
        'description': !exists(json, 'description') ? undefined : json['description'],
 | 
			
		||||
        'project': json['project'],
 | 
			
		||||
        'enabled': !exists(json, 'enabled') ? undefined : json['enabled'],
 | 
			
		||||
        'stale': !exists(json, 'stale') ? undefined : json['stale'],
 | 
			
		||||
        'impressionData': !exists(json, 'impressionData') ? undefined : json['impressionData'],
 | 
			
		||||
        'createdAt': !exists(json, 'createdAt') ? undefined : (json['createdAt'] === null ? null : new Date(json['createdAt'])),
 | 
			
		||||
        'lastSeenAt': !exists(json, 'lastSeenAt') ? undefined : (json['lastSeenAt'] === null ? null : new Date(json['lastSeenAt'])),
 | 
			
		||||
        'strategies': !exists(json, 'strategies') ? undefined : ((json['strategies'] as Array<any>).map(FeatureSchemaStrategiesFromJSON)),
 | 
			
		||||
        'variants': !exists(json, 'variants') ? undefined : ((json['variants'] as Array<any>).map(FeatureSchemaVariantsFromJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function FeaturesSchemaFeaturesToJSON(value?: FeaturesSchemaFeatures | null): any {
 | 
			
		||||
    if (value === undefined) {
 | 
			
		||||
        return undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (value === null) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    return {
 | 
			
		||||
        
 | 
			
		||||
        'name': value.name,
 | 
			
		||||
        'type': value.type,
 | 
			
		||||
        'description': value.description,
 | 
			
		||||
        'project': value.project,
 | 
			
		||||
        'enabled': value.enabled,
 | 
			
		||||
        'stale': value.stale,
 | 
			
		||||
        'impressionData': value.impressionData,
 | 
			
		||||
        'createdAt': value.createdAt === undefined ? undefined : (value.createdAt === null ? null : value.createdAt.toISOString().substr(0,10)),
 | 
			
		||||
        'lastSeenAt': value.lastSeenAt === undefined ? undefined : (value.lastSeenAt === null ? null : value.lastSeenAt.toISOString().substr(0,10)),
 | 
			
		||||
        'strategies': value.strategies === undefined ? undefined : ((value.strategies as Array<any>).map(FeatureSchemaStrategiesToJSON)),
 | 
			
		||||
        'variants': value.variants === undefined ? undefined : ((value.variants as Array<any>).map(FeatureSchemaVariantsToJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -14,11 +14,11 @@
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
import {
 | 
			
		||||
    ConstraintSchema,
 | 
			
		||||
    ConstraintSchemaFromJSON,
 | 
			
		||||
    ConstraintSchemaFromJSONTyped,
 | 
			
		||||
    ConstraintSchemaToJSON,
 | 
			
		||||
} from './ConstraintSchema';
 | 
			
		||||
    CreateStrategySchemaConstraints,
 | 
			
		||||
    CreateStrategySchemaConstraintsFromJSON,
 | 
			
		||||
    CreateStrategySchemaConstraintsFromJSONTyped,
 | 
			
		||||
    CreateStrategySchemaConstraintsToJSON,
 | 
			
		||||
} from './CreateStrategySchemaConstraints';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
@ -40,16 +40,16 @@ export interface StrategySchema {
 | 
			
		||||
    name: string;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<ConstraintSchema>}
 | 
			
		||||
     * @type {Array<CreateStrategySchemaConstraints>}
 | 
			
		||||
     * @memberof StrategySchema
 | 
			
		||||
     */
 | 
			
		||||
    constraints: Array<ConstraintSchema>;
 | 
			
		||||
    constraints: Array<CreateStrategySchemaConstraints>;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {object}
 | 
			
		||||
     * @type {{ [key: string]: string; }}
 | 
			
		||||
     * @memberof StrategySchema
 | 
			
		||||
     */
 | 
			
		||||
    parameters: object;
 | 
			
		||||
    parameters: { [key: string]: string; };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function StrategySchemaFromJSON(json: any): StrategySchema {
 | 
			
		||||
@ -64,7 +64,7 @@ export function StrategySchemaFromJSONTyped(json: any, ignoreDiscriminator: bool
 | 
			
		||||
        
 | 
			
		||||
        'id': json['id'],
 | 
			
		||||
        'name': json['name'],
 | 
			
		||||
        'constraints': ((json['constraints'] as Array<any>).map(ConstraintSchemaFromJSON)),
 | 
			
		||||
        'constraints': ((json['constraints'] as Array<any>).map(CreateStrategySchemaConstraintsFromJSON)),
 | 
			
		||||
        'parameters': json['parameters'],
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
@ -80,7 +80,7 @@ export function StrategySchemaToJSON(value?: StrategySchema | null): any {
 | 
			
		||||
        
 | 
			
		||||
        'id': value.id,
 | 
			
		||||
        'name': value.name,
 | 
			
		||||
        'constraints': ((value.constraints as Array<any>).map(ConstraintSchemaToJSON)),
 | 
			
		||||
        'constraints': ((value.constraints as Array<any>).map(CreateStrategySchemaConstraintsToJSON)),
 | 
			
		||||
        'parameters': value.parameters,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -14,11 +14,11 @@
 | 
			
		||||
 | 
			
		||||
import { exists, mapValues } from '../runtime';
 | 
			
		||||
import {
 | 
			
		||||
    OverrideSchema,
 | 
			
		||||
    OverrideSchemaFromJSON,
 | 
			
		||||
    OverrideSchemaFromJSONTyped,
 | 
			
		||||
    OverrideSchemaToJSON,
 | 
			
		||||
} from './OverrideSchema';
 | 
			
		||||
    FeatureSchemaOverrides,
 | 
			
		||||
    FeatureSchemaOverridesFromJSON,
 | 
			
		||||
    FeatureSchemaOverridesFromJSONTyped,
 | 
			
		||||
    FeatureSchemaOverridesToJSON,
 | 
			
		||||
} from './FeatureSchemaOverrides';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
@ -58,10 +58,10 @@ export interface VariantSchema {
 | 
			
		||||
    payload?: object;
 | 
			
		||||
    /**
 | 
			
		||||
     * 
 | 
			
		||||
     * @type {Array<OverrideSchema>}
 | 
			
		||||
     * @type {Array<FeatureSchemaOverrides>}
 | 
			
		||||
     * @memberof VariantSchema
 | 
			
		||||
     */
 | 
			
		||||
    overrides: Array<OverrideSchema>;
 | 
			
		||||
    overrides?: Array<FeatureSchemaOverrides>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function VariantSchemaFromJSON(json: any): VariantSchema {
 | 
			
		||||
@ -79,7 +79,7 @@ export function VariantSchemaFromJSONTyped(json: any, ignoreDiscriminator: boole
 | 
			
		||||
        'weightType': json['weightType'],
 | 
			
		||||
        'stickiness': json['stickiness'],
 | 
			
		||||
        'payload': !exists(json, 'payload') ? undefined : json['payload'],
 | 
			
		||||
        'overrides': ((json['overrides'] as Array<any>).map(OverrideSchemaFromJSON)),
 | 
			
		||||
        'overrides': !exists(json, 'overrides') ? undefined : ((json['overrides'] as Array<any>).map(FeatureSchemaOverridesFromJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -97,7 +97,7 @@ export function VariantSchemaToJSON(value?: VariantSchema | null): any {
 | 
			
		||||
        'weightType': value.weightType,
 | 
			
		||||
        'stickiness': value.stickiness,
 | 
			
		||||
        'payload': value.payload,
 | 
			
		||||
        'overrides': ((value.overrides as Array<any>).map(OverrideSchemaToJSON)),
 | 
			
		||||
        'overrides': value.overrides === undefined ? undefined : ((value.overrides as Array<any>).map(FeatureSchemaOverridesToJSON)),
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,16 @@
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
export * from './ChangeProjectSchema';
 | 
			
		||||
export * from './ConstraintSchema';
 | 
			
		||||
export * from './CreateFeatureSchema';
 | 
			
		||||
export * from './CreateStrategySchema';
 | 
			
		||||
export * from './CreateStrategySchemaConstraints';
 | 
			
		||||
export * from './FeatureSchema';
 | 
			
		||||
export * from './FeatureSchemaOverrides';
 | 
			
		||||
export * from './FeatureSchemaStrategies';
 | 
			
		||||
export * from './FeatureSchemaVariants';
 | 
			
		||||
export * from './FeaturesSchema';
 | 
			
		||||
export * from './FeaturesSchemaFeatures';
 | 
			
		||||
export * from './OverrideSchema';
 | 
			
		||||
export * from './StrategySchema';
 | 
			
		||||
export * from './VariantSchema';
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										31
									
								
								frontend/src/utils/cleanConstraint.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								frontend/src/utils/cleanConstraint.test.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
import { cleanConstraint } from 'utils/cleanConstraint';
 | 
			
		||||
 | 
			
		||||
test('cleanConstraint values', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
        cleanConstraint({
 | 
			
		||||
            contextName: '',
 | 
			
		||||
            operator: 'IN',
 | 
			
		||||
            value: '1',
 | 
			
		||||
            values: ['2'],
 | 
			
		||||
        })
 | 
			
		||||
    ).toEqual({
 | 
			
		||||
        contextName: '',
 | 
			
		||||
        operator: 'IN',
 | 
			
		||||
        values: ['2'],
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test('cleanConstraint value', () => {
 | 
			
		||||
    expect(
 | 
			
		||||
        cleanConstraint({
 | 
			
		||||
            contextName: '',
 | 
			
		||||
            operator: 'NUM_EQ',
 | 
			
		||||
            value: '1',
 | 
			
		||||
            values: ['2'],
 | 
			
		||||
        })
 | 
			
		||||
    ).toEqual({
 | 
			
		||||
        contextName: '',
 | 
			
		||||
        operator: 'NUM_EQ',
 | 
			
		||||
        value: '1',
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@ -1,31 +1,16 @@
 | 
			
		||||
import { singleValueOperators } from 'constants/operators';
 | 
			
		||||
import { IConstraint } from 'interfaces/strategy';
 | 
			
		||||
import { oneOf } from 'utils/oneOf';
 | 
			
		||||
 | 
			
		||||
const VALUES = 'values';
 | 
			
		||||
const VALUE = 'value';
 | 
			
		||||
import produce from 'immer';
 | 
			
		||||
 | 
			
		||||
export const cleanConstraint = (
 | 
			
		||||
    constraint: Readonly<IConstraint>
 | 
			
		||||
): IConstraint => {
 | 
			
		||||
    const constraintCopy: IConstraint = {
 | 
			
		||||
        contextName: '',
 | 
			
		||||
        operator: 'IN',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (oneOf(singleValueOperators, constraint.operator)) {
 | 
			
		||||
        for (const [key, value] of Object.entries(constraint)) {
 | 
			
		||||
            if (key !== VALUES) {
 | 
			
		||||
                constraintCopy[key] = value;
 | 
			
		||||
            }
 | 
			
		||||
    return produce(constraint, draft => {
 | 
			
		||||
        if (oneOf(singleValueOperators, constraint.operator)) {
 | 
			
		||||
            delete draft.values;
 | 
			
		||||
        } else {
 | 
			
		||||
            delete draft.value;
 | 
			
		||||
        }
 | 
			
		||||
        return constraintCopy;
 | 
			
		||||
    } else {
 | 
			
		||||
        for (const [key, value] of Object.entries(constraint)) {
 | 
			
		||||
            if (key !== VALUE) {
 | 
			
		||||
                constraintCopy[key] = value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return constraintCopy;
 | 
			
		||||
    }
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,8 @@
 | 
			
		||||
import { IStrategy, IParameter } from '../interfaces/strategy';
 | 
			
		||||
import {
 | 
			
		||||
    IStrategy,
 | 
			
		||||
    IStrategyParameter,
 | 
			
		||||
    IFeatureStrategyParameters,
 | 
			
		||||
} from 'interfaces/strategy';
 | 
			
		||||
import { resolveDefaultParamValue } from 'utils/resolveDefaultParamValue';
 | 
			
		||||
 | 
			
		||||
export const getStrategyObject = (
 | 
			
		||||
@ -9,9 +13,10 @@ export const getStrategyObject = (
 | 
			
		||||
    const selectedStrategy = selectableStrategies.find(
 | 
			
		||||
        strategy => strategy.name === name
 | 
			
		||||
    );
 | 
			
		||||
    const parameters = {} as IParameter;
 | 
			
		||||
 | 
			
		||||
    selectedStrategy?.parameters.forEach(({ name }: IParameter) => {
 | 
			
		||||
    const parameters: IFeatureStrategyParameters = {};
 | 
			
		||||
 | 
			
		||||
    selectedStrategy?.parameters.forEach(({ name }: IStrategyParameter) => {
 | 
			
		||||
        parameters[name] = resolveDefaultParamValue(name, featureId);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										36
									
								
								frontend/src/utils/parseParameter.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								frontend/src/utils/parseParameter.test.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
import {
 | 
			
		||||
    parseParameterNumber,
 | 
			
		||||
    parseParameterString,
 | 
			
		||||
    parseParameterStrings,
 | 
			
		||||
} from 'utils/parseParameter';
 | 
			
		||||
 | 
			
		||||
test('parseParameterNumber', () => {
 | 
			
		||||
    expect(parseParameterNumber(undefined)).toEqual(0);
 | 
			
		||||
    expect(parseParameterNumber('')).toEqual(0);
 | 
			
		||||
    expect(parseParameterNumber(0)).toEqual(0);
 | 
			
		||||
    expect(parseParameterNumber(1)).toEqual(1);
 | 
			
		||||
    expect(parseParameterNumber('a')).toEqual(0);
 | 
			
		||||
    expect(parseParameterNumber('0')).toEqual(0);
 | 
			
		||||
    expect(parseParameterNumber('1')).toEqual(1);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test('parseParameterString', () => {
 | 
			
		||||
    expect(parseParameterString(undefined)).toEqual('');
 | 
			
		||||
    expect(parseParameterString('')).toEqual('');
 | 
			
		||||
    expect(parseParameterString(0)).toEqual('0');
 | 
			
		||||
    expect(parseParameterString(1)).toEqual('1');
 | 
			
		||||
    expect(parseParameterString('a')).toEqual('a');
 | 
			
		||||
    expect(parseParameterString('0')).toEqual('0');
 | 
			
		||||
    expect(parseParameterString('1')).toEqual('1');
 | 
			
		||||
    expect(parseParameterString(' a, ,a ')).toEqual('a, ,a');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test('parseParameterStrings', () => {
 | 
			
		||||
    expect(parseParameterStrings(undefined)).toEqual([]);
 | 
			
		||||
    expect(parseParameterStrings('')).toEqual([]);
 | 
			
		||||
    expect(parseParameterStrings(0)).toEqual(['0']);
 | 
			
		||||
    expect(parseParameterStrings(1)).toEqual(['1']);
 | 
			
		||||
    expect(parseParameterStrings('a')).toEqual(['a']);
 | 
			
		||||
    expect(parseParameterStrings('a,b,c')).toEqual(['a', 'b', 'c']);
 | 
			
		||||
    expect(parseParameterStrings(' a,, b c ,,, d,')).toEqual(['a', 'b c', 'd']);
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										23
									
								
								frontend/src/utils/parseParameter.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								frontend/src/utils/parseParameter.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
import { IFeatureStrategyParameters } from 'interfaces/strategy';
 | 
			
		||||
 | 
			
		||||
export const parseParameterNumber = (
 | 
			
		||||
    value: IFeatureStrategyParameters[string]
 | 
			
		||||
): number => {
 | 
			
		||||
    const parsed = Number(parseParameterString(value));
 | 
			
		||||
    return Number.isFinite(parsed) ? parsed : 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const parseParameterString = (
 | 
			
		||||
    value: IFeatureStrategyParameters[string]
 | 
			
		||||
): string => {
 | 
			
		||||
    return String(value ?? '').trim();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const parseParameterStrings = (
 | 
			
		||||
    value: IFeatureStrategyParameters[string]
 | 
			
		||||
): string[] => {
 | 
			
		||||
    return parseParameterString(value)
 | 
			
		||||
        .split(',')
 | 
			
		||||
        .map(s => s.trim())
 | 
			
		||||
        .filter(Boolean);
 | 
			
		||||
};
 | 
			
		||||
@ -1,11 +1,11 @@
 | 
			
		||||
export const resolveDefaultParamValue = (
 | 
			
		||||
    name: string,
 | 
			
		||||
    featureToggleName: string
 | 
			
		||||
): string | number => {
 | 
			
		||||
): string => {
 | 
			
		||||
    switch (name) {
 | 
			
		||||
        case 'percentage':
 | 
			
		||||
        case 'rollout':
 | 
			
		||||
            return 100;
 | 
			
		||||
            return '100';
 | 
			
		||||
        case 'stickiness':
 | 
			
		||||
            return 'default';
 | 
			
		||||
        case 'groupId':
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user