Skip to content

Commit e9f81c9

Browse files
committed
#RI-2932 - Show Consumer Groups
#RI-2766 - Show Consumer Information
1 parent eb85d65 commit e9f81c9

40 files changed

+1091
-495
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,6 @@
202202
"opencollective-postinstall": "^2.0.3",
203203
"react-hot-loader": "^4.13.0",
204204
"react-refresh": "^0.9.0",
205-
"react-test-renderer": "^17.0.1",
206205
"redux-mock-store": "^1.5.4",
207206
"regenerator-runtime": "^0.13.5",
208207
"rimraf": "^3.0.2",

redisinsight/ui/src/components/range-filter/RangeFilter.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export interface Props {
1212
min: number
1313
start: number
1414
end: number
15+
disabled?: boolean
1516
handleChangeStart: (value: number, shouldSentEventTelemetry: boolean) => void
1617
handleChangeEnd: (value: number, shouldSentEventTelemetry: boolean) => void
1718
handleUpdateRangeMax: (value: number) => void
@@ -33,6 +34,7 @@ const RangeFilter = (props: Props) => {
3334
min,
3435
start,
3536
end,
37+
disabled = false,
3638
handleChangeStart,
3739
handleChangeEnd,
3840
handleUpdateRangeMax,
@@ -152,6 +154,7 @@ const RangeFilter = (props: Props) => {
152154
max={max}
153155
value={startVal}
154156
ref={minValRef}
157+
disabled={disabled}
155158
onChange={onChangeStart}
156159
onMouseUp={onMouseUpStart}
157160
className={cx(styles.thumb, styles.thumbZindex3)}
@@ -163,6 +166,7 @@ const RangeFilter = (props: Props) => {
163166
max={max}
164167
value={endVal}
165168
ref={maxValRef}
169+
disabled={disabled}
166170
onChange={onChangeEnd}
167171
onMouseUp={onMouseUpEnd}
168172
className={cx(styles.thumb, styles.thumbZindex4)}

redisinsight/ui/src/pages/browser/components/auto-refresh/AutoRefresh.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export interface Props {
2929
testid?: string
3030
containerClassName?: string
3131
turnOffAutoRefresh?: boolean
32-
onRefresh: (enableAutoRefresh?: boolean) => void
32+
onRefresh: (enableAutoRefresh: boolean) => void
3333
onEnableAutoRefresh?: (enableAutoRefresh: boolean, refreshRate: string) => void
3434
onChangeAutoRefreshRate?: (enableAutoRefresh: boolean, refreshRate: string) => void
3535
}
@@ -49,7 +49,7 @@ const AutoRefresh = ({
4949
onChangeAutoRefreshRate,
5050
}: Props) => {
5151
let intervalText: NodeJS.Timeout
52-
let timeoutRefresh: NodeJS.Timeout
52+
let intervalRefresh: NodeJS.Timeout
5353

5454
const [refreshMessage, setRefreshMessage] = useState(NOW)
5555
const [isPopoverOpen, setIsPopoverOpen] = useState(false)
@@ -74,7 +74,7 @@ const AutoRefresh = ({
7474
useEffect(() => {
7575
if (turnOffAutoRefresh && enableAutoRefresh) {
7676
setEnableAutoRefresh(false)
77-
clearInterval(timeoutRefresh)
77+
clearInterval(intervalRefresh)
7878
}
7979
}, [turnOffAutoRefresh])
8080

@@ -96,20 +96,20 @@ const AutoRefresh = ({
9696
updateLastRefresh()
9797

9898
if (enableAutoRefresh && !loading) {
99-
timeoutRefresh = setInterval(() => {
99+
intervalRefresh = setInterval(() => {
100100
if (document.hidden) return
101101

102102
handleRefresh()
103103
}, +refreshRate * 1_000)
104104
} else {
105-
clearInterval(timeoutRefresh)
105+
clearInterval(intervalRefresh)
106106
}
107107

108108
if (enableAutoRefresh) {
109109
updateAutoRefreshText(refreshRate)
110110
}
111111

112-
return () => clearInterval(timeoutRefresh)
112+
return () => clearInterval(intervalRefresh)
113113
}, [enableAutoRefresh, refreshRate, loading, lastRefreshTime])
114114

115115
const getLastRefreshDelta = (time:Nullable<number>) => (Date.now() - (time || 0)) / 1_000

redisinsight/ui/src/pages/browser/components/key-details/KeyDetailsWrapper.tsx

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useEffect } from 'react'
2-
import { useDispatch } from 'react-redux'
2+
import { useDispatch, useSelector } from 'react-redux'
33
import {
44
deleteKeyAction,
55
editKey,
@@ -15,7 +15,14 @@ import { fetchString, resetStringValue } from 'uiSrc/slices/browser/string'
1515
import { refreshSetMembersAction } from 'uiSrc/slices/browser/set'
1616
import { refreshListElementsAction } from 'uiSrc/slices/browser/list'
1717
import { fetchReJSON } from 'uiSrc/slices/browser/rejson'
18-
import { refreshStreamEntries } from 'uiSrc/slices/browser/stream'
18+
import {
19+
fetchConsumerGroups,
20+
fetchConsumerMessages,
21+
fetchConsumers,
22+
refreshStreamEntries,
23+
streamSelector,
24+
} from 'uiSrc/slices/browser/stream'
25+
import { StreamViewType } from 'uiSrc/slices/interfaces/stream'
1926
import KeyDetails from './KeyDetails/KeyDetails'
2027

2128
export interface Props {
@@ -39,6 +46,8 @@ const KeyDetailsWrapper = (props: Props) => {
3946
keyProp
4047
} = props
4148

49+
const { viewType: streamViewType } = useSelector(streamSelector)
50+
4251
const dispatch = useDispatch()
4352

4453
useEffect(() => {
@@ -90,7 +99,18 @@ const KeyDetailsWrapper = (props: Props) => {
9099
break
91100
}
92101
case KeyTypes.Stream: {
93-
dispatch(refreshStreamEntries(key, resetData))
102+
if (streamViewType === StreamViewType.Data) {
103+
dispatch(refreshStreamEntries(key, resetData))
104+
}
105+
if (streamViewType === StreamViewType.Groups) {
106+
dispatch<any>(fetchConsumerGroups(resetData))
107+
}
108+
if (streamViewType === StreamViewType.Consumers) {
109+
dispatch<any>(fetchConsumers(resetData))
110+
}
111+
if (streamViewType === StreamViewType.Messages) {
112+
dispatch<any>(fetchConsumerMessages(resetData))
113+
}
94114
break
95115
}
96116
default:
Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import React from 'react'
22
import { instance, mock } from 'ts-mockito'
3-
import { render } from 'uiSrc/utils/test-utils'
4-
import StreamDataViewWrapper, { Props } from './StreamDetailsWrapper'
3+
import { render, screen } from 'uiSrc/utils/test-utils'
4+
import StreamDetailsWrapper, { Props } from './StreamDetailsWrapper'
55

66
const mockedProps = mock<Props>()
77

88
describe('StreamDetailsWrapper', () => {
99
it('should render', () => {
10-
expect(render(<StreamDataViewWrapper {...instance(mockedProps)} />)).toBeTruthy()
10+
expect(render(<StreamDetailsWrapper {...instance(mockedProps)} />)).toBeTruthy()
11+
})
12+
13+
it('should render Stream Data container', () => {
14+
render(<StreamDetailsWrapper {...instance(mockedProps)} />)
15+
16+
expect(screen.getByTestId('stream-entries-container')).toBeInTheDocument()
1117
})
1218
})

redisinsight/ui/src/pages/browser/components/stream-details/StreamDetailsWrapper.tsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ import {
1515
fetchStreamEntries
1616
} from 'uiSrc/slices/browser/stream'
1717
import { StreamViewType } from 'uiSrc/slices/interfaces/stream'
18-
1918
import { connectedInstanceSelector } from 'uiSrc/slices/instances/instances'
2019
import { getNextId, getTimestampFromId } from 'uiSrc/utils/streamUtils'
2120
import { SortOrder } from 'uiSrc/constants'
2221
import { SCAN_COUNT_DEFAULT } from 'uiSrc/constants/api'
2322
import { selectedKeyDataSelector } from 'uiSrc/slices/browser/keys'
2423
import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry'
25-
import { GetStreamEntriesResponse } from 'apiSrc/modules/browser/dto/stream.dto'
2624
import RangeFilter from 'uiSrc/components/range-filter'
25+
import { GetStreamEntriesResponse } from 'apiSrc/modules/browser/dto/stream.dto'
26+
2727
import ConsumersViewWrapper from './consumers-view'
2828
import GroupsViewWrapper from './groups-view'
2929
import MessagesViewWrapper from './messages-view'
@@ -40,11 +40,7 @@ const StreamDetailsWrapper = (props: Props) => {
4040
const { viewType, loading, sortOrder: entryColumnSortOrder } = useSelector(streamSelector)
4141
const { loading: loadingGroups } = useSelector(streamGroupsSelector)
4242
const { start, end } = useSelector(streamRangeSelector)
43-
const {
44-
firstEntry,
45-
lastEntry,
46-
entries,
47-
} = useSelector(streamDataSelector)
43+
const { firstEntry, lastEntry, entries, } = useSelector(streamDataSelector)
4844
const { name: key } = useSelector(selectedKeyDataSelector) ?? { name: '' }
4945
const { id: instanceId } = useSelector(connectedInstanceSelector)
5046

@@ -80,7 +76,7 @@ const StreamDetailsWrapper = (props: Props) => {
8076
}, [lastEntryTimeStamp])
8177

8278
const loadMoreItems = () => {
83-
const lastLoadedEntryId = last(entries)?.id
79+
const lastLoadedEntryId = last(entries)?.id ?? ''
8480
const lastLoadedEntryTimeStamp = getTimestampFromId(lastLoadedEntryId)
8581

8682
const lastRangeEntryTimestamp = end ? parseInt(end, 10) : getTimestampFromId(lastEntry?.id)
@@ -189,6 +185,7 @@ const StreamDetailsWrapper = (props: Props) => {
189185
)}
190186
{shouldFilterRender ? (
191187
<RangeFilter
188+
disabled={viewType !== StreamViewType.Data}
192189
max={lastEntryTimeStamp}
193190
min={firstEntryTimeStamp}
194191
start={startNumber}
Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
import React from 'react'
22
import { instance, mock } from 'ts-mockito'
33
import { render } from 'uiSrc/utils/test-utils'
4-
import GroupsView, { Props } from './ConsumersView'
4+
import { ConsumerDto } from 'apiSrc/modules/browser/dto/stream.dto'
5+
import ConsumersView, { Props } from './ConsumersView'
56

67
const mockedProps = mock<Props>()
8+
const mockConsumers: ConsumerDto[] = [{
9+
name: 'test',
10+
idle: 123,
11+
pending: 321,
12+
}, {
13+
name: 'test2',
14+
idle: 13,
15+
pending: 31,
16+
}]
717

8-
describe('GroupsView', () => {
18+
describe('ConsumersView', () => {
919
it('should render', () => {
10-
expect(render(<GroupsView {...instance(mockedProps)} />)).toBeTruthy()
20+
expect(render(<ConsumersView {...instance(mockedProps)} data={mockConsumers} />)).toBeTruthy()
1121
})
1222
})

redisinsight/ui/src/pages/browser/components/stream-details/consumers-view/ConsumersView/ConsumersView.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from 'react'
1+
import React, { useEffect, useState } from 'react'
22
import { useSelector } from 'react-redux'
33
import cx from 'classnames'
44
import { orderBy } from 'lodash'
@@ -16,8 +16,6 @@ import styles from './styles.module.scss'
1616

1717
const headerHeight = 60
1818
const rowHeight = 54
19-
const actionsWidth = 54
20-
const minColumnWidth = 190
2119
const noItemsMessageString = 'Your Consumer Group has no Consumers available.'
2220

2321
export interface Props {
@@ -36,13 +34,17 @@ const ConsumersView = (props: Props) => {
3634

3735
const [consumers, setConsumers] = useState(data)
3836
const [sortedColumnName, setSortedColumnName] = useState<string>('name')
39-
const [sortedColumnOrder, setSortedColumnOrder] = useState<SortOrder>(SortOrder.DESC)
37+
const [sortedColumnOrder, setSortedColumnOrder] = useState<SortOrder>(SortOrder.ASC)
38+
39+
useEffect(() => {
40+
setConsumers(orderBy(data, sortedColumnName, sortedColumnOrder?.toLowerCase()))
41+
}, [data])
4042

4143
const onChangeSorting = (column: any, order: SortOrder) => {
4244
setSortedColumnName(column)
4345
setSortedColumnOrder(order)
4446

45-
setConsumers(orderBy(consumers, 'name', order?.toLowerCase()))
47+
setConsumers(orderBy(consumers, column, order?.toLowerCase()))
4648
}
4749

4850
return (
@@ -54,24 +56,24 @@ const ConsumersView = (props: Props) => {
5456
styles.container,
5557
{ footerOpened: isFooterOpen }
5658
)}
57-
data-test-id="stream-consumers-container"
59+
data-testid="stream-consumers-container"
5860
>
5961
<VirtualTable
6062
hideProgress
6163
onRowClick={onSelectConsumer}
6264
selectable={false}
6365
keyName={key}
64-
totalItemsCount={data.length}
65-
headerHeight={data?.length ? headerHeight : 0}
66+
totalItemsCount={consumers.length}
67+
headerHeight={consumers?.length ? headerHeight : 0}
6668
rowHeight={rowHeight}
6769
columns={columns}
6870
footerHeight={0}
6971
loading={loading}
70-
items={data}
72+
items={consumers}
7173
onWheel={onClosePopover}
7274
onChangeSorting={onChangeSorting}
7375
noItemsMessage={noItemsMessageString}
74-
sortedColumn={data?.length ? {
76+
sortedColumn={consumers?.length ? {
7577
column: sortedColumnName,
7678
order: sortedColumnOrder,
7779
} : undefined}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
import GroupsView from './ConsumersView'
1+
import ConsumersView from './ConsumersView'
22

3-
export default GroupsView
3+
export * from './ConsumersView'
4+
5+
export default ConsumersView

redisinsight/ui/src/pages/browser/components/stream-details/consumers-view/ConsumersView/styles.module.scss

Lines changed: 0 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -4,79 +4,9 @@
44
width: 100%;
55
padding-top: 3px;
66
background-color: var(--euiColorEmptyShade);
7-
8-
:global {
9-
.ReactVirtualized__Grid__innerScrollContainer {
10-
.ReactVirtualized__Table__rowColumn {
11-
border-right: 1px solid var(--tableDarkestBorderColor) !important;
12-
13-
&:last-of-type,
14-
&:nth-last-of-type(2) {
15-
border-right: none !important;
16-
}
17-
}
18-
19-
.ReactVirtualized__Table__row {
20-
border-bottom: 1px solid var(--tableDarkestBorderColor) !important;
21-
&:last-of-type {
22-
border-bottom: none !important;
23-
}
24-
}
25-
26-
& > div:hover {
27-
background: var(--euiColorLightestShade);
28-
29-
.value-table-actions {
30-
background-color: var(--euiColorLightestShade) !important;
31-
}
32-
33-
.streamEntry {
34-
color: var(--inputTextColor) !important;
35-
}
36-
37-
.streamEntryId {
38-
color: var(--euiTextSubduedColor) !important;
39-
}
40-
}
41-
}
42-
43-
.ReactVirtualized__Table__headerRow {
44-
border: none !important;
45-
}
46-
47-
.ReactVirtualized__Table__Grid {
48-
border: 1px solid var(--tableDarkestBorderColor) !important;
49-
}
50-
}
51-
52-
.cellHeader {
53-
border: none !important;
54-
}
55-
}
56-
57-
:global(.streamEntry) {
58-
color: var(--euiTextSubduedColor) !important;
59-
white-space: normal;
60-
max-width: 100%;
61-
word-break: break-all;
62-
}
63-
64-
:global(.streamEntryId) {
65-
color: var(--euiColorMediumShade) !important;
66-
display: flex;
67-
}
68-
69-
:global(.stream-entry-actions) {
70-
margin-left: -5px;
717
}
728

739
.actions,
7410
.actionsHeader {
7511
width: 54px;
7612
}
77-
78-
.actions {
79-
:global(.value-table-actions) {
80-
background-color: var(--euiColorEmptyShade) !important;
81-
}
82-
}

0 commit comments

Comments
 (0)