Review all tables and unify the way of data displaying. #602 (#687)

This commit is contained in:
MBovtriukProvectus 2021-07-19 12:11:53 +03:00 committed by GitHub
parent 36f47d8dea
commit c035f58f5a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 324 additions and 129 deletions

View file

@ -96,6 +96,11 @@ const Details: React.FC<Props> = ({
</tr>
</thead>
<tbody>
{items.length === 0 && (
<tr>
<td colSpan={10}>No active consumer groups</td>
</tr>
)}
{items.map((consumer) => (
<ListItem
key={consumer.consumerId}

View file

@ -0,0 +1,8 @@
import React from 'react';
import { containerRendersView } from 'lib/testHelpers';
import Details from 'components/ConsumerGroups/Details/Details';
import DetailsContainer from 'components/ConsumerGroups/Details/DetailsContainer';
describe('DetailsContainer', () => {
containerRendersView(<DetailsContainer />, Details);
});

View file

@ -22,51 +22,52 @@ const List: React.FC<Props> = ({ consumerGroups }) => {
<Breadcrumb>All Consumer Groups</Breadcrumb>
<div className="box">
{consumerGroups.length > 0 ? (
<div>
<div className="columns">
<div className="column is-half is-offset-half">
<input
id="searchText"
type="text"
name="searchText"
className="input"
placeholder="Search"
value={searchText}
onChange={handleInputChange}
/>
</div>
<div>
<div className="columns">
<div className="column is-half is-offset-half">
<input
id="searchText"
type="text"
name="searchText"
className="input"
placeholder="Search"
value={searchText}
onChange={handleInputChange}
/>
</div>
<table className="table is-striped is-fullwidth is-hoverable">
<thead>
<tr>
<th>Consumer group ID</th>
<th>Num of members</th>
<th>Num of topics</th>
<th>Messages behind</th>
<th>Coordinator</th>
<th>State</th>
</tr>
</thead>
<tbody>
{consumerGroups
.filter(
(consumerGroup) =>
!searchText ||
consumerGroup?.groupId?.indexOf(searchText) >= 0
)
.map((consumerGroup) => (
<ListItem
key={consumerGroup.groupId}
consumerGroup={consumerGroup}
/>
))}
</tbody>
</table>
</div>
) : (
'No active consumer groups'
)}
<table className="table is-striped is-fullwidth is-hoverable">
<thead>
<tr>
<th>Consumer group ID</th>
<th>Num of members</th>
<th>Num of topics</th>
<th>Messages behind</th>
<th>Coordinator</th>
<th>State</th>
</tr>
</thead>
<tbody>
{consumerGroups
.filter(
(consumerGroup) =>
!searchText ||
consumerGroup?.groupId?.indexOf(searchText) >= 0
)
.map((consumerGroup) => (
<ListItem
key={consumerGroup.groupId}
consumerGroup={consumerGroup}
/>
))}
{consumerGroups.length === 0 && (
<tr>
<td colSpan={10}>No active consumer groups</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
</div>
);

View file

@ -0,0 +1,46 @@
import React from 'react';
import { shallow, mount } from 'enzyme';
import List from 'components/ConsumerGroups/List/List';
describe('List', () => {
const mockConsumerGroups = [
{
groupId: 'groupId',
members: 0,
topics: 1,
simple: false,
partitionAssignor: '',
coordinator: {
id: 1,
host: 'host',
},
partitions: [
{
consumerId: null,
currentOffset: 0,
endOffset: 0,
host: null,
messagesBehind: 0,
partition: 1,
topic: 'topic',
},
],
},
];
const component = shallow(
<List consumerGroups={mockConsumerGroups} clusterName="cluster" />
);
const componentEmpty = mount(
<List consumerGroups={[]} clusterName="cluster" />
);
it('render empty List consumer Groups', () => {
expect(componentEmpty.find('td').text()).toEqual(
'No active consumer groups'
);
});
it('render List consumer Groups', () => {
expect(component.exists('.section')).toBeTruthy();
});
});

View file

@ -0,0 +1,8 @@
import React from 'react';
import { containerRendersView } from 'lib/testHelpers';
import ListContainer from 'components/ConsumerGroups/List/ListContainer';
import List from 'components/ConsumerGroups/List/List';
describe('ListContainer', () => {
containerRendersView(<ListContainer />, List);
});

View file

@ -0,0 +1,33 @@
import React from 'react';
import { shallow } from 'enzyme';
import ListItem from 'components/ConsumerGroups/List/ListItem';
describe('List', () => {
const mockConsumerGroup = {
groupId: 'groupId',
members: 0,
topics: 1,
simple: false,
partitionAssignor: '',
coordinator: {
id: 1,
host: 'host',
},
partitions: [
{
consumerId: null,
currentOffset: 0,
endOffset: 0,
host: null,
messagesBehind: 0,
partition: 1,
topic: 'topic',
},
],
};
const component = shallow(<ListItem consumerGroup={mockConsumerGroup} />);
it('render empty ListItem', () => {
expect(component.exists('.is-clickable')).toBeTruthy();
});
});

View file

@ -124,6 +124,11 @@ const Details: React.FC<DetailsProps> = ({
{versions.map((version) => (
<SchemaVersion key={version.id} version={version} />
))}
{versions.length === 0 && (
<tr>
<td colSpan={10}>No active Schema</td>
</tr>
)}
</tbody>
</table>
</div>

View file

@ -49,6 +49,13 @@ describe('Details', () => {
{...props}
/>
);
describe('empty table', () => {
it('render empty table', () => {
const component = shallow(setupWrapper());
expect(component.find('td').text()).toEqual('No active Schema');
});
});
describe('Initial state', () => {
it('should call fetchSchemaVersions every render', () => {
mount(

View file

@ -110,7 +110,15 @@ exports[`Details View Initial state matches snapshot 1`] = `
</th>
</tr>
</thead>
<tbody />
<tbody>
<tr>
<td
colSpan={10}
>
No active Schema
</td>
</tr>
</tbody>
</table>
</div>
</div>
@ -393,7 +401,15 @@ exports[`Details View when page with schema versions loaded when versions are em
</th>
</tr>
</thead>
<tbody />
<tbody>
<tr>
<td
colSpan={10}
>
No active Schema
</td>
</tr>
</tbody>
</table>
</div>
</div>

View file

@ -34,38 +34,39 @@ const TopicConsumerGroups: React.FC<Props> = ({
return (
<div className="box">
{consumerGroups.length > 0 ? (
<table className="table is-striped is-fullwidth">
<thead>
<tr>
<th>Consumer group ID</th>
<th>Num of members</th>
<th>Messages behind</th>
<th>Coordinator</th>
<th>State</th>
<table className="table is-striped is-fullwidth">
<thead>
<tr>
<th>Consumer group ID</th>
<th>Num of members</th>
<th>Messages behind</th>
<th>Coordinator</th>
<th>State</th>
</tr>
</thead>
<tbody>
{consumerGroups.map((consumer) => (
<tr
key={consumer.groupId}
className="is-clickable"
onClick={() => goToConsumerGroupDetails(consumer)}
>
<td>{consumer.groupId}</td>
<td>{consumer.members}</td>
<td>{consumer.messagesBehind}</td>
<td>{consumer.coordinator?.id}</td>
<td>
<ConsumerGroupStateTag state={consumer.state} />
</td>
</tr>
</thead>
<tbody>
{consumerGroups.map((consumer) => (
<tr
key={consumer.groupId}
className="is-clickable"
onClick={() => goToConsumerGroupDetails(consumer)}
>
<td>{consumer.groupId}</td>
<td>{consumer.members}</td>
<td>{consumer.messagesBehind}</td>
<td>{consumer.coordinator?.id}</td>
<td>
<ConsumerGroupStateTag state={consumer.state} />
</td>
</tr>
))}
</tbody>
</table>
) : (
'No active consumer groups'
)}
))}
{consumerGroups.length === 0 && (
<tr>
<td colSpan={10}>No active consumer groups</td>
</tr>
)}
</tbody>
</table>
</div>
);
};

View file

@ -40,8 +40,7 @@ describe('Details', () => {
topicName={mockTopicName}
/>
);
expect(component.exists('.table')).toBeFalsy();
expect(component.find('td').text()).toEqual('No active consumer groups');
});
it('render ConsumerGroups in Topic', () => {
@ -54,7 +53,6 @@ describe('Details', () => {
topicName={mockTopicName}
/>
);
expect(component.exists('.table')).toBeTruthy();
expect(component.exists('tbody')).toBeTruthy();
});
});

View file

@ -9,51 +9,50 @@ export interface MessagesTableProp {
onNext(event: React.MouseEvent<HTMLButtonElement>): void;
}
const MessagesTable: React.FC<MessagesTableProp> = ({ messages, onNext }) => {
if (!messages.length) {
return <div>No messages at selected topic</div>;
}
return (
<>
<table className="table is-fullwidth is-narrow">
<thead>
const MessagesTable: React.FC<MessagesTableProp> = ({ messages, onNext }) => (
<>
<table className="table is-fullwidth is-narrow">
<thead>
<tr>
<th>Timestamp</th>
<th>Key</th>
<th>Offset</th>
<th>Partition</th>
<th>Content</th>
<th> </th>
</tr>
</thead>
<tbody>
{messages.map(
({ partition, offset, timestamp, content, key }: TopicMessage) => (
<MessageItem
key={`message-${timestamp.getTime()}-${offset}`}
partition={partition}
offset={offset}
timestamp={timestamp}
content={content}
messageKey={key}
/>
)
)}
{messages.length === 0 && (
<tr>
<th>Timestamp</th>
<th>Key</th>
<th>Offset</th>
<th>Partition</th>
<th>Content</th>
<th> </th>
<td colSpan={10}>No messages at selected topic</td>
</tr>
</thead>
<tbody>
{messages.map(
({ partition, offset, timestamp, content, key }: TopicMessage) => (
<MessageItem
key={`message-${timestamp.getTime()}-${offset}`}
partition={partition}
offset={offset}
timestamp={timestamp}
content={content}
messageKey={key}
/>
)
)}
</tbody>
</table>
<div className="columns">
<div className="column is-full">
<CustomParamButton
className="is-link is-pulled-right"
type="fa-chevron-right"
onClick={onNext}
btnText="Next"
/>
</div>
)}
</tbody>
</table>
<div className="columns">
<div className="column is-full">
<CustomParamButton
className="is-link is-pulled-right"
type="fa-chevron-right"
onClick={onNext}
btnText="Next"
/>
</div>
</>
);
};
</div>
</>
);
export default MessagesTable;

View file

@ -18,9 +18,9 @@ describe('MessagesTable', () => {
describe('when topic is empty', () => {
it('renders table row with JSONEditor', () => {
const wrapper = shallow(setupWrapper());
expect(wrapper.exists('table')).toBeFalsy();
expect(wrapper.exists('CustomParamButton')).toBeFalsy();
expect(wrapper.text()).toEqual('No messages at selected topic');
expect(wrapper.find('td').text()).toEqual(
'No messages at selected topic'
);
});
it('matches snapshot', () => {

View file

@ -63,7 +63,55 @@ exports[`MessagesTable when topic contains messages matches snapshot 1`] = `
`;
exports[`MessagesTable when topic is empty matches snapshot 1`] = `
<div>
No messages at selected topic
</div>
<Fragment>
<table
className="table is-fullwidth is-narrow"
>
<thead>
<tr>
<th>
Timestamp
</th>
<th>
Key
</th>
<th>
Offset
</th>
<th>
Partition
</th>
<th>
Content
</th>
<th>
</th>
</tr>
</thead>
<tbody>
<tr>
<td
colSpan={10}
>
No messages at selected topic
</td>
</tr>
</tbody>
</table>
<div
className="columns"
>
<div
className="column is-full"
>
<CustomParamButton
btnText="Next"
className="is-link is-pulled-right"
onClick={[MockFunction]}
type="fa-chevron-right"
/>
</div>
</div>
</Fragment>
`;

View file

@ -102,6 +102,11 @@ const Overview: React.FC<Props> = ({
</td>
</tr>
))}
{partitions?.length === 0 && (
<tr>
<td colSpan={10}>No Partitions found</td>
</tr>
)}
</tbody>
</table>
</div>

View file

@ -38,5 +38,20 @@ describe('Overview', () => {
expect(component.exists('Dropdown')).toBeTruthy();
});
it('does not render Partitions', () => {
const componentEmpty = shallow(
<Overview
name={mockTopicName}
partitions={[]}
internal={mockInternal}
clusterName={mockClusterName}
topicName={mockTopicName}
clearTopicMessages={mockClearTopicMessages}
/>
);
expect(componentEmpty.find('td').text()).toEqual('No Partitions found');
});
});
});