mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	Feat: update variants placement (#9832)
This commit is contained in:
		
							parent
							
								
									81c1fb9143
								
							
						
					
					
						commit
						0e2f7374e5
					
				@ -5,6 +5,7 @@ import { disabledStrategyClassName } from 'component/common/StrategyItemContaine
 | 
			
		||||
export type StrategyEvaluationItemProps = {
 | 
			
		||||
    type?: ReactNode;
 | 
			
		||||
    children?: ReactNode;
 | 
			
		||||
    alignType?: 'center' | 'top';
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const StyledContainer = styled('div')(({ theme }) => ({
 | 
			
		||||
@ -22,6 +23,8 @@ const StyledContent = styled('div')(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    gap: theme.spacing(1),
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
    flexGrow: 1,
 | 
			
		||||
    position: 'relative',
 | 
			
		||||
    [`.${disabledStrategyClassName} &`]: {
 | 
			
		||||
        filter: 'grayscale(1)',
 | 
			
		||||
        color: theme.palette.text.secondary,
 | 
			
		||||
@ -31,7 +34,9 @@ const StyledContent = styled('div')(({ theme }) => ({
 | 
			
		||||
    },
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledType = styled('span')(({ theme }) => ({
 | 
			
		||||
const StyledType = styled('span')<{
 | 
			
		||||
    align?: 'top' | 'center';
 | 
			
		||||
}>(({ theme, align }) => ({
 | 
			
		||||
    display: 'block',
 | 
			
		||||
    flexShrink: 0,
 | 
			
		||||
    fontSize: theme.fontSizes.smallerBody,
 | 
			
		||||
@ -41,6 +46,9 @@ const StyledType = styled('span')(({ theme }) => ({
 | 
			
		||||
    [theme.breakpoints.down('sm')]: {
 | 
			
		||||
        width: '100%',
 | 
			
		||||
    },
 | 
			
		||||
    ...(align === 'top' && {
 | 
			
		||||
        alignSelf: 'flex-start',
 | 
			
		||||
    }),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -49,10 +57,11 @@ const StyledType = styled('span')(({ theme }) => ({
 | 
			
		||||
export const StrategyEvaluationItem: FC<StrategyEvaluationItemProps> = ({
 | 
			
		||||
    type,
 | 
			
		||||
    children,
 | 
			
		||||
    alignType,
 | 
			
		||||
}) => {
 | 
			
		||||
    return (
 | 
			
		||||
        <StyledContainer>
 | 
			
		||||
            <StyledType>{type}</StyledType>
 | 
			
		||||
            <StyledType align={alignType}>{type}</StyledType>
 | 
			
		||||
            <StyledContent>{children}</StyledContent>
 | 
			
		||||
        </StyledContainer>
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,97 @@
 | 
			
		||||
import { Box, styled, Typography } from '@mui/material';
 | 
			
		||||
import type { StrategyVariantSchema } from 'openapi';
 | 
			
		||||
 | 
			
		||||
const StyledTooltipContainer = styled(Box)(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    flexDirection: 'column',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledVariantContainer = styled(Box)(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
    minWidth: '250px',
 | 
			
		||||
    gap: theme.spacing(1),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledPayloadContainer = styled(Box)(({ theme }) => ({
 | 
			
		||||
    padding: theme.spacing(1, 0, 0.75, 0),
 | 
			
		||||
    flexDirection: 'column',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledPayloadLabel = styled('span')(({ theme }) => ({
 | 
			
		||||
    marginBottom: theme.spacing(1),
 | 
			
		||||
    fontSize: theme.typography.body2.fontSize,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledVariantBox = styled(Box, {
 | 
			
		||||
    shouldForwardProp: (prop) => prop !== 'index',
 | 
			
		||||
})<{ index: number }>(({ theme, index }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
    figure: {
 | 
			
		||||
        margin: 0,
 | 
			
		||||
        padding: 0,
 | 
			
		||||
        width: theme.spacing(1.6),
 | 
			
		||||
        height: theme.spacing(1.6),
 | 
			
		||||
        borderRadius: '50%',
 | 
			
		||||
        background:
 | 
			
		||||
            theme.palette.variants[index % theme.palette.variants.length],
 | 
			
		||||
    },
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledVariantType = styled('span')(({ theme }) => ({
 | 
			
		||||
    display: 'inline-block',
 | 
			
		||||
    background: theme.palette.background.elevation2,
 | 
			
		||||
    borderRadius: theme.shape.borderRadiusLarge,
 | 
			
		||||
    padding: theme.spacing(0.25, 1),
 | 
			
		||||
    align: 'center',
 | 
			
		||||
    fontSize: theme.fontSizes.smallBody,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledVariantPayload = styled('code')(({ theme }) => ({
 | 
			
		||||
    display: 'inline-block',
 | 
			
		||||
    background: theme.palette.background.elevation2,
 | 
			
		||||
    borderRadius: theme.shape.borderRadiusLarge,
 | 
			
		||||
    padding: theme.spacing(0.25, 1),
 | 
			
		||||
    fontSize: theme.fontSizes.smallerBody,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
type SplitPreviewTooltipProps = {
 | 
			
		||||
    variant: StrategyVariantSchema;
 | 
			
		||||
    index: number;
 | 
			
		||||
    selected?: boolean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const SplitPreviewTooltip = ({
 | 
			
		||||
    variant: { name, weight, payload },
 | 
			
		||||
    index,
 | 
			
		||||
    selected,
 | 
			
		||||
}: SplitPreviewTooltipProps) => (
 | 
			
		||||
    <StyledTooltipContainer>
 | 
			
		||||
        <StyledVariantContainer>
 | 
			
		||||
            <StyledVariantBox index={index}>
 | 
			
		||||
                <figure />
 | 
			
		||||
            </StyledVariantBox>
 | 
			
		||||
 | 
			
		||||
            <Typography variant='subtitle2'>
 | 
			
		||||
                {weight / 10}% - {name}
 | 
			
		||||
            </Typography>
 | 
			
		||||
        </StyledVariantContainer>
 | 
			
		||||
 | 
			
		||||
        {payload ? (
 | 
			
		||||
            <StyledPayloadContainer
 | 
			
		||||
                sx={{
 | 
			
		||||
                    display: ['json', 'csv'].includes(payload.type)
 | 
			
		||||
                        ? 'flex'
 | 
			
		||||
                        : 'block',
 | 
			
		||||
                }}
 | 
			
		||||
            >
 | 
			
		||||
                <StyledPayloadLabel>
 | 
			
		||||
                    <StyledVariantType>{payload.type}</StyledVariantType>
 | 
			
		||||
                    {' payload: '}
 | 
			
		||||
                </StyledPayloadLabel>
 | 
			
		||||
                <StyledVariantPayload>{payload.value}</StyledVariantPayload>
 | 
			
		||||
            </StyledPayloadContainer>
 | 
			
		||||
        ) : null}
 | 
			
		||||
    </StyledTooltipContainer>
 | 
			
		||||
);
 | 
			
		||||
@ -0,0 +1,145 @@
 | 
			
		||||
import { Box, Typography, styled } from '@mui/material';
 | 
			
		||||
import { TooltipResolver } from 'component/common/TooltipResolver/TooltipResolver';
 | 
			
		||||
import { Truncator } from 'component/common/Truncator/Truncator';
 | 
			
		||||
import type { StrategyVariantSchema } from 'openapi';
 | 
			
		||||
import { SplitPreviewTooltip } from './SplitPreviewTooltip/SplitPreviewTooltip';
 | 
			
		||||
 | 
			
		||||
const StyledContainer = styled(Box)(() => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    width: '100%',
 | 
			
		||||
    position: 'relative',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledVariantItem = styled(Box)<{ selected?: boolean }>(
 | 
			
		||||
    ({ theme, selected }) => ({
 | 
			
		||||
        position: 'relative',
 | 
			
		||||
        fontSize: theme.fontSizes.smallerBody,
 | 
			
		||||
        ...(selected
 | 
			
		||||
            ? {
 | 
			
		||||
                  fontWeight: theme.typography.fontWeightBold,
 | 
			
		||||
              }
 | 
			
		||||
            : {}),
 | 
			
		||||
    }),
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const StyledVariantItemTrack = styled(Box)<{
 | 
			
		||||
    index: number;
 | 
			
		||||
    hasError?: boolean;
 | 
			
		||||
    isFirst?: boolean;
 | 
			
		||||
    isLast?: boolean;
 | 
			
		||||
}>(({ theme, index, hasError, isFirst, isLast }) => ({
 | 
			
		||||
    height: theme.spacing(2),
 | 
			
		||||
    width: '100%',
 | 
			
		||||
    position: 'relative',
 | 
			
		||||
    color: hasError ? theme.palette.error.main : 'inherit',
 | 
			
		||||
    background: theme.palette.variants[index % theme.palette.variants.length],
 | 
			
		||||
    ...(isFirst
 | 
			
		||||
        ? {
 | 
			
		||||
              borderTopLeftRadius: theme.shape.borderRadius,
 | 
			
		||||
              borderBottomLeftRadius: theme.shape.borderRadius,
 | 
			
		||||
          }
 | 
			
		||||
        : {}),
 | 
			
		||||
    ...(isLast
 | 
			
		||||
        ? {
 | 
			
		||||
              borderTopRightRadius: theme.shape.borderRadius,
 | 
			
		||||
              borderBottomRightRadius: theme.shape.borderRadius,
 | 
			
		||||
          }
 | 
			
		||||
        : {}),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledTrackPercentage = styled(Box)(({ theme }) => ({
 | 
			
		||||
    padding: theme.spacing(0.25, 0.25),
 | 
			
		||||
    lineHeight: 1,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledVariantItemInfo = styled(Box)(({ theme }) => ({
 | 
			
		||||
    padding: theme.spacing(0.125, 0.25, 0),
 | 
			
		||||
    overflow: 'hidden',
 | 
			
		||||
    color: theme.palette.text.secondary,
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledHeaderContainer = styled(Box)(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
    marginBottom: theme.spacing(1),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledTypography = styled(Typography)(({ theme }) => ({
 | 
			
		||||
    marginY: theme.spacing(1),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
type VariantsSplitPreviewProps = {
 | 
			
		||||
    variants: StrategyVariantSchema[];
 | 
			
		||||
    weightsError?: boolean;
 | 
			
		||||
    header?: boolean;
 | 
			
		||||
    selected?: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const VariantsSplitPreview = ({
 | 
			
		||||
    variants,
 | 
			
		||||
    weightsError,
 | 
			
		||||
    header = true,
 | 
			
		||||
    selected,
 | 
			
		||||
}: VariantsSplitPreviewProps) => {
 | 
			
		||||
    if (variants.length < 1) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <Box sx={(theme) => ({ marginTop: theme.spacing(header ? 2 : 0) })}>
 | 
			
		||||
            {header ? (
 | 
			
		||||
                <StyledHeaderContainer>
 | 
			
		||||
                    <StyledTypography variant='body2'>
 | 
			
		||||
                        Flag variants ({variants.length})
 | 
			
		||||
                    </StyledTypography>
 | 
			
		||||
                </StyledHeaderContainer>
 | 
			
		||||
            ) : null}
 | 
			
		||||
            <StyledContainer>
 | 
			
		||||
                {variants.map((variant, index) => {
 | 
			
		||||
                    const value = variant.weight / 10;
 | 
			
		||||
                    if (value === 0) {
 | 
			
		||||
                        return null;
 | 
			
		||||
                    }
 | 
			
		||||
                    return (
 | 
			
		||||
                        <TooltipResolver
 | 
			
		||||
                            variant='custom'
 | 
			
		||||
                            key={index}
 | 
			
		||||
                            arrow
 | 
			
		||||
                            onClick={(e) => e.preventDefault()}
 | 
			
		||||
                            titleComponent={
 | 
			
		||||
                                <SplitPreviewTooltip
 | 
			
		||||
                                    variant={variant}
 | 
			
		||||
                                    index={index}
 | 
			
		||||
                                    selected={selected === variant.name}
 | 
			
		||||
                                />
 | 
			
		||||
                            }
 | 
			
		||||
                        >
 | 
			
		||||
                            <StyledVariantItem
 | 
			
		||||
                                sx={{ width: `${value}%` }}
 | 
			
		||||
                                selected={selected === variant.name}
 | 
			
		||||
                            >
 | 
			
		||||
                                <StyledVariantItemTrack
 | 
			
		||||
                                    index={index}
 | 
			
		||||
                                    isFirst={index === 0}
 | 
			
		||||
                                    isLast={index === variants.length - 1}
 | 
			
		||||
                                    hasError={weightsError}
 | 
			
		||||
                                >
 | 
			
		||||
                                    <StyledTrackPercentage>
 | 
			
		||||
                                        <Truncator lines={1}>
 | 
			
		||||
                                            {`${value}%`}
 | 
			
		||||
                                        </Truncator>
 | 
			
		||||
                                    </StyledTrackPercentage>
 | 
			
		||||
                                </StyledVariantItemTrack>
 | 
			
		||||
                                <StyledVariantItemInfo>
 | 
			
		||||
                                    <Truncator lines={1}>
 | 
			
		||||
                                        {variant.name}
 | 
			
		||||
                                    </Truncator>
 | 
			
		||||
                                </StyledVariantItemInfo>
 | 
			
		||||
                            </StyledVariantItem>
 | 
			
		||||
                        </TooltipResolver>
 | 
			
		||||
                    );
 | 
			
		||||
                })}
 | 
			
		||||
            </StyledContainer>
 | 
			
		||||
        </Box>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
@ -13,7 +13,7 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
 | 
			
		||||
import { CopyStrategyIconMenu } from './CopyStrategyIconMenu/CopyStrategyIconMenu';
 | 
			
		||||
import { StrategyItemContainer } from 'component/common/StrategyItemContainer/LegacyStrategyItemContainer';
 | 
			
		||||
import MenuStrategyRemove from './MenuStrategyRemove/MenuStrategyRemove';
 | 
			
		||||
import SplitPreviewSlider from 'component/feature/StrategyTypes/SplitPreviewSlider/SplitPreviewSlider';
 | 
			
		||||
import { VariantsSplitPreview } from 'component/common/VariantsSplitPreview/VariantsSplitPreview';
 | 
			
		||||
import { Box } from '@mui/material';
 | 
			
		||||
interface IStrategyItemProps {
 | 
			
		||||
    environmentId: string;
 | 
			
		||||
@ -93,10 +93,10 @@ export const StrategyItem: FC<IStrategyItemProps> = ({
 | 
			
		||||
                strategy.variants.length > 0 &&
 | 
			
		||||
                (strategy.disabled ? (
 | 
			
		||||
                    <Box sx={{ opacity: '0.5' }}>
 | 
			
		||||
                        <SplitPreviewSlider variants={strategy.variants} />
 | 
			
		||||
                        <VariantsSplitPreview variants={strategy.variants} />
 | 
			
		||||
                    </Box>
 | 
			
		||||
                ) : (
 | 
			
		||||
                    <SplitPreviewSlider variants={strategy.variants} />
 | 
			
		||||
                    <VariantsSplitPreview variants={strategy.variants} />
 | 
			
		||||
                ))}
 | 
			
		||||
        </StrategyItemContainer>
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
@ -1,17 +1,15 @@
 | 
			
		||||
import type { FC } from 'react';
 | 
			
		||||
import { StrategyEvaluationChip } from 'component/common/ConstraintsList/StrategyEvaluationChip/StrategyEvaluationChip';
 | 
			
		||||
import { StrategyEvaluationItem } from 'component/common/ConstraintsList/StrategyEvaluationItem/StrategyEvaluationItem';
 | 
			
		||||
import type { ParametersSchema, StrategyVariantSchema } from 'openapi';
 | 
			
		||||
import type { FC } from 'react';
 | 
			
		||||
import type { ParametersSchema } from 'openapi';
 | 
			
		||||
import { parseParameterNumber } from 'utils/parseParameter';
 | 
			
		||||
import { RolloutVariants } from './RolloutVariants/RolloutVariants';
 | 
			
		||||
 | 
			
		||||
export const RolloutParameter: FC<{
 | 
			
		||||
    value: string;
 | 
			
		||||
    parameters?: ParametersSchema;
 | 
			
		||||
    hasConstraints?: boolean;
 | 
			
		||||
    variants?: StrategyVariantSchema[];
 | 
			
		||||
    displayGroupId?: boolean;
 | 
			
		||||
}> = ({ value, parameters, hasConstraints, variants, displayGroupId }) => {
 | 
			
		||||
}> = ({ value, parameters, hasConstraints, displayGroupId }) => {
 | 
			
		||||
    const percentage = parseParameterNumber(value);
 | 
			
		||||
 | 
			
		||||
    const explainStickiness =
 | 
			
		||||
@ -43,7 +41,6 @@ export const RolloutParameter: FC<{
 | 
			
		||||
                    ) : null}
 | 
			
		||||
                </p>
 | 
			
		||||
            </StrategyEvaluationItem>
 | 
			
		||||
            <RolloutVariants variants={variants} />
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -1,71 +0,0 @@
 | 
			
		||||
import { styled } from '@mui/material';
 | 
			
		||||
import { StrategyEvaluationChip } from 'component/common/ConstraintsList/StrategyEvaluationChip/StrategyEvaluationChip';
 | 
			
		||||
import { StrategyEvaluationItem } from 'component/common/ConstraintsList/StrategyEvaluationItem/StrategyEvaluationItem';
 | 
			
		||||
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
 | 
			
		||||
import type { StrategyVariantSchema } from 'openapi';
 | 
			
		||||
import type { FC } from 'react';
 | 
			
		||||
 | 
			
		||||
const StyledVariantChip = styled(StrategyEvaluationChip)<{ order: number }>(
 | 
			
		||||
    ({ theme, order }) => ({
 | 
			
		||||
        borderRadius: theme.shape.borderRadiusExtraLarge,
 | 
			
		||||
        border: 'none',
 | 
			
		||||
        color: theme.palette.text.primary,
 | 
			
		||||
        background:
 | 
			
		||||
            theme.palette.variants[order % theme.palette.variants.length],
 | 
			
		||||
        fontWeight: theme.typography.fontWeightRegular,
 | 
			
		||||
    }),
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const StyledPayloadHeader = styled('div')(({ theme }) => ({
 | 
			
		||||
    fontSize: theme.typography.body2.fontSize,
 | 
			
		||||
    marginBottom: theme.spacing(1),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledValuesContainer = styled('div')(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    gap: theme.spacing(0.75, 0.5),
 | 
			
		||||
    flexWrap: 'wrap',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const RolloutVariants: FC<{
 | 
			
		||||
    variants?: StrategyVariantSchema[];
 | 
			
		||||
}> = ({ variants }) => {
 | 
			
		||||
    if (!variants?.length) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <StrategyEvaluationItem type={`Variants (${variants.length})`}>
 | 
			
		||||
            <StyledValuesContainer>
 | 
			
		||||
                {variants.map((variant, i) => (
 | 
			
		||||
                    <HtmlTooltip
 | 
			
		||||
                        arrow
 | 
			
		||||
                        title={
 | 
			
		||||
                            variant.payload?.value ? (
 | 
			
		||||
                                <div>
 | 
			
		||||
                                    <StyledPayloadHeader>
 | 
			
		||||
                                        Payload:
 | 
			
		||||
                                    </StyledPayloadHeader>
 | 
			
		||||
                                    <code>{variant.payload?.value}</code>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            ) : null
 | 
			
		||||
                        }
 | 
			
		||||
                        key={variant.name}
 | 
			
		||||
                    >
 | 
			
		||||
                        <StyledVariantChip
 | 
			
		||||
                            key={variant.name}
 | 
			
		||||
                            order={i}
 | 
			
		||||
                            label={
 | 
			
		||||
                                <>
 | 
			
		||||
                                    <span>
 | 
			
		||||
                                        {variant.weight / 10}% – {variant.name}
 | 
			
		||||
                                    </span>
 | 
			
		||||
                                </>
 | 
			
		||||
                            }
 | 
			
		||||
                        />
 | 
			
		||||
                    </HtmlTooltip>
 | 
			
		||||
                ))}
 | 
			
		||||
            </StyledValuesContainer>
 | 
			
		||||
        </StrategyEvaluationItem>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
@ -0,0 +1,40 @@
 | 
			
		||||
import { styled } from '@mui/material';
 | 
			
		||||
import { StrategyEvaluationItem } from 'component/common/ConstraintsList/StrategyEvaluationItem/StrategyEvaluationItem';
 | 
			
		||||
import { VariantsSplitPreview } from 'component/common/VariantsSplitPreview/VariantsSplitPreview';
 | 
			
		||||
import type { StrategyVariantSchema } from 'openapi';
 | 
			
		||||
import type { FC } from 'react';
 | 
			
		||||
 | 
			
		||||
const StyledContainer = styled('div')(({ theme }) => ({
 | 
			
		||||
    padding: theme.spacing(3.5, 2, 0.5),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledTrack = styled('div')(() => ({
 | 
			
		||||
    width: '100%',
 | 
			
		||||
    position: 'relative',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const RolloutVariants: FC<{
 | 
			
		||||
    variants?: StrategyVariantSchema[];
 | 
			
		||||
    selected?: StrategyVariantSchema['name'];
 | 
			
		||||
}> = ({ variants, selected }) => {
 | 
			
		||||
    if (!variants?.length) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <StyledContainer>
 | 
			
		||||
            <StrategyEvaluationItem
 | 
			
		||||
                type={`Variants (${variants.length})`}
 | 
			
		||||
                alignType='top'
 | 
			
		||||
            >
 | 
			
		||||
                <StyledTrack>
 | 
			
		||||
                    <VariantsSplitPreview
 | 
			
		||||
                        variants={variants}
 | 
			
		||||
                        header={false}
 | 
			
		||||
                        selected={selected}
 | 
			
		||||
                    />
 | 
			
		||||
                </StyledTrack>
 | 
			
		||||
            </StrategyEvaluationItem>
 | 
			
		||||
        </StyledContainer>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
@ -14,6 +14,7 @@ import {
 | 
			
		||||
    ConstraintListItem,
 | 
			
		||||
    ConstraintsList,
 | 
			
		||||
} from 'component/common/ConstraintsList/ConstraintsList';
 | 
			
		||||
import { RolloutVariants } from './RolloutVariants/RolloutVariants';
 | 
			
		||||
 | 
			
		||||
type StrategyExecutionProps = {
 | 
			
		||||
    strategy: IFeatureStrategyPayload | FeatureStrategySchema;
 | 
			
		||||
@ -48,6 +49,7 @@ export const StrategyExecution: FC<StrategyExecutionProps> = ({
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <ConstraintsList>
 | 
			
		||||
                {strategySegments?.map((segment) => (
 | 
			
		||||
                    <SegmentItem segment={segment} key={segment.id} />
 | 
			
		||||
@ -58,11 +60,14 @@ export const StrategyExecution: FC<StrategyExecutionProps> = ({
 | 
			
		||||
                        constraint={constraint}
 | 
			
		||||
                    />
 | 
			
		||||
                ))}
 | 
			
		||||
            {(isCustomStrategy ? customStrategyItems : strategyParameters).map(
 | 
			
		||||
                (item, index) => (
 | 
			
		||||
                {(isCustomStrategy
 | 
			
		||||
                    ? customStrategyItems
 | 
			
		||||
                    : strategyParameters
 | 
			
		||||
                ).map((item, index) => (
 | 
			
		||||
                    <ConstraintListItem key={index}>{item}</ConstraintListItem>
 | 
			
		||||
                ),
 | 
			
		||||
            )}
 | 
			
		||||
                ))}
 | 
			
		||||
            </ConstraintsList>
 | 
			
		||||
            <RolloutVariants variants={strategy.variants} />
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,6 @@ export const useStrategyParameters = (
 | 
			
		||||
                    parameters={parameters}
 | 
			
		||||
                    hasConstraints={hasConstraints}
 | 
			
		||||
                    displayGroupId={displayGroupId}
 | 
			
		||||
                    variants={variants}
 | 
			
		||||
                />
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
// deprecated; remove with `flagOverviewRedesign` flag
 | 
			
		||||
import { Box, styled } from '@mui/material';
 | 
			
		||||
import { StrategyExecution } from '../../FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/StrategyExecution';
 | 
			
		||||
import SplitPreviewSlider from 'component/feature/StrategyTypes/SplitPreviewSlider/SplitPreviewSlider';
 | 
			
		||||
import { VariantsSplitPreview } from 'component/common/VariantsSplitPreview/VariantsSplitPreview';
 | 
			
		||||
import {
 | 
			
		||||
    formatStrategyName,
 | 
			
		||||
    getFeatureStrategyIcon,
 | 
			
		||||
@ -46,10 +46,10 @@ export const ReleasePlanMilestoneStrategy = ({
 | 
			
		||||
                strategy.variants.length > 0 &&
 | 
			
		||||
                (strategy.disabled ? (
 | 
			
		||||
                    <Box sx={{ opacity: '0.5' }}>
 | 
			
		||||
                        <SplitPreviewSlider variants={strategy.variants} />
 | 
			
		||||
                        <VariantsSplitPreview variants={strategy.variants} />
 | 
			
		||||
                    </Box>
 | 
			
		||||
                ) : (
 | 
			
		||||
                    <SplitPreviewSlider variants={strategy.variants} />
 | 
			
		||||
                    <VariantsSplitPreview variants={strategy.variants} />
 | 
			
		||||
                ))}
 | 
			
		||||
        </StyledStrategy>
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
@ -1,17 +1,17 @@
 | 
			
		||||
import { VariantForm } from '../FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/VariantForm/VariantForm';
 | 
			
		||||
import { updateWeightEdit } from '../../common/util';
 | 
			
		||||
import { updateWeightEdit } from 'component/common/util';
 | 
			
		||||
import type React from 'react';
 | 
			
		||||
import { type FC, useEffect, useState } from 'react';
 | 
			
		||||
import type { IFeatureVariantEdit } from '../FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/EnvironmentVariantsModal';
 | 
			
		||||
import PermissionButton from '../../common/PermissionButton/PermissionButton';
 | 
			
		||||
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
 | 
			
		||||
import { UPDATE_FEATURE_ENVIRONMENT_VARIANTS } from '../../providers/AccessProvider/permissions';
 | 
			
		||||
import { v4 as uuidv4 } from 'uuid';
 | 
			
		||||
import { WeightType } from '../../../constants/variantTypes';
 | 
			
		||||
import { Box, styled, Typography, useTheme } from '@mui/material';
 | 
			
		||||
import type { IFeatureStrategy } from 'interfaces/strategy';
 | 
			
		||||
import SplitPreviewSlider from './SplitPreviewSlider/SplitPreviewSlider';
 | 
			
		||||
import { HelpIcon } from '../../common/HelpIcon/HelpIcon';
 | 
			
		||||
import { StrategyVariantsUpgradeAlert } from '../../common/StrategyVariantsUpgradeAlert/StrategyVariantsUpgradeAlert';
 | 
			
		||||
import { VariantsSplitPreview } from 'component/common/VariantsSplitPreview/VariantsSplitPreview';
 | 
			
		||||
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
 | 
			
		||||
import { StrategyVariantsUpgradeAlert } from 'component/common/StrategyVariantsUpgradeAlert/StrategyVariantsUpgradeAlert';
 | 
			
		||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
 | 
			
		||||
import Add from '@mui/icons-material/Add';
 | 
			
		||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
			
		||||
@ -199,7 +199,7 @@ export const NewStrategyVariants: FC<{
 | 
			
		||||
            >
 | 
			
		||||
                Add variant
 | 
			
		||||
            </PermissionButton>
 | 
			
		||||
            <SplitPreviewSlider
 | 
			
		||||
            <VariantsSplitPreview
 | 
			
		||||
                variants={variantsEdit}
 | 
			
		||||
                weightsError={variantWeightsError}
 | 
			
		||||
            />
 | 
			
		||||
 | 
			
		||||
@ -1,214 +0,0 @@
 | 
			
		||||
import { Box, Typography, styled } from '@mui/material';
 | 
			
		||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
			
		||||
import { TooltipResolver } from 'component/common/TooltipResolver/TooltipResolver';
 | 
			
		||||
import type { IFeatureVariant } from 'interfaces/featureToggle';
 | 
			
		||||
 | 
			
		||||
const StyledContainer = styled(Box)(() => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    width: '100%',
 | 
			
		||||
    position: 'relative',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledTrack = styled(Box)(({ theme }) => ({
 | 
			
		||||
    position: 'absolute',
 | 
			
		||||
    height: theme.spacing(3),
 | 
			
		||||
    width: '100%',
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    overflow: 'hidden',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledSegment = styled(Box)(() => ({
 | 
			
		||||
    height: '100%',
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    flexDirection: 'column',
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
    width: '100%',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledSegmentTrack = styled(Box, {
 | 
			
		||||
    shouldForwardProp: (prop) => prop !== 'index',
 | 
			
		||||
})<{ index: number }>(({ theme, index }) => ({
 | 
			
		||||
    height: theme.spacing(1.8),
 | 
			
		||||
    width: '100%',
 | 
			
		||||
    position: 'relative',
 | 
			
		||||
    background: theme.palette.variants[index % theme.palette.variants.length],
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledHeaderContainer = styled(Box)(({ theme }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
    marginBottom: theme.spacing(1),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledTypography = styled(Typography)(({ theme }) => ({
 | 
			
		||||
    marginY: theme.spacing(1),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledVariantBoxContainer = styled(Box)(() => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
    marginLeft: 'auto',
 | 
			
		||||
    flexWrap: 'wrap',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledVariantBox = styled(Box, {
 | 
			
		||||
    shouldForwardProp: (prop) => prop !== 'index',
 | 
			
		||||
})<{ index: number }>(({ theme, index }) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
    marginRight: theme.spacing(2),
 | 
			
		||||
    '& div': {
 | 
			
		||||
        width: theme.spacing(1.6),
 | 
			
		||||
        height: theme.spacing(1.6),
 | 
			
		||||
        borderRadius: '50%',
 | 
			
		||||
        marginRight: theme.spacing(1),
 | 
			
		||||
        background:
 | 
			
		||||
            theme.palette.variants[index % theme.palette.variants.length],
 | 
			
		||||
    },
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledTypographySubtitle = styled(Typography)(({ theme }) => ({
 | 
			
		||||
    marginTop: theme.spacing(1),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
interface ISplitPreviewSliderProps {
 | 
			
		||||
    variants: IFeatureVariant[];
 | 
			
		||||
    weightsError?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const SplitPreviewSlider = ({
 | 
			
		||||
    variants,
 | 
			
		||||
    weightsError,
 | 
			
		||||
}: ISplitPreviewSliderProps) => {
 | 
			
		||||
    if (variants.length < 1) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <Box sx={(theme) => ({ marginTop: theme.spacing(2) })}>
 | 
			
		||||
            <SplitPreviewHeader variants={variants} />
 | 
			
		||||
            <StyledContainer>
 | 
			
		||||
                <StyledTrack />
 | 
			
		||||
 | 
			
		||||
                {variants.map((variant, index) => {
 | 
			
		||||
                    const value = variant.weight / 10;
 | 
			
		||||
                    return (
 | 
			
		||||
                        <TooltipResolver
 | 
			
		||||
                            variant='custom'
 | 
			
		||||
                            key={index}
 | 
			
		||||
                            arrow
 | 
			
		||||
                            onClick={(e) => e.preventDefault()}
 | 
			
		||||
                            titleComponent={
 | 
			
		||||
                                <SplitPreviewTooltip
 | 
			
		||||
                                    variant={variant}
 | 
			
		||||
                                    index={index}
 | 
			
		||||
                                />
 | 
			
		||||
                            }
 | 
			
		||||
                        >
 | 
			
		||||
                            <Box
 | 
			
		||||
                                style={{
 | 
			
		||||
                                    width: `${value}%`,
 | 
			
		||||
                                }}
 | 
			
		||||
                            >
 | 
			
		||||
                                {' '}
 | 
			
		||||
                                <StyledSegment>
 | 
			
		||||
                                    <StyledSegmentTrack index={index} />
 | 
			
		||||
                                    <StyledTypographySubtitle
 | 
			
		||||
                                        variant='subtitle2'
 | 
			
		||||
                                        color={
 | 
			
		||||
                                            weightsError ? 'error' : 'inherit'
 | 
			
		||||
                                        }
 | 
			
		||||
                                    >
 | 
			
		||||
                                        {value}%
 | 
			
		||||
                                    </StyledTypographySubtitle>
 | 
			
		||||
                                </StyledSegment>
 | 
			
		||||
                            </Box>
 | 
			
		||||
                        </TooltipResolver>
 | 
			
		||||
                    );
 | 
			
		||||
                })}
 | 
			
		||||
            </StyledContainer>
 | 
			
		||||
        </Box>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const SplitPreviewHeader = ({ variants }: ISplitPreviewSliderProps) => {
 | 
			
		||||
    return (
 | 
			
		||||
        <StyledHeaderContainer>
 | 
			
		||||
            <StyledTypography variant='body2'>
 | 
			
		||||
                Feature variants ({variants.length})
 | 
			
		||||
            </StyledTypography>
 | 
			
		||||
            <StyledVariantBoxContainer>
 | 
			
		||||
                {variants.map((variant, index) => (
 | 
			
		||||
                    <StyledVariantBox key={index} index={index}>
 | 
			
		||||
                        <Box />
 | 
			
		||||
                        <StyledTypography variant='body2'>
 | 
			
		||||
                            {variant.name}
 | 
			
		||||
                        </StyledTypography>
 | 
			
		||||
                    </StyledVariantBox>
 | 
			
		||||
                ))}
 | 
			
		||||
            </StyledVariantBoxContainer>
 | 
			
		||||
        </StyledHeaderContainer>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
interface ISplitPreviewTooltip {
 | 
			
		||||
    variant: IFeatureVariant;
 | 
			
		||||
    index: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const StyledTooltipContainer = styled(Box)(() => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    flexDirection: 'column',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledVariantContainer = styled(Box)(() => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    alignItems: 'center',
 | 
			
		||||
    minWidth: '250px',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledPayloadContainer = styled(Box)(({ theme }) => ({
 | 
			
		||||
    marginTop: theme.spacing(1),
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    flexDirection: 'column',
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const StyledPayloadLabel = styled(Typography)(({ theme }) => ({
 | 
			
		||||
    marginBottom: theme.spacing(1),
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
const SplitPreviewTooltip = ({ variant, index }: ISplitPreviewTooltip) => {
 | 
			
		||||
    return (
 | 
			
		||||
        <StyledTooltipContainer>
 | 
			
		||||
            <StyledVariantContainer>
 | 
			
		||||
                <StyledVariantBox index={index}>
 | 
			
		||||
                    <Box />
 | 
			
		||||
                </StyledVariantBox>
 | 
			
		||||
 | 
			
		||||
                <Typography variant='subtitle2'>
 | 
			
		||||
                    {variant.weight / 10}% - {variant.name}
 | 
			
		||||
                </Typography>
 | 
			
		||||
            </StyledVariantContainer>
 | 
			
		||||
 | 
			
		||||
            {variant.payload ? (
 | 
			
		||||
                <StyledPayloadContainer>
 | 
			
		||||
                    <StyledPayloadLabel variant='body2'>
 | 
			
		||||
                        Payload
 | 
			
		||||
                    </StyledPayloadLabel>
 | 
			
		||||
 | 
			
		||||
                    <ConditionallyRender
 | 
			
		||||
                        condition={variant.payload.type === 'json'}
 | 
			
		||||
                        show={<code>{variant.payload.value}</code>}
 | 
			
		||||
                        elseShow={
 | 
			
		||||
                            <Typography variant='body2'>
 | 
			
		||||
                                {variant.payload.value}
 | 
			
		||||
                            </Typography>
 | 
			
		||||
                        }
 | 
			
		||||
                    />
 | 
			
		||||
                </StyledPayloadContainer>
 | 
			
		||||
            ) : null}
 | 
			
		||||
        </StyledTooltipContainer>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default SplitPreviewSlider;
 | 
			
		||||
@ -1,17 +1,17 @@
 | 
			
		||||
import { VariantForm } from '../FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/VariantForm/VariantForm';
 | 
			
		||||
import { updateWeightEdit } from '../../common/util';
 | 
			
		||||
import { updateWeightEdit } from 'component/common/util';
 | 
			
		||||
import type React from 'react';
 | 
			
		||||
import { type FC, useEffect, useState } from 'react';
 | 
			
		||||
import type { IFeatureVariantEdit } from '../FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/EnvironmentVariantsModal';
 | 
			
		||||
import PermissionButton from '../../common/PermissionButton/PermissionButton';
 | 
			
		||||
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
 | 
			
		||||
import { UPDATE_FEATURE_ENVIRONMENT_VARIANTS } from '../../providers/AccessProvider/permissions';
 | 
			
		||||
import { v4 as uuidv4 } from 'uuid';
 | 
			
		||||
import { WeightType } from '../../../constants/variantTypes';
 | 
			
		||||
import { Link, styled, Typography, useTheme } from '@mui/material';
 | 
			
		||||
import type { IFeatureStrategy } from 'interfaces/strategy';
 | 
			
		||||
import SplitPreviewSlider from './SplitPreviewSlider/SplitPreviewSlider';
 | 
			
		||||
import { HelpIcon } from '../../common/HelpIcon/HelpIcon';
 | 
			
		||||
import { StrategyVariantsUpgradeAlert } from '../../common/StrategyVariantsUpgradeAlert/StrategyVariantsUpgradeAlert';
 | 
			
		||||
import { VariantsSplitPreview } from 'component/common/VariantsSplitPreview/VariantsSplitPreview';
 | 
			
		||||
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
 | 
			
		||||
import { StrategyVariantsUpgradeAlert } from 'component/common/StrategyVariantsUpgradeAlert/StrategyVariantsUpgradeAlert';
 | 
			
		||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
 | 
			
		||||
 | 
			
		||||
const StyledVariantForms = styled('div')({
 | 
			
		||||
@ -168,7 +168,7 @@ export const StrategyVariants: FC<{
 | 
			
		||||
            >
 | 
			
		||||
                Add variant
 | 
			
		||||
            </PermissionButton>
 | 
			
		||||
            <SplitPreviewSlider variants={variantsEdit} />
 | 
			
		||||
            <VariantsSplitPreview variants={variantsEdit} />
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@ import type {
 | 
			
		||||
} from 'openapi';
 | 
			
		||||
import { objectId } from 'utils/objectId';
 | 
			
		||||
import { StrategyItemContainer } from 'component/common/StrategyItemContainer/StrategyItemContainer';
 | 
			
		||||
import { StrategyExecution } from './StrategyExecution/StrategyExecution';
 | 
			
		||||
import { PlaygroundStrategyExecution } from './PlaygroundStrategyExecution/PlaygroundStrategyExecution';
 | 
			
		||||
 | 
			
		||||
interface IFeatureStrategyItemProps {
 | 
			
		||||
    strategy: PlaygroundStrategySchema;
 | 
			
		||||
@ -42,7 +42,10 @@ export const FeatureStrategyItem = ({
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        >
 | 
			
		||||
            <StrategyExecution strategyResult={strategy} input={input} />
 | 
			
		||||
            <PlaygroundStrategyExecution
 | 
			
		||||
                strategyResult={strategy}
 | 
			
		||||
                input={input}
 | 
			
		||||
            />
 | 
			
		||||
        </StrategyItemContainer>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -4,10 +4,10 @@ import type {
 | 
			
		||||
    PlaygroundStrategySchema,
 | 
			
		||||
    PlaygroundRequestSchema,
 | 
			
		||||
} from 'openapi';
 | 
			
		||||
import { StrategyExecution } from './StrategyExecution/LegacyStrategyExecution';
 | 
			
		||||
import { StrategyExecution } from './PlaygroundStrategyExecution/LegacyStrategyExecution';
 | 
			
		||||
import { objectId } from 'utils/objectId';
 | 
			
		||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
			
		||||
import { DisabledStrategyExecution } from './StrategyExecution/DisabledStrategyExecution';
 | 
			
		||||
import { DisabledStrategyExecution } from './PlaygroundStrategyExecution/DisabledStrategyExecution';
 | 
			
		||||
import { StrategyItemContainer } from 'component/common/StrategyItemContainer/LegacyStrategyItemContainer';
 | 
			
		||||
 | 
			
		||||
interface IFeatureStrategyItemProps {
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,8 @@
 | 
			
		||||
import type {
 | 
			
		||||
    PlaygroundFeatureSchemaVariant,
 | 
			
		||||
    PlaygroundRequestSchema,
 | 
			
		||||
    PlaygroundStrategySchema,
 | 
			
		||||
    StrategyVariantSchema,
 | 
			
		||||
} from 'openapi';
 | 
			
		||||
import { ConstraintExecution } from './ConstraintExecution/ConstraintExecution';
 | 
			
		||||
import { formattedStrategyNames } from 'utils/strategyNames';
 | 
			
		||||
@ -16,6 +18,7 @@ import { SegmentExecution } from './SegmentExecution/SegmentExecution';
 | 
			
		||||
import { useStrategyParameters } from 'component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/hooks/useStrategyParameters';
 | 
			
		||||
import { useStrategies } from 'hooks/api/getters/useStrategies/useStrategies';
 | 
			
		||||
import { useCustomStrategyParameters } from 'component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/hooks/useCustomStrategyParameters';
 | 
			
		||||
import { RolloutVariants } from 'component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/RolloutVariants/RolloutVariants';
 | 
			
		||||
 | 
			
		||||
type StrategyExecutionProps = {
 | 
			
		||||
    strategyResult: PlaygroundStrategySchema;
 | 
			
		||||
@ -23,7 +26,7 @@ type StrategyExecutionProps = {
 | 
			
		||||
    input?: PlaygroundRequestSchema;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const StrategyExecution: FC<StrategyExecutionProps> = ({
 | 
			
		||||
export const PlaygroundStrategyExecution: FC<StrategyExecutionProps> = ({
 | 
			
		||||
    strategyResult,
 | 
			
		||||
    input,
 | 
			
		||||
}) => {
 | 
			
		||||
@ -79,5 +82,17 @@ export const StrategyExecution: FC<StrategyExecutionProps> = ({
 | 
			
		||||
        ),
 | 
			
		||||
    ].filter(Boolean);
 | 
			
		||||
 | 
			
		||||
    return <ConstraintsList>{items}</ConstraintsList>;
 | 
			
		||||
    const { variant, variants } = strategyResult.result as unknown as Partial<{
 | 
			
		||||
        variant: PlaygroundFeatureSchemaVariant;
 | 
			
		||||
        variants: StrategyVariantSchema[];
 | 
			
		||||
    }>;
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <ConstraintsList>{items}</ConstraintsList>
 | 
			
		||||
            {variants?.length ? (
 | 
			
		||||
                <RolloutVariants variants={variants} selected={variant?.name} />
 | 
			
		||||
            ) : null}
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
@ -10,7 +10,7 @@ import {
 | 
			
		||||
    PROJECT_DEFAULT_STRATEGY_WRITE,
 | 
			
		||||
    UPDATE_PROJECT,
 | 
			
		||||
} from '@server/types/permissions';
 | 
			
		||||
import SplitPreviewSlider from 'component/feature/StrategyTypes/SplitPreviewSlider/SplitPreviewSlider';
 | 
			
		||||
import { VariantsSplitPreview } from 'component/common/VariantsSplitPreview/VariantsSplitPreview';
 | 
			
		||||
import { StrategyItemContainer } from 'component/common/StrategyItemContainer/LegacyStrategyItemContainer';
 | 
			
		||||
 | 
			
		||||
interface ProjectEnvironmentDefaultStrategyProps {
 | 
			
		||||
@ -84,7 +84,7 @@ const ProjectEnvironmentDefaultStrategy = ({
 | 
			
		||||
                <StrategyExecution strategy={strategy} />
 | 
			
		||||
 | 
			
		||||
                {strategy.variants && strategy.variants.length > 0 ? (
 | 
			
		||||
                    <SplitPreviewSlider variants={strategy.variants} />
 | 
			
		||||
                    <VariantsSplitPreview variants={strategy.variants} />
 | 
			
		||||
                ) : null}
 | 
			
		||||
            </StrategyItemContainer>
 | 
			
		||||
        </>
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
import { Box, IconButton, styled } from '@mui/material';
 | 
			
		||||
import SplitPreviewSlider from 'component/feature/StrategyTypes/SplitPreviewSlider/SplitPreviewSlider';
 | 
			
		||||
import { VariantsSplitPreview } from 'component/common/VariantsSplitPreview/VariantsSplitPreview';
 | 
			
		||||
import {
 | 
			
		||||
    formatStrategyName,
 | 
			
		||||
    getFeatureStrategyIcon,
 | 
			
		||||
@ -88,10 +88,12 @@ export const MilestoneStrategyItem = ({
 | 
			
		||||
                    strategy.variants.length > 0 &&
 | 
			
		||||
                    (strategy.disabled ? (
 | 
			
		||||
                        <Box sx={{ opacity: '0.5' }}>
 | 
			
		||||
                            <SplitPreviewSlider variants={strategy.variants} />
 | 
			
		||||
                            <VariantsSplitPreview
 | 
			
		||||
                                variants={strategy.variants}
 | 
			
		||||
                            />
 | 
			
		||||
                        </Box>
 | 
			
		||||
                    ) : (
 | 
			
		||||
                        <SplitPreviewSlider variants={strategy.variants} />
 | 
			
		||||
                        <VariantsSplitPreview variants={strategy.variants} />
 | 
			
		||||
                    ))}
 | 
			
		||||
            </StyledStrategyExecution>
 | 
			
		||||
        </StyledStrategy>
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ import { updateWeightEdit } from 'component/common/util';
 | 
			
		||||
import { WeightType } from 'constants/variantTypes';
 | 
			
		||||
import { useTheme } from '@mui/material';
 | 
			
		||||
import Add from '@mui/icons-material/Add';
 | 
			
		||||
import SplitPreviewSlider from 'component/feature/StrategyTypes/SplitPreviewSlider/SplitPreviewSlider';
 | 
			
		||||
import { VariantsSplitPreview } from 'component/common/VariantsSplitPreview/VariantsSplitPreview';
 | 
			
		||||
 | 
			
		||||
const StyledVariantForms = styled('div')({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
@ -180,7 +180,7 @@ export const MilestoneStrategyVariants = ({
 | 
			
		||||
            <Button onClick={addVariant} variant='outlined' startIcon={<Add />}>
 | 
			
		||||
                Add variant
 | 
			
		||||
            </Button>
 | 
			
		||||
            <SplitPreviewSlider
 | 
			
		||||
            <VariantsSplitPreview
 | 
			
		||||
                variants={variantsEdit}
 | 
			
		||||
                weightsError={variantWeightsError}
 | 
			
		||||
            />
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user