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:
parent
6d8c6cace0
commit
ad2966f31b
8 changed files with 64 additions and 23 deletions
|
@ -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),
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -26,32 +26,37 @@ const InfoModal: React.FC<InfoModalProps> = ({ toggleIsOpen }) => {
|
|||
</S.InfoParagraph>
|
||||
<ol aria-label="info-list">
|
||||
<S.ListItem>
|
||||
`keyAsText != null && keyAsText ~"([Gg])roovy"` - regex for
|
||||
key as a string
|
||||
<code>keyAsText != null && keyAsText ~"([Gg])roovy"</code> -
|
||||
regex for key as a string
|
||||
</S.ListItem>
|
||||
<S.ListItem>
|
||||
`value.name == "iS.ListItemax" && value.age > 30` - in
|
||||
case value is json
|
||||
<code>
|
||||
value.name == "iS.ListItemax" && value.age > 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 == "some system" &&
|
||||
headers["sentAt"] == "2020-01-01"`
|
||||
<code>
|
||||
headers.sentBy == "some system" &&
|
||||
headers["sentAt"] == "2020-01-01"
|
||||
</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 == "iliax" && age == 30
|
||||
<br />
|
||||
```
|
||||
<S.InfoCodeSample>
|
||||
<code>
|
||||
def name = value.name
|
||||
<br />
|
||||
def age = value.age
|
||||
<br />
|
||||
name == "iliax" && age == 30
|
||||
<br />
|
||||
</code>
|
||||
</S.InfoCodeSample>
|
||||
</S.InfoParagraph>
|
||||
</ol>
|
||||
<S.ButtonContainer>
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
Loading…
Add table
Reference in a new issue