[ISSUE-1512]Added sorting by topics size

* [ISSUE-1512]Added sorting by topics size

* Add sort by Size.Refactoring sort order

* correct a little mistake

* Improve test coverage

* got rid code dupliction

* refactoring

Co-authored-by: ValentinPrischepa <valentin.prischepa@gmail.com>
Co-authored-by: Anton Zorin <ant.zorin@gmail.com>
Co-authored-by: Oleg Shur <workshur@gmail.com>
This commit is contained in:
Zorii4 2022-02-09 15:46:11 +03:00 committed by GitHub
parent 529cd0bd6e
commit 4eaf8ea2c6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 101 additions and 18 deletions

View file

@ -44,6 +44,8 @@ exports[`Tasks view matches snapshot 1`] = `
background: #FFFFFF;
cursor: default;
color: #73848C;
padding-right: 18px;
position: relative;
}
.c1 {
@ -217,6 +219,8 @@ exports[`Tasks view matches snapshot when no tasks 1`] = `
background: #FFFFFF;
cursor: default;
color: #73848C;
padding-right: 18px;
position: relative;
}
.c1 {

View file

@ -12,7 +12,11 @@ import ClusterContext from 'components/contexts/ClusterContext';
import PageLoader from 'components/common/PageLoader/PageLoader';
import Pagination from 'components/common/Pagination/Pagination';
import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
import { GetTopicsRequest, TopicColumnsToSort } from 'generated-sources';
import {
GetTopicsRequest,
SortOrder,
TopicColumnsToSort,
} from 'generated-sources';
import TableHeaderCell from 'components/common/table/TableHeaderCell/TableHeaderCell';
import Search from 'components/common/Search/Search';
import { PER_PAGE } from 'lib/constants';
@ -39,6 +43,7 @@ export interface TopicsListProps {
): void;
search: string;
orderBy: TopicColumnsToSort | null;
sortOrder: SortOrder;
setTopicsSearch(search: string): void;
setTopicsOrderBy(orderBy: TopicColumnsToSort | null): void;
}
@ -54,6 +59,7 @@ const List: React.FC<TopicsListProps> = ({
clearTopicsMessages,
search,
orderBy,
sortOrder,
setTopicsSearch,
setTopicsOrderBy,
}) => {
@ -69,6 +75,7 @@ const List: React.FC<TopicsListProps> = ({
page,
perPage,
orderBy: orderBy || undefined,
sortOrder,
search,
showInternal,
});
@ -78,6 +85,7 @@ const List: React.FC<TopicsListProps> = ({
page,
perPage,
orderBy,
sortOrder,
search,
showInternal,
]);
@ -215,24 +223,32 @@ const List: React.FC<TopicsListProps> = ({
title="Topic Name"
orderValue={TopicColumnsToSort.NAME}
orderBy={orderBy}
sortOrder={sortOrder}
handleOrderBy={setTopicsOrderBy}
/>
<TableHeaderCell
title="Total Partitions"
orderValue={TopicColumnsToSort.TOTAL_PARTITIONS}
orderBy={orderBy}
sortOrder={sortOrder}
handleOrderBy={setTopicsOrderBy}
/>
<TableHeaderCell
title="Out of sync replicas"
orderValue={TopicColumnsToSort.OUT_OF_SYNC_REPLICAS}
orderBy={orderBy}
sortOrder={sortOrder}
handleOrderBy={setTopicsOrderBy}
/>
<TableHeaderCell title="Replication Factor" />
<TableHeaderCell title="Number of messages" />
<TableHeaderCell title="Size" />
<TableHeaderCell />
<TableHeaderCell
title="Size"
orderValue={TopicColumnsToSort.SIZE}
orderBy={orderBy}
sortOrder={sortOrder}
handleOrderBy={setTopicsOrderBy}
/>
</tr>
</thead>
<tbody>

View file

@ -15,6 +15,7 @@ import {
getTopicListTotalPages,
getTopicsSearch,
getTopicsOrderBy,
getTopicsSortOrder,
} from 'redux/reducers/topics/selectors';
import List from './List';
@ -25,6 +26,7 @@ const mapStateToProps = (state: RootState) => ({
totalPages: getTopicListTotalPages(state),
search: getTopicsSearch(state),
orderBy: getTopicsOrderBy(state),
sortOrder: getTopicsSortOrder(state),
});
const mapDispatchToProps = {

View file

@ -13,6 +13,7 @@ import { externalTopicPayload } from 'redux/reducers/topics/__test__/fixtures';
import { ConfirmationModalProps } from 'components/common/ConfirmationModal/ConfirmationModal';
import theme from 'theme/theme';
import { ThemeProvider } from 'styled-components';
import { SortOrder } from 'generated-sources';
jest.mock(
'components/common/ConfirmationModal/ConfirmationModal',
@ -33,6 +34,7 @@ describe('List', () => {
clearTopicMessages={jest.fn()}
search=""
orderBy={null}
sortOrder={SortOrder.ASC}
setTopicsSearch={jest.fn()}
setTopicsOrderBy={jest.fn()}
{...props}
@ -104,6 +106,7 @@ describe('List', () => {
expect(fetchTopicsList).toHaveBeenLastCalledWith({
search: '',
showInternal: false,
sortOrder: SortOrder.ASC,
});
});

View file

@ -1,8 +1,10 @@
import { SortOrder } from 'generated-sources';
import styled, { css } from 'styled-components';
interface TitleProps {
isOrderable?: boolean;
isOrdered?: boolean;
sortOrder?: SortOrder;
}
const orderableMixin = css(
@ -45,20 +47,48 @@ const orderableMixin = css(
`
);
const orderedMixin = css(
const ASCMixin = css(
({ theme: { table } }) => `
color: ${table.th.color.active};
&::before {
border-bottom-color: ${table.th.color.active};
}
&::after {
border-top-color: ${table.th.color.active};
}
cursor: pointer;
&::after {
cursor: pointer;
border: 4px solid transparent;
content: '';
display: block;
height: 0;
right: 5px;
top: 50%;
position: absolute;
border-top-color: ${table.th.color.active};
margin-top: 1px;
}
`
);
const DESCMixin = css(
({ theme: { table } }) => `
color: ${table.th.color.active};
cursor: pointer;
&::before {
border: 4px solid transparent;
cursor: pointer;
content: '';
display: block;
height: 0;
right: 5px;
top: 50%;
position: absolute;
margin-top: -9px;
border-bottom-color: ${table.th.color.active};
}
`
);
export const Title = styled.span<TitleProps>(
({ isOrderable, isOrdered, theme: { table } }) => css`
({ isOrderable, isOrdered, sortOrder, theme: { table } }) => css`
font-family: Inter, sans-serif;
font-size: 12px;
font-style: normal;
@ -72,10 +102,14 @@ export const Title = styled.span<TitleProps>(
background: ${table.th.backgroundColor.normal};
cursor: default;
color: ${table.th.color.normal};
padding-right: 18px;
position: relative;
${isOrderable && orderableMixin}
${isOrderable && !isOrdered && orderableMixin}
${isOrderable && isOrdered && orderedMixin}
${isOrderable && isOrdered && sortOrder === SortOrder.ASC && ASCMixin}
${isOrderable && isOrdered && sortOrder === SortOrder.DESC && DESCMixin}
`
);

View file

@ -1,5 +1,5 @@
import React from 'react';
import { TopicColumnsToSort } from 'generated-sources';
import { SortOrder, TopicColumnsToSort } from 'generated-sources';
import * as S from 'components/common/table/TableHeaderCell/TableHeaderCell.styled';
export interface TableHeaderCellProps {
@ -7,6 +7,7 @@ export interface TableHeaderCellProps {
previewText?: string;
onPreview?: () => void;
orderBy?: TopicColumnsToSort | null;
sortOrder?: SortOrder;
orderValue?: TopicColumnsToSort | null;
handleOrderBy?: (orderBy: TopicColumnsToSort | null) => void;
}
@ -17,6 +18,7 @@ const TableHeaderCell: React.FC<TableHeaderCellProps> = (props) => {
previewText,
onPreview,
orderBy,
sortOrder,
orderValue,
handleOrderBy,
...restProps
@ -38,6 +40,7 @@ const TableHeaderCell: React.FC<TableHeaderCellProps> = (props) => {
};
const orderableProps = isOrderable && {
isOrderable,
sortOrder,
onClick: handleOnClick,
onKeyDown: handleOnKeyDown,
role: 'button',

View file

@ -4,7 +4,7 @@ import { render } from 'lib/testHelpers';
import TableHeaderCell, {
TableHeaderCellProps,
} from 'components/common/table/TableHeaderCell/TableHeaderCell';
import { TopicColumnsToSort } from 'generated-sources';
import { SortOrder, TopicColumnsToSort } from 'generated-sources';
import theme from 'theme/theme';
import userEvent from '@testing-library/user-event';
@ -50,6 +50,7 @@ describe('TableHeaderCell', () => {
title: testTitle,
orderBy: TopicColumnsToSort.NAME,
orderValue: TopicColumnsToSort.NAME,
sortOrder: SortOrder.ASC,
handleOrderBy,
});
const columnheader = screen.getByRole('columnheader');
@ -59,7 +60,6 @@ describe('TableHeaderCell', () => {
expect(title).toHaveStyle(`color: ${theme.table.th.color.active};`);
expect(title).toHaveStyle('cursor: pointer;');
});
it('renders click on title triggers handler', () => {
setupComponent({
title: testTitle,
@ -129,6 +129,7 @@ describe('TableHeaderCell', () => {
title: testTitle,
orderBy: TopicColumnsToSort.NAME,
orderValue: TopicColumnsToSort.NAME,
sortOrder: SortOrder.ASC,
handleOrderBy: jest.fn(),
});
const columnheader = screen.getByRole('columnheader');

View file

@ -4,6 +4,7 @@ import {
NewSchemaSubject,
SchemaSubject,
SchemaType,
SortOrder,
} from 'generated-sources';
export const clusterStats: ClusterStats = {
@ -42,5 +43,6 @@ export const mockTopicsState = {
messages: [],
search: '',
orderBy: null,
sortOrder: SortOrder.ASC,
consumerGroups: [],
};

View file

@ -9,6 +9,7 @@ import {
TopicMessage,
TopicMessageConsuming,
TopicMessageSchema,
SortOrder,
} from 'generated-sources';
export type TopicName = Topic['name'];
@ -53,6 +54,7 @@ export interface TopicsState {
totalPages: number;
search: string;
orderBy: TopicColumnsToSort | null;
sortOrder: SortOrder;
consumerGroups: ConsumerGroup[];
}

View file

@ -1,4 +1,8 @@
import { MessageSchemaSourceEnum, TopicColumnsToSort } from 'generated-sources';
import {
MessageSchemaSourceEnum,
SortOrder,
TopicColumnsToSort,
} from 'generated-sources';
import {
deleteTopicAction,
clearMessagesTopicAction,
@ -72,6 +76,7 @@ let state = {
totalPages: 1,
search: '',
orderBy: null,
sortOrder: SortOrder.ASC,
consumerGroups: [],
};
@ -130,6 +135,7 @@ describe('topics reducer', () => {
totalPages: 1,
search: '',
orderBy: null,
sortOrder: SortOrder.ASC,
consumerGroups: [],
};
expect(

View file

@ -2,7 +2,7 @@ import { Action, TopicsState } from 'redux/interfaces';
import { getType } from 'typesafe-actions';
import * as actions from 'redux/actions';
import * as _ from 'lodash';
import { TopicColumnsToSort } from 'generated-sources';
import { SortOrder, TopicColumnsToSort } from 'generated-sources';
export const initialState: TopicsState = {
byName: {},
@ -10,6 +10,7 @@ export const initialState: TopicsState = {
totalPages: 1,
search: '',
orderBy: TopicColumnsToSort.NAME,
sortOrder: SortOrder.ASC,
consumerGroups: [],
};
@ -41,6 +42,10 @@ const reducer = (state = initialState, action: Action): TopicsState => {
return {
...state,
orderBy: action.payload,
sortOrder:
state.orderBy === action.payload && state.sortOrder === SortOrder.ASC
? SortOrder.DESC
: SortOrder.ASC,
};
}
case getType(actions.fetchTopicMessageSchemaAction.success): {

View file

@ -157,6 +157,11 @@ export const getTopicsOrderBy = createSelector(
(state) => state.orderBy
);
export const getTopicsSortOrder = createSelector(
topicsState,
(state) => state.sortOrder
);
export const getIsTopicInternal = createSelector(
getTopicByName,
(topic) => !!topic?.internal