Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better handling of long names in the tables & breadcrumbs #1124

Merged
merged 4 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 59 additions & 46 deletions frontend/src/components/layout/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,62 +14,75 @@ import { observer } from 'mobx-react';
import { Link, useRouteMatch } from 'react-router-dom';
import { isEmbedded } from '../../config';
import { uiState } from '../../state/uiState';
import { MotionDiv } from '../../utils/animationProps';
import { ZeroSizeWrapper } from '../../utils/tsxUtils';
import { UserPreferencesButton } from '../misc/UserPreferences';
import DataRefreshButton from '../misc/buttons/data-refresh/Component';
import { IsDev } from '../../utils/env';
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbLinkProps, ColorModeSwitch, Flex } from '@redpanda-data/ui';
import { Box, Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbLinkProps, CopyButton, ColorModeSwitch, Flex } from '@redpanda-data/ui';

const AppPageHeader = observer(() => {
const showRefresh = useShouldShowRefresh();

return <MotionDiv identityKey={uiState.pageTitle} className="pageTitle" style={{ display: 'flex', paddingRight: '16px', alignItems: 'center', marginBottom: '10px' }}>
<Breadcrumb spacing="8px" separator={<ChevronRightIcon/>}>
{!isEmbedded() && uiState.selectedClusterName &&
<BreadcrumbItem>
<BreadcrumbLink as={Link} to="/">
Cluster
</BreadcrumbLink>
</BreadcrumbItem>
}
{uiState.pageBreadcrumbs.filter((_,i,arr) => {
const isCurrentPage = arr.length - 1 === i
return !isEmbedded() || isCurrentPage
}).map((entry, i, arr) => {
const isCurrentPage = arr.length - 1 === i;
const currentBreadcrumbProps: BreadcrumbLinkProps = isCurrentPage ? {
as: 'span',
fontWeight: 700,
fontSize: 'xl',
} : {};

return (
<BreadcrumbItem key={entry.linkTo} isCurrentPage={isCurrentPage}>
<BreadcrumbLink
to={entry.linkTo}
as={isCurrentPage ? 'span': Link}
{...currentBreadcrumbProps}
>
{entry.title}
</BreadcrumbLink>

{isCurrentPage && showRefresh && (
<ZeroSizeWrapper justifyContent="start">
<DataRefreshButton/>
</ZeroSizeWrapper>
)}
</BreadcrumbItem>
);
return <Box> {/* we need to refactor out #mainLayout > div rule, for now I've added this box as a workaround */}
<Flex mb={5} alignItems="center" justifyContent="space-between">
<Breadcrumb spacing="8px" separator={<ChevronRightIcon/>}>
{!isEmbedded() && uiState.selectedClusterName &&
<BreadcrumbItem>
<BreadcrumbLink as={Link} to="/">
Cluster
</BreadcrumbLink>
</BreadcrumbItem>
}
)}
</Breadcrumb>
{uiState.pageBreadcrumbs.filter((_, i, arr) => {
const isCurrentPage = arr.length - 1 === i;
return !isEmbedded() || isCurrentPage;
}).map((entry, i, arr) => {
const isCurrentPage = arr.length - 1 === i;
const currentBreadcrumbProps: BreadcrumbLinkProps = isCurrentPage ? {
as: 'span',
fontWeight: 700,
fontSize: 'xl',
} : {
};

return (
<BreadcrumbItem key={entry.linkTo} isCurrentPage={isCurrentPage}>
<BreadcrumbLink
to={entry.linkTo}
as={isCurrentPage ? 'span' : Link}
noOfLines={1}
{...currentBreadcrumbProps}
{...(entry.options?.canBeTruncated ? {
wordBreak: 'break-all',
whiteSpace: 'break-spaces',
} : {
whiteSpace: 'nowrap'
})}
>
{entry.title}
</BreadcrumbLink>

<Flex ml={2}>
{isCurrentPage && entry.options?.canBeCopied && <CopyButton content={entry.title} variant="ghost"/>}

{isCurrentPage && showRefresh && (
<Box minW={250}>
<DataRefreshButton/>
</Box>
)}
</Flex>

</BreadcrumbItem>
);
}
)}
</Breadcrumb>

<Flex ml="auto" alignItems="center" gap={3}>
<UserPreferencesButton />
{(IsDev && !isEmbedded()) && <ColorModeSwitch />}
<Flex alignItems="center" gap={1}>
<UserPreferencesButton/>
{(IsDev && !isEmbedded()) && <ColorModeSwitch/>}
</Flex>
</Flex>
</MotionDiv>;
</Box>;
});

export default AppPageHeader;
Expand Down
1 change: 0 additions & 1 deletion frontend/src/components/misc/buttons/buttons.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
.dataRefreshButton {
height: 32px;
display: inline-flex;
margin-left: 10px;

background: $color-reload-spinner-bg;
color: $color-reload-spinner;
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/pages/Page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

import { makeAutoObservable } from 'mobx';
import React from 'react';
import { uiState } from '../../state/uiState';
import { BreadcrumbOptions, uiState } from '../../state/uiState';


//
Expand All @@ -24,7 +24,7 @@ export class PageInitHelper {
makeAutoObservable(this);
}
set title(title: string) { uiState.pageTitle = title; }
addBreadcrumb(title: string, to: string) { uiState.pageBreadcrumbs.push({ title: title, linkTo: to }) }
addBreadcrumb(title: string, to: string, options?: BreadcrumbOptions) { uiState.pageBreadcrumbs.push({ title: title, linkTo: to, options }) }
}
export abstract class PageComponent<TRouteParams = Record<string, unknown>> extends React.Component<PageProps<TRouteParams>> {

Expand Down
16 changes: 9 additions & 7 deletions frontend/src/components/pages/acls/Acl.List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { AclPrincipalGroupEditor } from './PrincipalGroupEditor';
import Section from '../../misc/Section';
import PageContent from '../../misc/PageContent';
import { Features } from '../../../state/supportedFeatures';
import { Alert, AlertDialog, AlertDialogBody, AlertDialogContent, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertIcon, Badge, Button, createStandaloneToast, Icon, redpandaToastOptions, SearchField, Tooltip, Text, redpandaTheme, Menu, MenuButton, MenuItem, MenuList, Result, DataTable } from '@redpanda-data/ui';
import { Alert, AlertDialog, AlertDialogBody, AlertDialogContent, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertIcon, Badge, Button, createStandaloneToast, DataTable, Flex, Icon, Menu, MenuButton, MenuItem, MenuList, redpandaTheme, redpandaToastOptions, Result, SearchField, Text, Tooltip } from '@redpanda-data/ui';
import React, { FC, useRef } from 'react';
import { openCreateUserModal } from './CreateServiceAccountModal';

Expand Down Expand Up @@ -142,15 +142,17 @@ class AclList extends PageComponent {
this.editorType = 'edit';
this.edittingPrincipalGroup = clone(record);
}}>
<Badge variant="subtle" mr="2">{principalType}</Badge>
<span>{record.principalName}</span>
{showWarning && (
<Tooltip label="User / ServiceAccount does not exist" placement="top" hasArrow>
<Flex>
<Badge variant="subtle" mr="2">{principalType}</Badge>
<Text as="span" wordBreak="break-word" whiteSpace="break-spaces" noOfLines={1}>{record.principalName}</Text>
{showWarning && (
<Tooltip label="User / ServiceAccount does not exist" placement="top" hasArrow>
<span style={{marginLeft: '4px'}}>
<QuestionIcon fill="orange" size={16}/>
</span>
</Tooltip>
)}
</Tooltip>
)}
</Flex>
</button>
);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ const CreateUserConfirmationModal = observer((p: { state: CreateUserModalState;
</Box>
<Box>
<Flex alignItems="center" gap={2}>
<Text textOverflow="ellipsis" whiteSpace="nowrap" overflow="hidden" isTruncated={true}>
<Text wordBreak="break-all" overflow="hidden">
{p.state.username}
</Text>

Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/pages/connect/Cluster.Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { PageComponent, PageInitHelper } from '../Page';
import { ClusterStatisticsCard, ConnectorClass, NotConfigured, TasksColumn, TaskState } from './helper';
import { isEmbedded } from '../../../config';
import { Link } from 'react-router-dom';
import { Box, Button, DataTable } from '@redpanda-data/ui';
import { Box, Button, DataTable, Text } from '@redpanda-data/ui';
import { ClusterAdditionalInfo, ClusterConnectorInfo } from '../../../state/restInterfaces';
import SearchBar from '../../misc/SearchBar';
import { uiSettings } from '../../../state/ui';
Expand Down Expand Up @@ -116,7 +116,7 @@ class KafkaClusterDetails extends PageComponent<{ clusterName: string }> {
accessorKey: 'name',
cell: ({row: {original}}) => (
<Link to={`/connect-clusters/${encodeURIComponent(clusterName)}/${encodeURIComponent(original.name)}`}>
{original.name}
<Text wordBreak="break-word" whiteSpace="break-spaces" noOfLines={1}>{original.name}</Text>
</Link>
),
size: Infinity
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/components/pages/connect/Connector.Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ const ConnectorErrorModal = observer((p: { error: ConnectorError }) => {
return <>
<Alert status={errorType} variant="solid" height="12" borderRadius="8px" onClick={onOpen}>
<AlertIcon />
{p.error.title}
<Box wordBreak="break-all" whiteSpace="break-spaces">{p.error.title}</Box>
<Button ml="auto" variant="ghost" colorScheme="gray" size="sm" mt="1px">View details</Button>
</Alert>

Expand Down Expand Up @@ -380,7 +380,10 @@ class KafkaConnectorDetails extends PageComponent<{ clusterName: string; connect
p.title = connector;
p.addBreadcrumb('Connectors', '/connect-clusters');
p.addBreadcrumb(clusterName, `/connect-clusters/${encodeURIComponent(clusterName)}`);
p.addBreadcrumb(connector, `/connect-clusters/${encodeURIComponent(clusterName)}/${encodeURIComponent(connector)}`);
p.addBreadcrumb(connector, `/connect-clusters/${encodeURIComponent(clusterName)}/${encodeURIComponent(connector)}`, {
canBeTruncated: true,
canBeCopied: true
});
this.refreshData(true);
appGlobal.onRefresh = () => this.refreshData(true);
}
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/pages/connect/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { PageComponent, PageInitHelper } from '../Page';
import { ConnectorClass, ConnectorsColumn, errIcon, mr05, NotConfigured, OverviewStatisticsCard, TasksColumn, TaskState } from './helper';
import Section from '../../misc/Section';
import PageContent from '../../misc/PageContent';
import { DataTable, Tooltip } from '@redpanda-data/ui';
import { DataTable, Tooltip, Text } from '@redpanda-data/ui';

@observer
class KafkaConnectOverview extends PageComponent {
Expand Down Expand Up @@ -212,9 +212,9 @@ class TabTasks extends Component {
header: 'Connector',
accessorKey: 'name', // Assuming 'name' is correct based on your initial dataIndex
cell: ({ row: { original } }) => (
<span className="hoverLink" onClick={() => appGlobal.history.push(`/connect-clusters/${encodeURIComponent(original.cluster.clusterName)}/${encodeURIComponent(original.connectorName)}`)}>
<Text wordBreak="break-word" whiteSpace="break-spaces" noOfLines={1} className="hoverLink" onClick={() => appGlobal.history.push(`/connect-clusters/${encodeURIComponent(original.cluster.clusterName)}/${encodeURIComponent(original.connectorName)}`)}>
{original.connectorName}
</span>
</Text>
),
size: 300
},
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/components/pages/consumers/Group.Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ class GroupDetails extends PageComponent<{ groupId: string }> {

p.title = this.props.groupId;
p.addBreadcrumb('Consumer Groups', '/groups');
if (group) p.addBreadcrumb(group, '/' + group);
if (group) p.addBreadcrumb(group, '/' + group, {
canBeCopied: true,
canBeTruncated: true,
});

this.refreshData(true);
appGlobal.onRefresh = () => this.refreshData(true);
Expand Down
10 changes: 7 additions & 3 deletions frontend/src/components/pages/consumers/Group.List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { BrokerList } from '../../misc/BrokerList';
import { ShortNum } from '../../misc/ShortNum';
import Section from '../../misc/Section';
import PageContent from '../../misc/PageContent';
import { DataTable, Flex, SearchField, Tag } from '@redpanda-data/ui';
import { DataTable, Flex, SearchField, Tag, Text } from '@redpanda-data/ui';
import { Statistic } from '../../misc/Statistic';
import { Link } from 'react-router-dom';

Expand Down Expand Up @@ -189,11 +189,15 @@ class GroupList extends PageComponent {
GroupId = (p: { group: GroupDescription }) => {
const protocol = p.group.protocolType;

if (protocol == 'consumer') return <>{p.group.groupId}</>;
const groupIdEl = <Text wordBreak="break-word" whiteSpace="break-spaces" noOfLines={1}>{p.group.groupId}</Text>

if (protocol == 'consumer') {
return groupIdEl;
}

return <Flex alignItems="center" gap={2}>
<Tag>Protocol: {protocol}</Tag>
<span>{p.group.groupId}</span>
{groupIdEl}
</Flex>;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import Highlighter from 'react-highlight-words';
import { uiSettings } from '../../../state/ui';
import { WarningTwoTone } from '@ant-design/icons';
import { SearchTitle } from '../../misc/KowlTable';
import { Checkbox, DataTable, Popover } from '@redpanda-data/ui'
import { Box, Checkbox, DataTable, Popover } from '@redpanda-data/ui'
import { Row } from '@tanstack/react-table';

export type TopicWithPartitions = Topic & { partitions: Partition[], activeReassignments: PartitionReassignmentsPartition[] };
Expand Down Expand Up @@ -108,13 +108,13 @@ export class StepSelectPartitions extends Component<{ partitionSelection: Partit
: record.topicName;

if (this.props.throttledTopics.includes(record.topicName)) {
return <div>
return <Box wordBreak="break-word" whiteSpace="break-spaces" noOfLines={4}>
<span>{content}</span>
<WarningToolip content="Topic replication is throttled" position="top"/>
</div>
</Box>
}

return content;
return <Box wordBreak="break-word" whiteSpace="break-spaces" noOfLines={4}>{content}</Box>;
},
size: Infinity,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ function EditSchemaCompatibility(p: {

<GridItem>
{(subjectName && schema) && <>
<Text mt="4" fontSize="lg" fontWeight="bold">{subjectName}</Text>
<Text mt="4" fontSize="lg" fontWeight="bold" wordBreak="break-word" whiteSpace="break-spaces">{subjectName}</Text>

<Text mt="8" mb="4" fontSize="lg" fontWeight="bold">Schema</Text>
<Box maxHeight="600px" overflow="scroll">
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/components/pages/schemas/Schema.Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,10 @@ class SchemaDetailsView extends PageComponent<{ subjectName: string }> {
uiState.pageTitle = subjectNameRaw;
uiState.pageBreadcrumbs = [];
uiState.pageBreadcrumbs.push({ title: 'Schema Registry', linkTo: '/schema-registry' });
uiState.pageBreadcrumbs.push({ title: subjectNameRaw, linkTo: `/schema-registry/${encodeURIComponent(subjectNameRaw)}?version=${version}` });
uiState.pageBreadcrumbs.push({ title: subjectNameRaw, linkTo: `/schema-registry/${encodeURIComponent(subjectNameRaw)}?version=${version}`, options: {
canBeTruncated: true,
canBeCopied: true,
}});
}

refreshData(force?: boolean) {
Expand Down
Loading
Loading