1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-07-12 13:48:35 +02:00

parameter handling

This commit is contained in:
andreas-unleash 2022-08-03 14:03:04 +03:00
parent 1a753a3bcb
commit 0d083231a3
13 changed files with 624 additions and 188 deletions

View File

@ -16,10 +16,9 @@ import {
parseParameterNumber, parseParameterNumber,
parseParameterStrings, parseParameterStrings,
} from 'utils/parseParameter'; } from 'utils/parseParameter';
import { PlaygroundFeatureStrategyResult } from 'hooks/api/actions/usePlayground/playground.model';
interface IStrategyExecutionProps { interface IStrategyExecutionProps {
strategy: IFeatureStrategy | PlaygroundFeatureStrategyResult; strategy: IFeatureStrategy;
percentageFill?: string; percentageFill?: string;
} }

View File

@ -5,13 +5,8 @@ import {
import { IconButton, Popover, styled } from '@mui/material'; import { IconButton, Popover, styled } from '@mui/material';
import { InfoOutlined } from '@mui/icons-material'; import { InfoOutlined } from '@mui/icons-material';
import React, { useRef, useState } from 'react'; import React, { useRef, useState } from 'react';
import { ConditionallyRender } from '../../../../common/ConditionallyRender/ConditionallyRender';
import { useStyles } from './FeatureResultInfoPopoverCell.styles'; import { useStyles } from './FeatureResultInfoPopoverCell.styles';
import { PlaygroundResultFeatureDetails } from './PlaygroundResultFeatureDetails/PlaygroundResultFeatureDetails'; import { PlaygroundResultFeatureDetails } from './PlaygroundResultFeatureDetails/PlaygroundResultFeatureDetails';
import {
PlaygroundResultStrategyLists,
WrappedPlaygroundResultStrategyList,
} from './PlaygroundResultFeatureStrategyList/PlaygroundResultStrategyList/playgroundResultStrategyLists';
import { PlaygroundResultFeatureStrategyList } from './PlaygroundResultFeatureStrategyList/PlaygroundResultFeatureStrategyList'; import { PlaygroundResultFeatureStrategyList } from './PlaygroundResultFeatureStrategyList/PlaygroundResultFeatureStrategyList';
interface FeatureResultInfoPopoverCellProps { interface FeatureResultInfoPopoverCellProps {

View File

@ -9,6 +9,7 @@ import { CloseOutlined } from '@mui/icons-material';
import React from 'react'; import React from 'react';
import { ConditionallyRender } from '../../../../../common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from '../../../../../common/ConditionallyRender/ConditionallyRender';
import { checkForEmptyValues } from './helpers'; import { checkForEmptyValues } from './helpers';
interface PlaygroundFeatureResultDetailsProps { interface PlaygroundFeatureResultDetailsProps {
feature: PlaygroundFeatureSchema; feature: PlaygroundFeatureSchema;
input?: PlaygroundRequestSchema; input?: PlaygroundRequestSchema;
@ -22,22 +23,22 @@ export const PlaygroundResultFeatureDetails = ({
const { classes: styles } = useStyles(); const { classes: styles } = useStyles();
const theme = useTheme(); const theme = useTheme();
const description = Boolean(feature.isEnabled) const description = feature.isEnabled
? `This feature toggle is True in ${input?.environment} because ` ? `This feature toggle is True in ${input?.environment} because `
: `This feature toggle is False in ${input?.environment} because `; : `This feature toggle is False in ${input?.environment} because `;
const reason = Boolean(feature.isEnabled) const reason = feature.isEnabled
? 'at least one strategy is True' ? 'at least one strategy is True'
: !feature?.isEnabledInCurrentEnvironment : feature?.isEnabledInCurrentEnvironment
? 'the environment is disabled' ? 'the environment is disabled'
: 'all strategies are False'; : 'all strategies are False';
const color = Boolean(feature.isEnabled) const color = feature.isEnabled
? theme.palette.success.main ? theme.palette.success.main
: theme.palette.error.main; : theme.palette.error.main;
const noValueTxt = checkForEmptyValues(input?.context) const noValueTxt = checkForEmptyValues(input?.context)
? 'You did not provide a value for your context filed in step 2 of the configuration' ? 'You did not provide a value for your context field in step 2 of the configuration'
: undefined; : undefined;
const onCloseClick = const onCloseClick =

View File

@ -20,20 +20,22 @@ export const PlaygroundResultFeatureStrategyList = ({
}: PlaygroundResultFeatureStrategyListProps) => { }: PlaygroundResultFeatureStrategyListProps) => {
return ( return (
<ConditionallyRender <ConditionallyRender
condition={!feature.isEnabledInCurrentEnvironment} condition={
show={ !feature.isEnabled && feature.isEnabledInCurrentEnvironment
<PlaygroundResultStrategyLists
strategies={feature?.strategies}
input={input}
/>
} }
elseShow={ show={
<WrappedPlaygroundResultStrategyList <WrappedPlaygroundResultStrategyList
strategies={feature?.strategies} strategies={feature?.strategies}
feature={feature} feature={feature}
input={input} input={input}
/> />
} }
elseShow={
<PlaygroundResultStrategyLists
strategies={feature?.strategies}
input={input}
/>
}
/> />
); );
}; };

View File

@ -0,0 +1,28 @@
import { makeStyles } from 'tss-react/mui';
export const useStyles = makeStyles()(theme => ({
container: {
width: '100%',
padding: theme.spacing(2, 3),
borderRadius: theme.shape.borderRadius,
border: `1px solid ${theme.palette.divider}`,
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
gap: theme.spacing(2),
},
chip: {
margin: '0.25rem',
},
column: {
flexDirection: 'column',
},
paragraph: {
display: 'inline',
margin: '0.25rem 0',
maxWidth: '95%',
textAlign: 'center',
wordBreak: 'break-word',
},
}));

View File

@ -0,0 +1,78 @@
import { Chip, Typography, useTheme } from '@mui/material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { useStyles } from './PlaygroundConstraintItem.styles';
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
import { CancelOutlined } from "@mui/icons-material";
interface IConstraintItemProps {
value: string[];
text: string;
input?: string | number | boolean | 'no value';
showReason?: boolean;
}
export const PlaygroundConstraintItem = ({
value,
text,
input,
showReason = false,
}: IConstraintItemProps) => {
const { classes: styles } = useStyles();
const theme = useTheme();
const color = input === 'no value' ? 'error' : 'neutral';
const reason = `value does not match any ${text}`;
console.log(value, text, input, showReason);
return (
<div className={styles.container}>
<Typography variant="subtitle1" color={theme.palette[color].main}>
{input}
</Typography>
<div className={styles.column}>
<ConditionallyRender
condition={Boolean(showReason)}
show={
<Typography
variant="subtitle1"
color={theme.palette.error.main}
>
{reason}
</Typography>
}
/>
<ConditionallyRender
condition={value.length === 0}
show={<p>No {text}s added yet.</p>}
elseShow={
<div>
<p className={styles.paragraph}>
{value.length}{' '}
{value.length > 1 ? `${text}s` : text} will get
access.
</p>
{value.map((v: string) => (
<Chip
key={v}
label={
<StringTruncator
maxWidth="300"
text={v}
maxLength={50}
/>
}
className={styles.chip}
/>
))}
</div>
}
/>
</div>
<ConditionallyRender
condition={Boolean(showReason)}
show={<CancelOutlined color={'error'} />}
/>
</div>
);
};

View File

@ -1,5 +1,5 @@
import { import {
PlaygroundFeatureStrategyConstraintResult, PlaygroundConstraintSchema,
PlaygroundRequestSchema, PlaygroundRequestSchema,
} from 'hooks/api/actions/usePlayground/playground.model'; } from 'hooks/api/actions/usePlayground/playground.model';
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
@ -10,7 +10,7 @@ import { ConstraintAccordionView } from '../../../../../../../../common/Constrai
import { styled } from '@mui/material'; import { styled } from '@mui/material';
interface PlaygroundResultConstraintExecutionProps { interface PlaygroundResultConstraintExecutionProps {
constraints?: PlaygroundFeatureStrategyConstraintResult[]; constraints?: PlaygroundConstraintSchema[];
compact: boolean; compact: boolean;
input?: PlaygroundRequestSchema; input?: PlaygroundRequestSchema;
} }

View File

@ -8,14 +8,14 @@ import {
import StringTruncator from 'component/common/StringTruncator/StringTruncator'; import StringTruncator from 'component/common/StringTruncator/StringTruncator';
import { PlaygroundResultChip } from '../../../../PlaygroundResultChip/PlaygroundResultChip'; import { PlaygroundResultChip } from '../../../../PlaygroundResultChip/PlaygroundResultChip';
import { import {
PlaygroundFeatureStrategyResult, PlaygroundStrategySchema,
PlaygroundRequestSchema, PlaygroundRequestSchema,
} from 'hooks/api/actions/usePlayground/playground.model'; } from 'hooks/api/actions/usePlayground/playground.model';
import { PlaygroundResultStrategyExecution } from './PlaygroundResultStrategyExecution/PlaygroundResultStrategyExecution'; import { PlaygroundResultStrategyExecution } from './PlaygroundResultStrategyExecution/PlaygroundResultStrategyExecution';
import { useStyles } from './PlaygroundResultFeatureStrategyItem.styles'; import { useStyles } from './PlaygroundResultFeatureStrategyItem.styles';
interface IPlaygroundResultFeatureStrategyItemProps { interface IPlaygroundResultFeatureStrategyItemProps {
strategy: PlaygroundFeatureStrategyResult; strategy: PlaygroundStrategySchema;
index: number; index: number;
input?: PlaygroundRequestSchema; input?: PlaygroundRequestSchema;
compact: boolean; compact: boolean;
@ -40,8 +40,12 @@ export const PlaygroundResultFeatureStrategyItem = ({
const theme = useTheme(); const theme = useTheme();
const Icon = getFeatureStrategyIcon(strategy.name); const Icon = getFeatureStrategyIcon(strategy.name);
const label = const label =
result === undefined ? 'Not found' : result ? 'True' : 'False'; result.evaluationStatus !== 'complete'
const border = Boolean(result) ? 'Unevaluated'
: result.enabled
? 'True'
: 'False';
const border = result.enabled
? `1px solid ${theme.palette.success.main}` ? `1px solid ${theme.palette.success.main}`
: `1px solid ${theme.palette.divider}`; : `1px solid ${theme.palette.divider}`;
@ -71,7 +75,7 @@ export const PlaygroundResultFeatureStrategyItem = ({
</div> </div>
<PlaygroundResultChip <PlaygroundResultChip
showIcon={false} showIcon={false}
enabled={Boolean(result)} enabled={result.enabled}
label={label} label={label}
/> />
</div> </div>

View File

@ -1,5 +1,5 @@
import { import {
PlaygroundFeatureStrategySegmentResult, PlaygroundSegmentSchema,
PlaygroundRequestSchema, PlaygroundRequestSchema,
} from '../../../../../../../../../hooks/api/actions/usePlayground/playground.model'; } from '../../../../../../../../../hooks/api/actions/usePlayground/playground.model';
import { PlaygroundResultConstraintExecution } from '../PlaygroundResultConstraintExecution/PlaygroundResultConstraintExecution'; import { PlaygroundResultConstraintExecution } from '../PlaygroundResultConstraintExecution/PlaygroundResultConstraintExecution';
@ -11,7 +11,7 @@ import { styled, Typography } from '@mui/material';
import { ConditionallyRender } from '../../../../../../../../common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from '../../../../../../../../common/ConditionallyRender/ConditionallyRender';
interface PlaygroundResultSegmentExecutionProps { interface PlaygroundResultSegmentExecutionProps {
segments?: PlaygroundFeatureStrategySegmentResult[]; segments?: PlaygroundSegmentSchema[];
input?: PlaygroundRequestSchema; input?: PlaygroundRequestSchema;
hasConstraints: boolean; hasConstraints: boolean;
} }

View File

@ -11,6 +11,7 @@ export const useStyles = makeStyles()(theme => ({
}, },
summary: { summary: {
width: 'auto', width: 'auto',
height: 'auto',
padding: theme.spacing(2, 3), padding: theme.spacing(2, 3),
borderRadius: theme.shape.borderRadius, borderRadius: theme.shape.borderRadius,
border: `1px solid ${theme.palette.divider}`, border: `1px solid ${theme.palette.divider}`,

View File

@ -3,16 +3,28 @@ import { StrategySeparator } from '../../../../../../../../common/StrategySepara
import { Box, Chip, styled } from '@mui/material'; import { Box, Chip, styled } from '@mui/material';
import { useStyles } from './PlaygroundResultStrategyExecution.styles'; import { useStyles } from './PlaygroundResultStrategyExecution.styles';
import { import {
PlaygroundFeatureStrategyResult,
PlaygroundRequestSchema, PlaygroundRequestSchema,
PlaygroundStrategySchema,
} from '../../../../../../../../../hooks/api/actions/usePlayground/playground.model'; } from '../../../../../../../../../hooks/api/actions/usePlayground/playground.model';
import useUiConfig from '../../../../../../../../../hooks/api/getters/useUiConfig/useUiConfig'; import useUiConfig from '../../../../../../../../../hooks/api/getters/useUiConfig/useUiConfig';
import React from 'react'; import React, { Fragment } from 'react';
import { PlaygroundResultConstraintExecution } from '../PlaygroundResultConstraintExecution/PlaygroundResultConstraintExecution'; import { PlaygroundResultConstraintExecution } from '../PlaygroundResultConstraintExecution/PlaygroundResultConstraintExecution';
import { PlaygroundResultSegmentExecution } from '../PlaygroundResultSegmentExecution/PlaygroundResultSegmentExecution'; import { PlaygroundResultSegmentExecution } from '../PlaygroundResultSegmentExecution/PlaygroundResultSegmentExecution';
import {
parseParameterNumber,
parseParameterString,
parseParameterStrings,
} from '../../../../../../../../../utils/parseParameter';
import PercentageCircle from '../../../../../../../../common/PercentageCircle/PercentageCircle';
import StringTruncator from '../../../../../../../../common/StringTruncator/StringTruncator';
import { useStrategies } from '../../../../../../../../../hooks/api/getters/useStrategies/useStrategies';
import { PlaygroundConstraintItem } from '../PlaygroundConstraintItem/PlaygroundConstraintItem';
import {
ConstraintItem
} from "../../../../../../../../feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/ConstraintItem/ConstraintItem";
interface PlaygroundResultStrategyExecutionProps { interface PlaygroundResultStrategyExecutionProps {
strategyResult: PlaygroundFeatureStrategyResult; strategyResult: PlaygroundStrategySchema;
percentageFill?: string; percentageFill?: string;
input?: PlaygroundRequestSchema; input?: PlaygroundRequestSchema;
} }
@ -25,13 +37,274 @@ export const PlaygroundResultStrategyExecution = ({
strategyResult, strategyResult,
input, input,
}: PlaygroundResultStrategyExecutionProps) => { }: PlaygroundResultStrategyExecutionProps) => {
const { name, constraints, segments } = strategyResult; const { name, constraints, segments, parameters } = strategyResult;
const { strategies } = useStrategies();
const { uiConfig } = useUiConfig(); const { uiConfig } = useUiConfig();
const { classes: styles } = useStyles(); const { classes: styles } = useStyles();
const hasConstraints = Boolean(constraints && constraints.length > 0); const hasConstraints = Boolean(constraints && constraints.length > 0);
if (!parameters) {
return null;
}
const definition = strategies.find(strategyDefinition => {
return strategyDefinition.name === strategyResult.name;
});
const renderParameters = () => {
return Object.keys(parameters).map(key => {
switch (key) {
case 'rollout':
case 'Rollout':
const percentage = parseParameterNumber(parameters[key]);
return (
<Box
className={styles.summary}
key={key}
sx={{ display: 'flex', alignItems: 'center' }}
>
<Box sx={{ mr: '1rem' }}>
<PercentageCircle
percentage={percentage}
size="2rem"
/>
</Box>
<div>
<Chip
color="success"
variant="outlined"
size="small"
label={`${percentage}%`}
/>{' '}
of your base{' '}
{constraints.length > 0
? 'who match constraints'
: ''}{' '}
is included.
</div>
</Box>
);
case 'userIds':
case 'UserIds':
const users = parseParameterStrings(parameters[key]);
return (
<PlaygroundConstraintItem
key={key}
value={users}
text="user"
input={
Boolean(input?.context?.[key])
? input?.context?.[key]
: 'no value'
}
showReason={
Boolean(input?.context?.[key])
? !users.includes(input?.context?.[key])
: undefined
}
/>
);
case 'hostNames':
case 'HostNames':
const hosts = parseParameterStrings(parameters[key]);
console.log(input?.context);
console.log(key);
console.log(input?.context?.[key]);
console.log(hosts.includes(input?.context?.[key]));
return (
<PlaygroundConstraintItem
key={key}
value={hosts}
text={'host'}
input={
Boolean(input?.context?.[key])
? input?.context?.[key]
: 'no value'
}
showReason={
Boolean(input?.context?.[key])
? !hosts.includes(input?.context?.[key])
: undefined
}
/>
);
case 'IPs':
const IPs = parseParameterStrings(parameters[key]);
return (
<PlaygroundConstraintItem
key={key}
value={IPs}
text={'IP'}
input={
Boolean(input?.context?.[key])
? input?.context?.[key]
: 'no value'
}
showReason={
Boolean(input?.context?.[key])
? !IPs.includes(input?.context?.[key])
: undefined
}
/>
);
case 'stickiness':
case 'groupId':
return null;
default:
return null;
}
});
};
const renderCustomStrategy = () => {
if (!definition?.editable) return null;
return definition?.parameters.map((param: any, index: number) => {
const notLastItem = index !== definition?.parameters?.length - 1;
switch (param?.type) {
case 'list':
const values = parseParameterStrings(
strategyResult?.parameters[param.name]
);
return (
<Fragment key={param?.name}>
<ConstraintItem value={values} text={param.name} />
<ConditionallyRender
condition={notLastItem}
show={<StrategySeparator text="AND" />}
/>
</Fragment>
);
case 'percentage':
return (
<Fragment key={param?.name}>
<div>
<Chip
size="small"
variant="outlined"
color="success"
label={`${
strategyResult?.parameters[param.name]
}%`}
/>{' '}
of your base{' '}
{constraints?.length > 0
? 'who match constraints'
: ''}{' '}
is included.
</div>
<PercentageCircle
percentage={parseParameterNumber(
strategyResult.parameters[param.name]
)}
/>
<ConditionallyRender
condition={notLastItem}
show={<StrategySeparator text="AND" />}
/>
</Fragment>
);
case 'boolean':
return (
<Fragment key={param.name}>
<p key={param.name}>
<StringTruncator
maxLength={15}
maxWidth="150"
text={param.name}
/>{' '}
{strategyResult.parameters[param.name]}
</p>
<ConditionallyRender
condition={
typeof strategyResult.parameters[param.name] !==
'undefined'
}
show={
<ConditionallyRender
condition={notLastItem}
show={<StrategySeparator text="AND" />}
/>
}
/>
</Fragment>
);
case 'string':
const value = parseParameterString(
strategyResult.parameters[param.name]
);
return (
<ConditionallyRender
condition={
typeof strategyResult.parameters[param.name] !==
'undefined'
}
key={param.name}
show={
<>
<p className={styles.valueContainer}>
<StringTruncator
maxWidth="150"
maxLength={15}
text={param.name}
/>
<span className={styles.valueSeparator}>
is set to
</span>
<StringTruncator
maxWidth="300"
text={value}
maxLength={50}
/>
</p>
<ConditionallyRender
condition={notLastItem}
show={<StrategySeparator text="AND" />}
/>
</>
}
/>
);
case 'number':
const number = parseParameterNumber(
strategyResult.parameters[param.name]
);
return (
<ConditionallyRender
condition={number !== undefined}
key={param.name}
show={
<>
<p className={styles.valueContainer}>
<StringTruncator
maxLength={15}
maxWidth="150"
text={param.name}
/>
<span className={styles.valueSeparator}>
is set to
</span>
<StringTruncator
maxWidth="300"
text={String(number)}
maxLength={50}
/>
</p>
<ConditionallyRender
condition={notLastItem}
show={<StrategySeparator text="AND" />}
/>
</>
}
/>
);
case 'default':
return null;
}
return null;
});
};
return ( return (
<StyledStrategyExecutionWrapper> <StyledStrategyExecutionWrapper>
<ConditionallyRender <ConditionallyRender
@ -56,7 +329,12 @@ export const PlaygroundResultStrategyExecution = ({
compact={true} compact={true}
input={input} input={input}
/> />
<StrategySeparator text="AND" /> <ConditionallyRender
condition={Boolean(
constraints && constraints.length > 0
)}
show={<StrategySeparator text="AND" />}
/>
</> </>
} }
/> />
@ -64,7 +342,7 @@ export const PlaygroundResultStrategyExecution = ({
condition={name === 'default'} condition={name === 'default'}
show={ show={
<Box sx={{ width: '100%' }} className={styles.summary}> <Box sx={{ width: '100%' }} className={styles.summary}>
The standard strategy is{' '} The standard strategyResult is{' '}
<Chip <Chip
variant="outlined" variant="outlined"
size="small" size="small"
@ -75,6 +353,8 @@ export const PlaygroundResultStrategyExecution = ({
</Box> </Box>
} }
/> />
{renderParameters()}
{renderCustomStrategy()}
</StyledStrategyExecutionWrapper> </StyledStrategyExecutionWrapper>
); );
}; };

View File

@ -1,6 +1,6 @@
import { import {
PlaygroundFeatureSchema, PlaygroundFeatureSchema,
PlaygroundFeatureStrategyResult, PlaygroundStrategySchema,
PlaygroundRequestSchema, PlaygroundRequestSchema,
} from '../../../../../../../hooks/api/actions/usePlayground/playground.model'; } from '../../../../../../../hooks/api/actions/usePlayground/playground.model';
import { ConditionallyRender } from '../../../../../../common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from '../../../../../../common/ConditionallyRender/ConditionallyRender';
@ -12,7 +12,7 @@ const StyledAlertWrapper = styled('div')(({ theme }) => ({
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
borderRadius: theme.shape.borderRadiusMedium, borderRadius: theme.shape.borderRadiusMedium,
border: `1px solid ${theme.palette.info.main}`, border: `1px solid ${theme.palette.info.border}`,
})); }));
const StyledListWrapper = styled('div')(({ theme }) => ({ const StyledListWrapper = styled('div')(({ theme }) => ({
@ -25,7 +25,7 @@ const StyledAlert = styled(Alert)(({ theme }) => ({
})); }));
interface PlaygroundResultStrategyListProps { interface PlaygroundResultStrategyListProps {
strategies: PlaygroundFeatureStrategyResult[]; strategies: PlaygroundStrategySchema[];
input?: PlaygroundRequestSchema; input?: PlaygroundRequestSchema;
compact?: boolean; compact?: boolean;
} }
@ -35,6 +35,7 @@ export const PlaygroundResultStrategyLists = ({
input, input,
compact = false, compact = false,
}: PlaygroundResultStrategyListProps) => { }: PlaygroundResultStrategyListProps) => {
console.log(strategies);
return ( return (
<ConditionallyRender <ConditionallyRender
condition={strategies.length > 0} condition={strategies.length > 0}

View File

@ -1,40 +1,124 @@
// TODO: replace with auto-generated openapi code import { VariantSchema } from '../../../../openapi';
import { export const PlaygroundConstraintSchemaOperatorEnum = {
IConstraint, NotIn: 'NOT_IN',
IFeatureStrategyParameters, In: 'IN',
} from '../../../../interfaces/strategy'; StrEndsWith: 'STR_ENDS_WITH',
StrStartsWith: 'STR_STARTS_WITH',
StrContains: 'STR_CONTAINS',
NumEq: 'NUM_EQ',
NumGt: 'NUM_GT',
NumGte: 'NUM_GTE',
NumLt: 'NUM_LT',
NumLte: 'NUM_LTE',
DateAfter: 'DATE_AFTER',
DateBefore: 'DATE_BEFORE',
SemverEq: 'SEMVER_EQ',
SemverGt: 'SEMVER_GT',
SemverLt: 'SEMVER_LT',
} as const;
export type PlaygroundConstraintSchemaOperatorEnum =
typeof PlaygroundConstraintSchemaOperatorEnum[keyof typeof PlaygroundConstraintSchemaOperatorEnum];
export enum PlaygroundFeatureSchemaVariantPayloadTypeEnum { export interface PlaygroundConstraintSchema {
Json = 'json', /**
Csv = 'csv', * The name of the context field that this constraint should apply to.
String = 'string', * @type {string}
* @memberof PlaygroundConstraintSchema
*/
contextName: string;
/**
* The operator to use when evaluating this constraint. For more information about the various operators, refer to [the strategy constraint operator documentation](https://docs.getunleash.io/advanced/strategy_constraints#strategy-constraint-operators).
* @type {string}
* @memberof PlaygroundConstraintSchema
*/
operator: PlaygroundConstraintSchemaOperatorEnum;
/**
* Whether the operator should be case sensitive or not. Defaults to `false` (being case sensitive).
* @type {boolean}
* @memberof PlaygroundConstraintSchema
*/
caseInsensitive?: boolean;
/**
* Whether the result should be negated or not. If `true`, will turn a `true` result into a `false` result and vice versa.
* @type {boolean}
* @memberof PlaygroundConstraintSchema
*/
inverted?: boolean;
/**
* The context values that should be used for constraint evaluation. Use this property instead of `value` for properties that accept multiple values.
* @type {Array<string>}
* @memberof PlaygroundConstraintSchema
*/
values?: Array<string>;
/**
* The context value that should be used for constraint evaluation. Use this property instead of `values` for properties that only accept single values.
* @type {string}
* @memberof PlaygroundConstraintSchema
*/
value?: string;
/**
* Whether this was evaluated as true or false.
* @type {boolean}
* @memberof PlaygroundConstraintSchema
*/
result: boolean;
} }
export interface PlaygroundFeatureSchemaVariantPayload { export interface PlaygroundFeatureSchema {
/**
* The feature's name.
* @type {string}
* @memberof PlaygroundFeatureSchema
*/
name: string;
/**
* The ID of the project that contains this feature.
* @type {string}
* @memberof PlaygroundFeatureSchema
*/
projectId: string;
/**
* The strategies that apply to this feature.
* @type {Array<PlaygroundStrategySchema>}
* @memberof PlaygroundFeatureSchema
*/
strategies: Array<PlaygroundStrategySchema>;
/**
* Whether the feature is active and would be evaluated in the provided environment in a normal SDK context.
* @type {boolean}
* @memberof PlaygroundFeatureSchema
*/
isEnabledInCurrentEnvironment: boolean;
/** /**
* *
* @type {string} * @type {PlaygroundFeatureSchemaIsEnabled}
* @memberof PlaygroundFeatureSchemaVariantPayload * @memberof PlaygroundFeatureSchema
*/ */
type: PlaygroundFeatureSchemaVariantPayloadTypeEnum; isEnabled: boolean | 'unevaluated';
/** /**
* *
* @type {string} * @type {PlaygroundFeatureSchemaVariant}
* @memberof PlaygroundFeatureSchemaVariantPayload * @memberof PlaygroundFeatureSchema
*/ */
value: string; variant: PlaygroundFeatureSchemaVariant | null;
/**
*
* @type {Array<VariantSchema>}
* @memberof PlaygroundFeatureSchema
*/
variants: Array<VariantSchema>;
} }
export interface PlaygroundFeatureSchemaVariant { export interface PlaygroundFeatureSchemaVariant {
/** /**
* * The variant's name. If there is no variant or if the toggle is disabled, this will be `disabled`
* @type {string} * @type {string}
* @memberof PlaygroundFeatureSchemaVariant * @memberof PlaygroundFeatureSchemaVariant
*/ */
name: string; name: string;
/** /**
* * Whether the variant is enabled or not. If the feature is disabled or if it doesn't have variants, this property will be `false`
* @type {boolean} * @type {boolean}
* @memberof PlaygroundFeatureSchemaVariant * @memberof PlaygroundFeatureSchemaVariant
*/ */
@ -47,54 +131,32 @@ export interface PlaygroundFeatureSchemaVariant {
payload?: PlaygroundFeatureSchemaVariantPayload; payload?: PlaygroundFeatureSchemaVariantPayload;
} }
export interface PlaygroundFeatureSchema { export interface PlaygroundFeatureSchemaVariantPayload {
/** /**
* * The format of the payload.
* @type {string} * @type {string}
* @memberof PlaygroundFeatureSchema * @memberof PlaygroundFeatureSchemaVariantPayload
*/ */
name: string; type: PlaygroundFeatureSchemaVariantPayloadTypeEnum;
/** /**
* * The payload value stringified.
* @type {string} * @type {string}
* @memberof PlaygroundFeatureSchema * @memberof PlaygroundFeatureSchemaVariantPayload
*/ */
projectId: string; value: string;
/**
*
* @type {boolean}
* @memberof PlaygroundFeatureSchema
*/
isEnabled: boolean | 'unevaluated';
isEnabledInCurrentEnvironment: boolean;
/**
*
* @type {PlaygroundFeatureSchemaVariant}
* @memberof PlaygroundFeatureSchema
*/
variant: PlaygroundFeatureSchemaVariant | null;
strategies: PlaygroundFeatureStrategyResult[];
}
export interface PlaygroundResponseSchema {
/**
*
* @type {PlaygroundRequestSchema}
* @memberof PlaygroundResponseSchema
*/
input: PlaygroundRequestSchema;
/**
*
* @type {Array<PlaygroundFeatureSchema>}
* @memberof PlaygroundResponseSchema
*/
features: Array<PlaygroundFeatureSchema>;
} }
export const PlaygroundFeatureSchemaVariantPayloadTypeEnum = {
Json: 'json',
Csv: 'csv',
String: 'string',
} as const;
export type PlaygroundFeatureSchemaVariantPayloadTypeEnum =
typeof PlaygroundFeatureSchemaVariantPayloadTypeEnum[keyof typeof PlaygroundFeatureSchemaVariantPayloadTypeEnum];
export interface PlaygroundRequestSchema { export interface PlaygroundRequestSchema {
/** /**
* * The environment to evaluate toggles in.
* @type {string} * @type {string}
* @memberof PlaygroundRequestSchema * @memberof PlaygroundRequestSchema
*/ */
@ -104,7 +166,7 @@ export interface PlaygroundRequestSchema {
* @type {PlaygroundRequestSchemaProjects} * @type {PlaygroundRequestSchemaProjects}
* @memberof PlaygroundRequestSchema * @memberof PlaygroundRequestSchema
*/ */
projects?: Array<string> | string; projects?: PlaygroundRequestSchemaProjects;
/** /**
* *
* @type {SdkContextSchema} * @type {SdkContextSchema}
@ -113,68 +175,8 @@ export interface PlaygroundRequestSchema {
context: SdkContextSchema; context: SdkContextSchema;
} }
export interface PlaygroundFeatureSchemaVariantPayload { export type PlaygroundRequestSchemaProjects = Array<string> | string;
/**
*
* @type {string}
* @memberof PlaygroundFeatureSchemaVariantPayload
*/
type: PlaygroundFeatureSchemaVariantPayloadTypeEnum;
/**
*
* @type {string}
* @memberof PlaygroundFeatureSchemaVariantPayload
*/
value: string;
}
export interface PlaygroundFeatureSchemaVariant {
/**
*
* @type {string}
* @memberof PlaygroundFeatureSchemaVariant
*/
name: string;
/**
*
* @type {boolean}
* @memberof PlaygroundFeatureSchemaVariant
*/
enabled: boolean;
/**
*
* @type {PlaygroundFeatureSchemaVariantPayload}
* @memberof PlaygroundFeatureSchemaVariant
*/
payload?: PlaygroundFeatureSchemaVariantPayload;
}
export interface PlaygroundFeatureSchema {
/**
*
* @type {string}
* @memberof PlaygroundFeatureSchema
*/
name: string;
/**
*
* @type {string}
* @memberof PlaygroundFeatureSchema
*/
projectId: string;
/**
*
* @type {boolean}
* @memberof PlaygroundFeatureSchema
*/
enabled: boolean | 'unevaluated';
/**
*
* @type {PlaygroundFeatureSchemaVariant}
* @memberof PlaygroundFeatureSchema
*/
variant: PlaygroundFeatureSchemaVariant | null;
}
export interface PlaygroundResponseSchema { export interface PlaygroundResponseSchema {
/** /**
* *
@ -183,32 +185,98 @@ export interface PlaygroundResponseSchema {
*/ */
input: PlaygroundRequestSchema; input: PlaygroundRequestSchema;
/** /**
* * The list of features that have been evaluated.
* @type {Array<PlaygroundFeatureSchema>} * @type {Array<PlaygroundFeatureSchema>}
* @memberof PlaygroundResponseSchema * @memberof PlaygroundResponseSchema
*/ */
features: Array<PlaygroundFeatureSchema>; features: Array<PlaygroundFeatureSchema>;
} }
export interface PlaygroundRequestSchema { export interface PlaygroundSegmentSchema {
/** /**
* * The segment's id.
* @type {number}
* @memberof PlaygroundSegmentSchema
*/
id: number;
/**
* The name of the segment.
* @type {string} * @type {string}
* @memberof PlaygroundRequestSchema * @memberof PlaygroundSegmentSchema
*/ */
environment: string; name: string;
/**
* Whether this was evaluated as true or false.
* @type {boolean}
* @memberof PlaygroundSegmentSchema
*/
result: boolean;
/**
* The list of constraints in this segment.
* @type {Array<PlaygroundConstraintSchema>}
* @memberof PlaygroundSegmentSchema
*/
constraints: Array<PlaygroundConstraintSchema>;
}
export interface PlaygroundStrategySchema {
/**
* The strategy's name.
* @type {string}
* @memberof PlaygroundStrategySchema
*/
name: string;
/**
* The strategy's id.
* @type {string}
* @memberof PlaygroundStrategySchema
*/
id?: string;
/** /**
* *
* @type Array<string> | string * @type {PlaygroundStrategySchemaResult}
* @memberof PlaygroundRequestSchema * @memberof PlaygroundStrategySchema
*/ */
projects?: Array<string> | string; result: PlaygroundStrategySchemaResult;
/**
* The strategy's segments and their evaluation results.
* @type {Array<PlaygroundSegmentSchema>}
* @memberof PlaygroundStrategySchema
*/
segments: Array<PlaygroundSegmentSchema>;
/**
* The strategy's constraints and their evaluation results.
* @type {Array<PlaygroundConstraintSchema>}
* @memberof PlaygroundStrategySchema
*/
constraints: Array<PlaygroundConstraintSchema>;
/** /**
* *
* @type {SdkContextSchema} * @type {{ [key: string]: string; }}
* @memberof PlaygroundRequestSchema * @memberof PlaygroundStrategySchema
*/ */
context: SdkContextSchema; parameters: { [key: string]: string };
}
export const PlaygroundStrategySchemaResultEvaluationStatusEnum = {
Complete: 'complete',
} as const;
export type PlaygroundStrategySchemaResultEvaluationStatusEnum =
typeof PlaygroundStrategySchemaResultEvaluationStatusEnum[keyof typeof PlaygroundStrategySchemaResultEvaluationStatusEnum];
export interface PlaygroundStrategySchemaResult {
/**
* Signals that this strategy was evaluated successfully.
* @type {string}
* @memberof PlaygroundStrategySchemaResult
*/
evaluationStatus?: PlaygroundStrategySchemaResultEvaluationStatusEnum;
/**
* Whether this strategy evaluates to true or not.
* @type {boolean}
* @memberof PlaygroundStrategySchemaResult
*/
enabled: boolean;
} }
export interface SdkContextSchema { export interface SdkContextSchema {
@ -257,24 +325,3 @@ export interface SdkContextSchema {
*/ */
userId?: string; userId?: string;
} }
export interface PlaygroundFeatureStrategyConstraintResult extends IConstraint {
result: boolean;
}
export interface PlaygroundFeatureStrategySegmentResult {
id: number;
name: string;
result: boolean;
constraints?: PlaygroundFeatureStrategyConstraintResult[];
}
export interface PlaygroundFeatureStrategyResult {
id: string;
name: string;
result: boolean | 'not found';
type?: string;
constraints?: PlaygroundFeatureStrategyConstraintResult[];
segments?: PlaygroundFeatureStrategySegmentResult[];
parameters: IFeatureStrategyParameters;
}