mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-23 00:22:19 +01:00
Playground result info structure and initial styles
This commit is contained in:
parent
cdaf7299be
commit
352a4cca13
@ -16,9 +16,10 @@ import {
|
||||
parseParameterNumber,
|
||||
parseParameterStrings,
|
||||
} from 'utils/parseParameter';
|
||||
import { PlaygroundFeatureStrategyResult } from 'hooks/api/actions/usePlayground/playground.model';
|
||||
|
||||
interface IStrategyExecutionProps {
|
||||
strategy: IFeatureStrategy;
|
||||
strategy: IFeatureStrategy | PlaygroundFeatureStrategyResult;
|
||||
percentageFill?: string;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { DragIndicator, Edit } from '@mui/icons-material';
|
||||
import { styled, useTheme, IconButton, Chip } from '@mui/material';
|
||||
import { styled, useTheme, IconButton } from '@mui/material';
|
||||
import { Link } from 'react-router-dom';
|
||||
import {IFeatureStrategy, IPlaygroundFeatureStrategyResult} from 'interfaces/strategy';
|
||||
import { IFeatureStrategy } from 'interfaces/strategy';
|
||||
import {
|
||||
getFeatureStrategyIcon,
|
||||
formatStrategyName,
|
||||
@ -18,10 +18,8 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
|
||||
|
||||
interface IStrategyItemProps {
|
||||
environmentId: string;
|
||||
strategy: IFeatureStrategy | IPlaygroundFeatureStrategyResult;
|
||||
strategy: IFeatureStrategy;
|
||||
isDraggable?: boolean;
|
||||
showActions?: boolean;
|
||||
result?: boolean;
|
||||
}
|
||||
|
||||
const DragIcon = styled(IconButton)(({ theme }) => ({
|
||||
@ -34,8 +32,6 @@ export const StrategyItem = ({
|
||||
environmentId,
|
||||
strategy,
|
||||
isDraggable,
|
||||
showActions = true,
|
||||
result,
|
||||
}: IStrategyItemProps) => {
|
||||
const projectId = useRequiredPathParam('projectId');
|
||||
const featureId = useRequiredPathParam('featureId');
|
||||
@ -50,8 +46,6 @@ export const StrategyItem = ({
|
||||
strategy.id
|
||||
);
|
||||
|
||||
const showShouldShowResultChip = result !== undefined;
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.header}>
|
||||
@ -72,9 +66,6 @@ export const StrategyItem = ({
|
||||
maxLength={15}
|
||||
text={formatStrategyName(strategy.name)}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={showActions}
|
||||
show={
|
||||
<div className={styles.actions}>
|
||||
<PermissionIconButton
|
||||
permission={UPDATE_FEATURE_STRATEGY}
|
||||
@ -94,14 +85,6 @@ export const StrategyItem = ({
|
||||
icon
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={showShouldShowResultChip}
|
||||
show={
|
||||
<Featur>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.body}>
|
||||
<StrategyExecution
|
||||
|
@ -0,0 +1,14 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
popoverPaper: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'flex-start',
|
||||
padding: '48px',
|
||||
gap: '24px',
|
||||
width: '728px',
|
||||
height: 'auto',
|
||||
// overflowY: 'scroll',
|
||||
},
|
||||
}));
|
@ -1,8 +1,17 @@
|
||||
import { PlaygroundFeatureSchema } from '../../../../../hooks/api/actions/usePlayground/playground.model';
|
||||
import { Box, IconButton, Popover } from '@mui/material';
|
||||
import {
|
||||
PlaygroundFeatureSchema,
|
||||
PlaygroundFeatureStrategyResult,
|
||||
} from '../../../../../hooks/api/actions/usePlayground/playground.model';
|
||||
import { Box, IconButton, Popover, Typography } from '@mui/material';
|
||||
import { InfoOutlined } from '@mui/icons-material';
|
||||
import { IconCell } from '../../../../common/Table/cells/IconCell/IconCell';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { ConditionallyRender } from '../../../../common/ConditionallyRender/ConditionallyRender';
|
||||
import { StrategyDraggableItem } from '../../../../feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyDraggableItem';
|
||||
import { FeatureStrategyEmpty } from '../../../../feature/FeatureStrategy/FeatureStrategyEmpty/FeatureStrategyEmpty';
|
||||
import { PlaygroundResultFeatureStrategyItem } from './PlaygroundResultFeatureStrategyItem/PlaygroundResultFeatureStrategyItem';
|
||||
import { useStyles } from './FeatureResultInfoPopoverCell.styles';
|
||||
import { PlaygroundResultFeatureDetails } from './PlaygroundResultFeatureDetails/PlaygroundResultFeatureDetails';
|
||||
|
||||
interface FeatureResultInfoPopoverCellProps {
|
||||
feature?: PlaygroundFeatureSchema;
|
||||
@ -15,16 +24,18 @@ export const FeatureResultInfoPopoverCell = ({
|
||||
return null;
|
||||
}
|
||||
const [open, setOpen] = useState(false);
|
||||
const { classes: styles } = useStyles();
|
||||
const ref = useRef(null);
|
||||
|
||||
const togglePopover = (event: React.SyntheticEvent) => {
|
||||
setOpen(!open);
|
||||
};
|
||||
|
||||
const strategies = [
|
||||
const strategies: PlaygroundFeatureStrategyResult[] = [
|
||||
{
|
||||
type: 'standard',
|
||||
name: 'default',
|
||||
id: 'strategy-id',
|
||||
parameters: {},
|
||||
result: false,
|
||||
constraints: [
|
||||
{
|
||||
@ -54,10 +65,6 @@ export const FeatureResultInfoPopoverCell = ({
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'default',
|
||||
result: true,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
@ -77,8 +84,26 @@ export const FeatureResultInfoPopoverCell = ({
|
||||
vertical: 'center',
|
||||
horizontal: 'left',
|
||||
}}
|
||||
classes={{ paper: styles.popoverPaper }}
|
||||
>
|
||||
{feature.name}
|
||||
<PlaygroundResultFeatureDetails feature={feature} />
|
||||
<ConditionallyRender
|
||||
condition={strategies.length > 0}
|
||||
show={
|
||||
<>
|
||||
<Typography
|
||||
variant={'subtitle2'}
|
||||
>{`Strategies (${strategies.length})`}</Typography>
|
||||
{strategies.map((strategy, index) => (
|
||||
<PlaygroundResultFeatureStrategyItem
|
||||
key={strategy.id}
|
||||
strategy={strategy}
|
||||
index={index}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</Popover>
|
||||
</>
|
||||
);
|
||||
|
@ -0,0 +1,21 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
titleRow: {
|
||||
display: 'inline-flex',
|
||||
alignItems: 'flex-start',
|
||||
justifyItems: 'center',
|
||||
gap: '12px',
|
||||
},
|
||||
descriptionRow: {
|
||||
flexDirection: 'row',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'flex-start',
|
||||
justifyItems: 'center',
|
||||
gap: '6px',
|
||||
},
|
||||
name: {
|
||||
fontWeight: 600,
|
||||
padding: '4px',
|
||||
},
|
||||
}));
|
@ -0,0 +1,39 @@
|
||||
import { PlaygroundFeatureSchema } from '../../../../../../hooks/api/actions/usePlayground/playground.model';
|
||||
import { Typography } from '@mui/material';
|
||||
import { PlaygroundResultChip } from '../../PlaygroundResultChip/PlaygroundResultChip';
|
||||
import { useStyles } from './PlaygroundResultFeatureDetails.styles';
|
||||
interface PlaygroundFeatureResultDetailsProps {
|
||||
feature: PlaygroundFeatureSchema;
|
||||
}
|
||||
export const PlaygroundResultFeatureDetails = ({
|
||||
feature,
|
||||
}: PlaygroundFeatureResultDetailsProps) => {
|
||||
const { classes: styles } = useStyles();
|
||||
|
||||
const description = feature.isEnabled
|
||||
? 'This feature toggle is True in production because '
|
||||
: 'This feature toggle is False in production because ';
|
||||
const reason = feature.isEnabled
|
||||
? 'at least one strategy is True'
|
||||
: 'all strategies are False';
|
||||
const color = feature.isEnabled ? 'success' : 'error';
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.titleRow}>
|
||||
<Typography variant={'subtitle1'} className={styles.name}>
|
||||
{feature.name}
|
||||
</Typography>
|
||||
<span>
|
||||
<PlaygroundResultChip enabled={feature.isEnabled} />
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.descriptionRow}>
|
||||
<Typography variant={'body1'}>{description}</Typography>
|
||||
<Typography variant={'body1'} color={color}>
|
||||
{reason}
|
||||
</Typography>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,32 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
header: {
|
||||
display: 'flex',
|
||||
padding: theme.spacing(2, 2),
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
headerName: {
|
||||
padding: theme.spacing(0.5, 2),
|
||||
display: 'flex',
|
||||
gap: theme.spacing(1),
|
||||
alignItems: 'center',
|
||||
borderBottom: `1px solid ${theme.palette.divider}`,
|
||||
fontWeight: theme.typography.fontWeightMedium,
|
||||
},
|
||||
icon: {
|
||||
fill: theme.palette.inactiveIcon,
|
||||
},
|
||||
resultChip: {
|
||||
marginLeft: 'auto',
|
||||
},
|
||||
body: {
|
||||
padding: theme.spacing(2),
|
||||
justifyItems: 'center',
|
||||
},
|
||||
innerContainer: {
|
||||
[theme.breakpoints.down(400)]: {
|
||||
padding: '0.5rem',
|
||||
},
|
||||
},
|
||||
}));
|
@ -1,38 +1,75 @@
|
||||
import { ConditionallyRender } from '../../../../../common/ConditionallyRender/ConditionallyRender';
|
||||
import { StrategySeparator } from '../../../../../common/StrategySeparator/StrategySeparator';
|
||||
import { StrategyItem } from '../../../../../feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyItem';
|
||||
import { styled, useTheme } from '@mui/material';
|
||||
import { useStyles } from './PlaygroundResultFeatureStrategyItem.styles';
|
||||
import {
|
||||
IConstraint,
|
||||
IFeatureStrategy, IPlaygroundFeatureStrategyResult,
|
||||
} from '../../../../../../interfaces/strategy';
|
||||
import { ISegment } from '../../../../../../interfaces/segment';
|
||||
|
||||
formatStrategyName,
|
||||
getFeatureStrategyIcon,
|
||||
} from '../../../../../../utils/strategyNames';
|
||||
import StringTruncator from '../../../../../common/StringTruncator/StringTruncator';
|
||||
import { PlaygroundResultChip } from '../../PlaygroundResultChip/PlaygroundResultChip';
|
||||
import { StrategyExecution } from '../../../../../feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/StrategyExecution';
|
||||
import { PlaygroundFeatureStrategyResult } from 'hooks/api/actions/usePlayground/playground.model';
|
||||
|
||||
interface IPlaygroundResultFeatureStrategyItemProps {
|
||||
strategy: IPlaygroundFeatureStrategyResult;
|
||||
environmentName: string;
|
||||
strategy: PlaygroundFeatureStrategyResult;
|
||||
index: number;
|
||||
}
|
||||
|
||||
const StyledStrategyResultBox = styled('div')(({ theme }) => ({
|
||||
width: '100%',
|
||||
position: 'relative',
|
||||
paddingBottom: '1rem',
|
||||
borderRadius: theme.shape.borderRadiusMedium,
|
||||
'& + &': {
|
||||
marginTop: theme.spacing(2),
|
||||
},
|
||||
background: theme.palette.background.default,
|
||||
}));
|
||||
|
||||
export const PlaygroundResultFeatureStrategyItem = ({
|
||||
strategy,
|
||||
environmentName,
|
||||
index,
|
||||
}: IPlaygroundResultFeatureStrategyItemProps) => {
|
||||
const { result } = strategy;
|
||||
const { classes: styles } = useStyles();
|
||||
const theme = useTheme();
|
||||
const Icon = getFeatureStrategyIcon(strategy.name);
|
||||
const label =
|
||||
result === undefined ? 'Not found' : result ? 'True' : 'False';
|
||||
const border = Boolean(result)
|
||||
? `2px solid ${theme.palette.success.main}`
|
||||
: `1px solid ${theme.palette.divider}`;
|
||||
|
||||
return (
|
||||
<div key={strategy.id} className={``}>
|
||||
<StyledStrategyResultBox key={strategy.id} sx={{ border }}>
|
||||
<ConditionallyRender
|
||||
condition={index > 0}
|
||||
show={<StrategySeparator text="OR" />}
|
||||
/>
|
||||
<StrategyItem
|
||||
strategy={strategy}
|
||||
result={result}
|
||||
environmentId={environmentName}
|
||||
isDraggable={false}
|
||||
<div className={styles.innerContainer}>
|
||||
<div className={styles.header}>
|
||||
<div className={styles.headerName}>
|
||||
<Icon className={styles.icon} />
|
||||
<StringTruncator
|
||||
maxWidth="150"
|
||||
maxLength={15}
|
||||
text={formatStrategyName(strategy.name)}
|
||||
/>
|
||||
</div>
|
||||
<PlaygroundResultChip
|
||||
showIcon={false}
|
||||
enabled={Boolean(result)}
|
||||
label={label}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.body}>
|
||||
<StrategyExecution
|
||||
strategy={strategy}
|
||||
percentageFill={theme.palette.grey[200]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</StyledStrategyResultBox>
|
||||
);
|
||||
};
|
||||
|
@ -4,7 +4,7 @@ import { ReactComponent as FeatureEnabledIcon } from 'assets/icons/isenabled-tru
|
||||
import { ReactComponent as FeatureDisabledIcon } from 'assets/icons/isenabled-false.svg';
|
||||
import { Box, Chip, styled, useTheme } from '@mui/material';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import {ResultChip} from "../ResultChip/ResultChip";
|
||||
import { PlaygroundResultChip } from '../PlaygroundResultChip/PlaygroundResultChip';
|
||||
|
||||
interface IFeatureStatusCellProps {
|
||||
enabled: boolean;
|
||||
@ -21,31 +21,10 @@ const StyledChipWrapper = styled(Box)(() => ({
|
||||
}));
|
||||
|
||||
export const FeatureStatusCell = ({ enabled }: IFeatureStatusCellProps) => {
|
||||
const theme = useTheme();
|
||||
const icon = (
|
||||
<ConditionallyRender
|
||||
condition={enabled}
|
||||
show={
|
||||
<FeatureEnabledIcon
|
||||
color={theme.palette.success.main}
|
||||
strokeWidth="0.25"
|
||||
/>
|
||||
}
|
||||
elseShow={
|
||||
<FeatureDisabledIcon
|
||||
color={theme.palette.error.main}
|
||||
strokeWidth="0.25"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
const label = enabled ? 'True' : 'False';
|
||||
|
||||
return (
|
||||
<StyledCellBox>
|
||||
<StyledChipWrapper data-loading>
|
||||
<ResultChip enabled label={label} icon={icon} />
|
||||
<PlaygroundResultChip enabled />
|
||||
</StyledChipWrapper>
|
||||
</StyledCellBox>
|
||||
);
|
||||
|
@ -0,0 +1,84 @@
|
||||
import { Chip, styled, useTheme } from '@mui/material';
|
||||
import { colors } from '../../../../../themes/colors';
|
||||
import { ConditionallyRender } from '../../../../common/ConditionallyRender/ConditionallyRender';
|
||||
import React from 'react';
|
||||
import { ReactComponent as FeatureEnabledIcon } from '../../../../../assets/icons/isenabled-true.svg';
|
||||
import { ReactComponent as FeatureDisabledIcon } from '../../../../../assets/icons/isenabled-false.svg';
|
||||
|
||||
interface IResultChipProps {
|
||||
enabled: boolean;
|
||||
// Result icon - defaults to true
|
||||
showIcon?: boolean;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export const StyledFalseChip = styled(Chip)(({ theme }) => ({
|
||||
width: 80,
|
||||
borderRadius: '5px',
|
||||
border: `1px solid ${theme.palette.error.main}`,
|
||||
backgroundColor: colors.red['200'],
|
||||
['& .MuiChip-label']: {
|
||||
color: theme.palette.error.main,
|
||||
},
|
||||
['& .MuiChip-icon']: {
|
||||
color: theme.palette.error.main,
|
||||
},
|
||||
}));
|
||||
|
||||
export const StyledTrueChip = styled(Chip)(({ theme }) => ({
|
||||
width: 80,
|
||||
borderRadius: '5px',
|
||||
border: `1px solid ${theme.palette.success.main}`,
|
||||
backgroundColor: colors.green['100'],
|
||||
['& .MuiChip-label']: {
|
||||
color: theme.palette.success.main,
|
||||
},
|
||||
['& .MuiChip-icon']: {
|
||||
color: theme.palette.success.main,
|
||||
},
|
||||
}));
|
||||
|
||||
export const PlaygroundResultChip = ({
|
||||
enabled,
|
||||
showIcon = true,
|
||||
label,
|
||||
}: IResultChipProps) => {
|
||||
const theme = useTheme();
|
||||
const icon = (
|
||||
<ConditionallyRender
|
||||
condition={enabled}
|
||||
show={
|
||||
<FeatureEnabledIcon
|
||||
color={theme.palette.success.main}
|
||||
strokeWidth="0.25"
|
||||
/>
|
||||
}
|
||||
elseShow={
|
||||
<FeatureDisabledIcon
|
||||
color={theme.palette.error.main}
|
||||
strokeWidth="0.25"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
const defaultLabel = enabled ? 'True' : 'False';
|
||||
|
||||
return (
|
||||
<ConditionallyRender
|
||||
condition={enabled}
|
||||
show={
|
||||
<StyledTrueChip
|
||||
icon={showIcon ? icon : undefined}
|
||||
label={label || defaultLabel}
|
||||
/>
|
||||
}
|
||||
elseShow={
|
||||
<StyledFalseChip
|
||||
icon={showIcon ? icon : undefined}
|
||||
label={label || defaultLabel}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
@ -1,46 +0,0 @@
|
||||
import {Box, Chip, styled} from "@mui/material";
|
||||
import {colors} from "../../../../../themes/colors";
|
||||
import {ConditionallyRender} from "../../../../common/ConditionallyRender/ConditionallyRender";
|
||||
import React, {ReactElement} from "react";
|
||||
|
||||
interface IResultChipProps {
|
||||
enabled: boolean;
|
||||
icon?: ReactElement;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export const StyledFalseChip = styled(Chip)(({ theme }) => ({
|
||||
width: 80,
|
||||
borderRadius: '5px',
|
||||
border: `1px solid ${theme.palette.error.main}`,
|
||||
backgroundColor: colors.red['200'],
|
||||
['& .MuiChip-label']: {
|
||||
color: theme.palette.error.main,
|
||||
},
|
||||
['& .MuiChip-icon']: {
|
||||
color: theme.palette.error.main,
|
||||
},
|
||||
}));
|
||||
|
||||
export const StyledTrueChip = styled(Chip)(({ theme }) => ({
|
||||
width: 80,
|
||||
borderRadius: '5px',
|
||||
border: `1px solid ${theme.palette.success.main}`,
|
||||
backgroundColor: colors.green['100'],
|
||||
['& .MuiChip-label']: {
|
||||
color: theme.palette.success.main,
|
||||
},
|
||||
['& .MuiChip-icon']: {
|
||||
color: theme.palette.success.main,
|
||||
},
|
||||
}));
|
||||
|
||||
export const ResultChip = ({ enabled, icon, label}: IResultChipProps) => {
|
||||
return (
|
||||
<ConditionallyRender
|
||||
condition={enabled}
|
||||
show={<StyledTrueChip icon={Boolean(icon) ? icon : undefined} label={label}/>}
|
||||
elseShow={<StyledFalseChip icon={Boolean(icon) ? icon : undefined} label={label}/>}
|
||||
/>
|
||||
);
|
||||
}
|
@ -1,5 +1,10 @@
|
||||
// TODO: replace with auto-generated openapi code
|
||||
|
||||
import {
|
||||
IConstraint,
|
||||
IFeatureStrategyParameters,
|
||||
} from '../../../../interfaces/strategy';
|
||||
|
||||
export enum PlaygroundFeatureSchemaVariantPayloadTypeEnum {
|
||||
Json = 'json',
|
||||
Csv = 'csv',
|
||||
@ -158,7 +163,7 @@ export interface PlaygroundFeatureSchema {
|
||||
* @type {boolean}
|
||||
* @memberof PlaygroundFeatureSchema
|
||||
*/
|
||||
isEnabled: boolean;
|
||||
enabled: boolean | 'unevaluated';
|
||||
/**
|
||||
*
|
||||
* @type {PlaygroundFeatureSchemaVariant}
|
||||
@ -248,3 +253,24 @@ export interface SdkContextSchema {
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Operator } from 'constants/operators';
|
||||
import {ISegment} from "./segment";
|
||||
|
||||
export interface IFeatureStrategy {
|
||||
id: string;
|
||||
@ -57,20 +56,3 @@ export interface IFeatureStrategySortOrder {
|
||||
id: string;
|
||||
sortOrder: number;
|
||||
}
|
||||
|
||||
|
||||
export interface IPlaygroundFeatureStrategyConstraintResult extends IConstraint {
|
||||
result: boolean;
|
||||
}
|
||||
|
||||
export interface IPlaygroundFeatureStrategySegmentResult extends ISegment {
|
||||
result: boolean;
|
||||
}
|
||||
|
||||
export interface IPlaygroundFeatureStrategyResult {
|
||||
type: string;
|
||||
result: boolean;
|
||||
id?: string;
|
||||
constraints?: IPlaygroundFeatureStrategyConstraintResult[];
|
||||
segments?: IPlaygroundFeatureStrategySegmentResult[];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user