mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	chore: never wrap other text fields in global change requests table (#10841)
Prevents text wraps in the wrapping columns of the table: - Title - environment - status Also prevents the change request badge cells (change request badges in tables, such as the project CR table) from wrapping. Before: <img width="1054" height="302" alt="image" src="https://github.com/user-attachments/assets/a4f30661-c680-47ef-82f0-49c01293712b" /> <details> <summary>In extreme cases</summary> <img width="3024" height="20820" alt="image" src="https://github.com/user-attachments/assets/05a7c636-cabe-4e4e-9a9d-5e8a60d380ca" /> </details> After: <img width="1071" height="501" alt="image" src="https://github.com/user-attachments/assets/64990be7-d338-4878-8fd2-678e1bf6c341" /> and when it's wide enough to not horizontally scroll: <img width="1136" height="493" alt="image" src="https://github.com/user-attachments/assets/9757c019-0848-4abd-ae51-10679b0e58f4" /> ## Note: bug introduced (but fix is coming) This does introduce a rendering bug in Chrome, however, where the columns will take up all the width that they can without being truncated: <img width="1545" height="395" alt="image" src="https://github.com/user-attachments/assets/b247c37a-277c-48f4-a64a-29c95b6d6dd4" /> This does not happen in Firefox. However, it can be fixed by specifying a max width for the columns. I'll fix this in the next PR.
This commit is contained in:
		
							parent
							
								
									feed9ea3c9
								
							
						
					
					
						commit
						527d94d0fc
					
				| @ -1,5 +1,5 @@ | ||||
| import type { FC } from 'react'; | ||||
| import { Badge } from 'component/common/Badge/Badge'; | ||||
| import { Badge as MuiBadge } from 'component/common/Badge/Badge'; | ||||
| import AccessTime from '@mui/icons-material/AccessTime'; | ||||
| import Check from '@mui/icons-material/Check'; | ||||
| import CircleOutlined from '@mui/icons-material/CircleOutlined'; | ||||
| @ -12,6 +12,11 @@ import type { | ||||
|     ScheduledChangeRequest, | ||||
|     UnscheduledChangeRequest, | ||||
| } from '../changeRequest.types'; | ||||
| import { styled } from '@mui/material'; | ||||
| 
 | ||||
| const Badge = styled(MuiBadge)({ | ||||
|     whiteSpace: 'nowrap', | ||||
| }); | ||||
| 
 | ||||
| export interface IChangeRequestStatusBadgeProps { | ||||
|     changeRequest: | ||||
|  | ||||
| @ -39,6 +39,10 @@ const columnHelper = createColumnHelper<ChangeRequestSearchItemSchema>(); | ||||
| const StyledPaginatedTable = styled( | ||||
|     PaginatedTable<ChangeRequestSearchItemSchema>, | ||||
| )(() => ({ | ||||
|     th: { | ||||
|         whiteSpace: 'nowrap', | ||||
|     }, | ||||
| 
 | ||||
|     td: { | ||||
|         verticalAlign: 'top', | ||||
|     }, | ||||
| @ -98,16 +102,11 @@ const ChangeRequestsInner = () => { | ||||
| 
 | ||||
|     const columns = useMemo( | ||||
|         () => [ | ||||
|             columnHelper.accessor('title', { | ||||
|             columnHelper.accessor('id', { | ||||
|                 id: 'Title', | ||||
|                 header: 'Title', | ||||
|                 meta: { width: '300px' }, | ||||
|                 cell: ({ getValue, row }) => ( | ||||
|                     <GlobalChangeRequestTitleCell | ||||
|                         value={getValue()} | ||||
|                         row={row} | ||||
|                     /> | ||||
|                 ), | ||||
|                 cell: GlobalChangeRequestTitleCell, | ||||
|             }), | ||||
|             columnHelper.accessor('features', { | ||||
|                 id: 'Updated feature flags', | ||||
| @ -149,7 +148,9 @@ const ChangeRequestsInner = () => { | ||||
|                 id: 'Environment', | ||||
|                 header: 'Environment', | ||||
|                 meta: { width: '100px' }, | ||||
|                 cell: ({ getValue }) => <HighlightCell value={getValue()} />, | ||||
|                 cell: ({ getValue }) => ( | ||||
|                     <HighlightCell maxTitleLines={1} value={getValue()} /> | ||||
|                 ), | ||||
|             }), | ||||
|             columnHelper.accessor('state', { | ||||
|                 id: 'Status', | ||||
|  | ||||
| @ -2,27 +2,28 @@ import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; | ||||
| import { Link, styled, Typography } from '@mui/material'; | ||||
| import { Link as RouterLink, type LinkProps } from 'react-router-dom'; | ||||
| import { useProjectOverviewNameOrId } from 'hooks/api/getters/useProjectOverview/useProjectOverview'; | ||||
| 
 | ||||
| type IGlobalChangeRequestTitleCellProps = { | ||||
|     value?: any; | ||||
|     row: { original: any }; | ||||
| }; | ||||
| import { Truncator } from 'component/common/Truncator/Truncator'; | ||||
| import type { ChangeRequestSearchItemSchema } from 'openapi'; | ||||
| import type { Row } from '@tanstack/react-table'; | ||||
| 
 | ||||
| const LinkContainer = styled('div')(({ theme }) => ({ | ||||
|     color: theme.palette.text.secondary, | ||||
|     display: 'flex', | ||||
|     columnGap: theme.spacing(0.5), | ||||
| })); | ||||
| 
 | ||||
| const BaseLink = styled(({ children, ...props }: LinkProps) => ( | ||||
|     <Link component={RouterLink} {...props}> | ||||
|         {children} | ||||
|     </Link> | ||||
| ))(({ theme }) => ({ | ||||
| ))({ | ||||
|     whiteSpace: 'nowrap', | ||||
|     textDecoration: 'none', | ||||
|     color: 'inherit', | ||||
|     ':hover': { | ||||
|         textDecoration: 'underline', | ||||
|     }, | ||||
| })); | ||||
| }); | ||||
| 
 | ||||
| const ChangeRequestLink = styled(BaseLink)(({ theme }) => ({ | ||||
|     color: theme.palette.primary.main, | ||||
| @ -34,33 +35,43 @@ const UpdateText = styled(Typography)(({ theme }) => ({ | ||||
|     fontSize: theme.typography.body2.fontSize, | ||||
| })); | ||||
| 
 | ||||
| type GlobalChangeRequestTitleCellProps = { | ||||
|     row: Row<ChangeRequestSearchItemSchema>; | ||||
| }; | ||||
| 
 | ||||
| export const GlobalChangeRequestTitleCell = ({ | ||||
|     value, | ||||
|     row: { original }, | ||||
| }: IGlobalChangeRequestTitleCellProps) => { | ||||
|     const { | ||||
|         id, | ||||
|         title, | ||||
|         project, | ||||
|         features: featureChanges, | ||||
|         segments: segmentChanges, | ||||
|     } = original; | ||||
|     row: { | ||||
|         original: { | ||||
|             id, | ||||
|             title, | ||||
|             project, | ||||
|             features: featureChanges, | ||||
|             segments: segmentChanges, | ||||
|         }, | ||||
|     }, | ||||
| }: GlobalChangeRequestTitleCellProps) => { | ||||
|     const projectName = useProjectOverviewNameOrId(project); | ||||
|     const totalChanges = | ||||
|         featureChanges?.length ?? 0 + segmentChanges?.length ?? 0; | ||||
|     const projectPath = `/projects/${project}`; | ||||
|     const crPath = `${projectPath}/change-requests/${id}`; | ||||
| 
 | ||||
|     if (!value) { | ||||
|         return <TextCell />; | ||||
|     } | ||||
| 
 | ||||
|     return ( | ||||
|         <TextCell sx={{ minWidth: '300px' }}> | ||||
|             <LinkContainer> | ||||
|                 <BaseLink to={projectPath}>{projectName}</BaseLink> | ||||
|                 <span aria-hidden='true'> / </span> | ||||
|                 <ChangeRequestLink to={crPath}>{title}</ChangeRequestLink> | ||||
|                 <Truncator title={projectName}> | ||||
|                     <BaseLink to={projectPath}>{projectName}</BaseLink> | ||||
|                 </Truncator> | ||||
|                 <span aria-hidden='true'>/</span> | ||||
|                 {title ? ( | ||||
|                     <Truncator title={title}> | ||||
|                         <ChangeRequestLink to={crPath}> | ||||
|                             {title} | ||||
|                         </ChangeRequestLink> | ||||
|                     </Truncator> | ||||
|                 ) : ( | ||||
|                     <ChangeRequestLink to={crPath}>#{id}</ChangeRequestLink> | ||||
|                 )} | ||||
|             </LinkContainer> | ||||
|             <UpdateText> | ||||
|                 {`${totalChanges}`} {totalChanges === 1 ? `update` : 'updates'} | ||||
|  | ||||
| @ -16,14 +16,13 @@ export const ChangeRequestStatusCell: FC<IChangeRequestStatusCellProps> = ({ | ||||
|     value, | ||||
|     row: { original }, | ||||
| }) => { | ||||
|     const renderState = () => { | ||||
|         if (!value) return null; | ||||
|         return <ChangeRequestStatusBadge changeRequest={original} />; | ||||
|     }; | ||||
| 
 | ||||
|     if (!value) { | ||||
|         return <TextCell />; | ||||
|     } | ||||
| 
 | ||||
|     return <TextCell>{renderState()}</TextCell>; | ||||
|     return ( | ||||
|         <TextCell> | ||||
|             <ChangeRequestStatusBadge changeRequest={original} /> | ||||
|         </TextCell> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| @ -12,6 +12,7 @@ interface IHighlightCellProps { | ||||
|     subtitle?: string; | ||||
|     afterTitle?: React.ReactNode; | ||||
|     subtitleTooltip?: boolean; | ||||
|     maxTitleLines?: number; | ||||
| } | ||||
| 
 | ||||
| const StyledContainer = styled(Box)(({ theme }) => ({ | ||||
| @ -40,6 +41,7 @@ export const HighlightCell: FC<IHighlightCellProps> = ({ | ||||
|     subtitle, | ||||
|     afterTitle, | ||||
|     subtitleTooltip, | ||||
|     maxTitleLines, | ||||
| }) => { | ||||
|     const { searchQuery } = useSearchHighlightContext(); | ||||
| 
 | ||||
| @ -68,7 +70,7 @@ export const HighlightCell: FC<IHighlightCellProps> = ({ | ||||
|     return ( | ||||
|         <StyledContainer> | ||||
|             <Truncator | ||||
|                 lines={subtitle ? 1 : 2} | ||||
|                 lines={maxTitleLines ?? (subtitle ? 1 : 2)} | ||||
|                 title={value} | ||||
|                 arrow | ||||
|                 data-loading | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user