mirror of
https://github.com/Unleash/unleash.git
synced 2025-10-13 11:17:26 +02:00
bug fixes, improvements and env handling
This commit is contained in:
parent
9fee273cff
commit
42fbc27148
@ -18,14 +18,14 @@ import {
|
|||||||
import { useStyles } from '../ConstraintAccordion.styles';
|
import { useStyles } from '../ConstraintAccordion.styles';
|
||||||
import {
|
import {
|
||||||
PlaygroundFeatureStrategyConstraintResult,
|
PlaygroundFeatureStrategyConstraintResult,
|
||||||
SdkContextSchema,
|
PlaygroundRequestSchema,
|
||||||
} from '../../../../hooks/api/actions/usePlayground/playground.model';
|
} from '../../../../hooks/api/actions/usePlayground/playground.model';
|
||||||
|
|
||||||
interface IConstraintAccordionViewProps {
|
interface IConstraintAccordionViewProps {
|
||||||
constraint: IConstraint | PlaygroundFeatureStrategyConstraintResult;
|
constraint: IConstraint | PlaygroundFeatureStrategyConstraintResult;
|
||||||
onDelete?: () => void;
|
onDelete?: () => void;
|
||||||
onEdit?: () => void;
|
onEdit?: () => void;
|
||||||
playgroundContext?: SdkContextSchema;
|
playgroundInput?: PlaygroundRequestSchema;
|
||||||
maxLength?: number;
|
maxLength?: number;
|
||||||
sx?: SxProps<Theme>;
|
sx?: SxProps<Theme>;
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ export const ConstraintAccordionView = ({
|
|||||||
onDelete,
|
onDelete,
|
||||||
sx = undefined,
|
sx = undefined,
|
||||||
maxLength,
|
maxLength,
|
||||||
playgroundContext,
|
playgroundInput,
|
||||||
}: IConstraintAccordionViewProps) => {
|
}: IConstraintAccordionViewProps) => {
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
const [expandable, setExpandable] = useState(true);
|
const [expandable, setExpandable] = useState(true);
|
||||||
@ -46,7 +46,6 @@ export const ConstraintAccordionView = ({
|
|||||||
[...semVerOperators, ...numOperators, ...dateOperators],
|
[...semVerOperators, ...numOperators, ...dateOperators],
|
||||||
constraint.operator
|
constraint.operator
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (expandable) {
|
if (expandable) {
|
||||||
setExpanded(!expanded);
|
setExpanded(!expanded);
|
||||||
@ -79,7 +78,7 @@ export const ConstraintAccordionView = ({
|
|||||||
allowExpand={setExpandable}
|
allowExpand={setExpandable}
|
||||||
expanded={expanded}
|
expanded={expanded}
|
||||||
maxLength={maxLength ?? 112}
|
maxLength={maxLength ?? 112}
|
||||||
playgroundContext={playgroundContext}
|
playgroundInput={playgroundInput}
|
||||||
/>
|
/>
|
||||||
</AccordionSummary>
|
</AccordionSummary>
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { ConstraintAccordionHeaderActions } from '../../ConstraintAccordionHeade
|
|||||||
import { useStyles } from 'component/common/ConstraintAccordion/ConstraintAccordion.styles';
|
import { useStyles } from 'component/common/ConstraintAccordion/ConstraintAccordion.styles';
|
||||||
import {
|
import {
|
||||||
PlaygroundFeatureStrategyConstraintResult,
|
PlaygroundFeatureStrategyConstraintResult,
|
||||||
SdkContextSchema,
|
PlaygroundRequestSchema,
|
||||||
} from '../../../../../hooks/api/actions/usePlayground/playground.model';
|
} from '../../../../../hooks/api/actions/usePlayground/playground.model';
|
||||||
|
|
||||||
interface IConstraintAccordionViewHeaderProps {
|
interface IConstraintAccordionViewHeaderProps {
|
||||||
@ -15,7 +15,7 @@ interface IConstraintAccordionViewHeaderProps {
|
|||||||
singleValue: boolean;
|
singleValue: boolean;
|
||||||
expanded: boolean;
|
expanded: boolean;
|
||||||
allowExpand: (shouldExpand: boolean) => void;
|
allowExpand: (shouldExpand: boolean) => void;
|
||||||
playgroundContext?: SdkContextSchema;
|
playgroundInput?: PlaygroundRequestSchema;
|
||||||
maxLength?: number;
|
maxLength?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ export const ConstraintAccordionViewHeader = ({
|
|||||||
allowExpand,
|
allowExpand,
|
||||||
expanded,
|
expanded,
|
||||||
maxLength,
|
maxLength,
|
||||||
playgroundContext,
|
playgroundInput,
|
||||||
}: IConstraintAccordionViewHeaderProps) => {
|
}: IConstraintAccordionViewHeaderProps) => {
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ export const ConstraintAccordionViewHeader = ({
|
|||||||
expanded={expanded}
|
expanded={expanded}
|
||||||
result={'result' in constraint ? constraint.result : undefined}
|
result={'result' in constraint ? constraint.result : undefined}
|
||||||
maxLength={maxLength}
|
maxLength={maxLength}
|
||||||
playgroundContext={playgroundContext}
|
playgroundInput={playgroundInput}
|
||||||
/>
|
/>
|
||||||
<ConstraintAccordionHeaderActions
|
<ConstraintAccordionHeaderActions
|
||||||
onEdit={onEdit}
|
onEdit={onEdit}
|
||||||
|
@ -7,7 +7,7 @@ import React from 'react';
|
|||||||
import { IConstraint } from '../../../../../../interfaces/strategy';
|
import { IConstraint } from '../../../../../../interfaces/strategy';
|
||||||
import { useStyles } from '../../../ConstraintAccordion.styles';
|
import { useStyles } from '../../../ConstraintAccordion.styles';
|
||||||
import { CancelOutlined } from '@mui/icons-material';
|
import { CancelOutlined } from '@mui/icons-material';
|
||||||
import { SdkContextSchema } from '../../../../../../hooks/api/actions/usePlayground/playground.model';
|
import { PlaygroundRequestSchema } from '../../../../../../hooks/api/actions/usePlayground/playground.model';
|
||||||
|
|
||||||
const StyledHeaderText = styled('span')(({ theme }) => ({
|
const StyledHeaderText = styled('span')(({ theme }) => ({
|
||||||
display: '-webkit-box',
|
display: '-webkit-box',
|
||||||
@ -43,7 +43,7 @@ interface ConstraintAccordionViewHeaderMetaInfoProps {
|
|||||||
allowExpand: (shouldExpand: boolean) => void;
|
allowExpand: (shouldExpand: boolean) => void;
|
||||||
result?: boolean;
|
result?: boolean;
|
||||||
maxLength?: number;
|
maxLength?: number;
|
||||||
playgroundContext?: SdkContextSchema;
|
playgroundInput?: PlaygroundRequestSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ConstraintAccordionViewHeaderInfo = ({
|
export const ConstraintAccordionViewHeaderInfo = ({
|
||||||
@ -52,12 +52,17 @@ export const ConstraintAccordionViewHeaderInfo = ({
|
|||||||
allowExpand,
|
allowExpand,
|
||||||
expanded,
|
expanded,
|
||||||
result,
|
result,
|
||||||
|
playgroundInput,
|
||||||
maxLength = 112,
|
maxLength = 112,
|
||||||
playgroundContext,
|
|
||||||
}: ConstraintAccordionViewHeaderMetaInfoProps) => {
|
}: ConstraintAccordionViewHeaderMetaInfoProps) => {
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const isPlayground = Boolean(playgroundInput);
|
||||||
|
const constrainExistsInContext =
|
||||||
|
isPlayground &&
|
||||||
|
Boolean(playgroundInput?.context[constraint.contextName]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledHeaderWrapper>
|
<StyledHeaderWrapper>
|
||||||
<div className={styles.headerMetaInfo}>
|
<div className={styles.headerMetaInfo}>
|
||||||
@ -65,24 +70,17 @@ export const ConstraintAccordionViewHeaderInfo = ({
|
|||||||
<StyledHeaderText>
|
<StyledHeaderText>
|
||||||
{constraint.contextName}
|
{constraint.contextName}
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={
|
condition={isPlayground}
|
||||||
result !== undefined &&
|
|
||||||
Boolean(playgroundContext)
|
|
||||||
}
|
|
||||||
show={
|
show={
|
||||||
<Typography
|
<Typography
|
||||||
variant={'body1'}
|
variant={'body1'}
|
||||||
color={
|
color={
|
||||||
Boolean(
|
constrainExistsInContext
|
||||||
playgroundContext![
|
|
||||||
constraint.contextName
|
|
||||||
]
|
|
||||||
)
|
|
||||||
? theme.palette.neutral.dark
|
? theme.palette.neutral.dark
|
||||||
: theme.palette.error.main
|
: theme.palette.error.main
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{playgroundContext![
|
{playgroundInput?.context[
|
||||||
constraint.contextName
|
constraint.contextName
|
||||||
] || 'no value'}
|
] || 'no value'}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
@ -203,6 +203,7 @@ export const Playground: VFC<{}> = () => {
|
|||||||
<PlaygroundResultsTable
|
<PlaygroundResultsTable
|
||||||
loading={loading}
|
loading={loading}
|
||||||
features={results?.features}
|
features={results?.features}
|
||||||
|
input={results?.input}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
elseShow={<PlaygroundGuidance />}
|
elseShow={<PlaygroundGuidance />}
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
import {
|
import {
|
||||||
PlaygroundFeatureSchema,
|
PlaygroundFeatureSchema,
|
||||||
PlaygroundFeatureStrategyResult,
|
PlaygroundRequestSchema,
|
||||||
} from 'hooks/api/actions/usePlayground/playground.model';
|
} from 'hooks/api/actions/usePlayground/playground.model';
|
||||||
import { IconButton, Popover, styled, Typography } 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 { ConditionallyRender } from '../../../../common/ConditionallyRender/ConditionallyRender';
|
||||||
import { PlaygroundResultFeatureStrategyItem } from './PlaygroundResultFeatureStrategyItem/PlaygroundResultFeatureStrategyItem';
|
|
||||||
import { useStyles } from './FeatureResultInfoPopoverCell.styles';
|
import { useStyles } from './FeatureResultInfoPopoverCell.styles';
|
||||||
import { PlaygroundResultFeatureDetails } from './PlaygroundResultFeatureDetails/PlaygroundResultFeatureDetails';
|
import { PlaygroundResultFeatureDetails } from './PlaygroundResultFeatureDetails/PlaygroundResultFeatureDetails';
|
||||||
|
import {
|
||||||
|
PlaygroundResultStrategyList,
|
||||||
|
WrappedPlaygroundResultStrategyList,
|
||||||
|
} from './PlaygroundResultStrategyList/PlaygroundResultStrategyList';
|
||||||
|
|
||||||
interface FeatureResultInfoPopoverCellProps {
|
interface FeatureResultInfoPopoverCellProps {
|
||||||
feature?: PlaygroundFeatureSchema;
|
feature: PlaygroundFeatureSchema;
|
||||||
|
input?: PlaygroundRequestSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FeatureResultPopoverWrapper = styled('div')(({ theme }) => ({
|
const FeatureResultPopoverWrapper = styled('div')(({ theme }) => ({
|
||||||
@ -21,6 +25,7 @@ const FeatureResultPopoverWrapper = styled('div')(({ theme }) => ({
|
|||||||
|
|
||||||
export const FeatureResultInfoPopoverCell = ({
|
export const FeatureResultInfoPopoverCell = ({
|
||||||
feature,
|
feature,
|
||||||
|
input,
|
||||||
}: FeatureResultInfoPopoverCellProps) => {
|
}: FeatureResultInfoPopoverCellProps) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
@ -30,77 +35,6 @@ export const FeatureResultInfoPopoverCell = ({
|
|||||||
setOpen(!open);
|
setOpen(!open);
|
||||||
};
|
};
|
||||||
|
|
||||||
const dummyPlaygroundFeatureTrue: PlaygroundFeatureSchema = {
|
|
||||||
name: feature?.name as any,
|
|
||||||
projectId: 'default',
|
|
||||||
isEnabled: true,
|
|
||||||
} as any;
|
|
||||||
|
|
||||||
const dummyPlaygroundFeatureFalse: PlaygroundFeatureSchema = {
|
|
||||||
name: feature?.name as any,
|
|
||||||
projectId: 'default',
|
|
||||||
isEnabled: false,
|
|
||||||
} as any;
|
|
||||||
|
|
||||||
const strategies: PlaygroundFeatureStrategyResult[] = [
|
|
||||||
{
|
|
||||||
name: 'default',
|
|
||||||
id: 'strategy-id',
|
|
||||||
parameters: {},
|
|
||||||
result: feature?.isEnabled as any,
|
|
||||||
constraints: [
|
|
||||||
{
|
|
||||||
result: true,
|
|
||||||
contextName: 'appName',
|
|
||||||
operator: 'IN',
|
|
||||||
caseInsensitive: false,
|
|
||||||
inverted: false,
|
|
||||||
values: ['MyApp', 'MyOtherApp', 'Unleash'],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
segments: [
|
|
||||||
{
|
|
||||||
result: feature?.isEnabled as any,
|
|
||||||
id: 5,
|
|
||||||
name: 'my-segment',
|
|
||||||
constraints: [
|
|
||||||
{
|
|
||||||
result: feature?.isEnabled as any,
|
|
||||||
contextName: 'environment',
|
|
||||||
operator: 'IN',
|
|
||||||
caseInsensitive: false,
|
|
||||||
inverted: false,
|
|
||||||
values: ['development'],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'flexibleRollout',
|
|
||||||
id: 'strategy-id',
|
|
||||||
parameters: {},
|
|
||||||
result: false,
|
|
||||||
segments: [
|
|
||||||
{
|
|
||||||
result: false,
|
|
||||||
id: 6,
|
|
||||||
name: 'my-segment',
|
|
||||||
constraints: [
|
|
||||||
{
|
|
||||||
result: false,
|
|
||||||
contextName: 'appName',
|
|
||||||
operator: 'IN',
|
|
||||||
caseInsensitive: false,
|
|
||||||
inverted: false,
|
|
||||||
values: ['MyApp2'],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!feature) {
|
if (!feature) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -125,29 +59,24 @@ export const FeatureResultInfoPopoverCell = ({
|
|||||||
classes={{ paper: styles.popoverPaper }}
|
classes={{ paper: styles.popoverPaper }}
|
||||||
>
|
>
|
||||||
<PlaygroundResultFeatureDetails
|
<PlaygroundResultFeatureDetails
|
||||||
feature={
|
feature={feature}
|
||||||
feature.isEnabled
|
input={input}
|
||||||
? dummyPlaygroundFeatureTrue
|
|
||||||
: dummyPlaygroundFeatureFalse
|
|
||||||
}
|
|
||||||
onClose={() => setOpen(false)}
|
onClose={() => setOpen(false)}
|
||||||
/>
|
/>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={strategies.length > 0}
|
condition={!feature.isEnabledInCurrentEnvironment}
|
||||||
show={
|
show={
|
||||||
<>
|
<PlaygroundResultStrategyList
|
||||||
<Typography
|
strategies={feature?.strategies}
|
||||||
variant={'subtitle1'}
|
input={input}
|
||||||
sx={{ mb: 2, color: 'text.secondary' }}
|
/>
|
||||||
>{`Strategies (${strategies.length})`}</Typography>
|
}
|
||||||
{strategies.map((strategy, index) => (
|
elseShow={
|
||||||
<PlaygroundResultFeatureStrategyItem
|
<WrappedPlaygroundResultStrategyList
|
||||||
key={strategy.id}
|
strategies={feature?.strategies}
|
||||||
strategy={strategy}
|
feature={feature}
|
||||||
index={index}
|
input={input}
|
||||||
/>
|
/>
|
||||||
))}
|
|
||||||
</>
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
@ -9,9 +9,11 @@ export const useStyles = makeStyles()(theme => ({
|
|||||||
titleRow: {
|
titleRow: {
|
||||||
display: 'inline-flex',
|
display: 'inline-flex',
|
||||||
alignItems: 'flex-start',
|
alignItems: 'flex-start',
|
||||||
justifyItems: 'center',
|
justifyContent: 'center',
|
||||||
gap: '12px',
|
gap: '12px',
|
||||||
|
marginTop: '12px',
|
||||||
},
|
},
|
||||||
|
alertRow: {},
|
||||||
descriptionRow: {
|
descriptionRow: {
|
||||||
marginBottom: theme.spacing(2),
|
marginBottom: theme.spacing(2),
|
||||||
},
|
},
|
||||||
|
@ -1,30 +1,45 @@
|
|||||||
import { PlaygroundFeatureSchema } from '../../../../../../hooks/api/actions/usePlayground/playground.model';
|
import {
|
||||||
import { IconButton, Typography, useTheme } from '@mui/material';
|
PlaygroundFeatureSchema,
|
||||||
|
PlaygroundRequestSchema,
|
||||||
|
} from '../../../../../../hooks/api/actions/usePlayground/playground.model';
|
||||||
|
import { Alert, IconButton, Typography, useTheme } from '@mui/material';
|
||||||
import { PlaygroundResultChip } from '../../PlaygroundResultChip/PlaygroundResultChip';
|
import { PlaygroundResultChip } from '../../PlaygroundResultChip/PlaygroundResultChip';
|
||||||
import { useStyles } from './PlaygroundResultFeatureDetails.styles';
|
import { useStyles } from './PlaygroundResultFeatureDetails.styles';
|
||||||
import { CloseOutlined } from '@mui/icons-material';
|
import { CloseOutlined } from '@mui/icons-material';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { ConditionallyRender } from '../../../../../common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { checkForEmptyValues } from './helpers';
|
||||||
interface PlaygroundFeatureResultDetailsProps {
|
interface PlaygroundFeatureResultDetailsProps {
|
||||||
feature: PlaygroundFeatureSchema;
|
feature: PlaygroundFeatureSchema;
|
||||||
|
input?: PlaygroundRequestSchema;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
export const PlaygroundResultFeatureDetails = ({
|
export const PlaygroundResultFeatureDetails = ({
|
||||||
feature,
|
feature,
|
||||||
|
input,
|
||||||
onClose,
|
onClose,
|
||||||
}: PlaygroundFeatureResultDetailsProps) => {
|
}: PlaygroundFeatureResultDetailsProps) => {
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const description = feature.isEnabled
|
const description = Boolean(feature.isEnabled)
|
||||||
? 'This feature toggle is True in production because '
|
? `This feature toggle is True in ${input?.environment} because `
|
||||||
: 'This feature toggle is False in production because ';
|
: `This feature toggle is False in ${input?.environment} because `;
|
||||||
const reason = feature.isEnabled
|
|
||||||
|
const reason = Boolean(feature.isEnabled)
|
||||||
? 'at least one strategy is True'
|
? 'at least one strategy is True'
|
||||||
|
: feature?.isEnabledInCurrentEnvironment
|
||||||
|
? 'the environment is disabled'
|
||||||
: 'all strategies are False';
|
: 'all strategies are False';
|
||||||
const color = feature.isEnabled
|
|
||||||
|
const color = Boolean(feature.isEnabled)
|
||||||
? theme.palette.success.main
|
? theme.palette.success.main
|
||||||
: theme.palette.error.main;
|
: theme.palette.error.main;
|
||||||
|
|
||||||
|
const noValueTxt = checkForEmptyValues(input?.context)
|
||||||
|
? 'You did not provide a value for your context filed in step 2 of the configuration'
|
||||||
|
: undefined;
|
||||||
|
|
||||||
const onCloseClick =
|
const onCloseClick =
|
||||||
onClose &&
|
onClose &&
|
||||||
((event: React.SyntheticEvent) => {
|
((event: React.SyntheticEvent) => {
|
||||||
@ -55,6 +70,14 @@ export const PlaygroundResultFeatureDetails = ({
|
|||||||
{reason}
|
{reason}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={Boolean(noValueTxt)}
|
||||||
|
show={
|
||||||
|
<div className={styles.alertRow}>
|
||||||
|
<Alert color={'info'}>{noValueTxt}</Alert>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
export function checkForEmptyValues(object?: Object): boolean {
|
||||||
|
if (object === undefined) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return Object.values(object).every(v =>
|
||||||
|
v && typeof v === 'object' ? checkForEmptyValues(v) : v === null
|
||||||
|
);
|
||||||
|
}
|
@ -1,16 +1,18 @@
|
|||||||
import {
|
import {
|
||||||
PlaygroundFeatureStrategyConstraintResult,
|
PlaygroundFeatureStrategyConstraintResult,
|
||||||
SdkContextSchema,
|
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';
|
||||||
import { objectId } from '../../../../../../utils/objectId';
|
import { objectId } from '../../../../../../../utils/objectId';
|
||||||
import { ConditionallyRender } from '../../../../../common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from '../../../../../../common/ConditionallyRender/ConditionallyRender';
|
||||||
import { StrategySeparator } from '../../../../../common/StrategySeparator/StrategySeparator';
|
import { StrategySeparator } from '../../../../../../common/StrategySeparator/StrategySeparator';
|
||||||
import { ConstraintAccordionView } from '../../../../../common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView';
|
import { ConstraintAccordionView } from '../../../../../../common/ConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView';
|
||||||
import { styled } from '@mui/material';
|
import { styled } from '@mui/material';
|
||||||
|
|
||||||
interface PlaygroundResultConstraintExecutionProps {
|
interface PlaygroundResultConstraintExecutionProps {
|
||||||
constraints?: PlaygroundFeatureStrategyConstraintResult[];
|
constraints?: PlaygroundFeatureStrategyConstraintResult[];
|
||||||
|
compact: boolean;
|
||||||
|
input?: PlaygroundRequestSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PlaygroundResultConstraintExecutionWrapper = styled('div')(
|
export const PlaygroundResultConstraintExecutionWrapper = styled('div')(
|
||||||
@ -23,18 +25,9 @@ export const PlaygroundResultConstraintExecutionWrapper = styled('div')(
|
|||||||
|
|
||||||
export const PlaygroundResultConstraintExecution = ({
|
export const PlaygroundResultConstraintExecution = ({
|
||||||
constraints,
|
constraints,
|
||||||
|
compact,
|
||||||
|
input,
|
||||||
}: PlaygroundResultConstraintExecutionProps) => {
|
}: PlaygroundResultConstraintExecutionProps) => {
|
||||||
// const context = usePlaygroundContext();
|
|
||||||
const contextFalse: SdkContextSchema = {
|
|
||||||
appName: 'MyApp',
|
|
||||||
environment: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
const contextTrue: SdkContextSchema = {
|
|
||||||
appName: 'MyApp',
|
|
||||||
environment: 'development',
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!constraints) return null;
|
if (!constraints) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -47,12 +40,8 @@ export const PlaygroundResultConstraintExecution = ({
|
|||||||
/>
|
/>
|
||||||
<ConstraintAccordionView
|
<ConstraintAccordionView
|
||||||
constraint={constraint}
|
constraint={constraint}
|
||||||
playgroundContext={
|
playgroundInput={input}
|
||||||
Boolean(constraint.result)
|
maxLength={compact ? 25 : 50}
|
||||||
? contextTrue
|
|
||||||
: contextFalse
|
|
||||||
}
|
|
||||||
maxLength={80}
|
|
||||||
sx={{
|
sx={{
|
||||||
backgroundColor: 'transparent!important',
|
backgroundColor: 'transparent!important',
|
||||||
}}
|
}}
|
@ -28,6 +28,7 @@ export const useStyles = makeStyles()(theme => ({
|
|||||||
[theme.breakpoints.down(400)]: {
|
[theme.breakpoints.down(400)]: {
|
||||||
padding: '0.5rem',
|
padding: '0.5rem',
|
||||||
},
|
},
|
||||||
|
width: '100%',
|
||||||
paddingBottom: '1rem',
|
paddingBottom: '1rem',
|
||||||
borderRadius: theme.shape.borderRadiusMedium,
|
borderRadius: theme.shape.borderRadiusMedium,
|
||||||
background: theme.palette.background.default,
|
background: theme.palette.background.default,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Box, useTheme } from '@mui/material';
|
import { Box, styled, Typography, useTheme } from '@mui/material';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
|
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
|
||||||
import {
|
import {
|
||||||
@ -7,18 +7,33 @@ import {
|
|||||||
} from 'utils/strategyNames';
|
} from 'utils/strategyNames';
|
||||||
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 { PlaygroundFeatureStrategyResult } from 'hooks/api/actions/usePlayground/playground.model';
|
import {
|
||||||
import { PlaygroundResultStrategyExecution } from '../PlaygroundResultStrategyExecution/PlaygroundResultStrategyExecution';
|
PlaygroundFeatureStrategyResult,
|
||||||
|
PlaygroundRequestSchema,
|
||||||
|
} from 'hooks/api/actions/usePlayground/playground.model';
|
||||||
|
import { PlaygroundResultStrategyExecution } from './PlaygroundResultStrategyExecution/PlaygroundResultStrategyExecution';
|
||||||
import { useStyles } from './PlaygroundResultFeatureStrategyItem.styles';
|
import { useStyles } from './PlaygroundResultFeatureStrategyItem.styles';
|
||||||
|
|
||||||
interface IPlaygroundResultFeatureStrategyItemProps {
|
interface IPlaygroundResultFeatureStrategyItemProps {
|
||||||
strategy: PlaygroundFeatureStrategyResult;
|
strategy: PlaygroundFeatureStrategyResult;
|
||||||
index: number;
|
index: number;
|
||||||
|
input?: PlaygroundRequestSchema;
|
||||||
|
compact: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StyledItemWrapper = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginTop: '4px',
|
||||||
|
gap: '4px',
|
||||||
|
}));
|
||||||
|
|
||||||
export const PlaygroundResultFeatureStrategyItem = ({
|
export const PlaygroundResultFeatureStrategyItem = ({
|
||||||
strategy,
|
strategy,
|
||||||
|
input,
|
||||||
index,
|
index,
|
||||||
|
compact,
|
||||||
}: IPlaygroundResultFeatureStrategyItemProps) => {
|
}: IPlaygroundResultFeatureStrategyItemProps) => {
|
||||||
const { result, name } = strategy;
|
const { result, name } = strategy;
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
@ -31,34 +46,44 @@ export const PlaygroundResultFeatureStrategyItem = ({
|
|||||||
: `1px solid ${theme.palette.divider}`;
|
: `1px solid ${theme.palette.divider}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box key={strategy.id} sx={{ width: '100%', position: 'relative' }}>
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: '100%',
|
||||||
|
position: 'relative',
|
||||||
|
paddingRight: compact ? '12px' : 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={index > 0}
|
condition={index > 0}
|
||||||
show={<StrategySeparator text="OR" />}
|
show={<StrategySeparator text="OR" />}
|
||||||
/>
|
/>
|
||||||
<Box className={styles.innerContainer} sx={{ border }}>
|
<StyledItemWrapper>
|
||||||
<div className={styles.header}>
|
<Typography variant={'subtitle1'}>{index + 1}</Typography>
|
||||||
<div className={styles.headerName}>
|
<Box className={styles.innerContainer} sx={{ border }}>
|
||||||
<Icon className={styles.icon} />
|
<div className={styles.header}>
|
||||||
<StringTruncator
|
<div className={styles.headerName}>
|
||||||
maxWidth="150"
|
<Icon className={styles.icon} />
|
||||||
maxLength={15}
|
<StringTruncator
|
||||||
text={formatStrategyName(name)}
|
maxWidth="150"
|
||||||
|
maxLength={15}
|
||||||
|
text={formatStrategyName(name)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<PlaygroundResultChip
|
||||||
|
showIcon={false}
|
||||||
|
enabled={Boolean(result)}
|
||||||
|
label={label}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<PlaygroundResultChip
|
<div className={styles.body}>
|
||||||
showIcon={false}
|
<PlaygroundResultStrategyExecution
|
||||||
enabled={Boolean(result)}
|
strategyResult={strategy}
|
||||||
label={label}
|
input={input}
|
||||||
/>
|
percentageFill={theme.palette.tertiary.light}
|
||||||
</div>
|
/>
|
||||||
<div className={styles.body}>
|
</div>
|
||||||
<PlaygroundResultStrategyExecution
|
</Box>
|
||||||
strategyResult={strategy}
|
</StyledItemWrapper>
|
||||||
percentageFill={theme.palette.tertiary.light}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
import { PlaygroundFeatureStrategySegmentResult } from '../../../../../../hooks/api/actions/usePlayground/playground.model';
|
import {
|
||||||
|
PlaygroundFeatureStrategySegmentResult,
|
||||||
|
PlaygroundRequestSchema,
|
||||||
|
} from '../../../../../../../hooks/api/actions/usePlayground/playground.model';
|
||||||
import { PlaygroundResultConstraintExecution } from '../PlaygroundResultConstraintExecution/PlaygroundResultConstraintExecution';
|
import { PlaygroundResultConstraintExecution } from '../PlaygroundResultConstraintExecution/PlaygroundResultConstraintExecution';
|
||||||
import { CancelOutlined, DonutLarge } from '@mui/icons-material';
|
import { CancelOutlined, DonutLarge } from '@mui/icons-material';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { StrategySeparator } from '../../../../../common/StrategySeparator/StrategySeparator';
|
import { StrategySeparator } from '../../../../../../common/StrategySeparator/StrategySeparator';
|
||||||
import { useStyles } from './PlaygroundResultSegmentExecution.styles';
|
import { useStyles } from './PlaygroundResultSegmentExecution.styles';
|
||||||
import { styled, Typography } from '@mui/material';
|
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?: PlaygroundFeatureStrategySegmentResult[];
|
||||||
|
input?: PlaygroundRequestSchema;
|
||||||
|
hasConstraints: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SegmentExecutionLinkWrapper = styled('div')(({ theme }) => ({
|
const SegmentExecutionLinkWrapper = styled('div')(({ theme }) => ({
|
||||||
@ -55,8 +60,11 @@ const SegmentResultTextWrapper = styled('div')(({ theme }) => ({
|
|||||||
|
|
||||||
export const PlaygroundResultSegmentExecution = ({
|
export const PlaygroundResultSegmentExecution = ({
|
||||||
segments,
|
segments,
|
||||||
|
input,
|
||||||
|
hasConstraints,
|
||||||
}: PlaygroundResultSegmentExecutionProps) => {
|
}: PlaygroundResultSegmentExecutionProps) => {
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
|
|
||||||
if (!segments) return null;
|
if (!segments) return null;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -93,10 +101,14 @@ export const PlaygroundResultSegmentExecution = ({
|
|||||||
<SegmentExecutionConstraintWrapper>
|
<SegmentExecutionConstraintWrapper>
|
||||||
<PlaygroundResultConstraintExecution
|
<PlaygroundResultConstraintExecution
|
||||||
constraints={segment.constraints}
|
constraints={segment.constraints}
|
||||||
|
compact={true}
|
||||||
|
input={input}
|
||||||
/>
|
/>
|
||||||
</SegmentExecutionConstraintWrapper>
|
</SegmentExecutionConstraintWrapper>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={index < segments?.length - 1}
|
condition={
|
||||||
|
index === segments?.length - 1 && hasConstraints
|
||||||
|
}
|
||||||
show={<StrategySeparator text="AND" sx={{ pt: 1 }} />}
|
show={<StrategySeparator text="AND" sx={{ pt: 1 }} />}
|
||||||
/>
|
/>
|
||||||
</SegmentExecutionWrapper>
|
</SegmentExecutionWrapper>
|
@ -10,7 +10,7 @@ export const useStyles = makeStyles()(theme => ({
|
|||||||
color: theme.palette.grey[700],
|
color: theme.palette.grey[700],
|
||||||
},
|
},
|
||||||
summary: {
|
summary: {
|
||||||
width: '100%',
|
width: '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}`,
|
@ -1,9 +1,12 @@
|
|||||||
import { ConditionallyRender } from '../../../../../common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from '../../../../../../common/ConditionallyRender/ConditionallyRender';
|
||||||
import { StrategySeparator } from '../../../../../common/StrategySeparator/StrategySeparator';
|
import { StrategySeparator } from '../../../../../../common/StrategySeparator/StrategySeparator';
|
||||||
import { Box, Chip } from '@mui/material';
|
import { Box, Chip, styled } from '@mui/material';
|
||||||
import { useStyles } from './PlaygroundResultStrategyExecution.styles';
|
import { useStyles } from './PlaygroundResultStrategyExecution.styles';
|
||||||
import { PlaygroundFeatureStrategyResult } from '../../../../../../hooks/api/actions/usePlayground/playground.model';
|
import {
|
||||||
import useUiConfig from '../../../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
PlaygroundFeatureStrategyResult,
|
||||||
|
PlaygroundRequestSchema,
|
||||||
|
} from '../../../../../../../hooks/api/actions/usePlayground/playground.model';
|
||||||
|
import useUiConfig from '../../../../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { PlaygroundResultConstraintExecution } from '../PlaygroundResultConstraintExecution/PlaygroundResultConstraintExecution';
|
import { PlaygroundResultConstraintExecution } from '../PlaygroundResultConstraintExecution/PlaygroundResultConstraintExecution';
|
||||||
import { PlaygroundResultSegmentExecution } from '../PlaygroundResultSegmentExecution/PlaygroundResultSegmentExecution';
|
import { PlaygroundResultSegmentExecution } from '../PlaygroundResultSegmentExecution/PlaygroundResultSegmentExecution';
|
||||||
@ -11,24 +14,38 @@ import { PlaygroundResultSegmentExecution } from '../PlaygroundResultSegmentExec
|
|||||||
interface PlaygroundResultStrategyExecutionProps {
|
interface PlaygroundResultStrategyExecutionProps {
|
||||||
strategyResult: PlaygroundFeatureStrategyResult;
|
strategyResult: PlaygroundFeatureStrategyResult;
|
||||||
percentageFill?: string;
|
percentageFill?: string;
|
||||||
|
input?: PlaygroundRequestSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StyledStrategyExecutionWrapper = styled('div')(({ theme }) => ({
|
||||||
|
padding: theme.spacing(1),
|
||||||
|
}));
|
||||||
|
|
||||||
export const PlaygroundResultStrategyExecution = ({
|
export const PlaygroundResultStrategyExecution = ({
|
||||||
strategyResult,
|
strategyResult,
|
||||||
|
input,
|
||||||
}: PlaygroundResultStrategyExecutionProps) => {
|
}: PlaygroundResultStrategyExecutionProps) => {
|
||||||
const { name, constraints, segments } = strategyResult;
|
const { name, constraints, segments } = strategyResult;
|
||||||
|
|
||||||
const { uiConfig } = useUiConfig();
|
const { uiConfig } = useUiConfig();
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
|
|
||||||
|
const hasConstraints = Boolean(constraints && constraints.length > 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<StyledStrategyExecutionWrapper>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={
|
condition={
|
||||||
Boolean(uiConfig.flags.SE) &&
|
Boolean(uiConfig.flags.SE) &&
|
||||||
Boolean(segments && segments.length > 0)
|
Boolean(segments && segments.length > 0)
|
||||||
}
|
}
|
||||||
show={<PlaygroundResultSegmentExecution segments={segments} />}
|
show={
|
||||||
|
<PlaygroundResultSegmentExecution
|
||||||
|
segments={segments}
|
||||||
|
hasConstraints={hasConstraints}
|
||||||
|
input={input}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(constraints && constraints.length > 0)}
|
condition={Boolean(constraints && constraints.length > 0)}
|
||||||
@ -36,6 +53,8 @@ export const PlaygroundResultStrategyExecution = ({
|
|||||||
<>
|
<>
|
||||||
<PlaygroundResultConstraintExecution
|
<PlaygroundResultConstraintExecution
|
||||||
constraints={constraints}
|
constraints={constraints}
|
||||||
|
compact={true}
|
||||||
|
input={input}
|
||||||
/>
|
/>
|
||||||
<StrategySeparator text="AND" />
|
<StrategySeparator text="AND" />
|
||||||
</>
|
</>
|
||||||
@ -56,6 +75,6 @@ export const PlaygroundResultStrategyExecution = ({
|
|||||||
</Box>
|
</Box>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
</StyledStrategyExecutionWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
@ -0,0 +1,88 @@
|
|||||||
|
import {
|
||||||
|
PlaygroundFeatureSchema,
|
||||||
|
PlaygroundFeatureStrategyResult,
|
||||||
|
PlaygroundRequestSchema,
|
||||||
|
} from '../../../../../../hooks/api/actions/usePlayground/playground.model';
|
||||||
|
import { ConditionallyRender } from '../../../../../common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { Alert, styled, Typography } from '@mui/material';
|
||||||
|
import { PlaygroundResultFeatureStrategyItem } from '../PlaygroundResultFeatureStrategyItem/PlaygroundResultFeatureStrategyItem';
|
||||||
|
|
||||||
|
interface PlaygroundResultStrategyListProps {
|
||||||
|
strategies: PlaygroundFeatureStrategyResult[];
|
||||||
|
input?: PlaygroundRequestSchema;
|
||||||
|
compact?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PlaygroundResultStrategyList = ({
|
||||||
|
strategies,
|
||||||
|
input,
|
||||||
|
compact = false,
|
||||||
|
}: PlaygroundResultStrategyListProps) => {
|
||||||
|
return (
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={strategies.length > 0}
|
||||||
|
show={
|
||||||
|
<>
|
||||||
|
<Typography
|
||||||
|
variant={'subtitle1'}
|
||||||
|
sx={{ mt: 2, ml: 1, mb: 2, color: 'text.secondary' }}
|
||||||
|
>{`Strategies (${strategies.length})`}</Typography>
|
||||||
|
{strategies.map((strategy, index) => (
|
||||||
|
<PlaygroundResultFeatureStrategyItem
|
||||||
|
key={strategy.id}
|
||||||
|
strategy={strategy}
|
||||||
|
index={index}
|
||||||
|
compact={compact}
|
||||||
|
input={input}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyledAlertWrapper = styled('div')(({ theme }) => ({
|
||||||
|
width: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
borderRadius: theme.shape.borderRadiusMedium,
|
||||||
|
border: `1px solid ${theme.palette.info.main}`,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledListWrapper = styled('div')(({ theme }) => ({
|
||||||
|
padding: theme.spacing(1, 0.5),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledAlert = styled(Alert)(({ theme }) => ({
|
||||||
|
borderBottomLeftRadius: 0,
|
||||||
|
borderBottomRightRadius: 0,
|
||||||
|
}));
|
||||||
|
|
||||||
|
interface WrappedPlaygroundResultStrategyListProps
|
||||||
|
extends PlaygroundResultStrategyListProps {
|
||||||
|
feature: PlaygroundFeatureSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const WrappedPlaygroundResultStrategyList = ({
|
||||||
|
strategies,
|
||||||
|
feature,
|
||||||
|
input,
|
||||||
|
}: WrappedPlaygroundResultStrategyListProps) => {
|
||||||
|
return (
|
||||||
|
<StyledAlertWrapper>
|
||||||
|
<StyledAlert severity={'info'} color={'info'}>
|
||||||
|
If environment would be enabled then this feature would be{' '}
|
||||||
|
{feature.isEnabled ? 'TRUE' : 'FALSE'} and the strategies would
|
||||||
|
evaluate like this:{' '}
|
||||||
|
</StyledAlert>
|
||||||
|
<StyledListWrapper>
|
||||||
|
<PlaygroundResultStrategyList
|
||||||
|
strategies={strategies}
|
||||||
|
input={input}
|
||||||
|
compact
|
||||||
|
/>
|
||||||
|
</StyledListWrapper>
|
||||||
|
</StyledAlertWrapper>
|
||||||
|
);
|
||||||
|
};
|
@ -6,7 +6,7 @@ import { ReactComponent as FeatureEnabledIcon } from '../../../../../assets/icon
|
|||||||
import { ReactComponent as FeatureDisabledIcon } from '../../../../../assets/icons/isenabled-false.svg';
|
import { ReactComponent as FeatureDisabledIcon } from '../../../../../assets/icons/isenabled-false.svg';
|
||||||
|
|
||||||
interface IResultChipProps {
|
interface IResultChipProps {
|
||||||
enabled: boolean;
|
enabled: boolean | 'unevaluated';
|
||||||
// Result icon - defaults to true
|
// Result icon - defaults to true
|
||||||
showIcon?: boolean;
|
showIcon?: boolean;
|
||||||
label?: string;
|
label?: string;
|
||||||
@ -53,7 +53,7 @@ export const PlaygroundResultChip = ({
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const icon = (
|
const icon = (
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={enabled}
|
condition={Boolean(enabled)}
|
||||||
show={
|
show={
|
||||||
<FeatureEnabledIcon
|
<FeatureEnabledIcon
|
||||||
color={theme.palette.success.main}
|
color={theme.palette.success.main}
|
||||||
@ -73,7 +73,7 @@ export const PlaygroundResultChip = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={enabled}
|
condition={Boolean(enabled)}
|
||||||
show={
|
show={
|
||||||
<StyledTrueChip
|
<StyledTrueChip
|
||||||
icon={showIcon ? icon : undefined}
|
icon={showIcon ? icon : undefined}
|
||||||
|
@ -19,7 +19,10 @@ import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell';
|
|||||||
import { useSearch } from 'hooks/useSearch';
|
import { useSearch } from 'hooks/useSearch';
|
||||||
import { createLocalStorage } from 'utils/createLocalStorage';
|
import { createLocalStorage } from 'utils/createLocalStorage';
|
||||||
import { FeatureStatusCell } from './FeatureStatusCell/FeatureStatusCell';
|
import { FeatureStatusCell } from './FeatureStatusCell/FeatureStatusCell';
|
||||||
import { PlaygroundFeatureSchema } from 'hooks/api/actions/usePlayground/playground.model';
|
import {
|
||||||
|
PlaygroundFeatureSchema,
|
||||||
|
PlaygroundRequestSchema,
|
||||||
|
} from 'hooks/api/actions/usePlayground/playground.model';
|
||||||
import { Box, Typography, useMediaQuery, useTheme } from '@mui/material';
|
import { Box, Typography, useMediaQuery, useTheme } from '@mui/material';
|
||||||
import useLoading from 'hooks/useLoading';
|
import useLoading from 'hooks/useLoading';
|
||||||
import { VariantCell } from './VariantCell/VariantCell';
|
import { VariantCell } from './VariantCell/VariantCell';
|
||||||
@ -33,11 +36,13 @@ const { value, setValue } = createLocalStorage(
|
|||||||
|
|
||||||
interface IPlaygroundResultsTableProps {
|
interface IPlaygroundResultsTableProps {
|
||||||
features?: PlaygroundFeatureSchema[];
|
features?: PlaygroundFeatureSchema[];
|
||||||
|
input?: PlaygroundRequestSchema;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PlaygroundResultsTable = ({
|
export const PlaygroundResultsTable = ({
|
||||||
features,
|
features,
|
||||||
|
input,
|
||||||
loading,
|
loading,
|
||||||
}: IPlaygroundResultsTableProps) => {
|
}: IPlaygroundResultsTableProps) => {
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
@ -49,6 +54,75 @@ export const PlaygroundResultsTable = ({
|
|||||||
const isExtraSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
const isExtraSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
||||||
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
|
|
||||||
|
const COLUMNS = useMemo(() => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
Header: 'Name',
|
||||||
|
accessor: 'name',
|
||||||
|
searchable: true,
|
||||||
|
minWidth: 160,
|
||||||
|
Cell: ({ value, row: { original } }: any) => (
|
||||||
|
<LinkCell
|
||||||
|
title={value}
|
||||||
|
to={`/projects/${original?.projectId}/features/${value}`}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: 'Project ID',
|
||||||
|
accessor: 'projectId',
|
||||||
|
sortType: 'alphanumeric',
|
||||||
|
filterName: 'projectId',
|
||||||
|
searchable: true,
|
||||||
|
maxWidth: 170,
|
||||||
|
Cell: ({ value }: any) => (
|
||||||
|
<LinkCell title={value} to={`/projects/${value}`} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: 'Variant',
|
||||||
|
id: 'variant',
|
||||||
|
accessor: 'variant.name',
|
||||||
|
sortType: 'alphanumeric',
|
||||||
|
filterName: 'variant',
|
||||||
|
searchable: true,
|
||||||
|
width: 200,
|
||||||
|
Cell: ({
|
||||||
|
value,
|
||||||
|
row: {
|
||||||
|
original: { variant, feature, variants, isEnabled },
|
||||||
|
},
|
||||||
|
}: any) => (
|
||||||
|
<VariantCell
|
||||||
|
variant={variant?.enabled ? value : ''}
|
||||||
|
variants={variants}
|
||||||
|
feature={feature}
|
||||||
|
isEnabled={isEnabled}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: 'isEnabled',
|
||||||
|
accessor: 'isEnabled',
|
||||||
|
filterName: 'isEnabled',
|
||||||
|
filterParsing: (value: boolean) => (value ? 'true' : 'false'),
|
||||||
|
Cell: ({ value }: any) => <FeatureStatusCell enabled={value} />,
|
||||||
|
sortType: 'boolean',
|
||||||
|
sortInverted: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: '',
|
||||||
|
id: 'info',
|
||||||
|
Cell: ({ row }: any) => (
|
||||||
|
<FeatureResultInfoPopoverCell
|
||||||
|
feature={row.original}
|
||||||
|
input={input}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}, [input]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: searchedData,
|
data: searchedData,
|
||||||
getSearchText,
|
getSearchText,
|
||||||
@ -236,67 +310,3 @@ export const PlaygroundResultsTable = ({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const COLUMNS = [
|
|
||||||
{
|
|
||||||
Header: 'Name',
|
|
||||||
accessor: 'name',
|
|
||||||
searchable: true,
|
|
||||||
minWidth: 160,
|
|
||||||
Cell: ({ value, row: { original } }: any) => (
|
|
||||||
<LinkCell
|
|
||||||
title={value}
|
|
||||||
to={`/projects/${original?.projectId}/features/${value}`}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Header: 'Project ID',
|
|
||||||
accessor: 'projectId',
|
|
||||||
sortType: 'alphanumeric',
|
|
||||||
filterName: 'projectId',
|
|
||||||
searchable: true,
|
|
||||||
maxWidth: 170,
|
|
||||||
Cell: ({ value }: any) => (
|
|
||||||
<LinkCell title={value} to={`/projects/${value}`} />
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Header: 'Variant',
|
|
||||||
id: 'variant',
|
|
||||||
accessor: 'variant.name',
|
|
||||||
sortType: 'alphanumeric',
|
|
||||||
filterName: 'variant',
|
|
||||||
searchable: true,
|
|
||||||
width: 200,
|
|
||||||
Cell: ({
|
|
||||||
value,
|
|
||||||
row: {
|
|
||||||
original: { variant, feature, variants, isEnabled },
|
|
||||||
},
|
|
||||||
}: any) => (
|
|
||||||
<VariantCell
|
|
||||||
variant={variant?.enabled ? value : ''}
|
|
||||||
variants={variants}
|
|
||||||
feature={feature}
|
|
||||||
isEnabled={isEnabled}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Header: 'isEnabled',
|
|
||||||
accessor: 'isEnabled',
|
|
||||||
filterName: 'isEnabled',
|
|
||||||
filterParsing: (value: boolean) => (value ? 'true' : 'false'),
|
|
||||||
Cell: ({ value }: any) => <FeatureStatusCell enabled={value} />,
|
|
||||||
sortType: 'boolean',
|
|
||||||
sortInverted: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Header: '',
|
|
||||||
id: 'info',
|
|
||||||
Cell: ({ row }: any) => (
|
|
||||||
<FeatureResultInfoPopoverCell feature={row.original} />
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
@ -65,13 +65,17 @@ export interface PlaygroundFeatureSchema {
|
|||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
* @memberof PlaygroundFeatureSchema
|
* @memberof PlaygroundFeatureSchema
|
||||||
*/
|
*/
|
||||||
isEnabled: boolean;
|
isEnabled: boolean | 'unevaluated';
|
||||||
|
|
||||||
|
isEnabledInCurrentEnvironment: boolean;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @type {PlaygroundFeatureSchemaVariant}
|
* @type {PlaygroundFeatureSchemaVariant}
|
||||||
* @memberof PlaygroundFeatureSchema
|
* @memberof PlaygroundFeatureSchema
|
||||||
*/
|
*/
|
||||||
variant: PlaygroundFeatureSchemaVariant | null;
|
variant: PlaygroundFeatureSchemaVariant | null;
|
||||||
|
|
||||||
|
strategies: PlaygroundFeatureStrategyResult[];
|
||||||
}
|
}
|
||||||
export interface PlaygroundResponseSchema {
|
export interface PlaygroundResponseSchema {
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user