mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +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