Migrate Topic Overview to the new version of table #2684 (#2704)

* Migrate Topic Overview to the new version of table #2684

* changed Dropdown Toggle visibility to disabled and fixed test

* changed drop down button disabled rule

* deleted cleanUpPolicy form the some tests

Co-authored-by: davitbejanyan <dbejanyan@provectus.com>
Co-authored-by: Oleg Shur <workshur@gmail.com>
This commit is contained in:
David 2022-10-19 21:27:06 +04:00 committed by GitHub
parent 0e4a314082
commit 6581ee605b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 109 additions and 85 deletions

View file

@ -0,0 +1,35 @@
import React from 'react';
import { Partition } from 'generated-sources';
import { CellContext } from '@tanstack/react-table';
import { useAppDispatch } from 'lib/hooks/redux';
import ClusterContext from 'components/contexts/ClusterContext';
import { RouteParamsClusterTopic } from 'lib/paths';
import useAppParams from 'lib/hooks/useAppParams';
import { clearTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice';
import { Dropdown, DropdownItem } from 'components/common/Dropdown';
import { useTopicDetails } from 'lib/hooks/api/topics';
const ActionsCell: React.FC<CellContext<Partition, unknown>> = ({ row }) => {
const { clusterName, topicName } = useAppParams<RouteParamsClusterTopic>();
const { data } = useTopicDetails({ clusterName, topicName });
const { isReadOnly } = React.useContext(ClusterContext);
const { partition } = row.original;
const dispatch = useAppDispatch();
const clearTopicMessagesHandler = async () => {
await dispatch(
clearTopicMessages({ clusterName, topicName, partitions: [partition] })
).unwrap();
};
const disabled =
data?.internal || isReadOnly || data?.cleanUpPolicy !== 'DELETE';
return (
<Dropdown disabled={disabled}>
<DropdownItem onClick={clearTopicMessagesHandler} danger>
Clear Messages
</DropdownItem>
</Dropdown>
);
};
export default ActionsCell;

View file

@ -1,25 +1,20 @@
import React from 'react';
import { Partition, Replica } from 'generated-sources';
import ClusterContext from 'components/contexts/ClusterContext';
import BytesFormatted from 'components/common/BytesFormatted/BytesFormatted';
import { Table } from 'components/common/table/Table/Table.styled';
import TableHeaderCell from 'components/common/table/TableHeaderCell/TableHeaderCell';
import Table from 'components/common/NewTable';
import * as Metrics from 'components/common/Metrics';
import { Tag } from 'components/common/Tag/Tag.styled';
import { useAppDispatch } from 'lib/hooks/redux';
import { RouteParamsClusterTopic } from 'lib/paths';
import useAppParams from 'lib/hooks/useAppParams';
import { Dropdown, DropdownItem } from 'components/common/Dropdown';
import { clearTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice';
import { useTopicDetails } from 'lib/hooks/api/topics';
import { ColumnDef } from '@tanstack/react-table';
import * as S from './Overview.styled';
import ActionsCell from './ActionsCell';
const Overview: React.FC = () => {
const { clusterName, topicName } = useAppParams<RouteParamsClusterTopic>();
const dispatch = useAppDispatch();
const { data } = useTopicDetails({ clusterName, topicName });
const { isReadOnly } = React.useContext(ClusterContext);
const messageCount = React.useMemo(
() =>
@ -28,7 +23,65 @@ const Overview: React.FC = () => {
}, 0),
[data]
);
const newData = React.useMemo(() => {
if (!data?.partitions) return [];
return data.partitions.map((items: Partition) => {
return {
...items,
messageCount: items.offsetMax - items.offsetMin,
};
});
}, [data?.partitions]);
const columns = React.useMemo<ColumnDef<Partition>[]>(
() => [
{
header: 'Partition ID',
enableSorting: false,
accessorKey: 'partition',
},
{
header: 'Replicas',
enableSorting: false,
accessorKey: 'replicas',
cell: ({ getValue }) => {
const replicas = getValue<Partition['replicas']>();
if (replicas === undefined || replicas.length === 0) {
return 0;
}
return replicas?.map(({ broker, leader }: Replica) => (
<S.Replica
leader={leader}
key={broker}
title={leader ? 'Leader' : ''}
>
{broker}
</S.Replica>
));
},
},
{
header: 'First Offset',
enableSorting: false,
accessorKey: 'offsetMin',
},
{ header: 'Next Offset', enableSorting: false, accessorKey: 'offsetMax' },
{
header: 'Message Count',
enableSorting: false,
accessorKey: `messageCount`,
},
{
header: '',
enableSorting: false,
accessorKey: 'actions',
cell: ActionsCell,
},
],
[]
);
return (
<>
<Metrics.Wrapper>
@ -90,66 +143,12 @@ const Overview: React.FC = () => {
</Metrics.Indicator>
</Metrics.Section>
</Metrics.Wrapper>
<Table isFullwidth>
<thead>
<tr>
<TableHeaderCell title="Partition ID" />
<TableHeaderCell title="Replicas" />
<TableHeaderCell title="First Offset" />
<TableHeaderCell title="Next Offset" />
<TableHeaderCell title="Message Count" />
<TableHeaderCell title=" " />
</tr>
</thead>
<tbody>
{data?.partitions?.map((partition: Partition) => (
<tr key={`partition-list-item-key-${partition.partition}`}>
<td>{partition.partition}</td>
<td>
{partition.replicas?.map(({ broker, leader }: Replica) => (
<S.Replica
leader={leader}
key={broker}
title={leader ? 'Leader' : ''}
>
{broker}
</S.Replica>
))}
</td>
<td>{partition.offsetMin}</td>
<td>{partition.offsetMax}</td>
<td>{partition.offsetMax - partition.offsetMin}</td>
<td style={{ width: '5%' }}>
{!data?.internal &&
!isReadOnly &&
data?.cleanUpPolicy === 'DELETE' ? (
<Dropdown>
<DropdownItem
onClick={() =>
dispatch(
clearTopicMessages({
clusterName,
topicName,
partitions: [partition.partition],
})
).unwrap()
}
danger
>
Clear Messages
</DropdownItem>
</Dropdown>
) : null}
</td>
</tr>
))}
{data?.partitions?.length === 0 && (
<tr>
<td colSpan={10}>No Partitions found</td>
</tr>
)}
</tbody>
</Table>
<Table
columns={columns}
data={newData}
enableSorting
emptyMessage="No Partitions found "
/>
</>
);
};

View file

@ -122,39 +122,29 @@ describe('Overview', () => {
});
describe('when the table partition dropdown appearance', () => {
it('should check if the dropdown is not present when it is readOnly', () => {
it('should check if the dropdown is disabled when it is readOnly', () => {
renderComponent(
{
...internalTopicPayload,
cleanUpPolicy: CleanUpPolicy.DELETE,
...externalTopicPayload,
},
{ ...defaultContextValues, isReadOnly: true }
);
expect(screen.queryByText('Clear Messages')).not.toBeInTheDocument();
expect(screen.getByLabelText('Dropdown Toggle')).toBeDisabled();
});
it('should check if the dropdown is not present when it is internal', () => {
it('should check if the dropdown is disabled when it is internal', () => {
renderComponent({
...internalTopicPayload,
cleanUpPolicy: CleanUpPolicy.DELETE,
});
expect(screen.queryByText('Clear Messages')).not.toBeInTheDocument();
expect(screen.getByLabelText('Dropdown Toggle')).toBeDisabled();
});
it('should check if the dropdown is not present when cleanUpPolicy is not DELETE', () => {
it('should check if the dropdown is disabled when cleanUpPolicy is not DELETE', () => {
renderComponent({
...externalTopicPayload,
cleanUpPolicy: CleanUpPolicy.COMPACT,
});
expect(screen.queryByText('Clear Messages')).not.toBeInTheDocument();
});
it('should check if the dropdown action to be in visible', () => {
renderComponent({
...externalTopicPayload,
cleanUpPolicy: CleanUpPolicy.DELETE,
});
expect(screen.getByText('Clear Messages')).toBeInTheDocument();
expect(screen.getByLabelText('Dropdown Toggle')).toBeDisabled();
});
});
});