Topics sorted alphabetically (#1999)

* Added topics sorting and tests

* Sorting topics logic moved to redux, test improved

* LocaleCompare replaced with default sort function

* Shadow fixed on overview topic page

* Code samples fixed in InfoModal

* String type removed

* Unused import removed

* Default JS sort method removed with lodash library sorting method
This commit is contained in:
Kirill Morozov 2022-05-25 14:33:05 +03:00 committed by GitHub
parent 6d8c6cace0
commit ad2966f31b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 64 additions and 23 deletions

View file

@ -12,6 +12,7 @@ import {
getAreConnectorsFetching,
getConnectorSearch,
getFailedConnectors,
getSortedTopics,
getFailedTasks,
} from 'redux/reducers/connect/selectors';
import List from 'components/Connect/List/List';
@ -21,6 +22,7 @@ const mapStateToProps = (state: RootState) => ({
areConnectorsFetching: getAreConnectorsFetching(state),
connects: getConnects(state),
failedConnectors: getFailedConnectors(state),
sortedTopics: getSortedTopics(state),
failedTasks: getFailedTasks(state),
connectors: getConnectors(state),
search: getConnectorSearch(state),

View file

@ -52,6 +52,14 @@ describe('Connectors ListItem', () => {
expect(screen.getAllByRole('cell')[6]).toHaveTextContent('2 of 2');
});
it('topics tags are sorted', () => {
render(setupWrapper());
const getLink = screen.getAllByRole('link');
expect(getLink[1]).toHaveTextContent('a');
expect(getLink[2]).toHaveTextContent('b');
expect(getLink[3]).toHaveTextContent('c');
});
it('renders item with failed tasks', () => {
render(
setupWrapper({

View file

@ -125,6 +125,16 @@ export const InfoParagraph = styled.p`
color: ${({ theme }) => theme.table.td.color.normal};
`;
export const InfoCodeSample = styled.pre`
background: #f5f5f5;
padding: 5px;
border: 1px solid #e1e1e1;
border-radius: 5px;
width: fit-content;
margin: 5px 20px;
color: #cc0f35;
`;
export const MessageFilterModal = styled.div`
height: auto;
width: 560px;

View file

@ -26,32 +26,37 @@ const InfoModal: React.FC<InfoModalProps> = ({ toggleIsOpen }) => {
</S.InfoParagraph>
<ol aria-label="info-list">
<S.ListItem>
`keyAsText != null && keyAsText ~&quot;([Gg])roovy&quot;` - regex for
key as a string
<code>keyAsText != null && keyAsText ~&quot;([Gg])roovy&quot;</code> -
regex for key as a string
</S.ListItem>
<S.ListItem>
`value.name == &quot;iS.ListItemax&quot; && value.age &gt; 30` - in
case value is json
<code>
value.name == &quot;iS.ListItemax&quot; && value.age &gt; 30
</code>{' '}
- in case value is json
</S.ListItem>
<S.ListItem>
`value == null && valueAsText != null` - search for values that are
not nulls and are not json
<code>value == null && valueAsText != null</code> - search for values
that are not nulls and are not json
</S.ListItem>
<S.ListItem>
`headers.sentBy == &quot;some system&quot; &&
headers[&quot;sentAt&quot;] == &quot;2020-01-01&quot;`
<code>
headers.sentBy == &quot;some system&quot; &&
headers[&quot;sentAt&quot;] == &quot;2020-01-01&quot;
</code>
</S.ListItem>
<S.ListItem>multiline filters are also allowed:</S.ListItem>
<S.InfoParagraph>
```
<br />
def name = value.name
<br />
def age = value.age
<br />
name == &quot;iliax&quot; && age == 30
<br />
```
<S.InfoCodeSample>
<code>
def name = value.name
<br />
def age = value.age
<br />
name == &quot;iliax&quot; && age == 30
<br />
</code>
</S.InfoCodeSample>
</S.InfoParagraph>
</ol>
<S.ButtonContainer>

View file

@ -21,7 +21,6 @@ export const IndicatorWrapper = styled.div`
align-items: flex-start;
padding: 12px 16px;
box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.08);
margin: 0 0 3px 0;
flex-grow: 1;
`;
@ -36,10 +35,11 @@ export const IndicatorTitle = styled.div`
export const IndicatorsWrapper = styled.div`
display: flex;
gap: 1px;
gap: 2px;
flex-wrap: wrap;
border-radius: 8px;
overflow: auto;
box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.08);
`;
export const SectionTitle = styled.h5`

View file

@ -19,7 +19,7 @@ export const connectorsServerPayload = [
name: 'hdfs-source-connector',
connector_class: 'FileStreamSource',
type: ConnectorType.SOURCE,
topics: ['test-topic'],
topics: ['a', 'b', 'c'],
status: {
state: ConnectorTaskStatus.RUNNING,
workerId: 1,
@ -48,7 +48,7 @@ export const connectors: FullConnectorInfo[] = [
name: 'hdfs-source-connector',
connectorClass: 'FileStreamSource',
type: ConnectorType.SOURCE,
topics: ['test-topic'],
topics: ['a', 'b', 'c'],
status: {
state: ConnectorState.RUNNING,
},
@ -75,7 +75,7 @@ export const failedConnectors: FullConnectorInfo[] = [
name: 'hdfs-source-connector',
connectorClass: 'FileStreamSource',
type: ConnectorType.SOURCE,
topics: ['test-topic'],
topics: ['a', 'b', 'c'],
status: {
state: ConnectorState.FAILED,
},
@ -87,7 +87,7 @@ export const failedConnectors: FullConnectorInfo[] = [
name: 'hdfs2-source-connector',
connectorClass: 'FileStreamSource',
type: ConnectorType.SINK,
topics: ['test-topic'],
topics: ['a', 'b', 'c'],
status: {
state: ConnectorState.FAILED,
},

View file

@ -83,6 +83,17 @@ describe('Connect selectors', () => {
expect(selectors.getFailedTasks(store.getState())).toEqual(1);
});
it('returns sorted topics', () => {
store.dispatch({
type: fetchConnectors.fulfilled.type,
payload: { connectors },
});
const sortedTopics = selectors.getSortedTopics(store.getState());
if (sortedTopics[0] && sortedTopics[0].length > 1) {
expect(sortedTopics[0]).toEqual(['a', 'b', 'c']);
}
});
it('returns connector', () => {
store.dispatch({
type: fetchConnector.fulfilled.type,

View file

@ -6,6 +6,7 @@ import {
ConnectorState,
FullConnectorInfo,
} from 'generated-sources';
import { sortBy } from 'lodash';
import {
deleteConnector,
@ -63,6 +64,10 @@ export const getFailedTasks = createSelector(connectState, ({ connectors }) => {
.reduce((acc: number, value: number) => acc + value, 0);
});
export const getSortedTopics = createSelector(connectState, ({ connectors }) =>
connectors.map(({ topics }) => sortBy(topics || []))
);
const getConnectorFetchingStatus = createFetchingSelector(
fetchConnector.typePrefix
);