1
0
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:
Thomas Heartman 2025-10-23 10:42:08 +02:00 committed by GitHub
parent feed9ea3c9
commit 527d94d0fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 58 additions and 40 deletions

View File

@ -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:

View File

@ -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',

View File

@ -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'}

View File

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

View File

@ -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