1
0
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:
Tymoteusz Czech 2022-08-05 12:03:49 +02:00
parent e75f03b8f2
commit 85858cf11f
5 changed files with 125 additions and 88 deletions

View File

@ -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>
);
};

View File

@ -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>
); );
}; };

View File

@ -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 = () => (

View File

@ -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>
); );
}; };