mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-04 00:18:01 +01:00
refactor strategy item component for reuse
Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com>
This commit is contained in:
parent
e75f03b8f2
commit
85858cf11f
@ -0,0 +1,95 @@
|
|||||||
|
import { DragEventHandler, FC, ReactNode } from 'react';
|
||||||
|
import { DragIndicator } from '@mui/icons-material';
|
||||||
|
import { styled, IconButton, Box } from '@mui/material';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { IFeatureStrategy } from 'interfaces/strategy';
|
||||||
|
import {
|
||||||
|
getFeatureStrategyIcon,
|
||||||
|
formatStrategyName,
|
||||||
|
} from 'utils/strategyNames';
|
||||||
|
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { useStyles } from './StrategyItemContainer.styles';
|
||||||
|
|
||||||
|
interface IStrategyItemContainerProps {
|
||||||
|
strategy: IFeatureStrategy;
|
||||||
|
onDragStart?: DragEventHandler<HTMLButtonElement>;
|
||||||
|
onDragEnd?: DragEventHandler<HTMLButtonElement>;
|
||||||
|
actions?: ReactNode;
|
||||||
|
orderNumber?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DragIcon = styled(IconButton)(({ theme }) => ({
|
||||||
|
padding: 0,
|
||||||
|
cursor: 'inherit',
|
||||||
|
transition: 'color 0.2s ease-in-out',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledIndexLabel = styled('div')(({ theme }) => ({
|
||||||
|
fontSize: theme.typography.fontSize,
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
position: 'absolute',
|
||||||
|
display: 'none',
|
||||||
|
right: 'calc(100% + 6px)',
|
||||||
|
top: theme.spacing(2.5),
|
||||||
|
[theme.breakpoints.up('md')]: {
|
||||||
|
display: 'block',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const StrategyItemContainer: FC<IStrategyItemContainerProps> = ({
|
||||||
|
strategy,
|
||||||
|
onDragStart,
|
||||||
|
onDragEnd,
|
||||||
|
actions,
|
||||||
|
children,
|
||||||
|
orderNumber,
|
||||||
|
}) => {
|
||||||
|
const { classes: styles } = useStyles();
|
||||||
|
const Icon = getFeatureStrategyIcon(strategy.name);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ position: 'relative' }}>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={orderNumber !== undefined}
|
||||||
|
show={<StyledIndexLabel>{orderNumber}</StyledIndexLabel>}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div
|
||||||
|
className={classNames(styles.header, {
|
||||||
|
[styles.headerDraggable]: Boolean(onDragStart),
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={Boolean(onDragStart)}
|
||||||
|
show={() => (
|
||||||
|
<DragIcon
|
||||||
|
draggable
|
||||||
|
disableRipple
|
||||||
|
size="small"
|
||||||
|
onDragStart={onDragStart}
|
||||||
|
onDragEnd={onDragEnd}
|
||||||
|
sx={{ cursor: 'move' }}
|
||||||
|
>
|
||||||
|
<DragIndicator
|
||||||
|
titleAccess="Drag to reorder"
|
||||||
|
cursor="grab"
|
||||||
|
sx={{ color: 'neutral.main' }}
|
||||||
|
/>
|
||||||
|
</DragIcon>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Icon className={styles.icon} />
|
||||||
|
<StringTruncator
|
||||||
|
maxWidth="150"
|
||||||
|
maxLength={15}
|
||||||
|
text={formatStrategyName(strategy.name)}
|
||||||
|
/>
|
||||||
|
<div className={styles.actions}>{actions}</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.body}>{children}</div>
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
@ -1,9 +1,9 @@
|
|||||||
import { Box, styled } from '@mui/material';
|
import { DragEventHandler, RefObject, useRef } from 'react';
|
||||||
|
import { Box } from '@mui/material';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
|
import { StrategySeparator } from 'component/common/StrategySeparator/StrategySeparator';
|
||||||
import { IFeatureEnvironment } from 'interfaces/featureToggle';
|
import { IFeatureEnvironment } from 'interfaces/featureToggle';
|
||||||
import { IFeatureStrategy } from 'interfaces/strategy';
|
import { IFeatureStrategy } from 'interfaces/strategy';
|
||||||
import { DragEventHandler, RefObject, useRef } from 'react';
|
|
||||||
import { StrategyItem } from './StrategyItem/StrategyItem';
|
import { StrategyItem } from './StrategyItem/StrategyItem';
|
||||||
|
|
||||||
interface IStrategyDraggableItemProps {
|
interface IStrategyDraggableItemProps {
|
||||||
@ -22,19 +22,6 @@ interface IStrategyDraggableItemProps {
|
|||||||
) => DragEventHandler<HTMLDivElement>;
|
) => DragEventHandler<HTMLDivElement>;
|
||||||
onDragEnd: () => void;
|
onDragEnd: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyledIndexLabel = styled('div')(({ theme }) => ({
|
|
||||||
fontSize: theme.typography.fontSize,
|
|
||||||
color: theme.palette.text.secondary,
|
|
||||||
position: 'absolute',
|
|
||||||
display: 'none',
|
|
||||||
right: 'calc(100% + 6px)',
|
|
||||||
top: theme.spacing(2.5),
|
|
||||||
[theme.breakpoints.up('md')]: {
|
|
||||||
display: 'block',
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const StrategyDraggableItem = ({
|
export const StrategyDraggableItem = ({
|
||||||
strategy,
|
strategy,
|
||||||
index,
|
index,
|
||||||
@ -58,16 +45,15 @@ export const StrategyDraggableItem = ({
|
|||||||
condition={index > 0}
|
condition={index > 0}
|
||||||
show={<StrategySeparator text="OR" />}
|
show={<StrategySeparator text="OR" />}
|
||||||
/>
|
/>
|
||||||
<Box sx={{ position: 'relative' }}>
|
|
||||||
<StyledIndexLabel>{index + 1}</StyledIndexLabel>
|
|
||||||
<StrategyItem
|
<StrategyItem
|
||||||
strategy={strategy}
|
strategy={strategy}
|
||||||
environmentId={environmentName}
|
environmentId={environmentName}
|
||||||
otherEnvironments={otherEnvironments}
|
otherEnvironments={otherEnvironments}
|
||||||
onDragStart={onDragStartRef(ref, index)}
|
onDragStart={onDragStartRef(ref, index)}
|
||||||
onDragEnd={onDragEnd}
|
onDragEnd={onDragEnd}
|
||||||
|
orderNumber={index + 1}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -20,7 +20,6 @@ import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
|||||||
|
|
||||||
interface IStrategyExecutionProps {
|
interface IStrategyExecutionProps {
|
||||||
strategy: IFeatureStrategy;
|
strategy: IFeatureStrategy;
|
||||||
percentageFill?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const NoItems: VFC = () => (
|
const NoItems: VFC = () => (
|
||||||
|
@ -1,24 +1,17 @@
|
|||||||
import { DragEventHandler } from 'react';
|
import { DragEventHandler, VFC } from 'react';
|
||||||
import { DragIndicator, Edit } from '@mui/icons-material';
|
import { Edit } from '@mui/icons-material';
|
||||||
import { styled, useTheme, IconButton } from '@mui/material';
|
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import classNames from 'classnames';
|
|
||||||
import { IFeatureEnvironment } from 'interfaces/featureToggle';
|
import { IFeatureEnvironment } from 'interfaces/featureToggle';
|
||||||
import { IFeatureStrategy } from 'interfaces/strategy';
|
import { IFeatureStrategy } from 'interfaces/strategy';
|
||||||
import {
|
|
||||||
getFeatureStrategyIcon,
|
|
||||||
formatStrategyName,
|
|
||||||
} from 'utils/strategyNames';
|
|
||||||
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
||||||
import { UPDATE_FEATURE_STRATEGY } from 'component/providers/AccessProvider/permissions';
|
import { UPDATE_FEATURE_STRATEGY } from 'component/providers/AccessProvider/permissions';
|
||||||
import { formatEditStrategyPath } from 'component/feature/FeatureStrategy/FeatureStrategyEdit/FeatureStrategyEdit';
|
import { formatEditStrategyPath } from 'component/feature/FeatureStrategy/FeatureStrategyEdit/FeatureStrategyEdit';
|
||||||
import { FeatureStrategyRemove } from 'component/feature/FeatureStrategy/FeatureStrategyRemove/FeatureStrategyRemove';
|
import { FeatureStrategyRemove } from 'component/feature/FeatureStrategy/FeatureStrategyRemove/FeatureStrategyRemove';
|
||||||
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
import { StrategyExecution } from './StrategyExecution/StrategyExecution';
|
import { StrategyExecution } from './StrategyExecution/StrategyExecution';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { CopyStrategyIconMenu } from './CopyStrategyIconMenu/CopyStrategyIconMenu';
|
import { CopyStrategyIconMenu } from './CopyStrategyIconMenu/CopyStrategyIconMenu';
|
||||||
import { useStyles } from './StrategyItem.styles';
|
import { StrategyItemContainer } from 'component/common/StrategyItemContainer/StrategyItemContainer';
|
||||||
|
|
||||||
interface IStrategyItemProps {
|
interface IStrategyItemProps {
|
||||||
environmentId: string;
|
environmentId: string;
|
||||||
@ -26,26 +19,19 @@ interface IStrategyItemProps {
|
|||||||
onDragStart?: DragEventHandler<HTMLButtonElement>;
|
onDragStart?: DragEventHandler<HTMLButtonElement>;
|
||||||
onDragEnd?: DragEventHandler<HTMLButtonElement>;
|
onDragEnd?: DragEventHandler<HTMLButtonElement>;
|
||||||
otherEnvironments?: IFeatureEnvironment['name'][];
|
otherEnvironments?: IFeatureEnvironment['name'][];
|
||||||
|
orderNumber?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DragIcon = styled(IconButton)(({ theme }) => ({
|
export const StrategyItem: VFC<IStrategyItemProps> = ({
|
||||||
padding: 0,
|
|
||||||
cursor: 'inherit',
|
|
||||||
transition: 'color 0.2s ease-in-out',
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const StrategyItem = ({
|
|
||||||
environmentId,
|
environmentId,
|
||||||
strategy,
|
strategy,
|
||||||
onDragStart,
|
onDragStart,
|
||||||
onDragEnd,
|
onDragEnd,
|
||||||
otherEnvironments,
|
otherEnvironments,
|
||||||
}: IStrategyItemProps) => {
|
orderNumber,
|
||||||
|
}) => {
|
||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
const featureId = useRequiredPathParam('featureId');
|
const featureId = useRequiredPathParam('featureId');
|
||||||
const theme = useTheme();
|
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
const Icon = getFeatureStrategyIcon(strategy.name);
|
|
||||||
|
|
||||||
const editStrategyPath = formatEditStrategyPath(
|
const editStrategyPath = formatEditStrategyPath(
|
||||||
projectId,
|
projectId,
|
||||||
@ -55,38 +41,13 @@ export const StrategyItem = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<StrategyItemContainer
|
||||||
<div
|
strategy={strategy}
|
||||||
className={classNames(styles.header, {
|
|
||||||
[styles.headerDraggable]: Boolean(onDragStart),
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={Boolean(onDragStart)}
|
|
||||||
show={() => (
|
|
||||||
<DragIcon
|
|
||||||
draggable
|
|
||||||
disableRipple
|
|
||||||
size="small"
|
|
||||||
onDragStart={onDragStart}
|
onDragStart={onDragStart}
|
||||||
onDragEnd={onDragEnd}
|
onDragEnd={onDragEnd}
|
||||||
sx={{ cursor: 'move' }}
|
orderNumber={orderNumber}
|
||||||
>
|
actions={
|
||||||
<DragIndicator
|
<>
|
||||||
titleAccess="Drag to reorder"
|
|
||||||
cursor="grab"
|
|
||||||
sx={{ color: 'neutral.main' }}
|
|
||||||
/>
|
|
||||||
</DragIcon>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Icon className={styles.icon} />
|
|
||||||
<StringTruncator
|
|
||||||
maxWidth="150"
|
|
||||||
maxLength={15}
|
|
||||||
text={formatStrategyName(strategy.name)}
|
|
||||||
/>
|
|
||||||
<div className={styles.actions}>
|
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(
|
condition={Boolean(
|
||||||
otherEnvironments && otherEnvironments?.length > 0
|
otherEnvironments && otherEnvironments?.length > 0
|
||||||
@ -115,14 +76,10 @@ export const StrategyItem = ({
|
|||||||
strategyId={strategy.id}
|
strategyId={strategy.id}
|
||||||
icon
|
icon
|
||||||
/>
|
/>
|
||||||
</div>
|
</>
|
||||||
</div>
|
}
|
||||||
<div className={styles.body}>
|
>
|
||||||
<StrategyExecution
|
<StrategyExecution strategy={strategy} />
|
||||||
strategy={strategy}
|
</StrategyItemContainer>
|
||||||
percentageFill={theme.palette.grey[200]}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user