mirror of
https://github.com/Unleash/unleash.git
synced 2025-09-01 13:47:27 +02: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 = {
|
export type StrategyEvaluationItemProps = {
|
||||||
type?: ReactNode;
|
type?: ReactNode;
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
|
alignType?: 'center' | 'top';
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledContainer = styled('div')(({ theme }) => ({
|
const StyledContainer = styled('div')(({ theme }) => ({
|
||||||
@ -22,6 +23,8 @@ const StyledContent = styled('div')(({ theme }) => ({
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
gap: theme.spacing(1),
|
gap: theme.spacing(1),
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
flexGrow: 1,
|
||||||
|
position: 'relative',
|
||||||
[`.${disabledStrategyClassName} &`]: {
|
[`.${disabledStrategyClassName} &`]: {
|
||||||
filter: 'grayscale(1)',
|
filter: 'grayscale(1)',
|
||||||
color: theme.palette.text.secondary,
|
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',
|
display: 'block',
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
fontSize: theme.fontSizes.smallerBody,
|
fontSize: theme.fontSizes.smallerBody,
|
||||||
@ -41,6 +46,9 @@ const StyledType = styled('span')(({ theme }) => ({
|
|||||||
[theme.breakpoints.down('sm')]: {
|
[theme.breakpoints.down('sm')]: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
},
|
},
|
||||||
|
...(align === 'top' && {
|
||||||
|
alignSelf: 'flex-start',
|
||||||
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,10 +57,11 @@ const StyledType = styled('span')(({ theme }) => ({
|
|||||||
export const StrategyEvaluationItem: FC<StrategyEvaluationItemProps> = ({
|
export const StrategyEvaluationItem: FC<StrategyEvaluationItemProps> = ({
|
||||||
type,
|
type,
|
||||||
children,
|
children,
|
||||||
|
alignType,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<StyledType>{type}</StyledType>
|
<StyledType align={alignType}>{type}</StyledType>
|
||||||
<StyledContent>{children}</StyledContent>
|
<StyledContent>{children}</StyledContent>
|
||||||
</StyledContainer>
|
</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 { CopyStrategyIconMenu } from './CopyStrategyIconMenu/CopyStrategyIconMenu';
|
||||||
import { StrategyItemContainer } from 'component/common/StrategyItemContainer/LegacyStrategyItemContainer';
|
import { StrategyItemContainer } from 'component/common/StrategyItemContainer/LegacyStrategyItemContainer';
|
||||||
import MenuStrategyRemove from './MenuStrategyRemove/MenuStrategyRemove';
|
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';
|
import { Box } from '@mui/material';
|
||||||
interface IStrategyItemProps {
|
interface IStrategyItemProps {
|
||||||
environmentId: string;
|
environmentId: string;
|
||||||
@ -93,10 +93,10 @@ export const StrategyItem: FC<IStrategyItemProps> = ({
|
|||||||
strategy.variants.length > 0 &&
|
strategy.variants.length > 0 &&
|
||||||
(strategy.disabled ? (
|
(strategy.disabled ? (
|
||||||
<Box sx={{ opacity: '0.5' }}>
|
<Box sx={{ opacity: '0.5' }}>
|
||||||
<SplitPreviewSlider variants={strategy.variants} />
|
<VariantsSplitPreview variants={strategy.variants} />
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<SplitPreviewSlider variants={strategy.variants} />
|
<VariantsSplitPreview variants={strategy.variants} />
|
||||||
))}
|
))}
|
||||||
</StrategyItemContainer>
|
</StrategyItemContainer>
|
||||||
);
|
);
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
|
import type { FC } from 'react';
|
||||||
import { StrategyEvaluationChip } from 'component/common/ConstraintsList/StrategyEvaluationChip/StrategyEvaluationChip';
|
import { StrategyEvaluationChip } from 'component/common/ConstraintsList/StrategyEvaluationChip/StrategyEvaluationChip';
|
||||||
import { StrategyEvaluationItem } from 'component/common/ConstraintsList/StrategyEvaluationItem/StrategyEvaluationItem';
|
import { StrategyEvaluationItem } from 'component/common/ConstraintsList/StrategyEvaluationItem/StrategyEvaluationItem';
|
||||||
import type { ParametersSchema, StrategyVariantSchema } from 'openapi';
|
import type { ParametersSchema } from 'openapi';
|
||||||
import type { FC } from 'react';
|
|
||||||
import { parseParameterNumber } from 'utils/parseParameter';
|
import { parseParameterNumber } from 'utils/parseParameter';
|
||||||
import { RolloutVariants } from './RolloutVariants/RolloutVariants';
|
|
||||||
|
|
||||||
export const RolloutParameter: FC<{
|
export const RolloutParameter: FC<{
|
||||||
value: string;
|
value: string;
|
||||||
parameters?: ParametersSchema;
|
parameters?: ParametersSchema;
|
||||||
hasConstraints?: boolean;
|
hasConstraints?: boolean;
|
||||||
variants?: StrategyVariantSchema[];
|
|
||||||
displayGroupId?: boolean;
|
displayGroupId?: boolean;
|
||||||
}> = ({ value, parameters, hasConstraints, variants, displayGroupId }) => {
|
}> = ({ value, parameters, hasConstraints, displayGroupId }) => {
|
||||||
const percentage = parseParameterNumber(value);
|
const percentage = parseParameterNumber(value);
|
||||||
|
|
||||||
const explainStickiness =
|
const explainStickiness =
|
||||||
@ -43,7 +41,6 @@ export const RolloutParameter: FC<{
|
|||||||
) : null}
|
) : null}
|
||||||
</p>
|
</p>
|
||||||
</StrategyEvaluationItem>
|
</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,
|
ConstraintListItem,
|
||||||
ConstraintsList,
|
ConstraintsList,
|
||||||
} from 'component/common/ConstraintsList/ConstraintsList';
|
} from 'component/common/ConstraintsList/ConstraintsList';
|
||||||
|
import { RolloutVariants } from './RolloutVariants/RolloutVariants';
|
||||||
|
|
||||||
type StrategyExecutionProps = {
|
type StrategyExecutionProps = {
|
||||||
strategy: IFeatureStrategyPayload | FeatureStrategySchema;
|
strategy: IFeatureStrategyPayload | FeatureStrategySchema;
|
||||||
@ -48,21 +49,25 @@ export const StrategyExecution: FC<StrategyExecutionProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConstraintsList>
|
<>
|
||||||
{strategySegments?.map((segment) => (
|
<ConstraintsList>
|
||||||
<SegmentItem segment={segment} key={segment.id} />
|
{strategySegments?.map((segment) => (
|
||||||
))}
|
<SegmentItem segment={segment} key={segment.id} />
|
||||||
{constraints?.map((constraint, index) => (
|
))}
|
||||||
<ConstraintAccordionView
|
{constraints?.map((constraint, index) => (
|
||||||
key={`${objectId(constraint)}-${index}`}
|
<ConstraintAccordionView
|
||||||
constraint={constraint}
|
key={`${objectId(constraint)}-${index}`}
|
||||||
/>
|
constraint={constraint}
|
||||||
))}
|
/>
|
||||||
{(isCustomStrategy ? customStrategyItems : strategyParameters).map(
|
))}
|
||||||
(item, index) => (
|
{(isCustomStrategy
|
||||||
|
? customStrategyItems
|
||||||
|
: strategyParameters
|
||||||
|
).map((item, index) => (
|
||||||
<ConstraintListItem key={index}>{item}</ConstraintListItem>
|
<ConstraintListItem key={index}>{item}</ConstraintListItem>
|
||||||
),
|
))}
|
||||||
)}
|
</ConstraintsList>
|
||||||
</ConstraintsList>
|
<RolloutVariants variants={strategy.variants} />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -30,7 +30,6 @@ export const useStrategyParameters = (
|
|||||||
parameters={parameters}
|
parameters={parameters}
|
||||||
hasConstraints={hasConstraints}
|
hasConstraints={hasConstraints}
|
||||||
displayGroupId={displayGroupId}
|
displayGroupId={displayGroupId}
|
||||||
variants={variants}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// deprecated; remove with `flagOverviewRedesign` flag
|
// deprecated; remove with `flagOverviewRedesign` flag
|
||||||
import { Box, styled } from '@mui/material';
|
import { Box, styled } from '@mui/material';
|
||||||
import { StrategyExecution } from '../../FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/StrategyExecution';
|
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 {
|
import {
|
||||||
formatStrategyName,
|
formatStrategyName,
|
||||||
getFeatureStrategyIcon,
|
getFeatureStrategyIcon,
|
||||||
@ -46,10 +46,10 @@ export const ReleasePlanMilestoneStrategy = ({
|
|||||||
strategy.variants.length > 0 &&
|
strategy.variants.length > 0 &&
|
||||||
(strategy.disabled ? (
|
(strategy.disabled ? (
|
||||||
<Box sx={{ opacity: '0.5' }}>
|
<Box sx={{ opacity: '0.5' }}>
|
||||||
<SplitPreviewSlider variants={strategy.variants} />
|
<VariantsSplitPreview variants={strategy.variants} />
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<SplitPreviewSlider variants={strategy.variants} />
|
<VariantsSplitPreview variants={strategy.variants} />
|
||||||
))}
|
))}
|
||||||
</StyledStrategy>
|
</StyledStrategy>
|
||||||
);
|
);
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import { VariantForm } from '../FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/VariantForm/VariantForm';
|
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 React from 'react';
|
||||||
import { type FC, useEffect, useState } from 'react';
|
import { type FC, useEffect, useState } from 'react';
|
||||||
import type { IFeatureVariantEdit } from '../FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/EnvironmentVariantsModal';
|
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 { UPDATE_FEATURE_ENVIRONMENT_VARIANTS } from '../../providers/AccessProvider/permissions';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { WeightType } from '../../../constants/variantTypes';
|
import { WeightType } from '../../../constants/variantTypes';
|
||||||
import { Box, styled, Typography, useTheme } from '@mui/material';
|
import { Box, styled, Typography, useTheme } from '@mui/material';
|
||||||
import type { IFeatureStrategy } from 'interfaces/strategy';
|
import type { IFeatureStrategy } from 'interfaces/strategy';
|
||||||
import SplitPreviewSlider from './SplitPreviewSlider/SplitPreviewSlider';
|
import { VariantsSplitPreview } from 'component/common/VariantsSplitPreview/VariantsSplitPreview';
|
||||||
import { HelpIcon } from '../../common/HelpIcon/HelpIcon';
|
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
|
||||||
import { StrategyVariantsUpgradeAlert } from '../../common/StrategyVariantsUpgradeAlert/StrategyVariantsUpgradeAlert';
|
import { StrategyVariantsUpgradeAlert } from 'component/common/StrategyVariantsUpgradeAlert/StrategyVariantsUpgradeAlert';
|
||||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||||
import Add from '@mui/icons-material/Add';
|
import Add from '@mui/icons-material/Add';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
@ -199,7 +199,7 @@ export const NewStrategyVariants: FC<{
|
|||||||
>
|
>
|
||||||
Add variant
|
Add variant
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
<SplitPreviewSlider
|
<VariantsSplitPreview
|
||||||
variants={variantsEdit}
|
variants={variantsEdit}
|
||||||
weightsError={variantWeightsError}
|
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 { 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 React from 'react';
|
||||||
import { type FC, useEffect, useState } from 'react';
|
import { type FC, useEffect, useState } from 'react';
|
||||||
import type { IFeatureVariantEdit } from '../FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/EnvironmentVariantsModal';
|
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 { UPDATE_FEATURE_ENVIRONMENT_VARIANTS } from '../../providers/AccessProvider/permissions';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { WeightType } from '../../../constants/variantTypes';
|
import { WeightType } from '../../../constants/variantTypes';
|
||||||
import { Link, styled, Typography, useTheme } from '@mui/material';
|
import { Link, styled, Typography, useTheme } from '@mui/material';
|
||||||
import type { IFeatureStrategy } from 'interfaces/strategy';
|
import type { IFeatureStrategy } from 'interfaces/strategy';
|
||||||
import SplitPreviewSlider from './SplitPreviewSlider/SplitPreviewSlider';
|
import { VariantsSplitPreview } from 'component/common/VariantsSplitPreview/VariantsSplitPreview';
|
||||||
import { HelpIcon } from '../../common/HelpIcon/HelpIcon';
|
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
|
||||||
import { StrategyVariantsUpgradeAlert } from '../../common/StrategyVariantsUpgradeAlert/StrategyVariantsUpgradeAlert';
|
import { StrategyVariantsUpgradeAlert } from 'component/common/StrategyVariantsUpgradeAlert/StrategyVariantsUpgradeAlert';
|
||||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||||
|
|
||||||
const StyledVariantForms = styled('div')({
|
const StyledVariantForms = styled('div')({
|
||||||
@ -168,7 +168,7 @@ export const StrategyVariants: FC<{
|
|||||||
>
|
>
|
||||||
Add variant
|
Add variant
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
<SplitPreviewSlider variants={variantsEdit} />
|
<VariantsSplitPreview variants={variantsEdit} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,7 @@ import type {
|
|||||||
} from 'openapi';
|
} from 'openapi';
|
||||||
import { objectId } from 'utils/objectId';
|
import { objectId } from 'utils/objectId';
|
||||||
import { StrategyItemContainer } from 'component/common/StrategyItemContainer/StrategyItemContainer';
|
import { StrategyItemContainer } from 'component/common/StrategyItemContainer/StrategyItemContainer';
|
||||||
import { StrategyExecution } from './StrategyExecution/StrategyExecution';
|
import { PlaygroundStrategyExecution } from './PlaygroundStrategyExecution/PlaygroundStrategyExecution';
|
||||||
|
|
||||||
interface IFeatureStrategyItemProps {
|
interface IFeatureStrategyItemProps {
|
||||||
strategy: PlaygroundStrategySchema;
|
strategy: PlaygroundStrategySchema;
|
||||||
@ -42,7 +42,10 @@ export const FeatureStrategyItem = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<StrategyExecution strategyResult={strategy} input={input} />
|
<PlaygroundStrategyExecution
|
||||||
|
strategyResult={strategy}
|
||||||
|
input={input}
|
||||||
|
/>
|
||||||
</StrategyItemContainer>
|
</StrategyItemContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -4,10 +4,10 @@ import type {
|
|||||||
PlaygroundStrategySchema,
|
PlaygroundStrategySchema,
|
||||||
PlaygroundRequestSchema,
|
PlaygroundRequestSchema,
|
||||||
} from 'openapi';
|
} from 'openapi';
|
||||||
import { StrategyExecution } from './StrategyExecution/LegacyStrategyExecution';
|
import { StrategyExecution } from './PlaygroundStrategyExecution/LegacyStrategyExecution';
|
||||||
import { objectId } from 'utils/objectId';
|
import { objectId } from 'utils/objectId';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { DisabledStrategyExecution } from './StrategyExecution/DisabledStrategyExecution';
|
import { DisabledStrategyExecution } from './PlaygroundStrategyExecution/DisabledStrategyExecution';
|
||||||
import { StrategyItemContainer } from 'component/common/StrategyItemContainer/LegacyStrategyItemContainer';
|
import { StrategyItemContainer } from 'component/common/StrategyItemContainer/LegacyStrategyItemContainer';
|
||||||
|
|
||||||
interface IFeatureStrategyItemProps {
|
interface IFeatureStrategyItemProps {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import type {
|
import type {
|
||||||
|
PlaygroundFeatureSchemaVariant,
|
||||||
PlaygroundRequestSchema,
|
PlaygroundRequestSchema,
|
||||||
PlaygroundStrategySchema,
|
PlaygroundStrategySchema,
|
||||||
|
StrategyVariantSchema,
|
||||||
} from 'openapi';
|
} from 'openapi';
|
||||||
import { ConstraintExecution } from './ConstraintExecution/ConstraintExecution';
|
import { ConstraintExecution } from './ConstraintExecution/ConstraintExecution';
|
||||||
import { formattedStrategyNames } from 'utils/strategyNames';
|
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 { useStrategyParameters } from 'component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/hooks/useStrategyParameters';
|
||||||
import { useStrategies } from 'hooks/api/getters/useStrategies/useStrategies';
|
import { useStrategies } from 'hooks/api/getters/useStrategies/useStrategies';
|
||||||
import { useCustomStrategyParameters } from 'component/feature/FeatureView/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/EnvironmentAccordionBody/StrategyDraggableItem/StrategyItem/StrategyExecution/hooks/useCustomStrategyParameters';
|
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 = {
|
type StrategyExecutionProps = {
|
||||||
strategyResult: PlaygroundStrategySchema;
|
strategyResult: PlaygroundStrategySchema;
|
||||||
@ -23,7 +26,7 @@ type StrategyExecutionProps = {
|
|||||||
input?: PlaygroundRequestSchema;
|
input?: PlaygroundRequestSchema;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const StrategyExecution: FC<StrategyExecutionProps> = ({
|
export const PlaygroundStrategyExecution: FC<StrategyExecutionProps> = ({
|
||||||
strategyResult,
|
strategyResult,
|
||||||
input,
|
input,
|
||||||
}) => {
|
}) => {
|
||||||
@ -79,5 +82,17 @@ export const StrategyExecution: FC<StrategyExecutionProps> = ({
|
|||||||
),
|
),
|
||||||
].filter(Boolean);
|
].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,
|
PROJECT_DEFAULT_STRATEGY_WRITE,
|
||||||
UPDATE_PROJECT,
|
UPDATE_PROJECT,
|
||||||
} from '@server/types/permissions';
|
} 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';
|
import { StrategyItemContainer } from 'component/common/StrategyItemContainer/LegacyStrategyItemContainer';
|
||||||
|
|
||||||
interface ProjectEnvironmentDefaultStrategyProps {
|
interface ProjectEnvironmentDefaultStrategyProps {
|
||||||
@ -84,7 +84,7 @@ const ProjectEnvironmentDefaultStrategy = ({
|
|||||||
<StrategyExecution strategy={strategy} />
|
<StrategyExecution strategy={strategy} />
|
||||||
|
|
||||||
{strategy.variants && strategy.variants.length > 0 ? (
|
{strategy.variants && strategy.variants.length > 0 ? (
|
||||||
<SplitPreviewSlider variants={strategy.variants} />
|
<VariantsSplitPreview variants={strategy.variants} />
|
||||||
) : null}
|
) : null}
|
||||||
</StrategyItemContainer>
|
</StrategyItemContainer>
|
||||||
</>
|
</>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Box, IconButton, styled } from '@mui/material';
|
import { Box, IconButton, styled } from '@mui/material';
|
||||||
import SplitPreviewSlider from 'component/feature/StrategyTypes/SplitPreviewSlider/SplitPreviewSlider';
|
import { VariantsSplitPreview } from 'component/common/VariantsSplitPreview/VariantsSplitPreview';
|
||||||
import {
|
import {
|
||||||
formatStrategyName,
|
formatStrategyName,
|
||||||
getFeatureStrategyIcon,
|
getFeatureStrategyIcon,
|
||||||
@ -88,10 +88,12 @@ export const MilestoneStrategyItem = ({
|
|||||||
strategy.variants.length > 0 &&
|
strategy.variants.length > 0 &&
|
||||||
(strategy.disabled ? (
|
(strategy.disabled ? (
|
||||||
<Box sx={{ opacity: '0.5' }}>
|
<Box sx={{ opacity: '0.5' }}>
|
||||||
<SplitPreviewSlider variants={strategy.variants} />
|
<VariantsSplitPreview
|
||||||
|
variants={strategy.variants}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<SplitPreviewSlider variants={strategy.variants} />
|
<VariantsSplitPreview variants={strategy.variants} />
|
||||||
))}
|
))}
|
||||||
</StyledStrategyExecution>
|
</StyledStrategyExecution>
|
||||||
</StyledStrategy>
|
</StyledStrategy>
|
||||||
|
@ -10,7 +10,7 @@ import { updateWeightEdit } from 'component/common/util';
|
|||||||
import { WeightType } from 'constants/variantTypes';
|
import { WeightType } from 'constants/variantTypes';
|
||||||
import { useTheme } from '@mui/material';
|
import { useTheme } from '@mui/material';
|
||||||
import Add from '@mui/icons-material/Add';
|
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')({
|
const StyledVariantForms = styled('div')({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -180,7 +180,7 @@ export const MilestoneStrategyVariants = ({
|
|||||||
<Button onClick={addVariant} variant='outlined' startIcon={<Add />}>
|
<Button onClick={addVariant} variant='outlined' startIcon={<Add />}>
|
||||||
Add variant
|
Add variant
|
||||||
</Button>
|
</Button>
|
||||||
<SplitPreviewSlider
|
<VariantsSplitPreview
|
||||||
variants={variantsEdit}
|
variants={variantsEdit}
|
||||||
weightsError={variantWeightsError}
|
weightsError={variantWeightsError}
|
||||||
/>
|
/>
|
||||||
|
Loading…
Reference in New Issue
Block a user