Skip to content

Commit 0960e72

Browse files
committed
#RI-2936 - integrations with list
1 parent bcb2308 commit 0960e72

File tree

5 files changed

+99
-51
lines changed

5 files changed

+99
-51
lines changed

redisinsight/ui/src/constants/texts.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,12 @@ export const ScanNoResultsFoundText = (
2525
</EuiText>
2626
</>
2727
)
28+
29+
export const lastDeliveredIDTooltipText = (
30+
<>
31+
Specify the ID of the last delivered entry in the stream from the new group's perspective.
32+
<EuiSpacer size="xs" />
33+
Otherwise, <b>$</b> represents the ID of the last entry in the stream,&nbsp;
34+
<b>0</b> fetches the entire stream from the beginning.
35+
</>
36+
)

redisinsight/ui/src/pages/browser/components/key-details-add-items/add-stream-group/AddStreamGroup.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
import cx from 'classnames'
1414
import React, { ChangeEvent, useEffect, useState } from 'react'
1515
import { useDispatch, useSelector } from 'react-redux'
16+
import { lastDeliveredIDTooltipText } from 'uiSrc/constants/texts'
1617

1718
import { selectedKeyDataSelector } from 'uiSrc/slices/browser/keys'
1819
import { addNewGroupAction } from 'uiSrc/slices/browser/stream'
@@ -111,14 +112,7 @@ const AddStreamGroup = (props: Props) => {
111112
className={styles.entryIdTooltip}
112113
position="left"
113114
title="Enter Valid ID, 0 or $"
114-
content={(
115-
<>
116-
Specify the ID of the last delivered entry in the stream from the new group's perspective.
117-
<EuiSpacer size="xs" />
118-
Otherwise, <b>$</b> represents the ID of the last entry in the stream,&nbsp;
119-
<b>0</b> fetches the entire stream from the beginning.
120-
</>
121-
)}
115+
content={lastDeliveredIDTooltipText}
122116
>
123117
<EuiIcon type="iInCircle" style={{ cursor: 'pointer' }} />
124118
</EuiToolTip>

redisinsight/ui/src/pages/browser/components/stream-details/groups-view/GroupsView/styles.module.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,15 @@
1818
.editLastId {
1919
margin-right: 4px;
2020
}
21+
22+
.idText, .error {
23+
display: inline-block;
24+
color: var(--euiColorMediumShade);
25+
font: normal normal normal 12px/18px Graphik;
26+
margin-top: 6px;
27+
padding-right: 6px;
28+
}
29+
30+
.error {
31+
color: var(--euiColorDangerText);
32+
}

redisinsight/ui/src/pages/browser/components/stream-details/groups-view/GroupsViewWrapper.tsx

Lines changed: 55 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { EuiFieldText, EuiIcon, EuiSpacer, EuiText, EuiToolTip } from '@elastic/eui'
1+
import { EuiFieldText, EuiIcon, EuiText, EuiToolTip } from '@elastic/eui'
22
import React, { useCallback, useEffect, useState } from 'react'
33
import { useDispatch, useSelector } from 'react-redux'
44
import PopoverItemEditor from 'uiSrc/components/popover-item-editor'
5-
import { selectedKeyDataSelector } from 'uiSrc/slices/browser/keys'
5+
import { lastDeliveredIDTooltipText } from 'uiSrc/constants/texts'
6+
import { selectedKeyDataSelector, updateSelectedKeyRefreshTime } from 'uiSrc/slices/browser/keys'
67

78
import {
89
streamGroupsSelector,
@@ -13,12 +14,13 @@ import {
1314
} from 'uiSrc/slices/browser/stream'
1415
import { ITableColumn } from 'uiSrc/components/virtual-table/interfaces'
1516
import PopoverDelete from 'uiSrc/pages/browser/components/popover-delete/PopoverDelete'
17+
import { consumerGroupIdRegex } from 'uiSrc/utils'
1618
import { getFormatTime } from 'uiSrc/utils/streamUtils'
1719
import { KeyTypes, TableCellTextAlignment } from 'uiSrc/constants'
1820
import { connectedInstanceSelector } from 'uiSrc/slices/instances/instances'
1921
import { StreamViewType } from 'uiSrc/slices/interfaces/stream'
20-
import { updateSelectedKeyRefreshTime } from 'uiSrc/slices/browser/keys'
21-
import { ConsumerGroupDto } from 'apiSrc/modules/browser/dto/stream.dto'
22+
23+
import { ConsumerGroupDto, UpdateConsumerGroupDto } from 'apiSrc/modules/browser/dto/stream.dto'
2224

2325
import GroupsView from './GroupsView'
2426

@@ -39,15 +41,18 @@ const GroupsViewWrapper = (props: Props) => {
3941
const {
4042
lastRefreshTime,
4143
data: loadedGroups = [],
44+
loading
4245
} = useSelector(streamGroupsSelector)
4346
const { name: key = '' } = useSelector(connectedInstanceSelector)
44-
const { name: selectedKey } = useSelector(selectedKeyDataSelector)
47+
const { name: selectedKey } = useSelector(selectedKeyDataSelector) ?? {}
4548

4649
const dispatch = useDispatch()
4750

4851
const [groups, setGroups] = useState<IConsumerGroup[]>([])
4952
const [deleting, setDeleting] = useState<string>('')
5053
const [editValue, setEditValue] = useState<string>('')
54+
const [idError, setIdError] = useState<string>('')
55+
const [isIdFocused, setIsIdFocused] = useState<boolean>(false)
5156

5257
useEffect(() => {
5358
dispatch(updateSelectedKeyRefreshTime(lastRefreshTime))
@@ -62,6 +67,14 @@ const GroupsViewWrapper = (props: Props) => {
6267
setGroups(streamItem)
6368
}, [loadedGroups, deleting])
6469

70+
useEffect(() => {
71+
if (!consumerGroupIdRegex.test(editValue)) {
72+
setIdError('ID format is not correct')
73+
return
74+
}
75+
setIdError('')
76+
}, [editValue])
77+
6578
const closePopover = useCallback(() => {
6679
setDeleting('')
6780
}, [])
@@ -98,12 +111,14 @@ const GroupsViewWrapper = (props: Props) => {
98111
}
99112

100113
const handleApplyEditId = (groupName: string) => {
101-
const data = {
102-
keyName: selectedKey,
103-
name: groupName,
104-
lastDeliveredId: editValue
114+
if (!!groupName.length && !idError && selectedKey) {
115+
const data: UpdateConsumerGroupDto = {
116+
keyName: selectedKey,
117+
name: groupName,
118+
lastDeliveredId: editValue
119+
}
120+
dispatch(modifyLastDeliveredIdAction(data))
105121
}
106-
dispatch(modifyLastDeliveredIdAction(data))
107122
}
108123

109124
const columns: ITableColumn[] = [
@@ -193,43 +208,44 @@ const GroupsViewWrapper = (props: Props) => {
193208
maxWidth: actionsWidth,
194209
minWidth: actionsWidth,
195210
render: function Actions(_act: any, { lastDeliveredId, name }: ConsumerGroupDto) {
211+
const showIdError = !isIdFocused && idError
196212
return (
197213
<div>
198214
<PopoverItemEditor
199215
btnTestId={`edit-stream-last-id-${lastDeliveredId}`}
200216
onOpen={() => setEditValue(lastDeliveredId)}
201217
onApply={() => handleApplyEditId(name)}
202218
className={styles.editLastId}
219+
isDisabled={!editValue.length || !!idError}
220+
isLoading={loading}
203221
>
204-
<EuiFieldText
205-
fullWidth
206-
name="id"
207-
id="id"
208-
placeholder="ID*"
209-
value={editValue}
210-
onChange={(e: any) => setEditValue(e.target.value)}
211-
append={(
212-
<EuiToolTip
213-
anchorClassName="inputAppendIcon"
214-
className={styles.entryIdTooltip}
215-
position="left"
216-
title="Enter Valid ID, 0 or $"
217-
content={(
218-
<>
219-
Specify the ID of the last delivered entry in the stream from the new group's perspective.
220-
<EuiSpacer size="xs" />
221-
Otherwise, <b>$</b> represents the ID of the last entry in the stream,&nbsp;
222-
<b>0</b> fetches the entire stream from the beginning.
223-
</>
224-
)}
225-
>
226-
<EuiIcon type="iInCircle" style={{ cursor: 'pointer' }} />
227-
</EuiToolTip>
228-
)}
229-
style={{ width: 240 }}
230-
autoComplete="off"
231-
data-testid="id-field"
232-
/>
222+
<>
223+
<EuiFieldText
224+
fullWidth
225+
name="id"
226+
id="id"
227+
placeholder="ID*"
228+
value={editValue}
229+
onChange={(e: any) => setEditValue(e.target.value)}
230+
onBlur={() => setIsIdFocused(false)}
231+
onFocus={() => setIsIdFocused(true)}
232+
append={(
233+
<EuiToolTip
234+
anchorClassName="inputAppendIcon"
235+
position="left"
236+
title="Enter Valid ID, 0 or $"
237+
content={lastDeliveredIDTooltipText}
238+
>
239+
<EuiIcon type="iInCircle" style={{ cursor: 'pointer' }} />
240+
</EuiToolTip>
241+
)}
242+
style={{ width: 240 }}
243+
autoComplete="off"
244+
data-testid="last-id-field"
245+
/>
246+
{!showIdError && <span className={styles.idText} data-testid="id-help-text">Timestamp - Sequence Number or $</span>}
247+
{showIdError && <span className={styles.error} data-testid="id-error">{idError}</span>}
248+
</>
233249
</PopoverItemEditor>
234250
<PopoverDelete
235251
text={(

redisinsight/ui/src/slices/browser/stream.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
CreateConsumerGroupsDto,
1717
GetStreamEntriesResponse,
1818
PendingEntryDto,
19+
UpdateConsumerGroupDto,
1920
} from 'apiSrc/modules/browser/dto/stream.dto'
2021
import { AppDispatch, RootState } from '../store'
2122
import { StateStream, StreamViewType } from '../interfaces/stream'
@@ -171,6 +172,19 @@ const streamSlice = createSlice({
171172
state.groups.selectedGroup = payload
172173
},
173174

175+
modifyLastDeliveredId: (state) => {
176+
state.groups.loading = true
177+
},
178+
179+
modifyLastDeliveredIdSuccess: (state) => {
180+
state.groups.loading = false
181+
},
182+
183+
modifyLastDeliveredIdFailure: (state, { payload }) => {
184+
state.groups.loading = false
185+
state.groups.error = payload
186+
},
187+
174188
setSelectedConsumer: (state, { payload }) => {
175189
state.groups.selectedGroup = {
176190
...state.groups.selectedGroup,
@@ -248,6 +262,9 @@ export const {
248262
loadConsumerGroups,
249263
loadConsumerGroupsSuccess,
250264
loadConsumerGroupsFailure,
265+
modifyLastDeliveredId,
266+
modifyLastDeliveredIdSuccess,
267+
modifyLastDeliveredIdFailure,
251268
loadConsumersSuccess,
252269
loadConsumersFailure,
253270
loadConsumerMessagesSuccess,
@@ -643,12 +660,12 @@ export function fetchConsumerMessages(
643660

644661
// Asynchronous thunk action
645662
export function modifyLastDeliveredIdAction(
646-
data: any,
663+
data: UpdateConsumerGroupDto,
647664
onSuccess?: () => void,
648665
onFailed?: () => void
649666
) {
650667
return async (dispatch: AppDispatch, stateInit: () => RootState) => {
651-
//dispatch(addNewEntries())
668+
dispatch(modifyLastDeliveredId())
652669

653670
try {
654671
const state = stateInit()
@@ -662,7 +679,7 @@ export function modifyLastDeliveredIdAction(
662679
)
663680

664681
if (isStatusSuccessful(status)) {
665-
//dispatch(addNewEntriesSuccess())
682+
dispatch(modifyLastDeliveredIdSuccess())
666683
dispatch<any>(fetchConsumerGroups(false))
667684
keyName && dispatch<any>(refreshKeyInfoAction(keyName))
668685
onSuccess?.()
@@ -671,7 +688,7 @@ export function modifyLastDeliveredIdAction(
671688
const error = _err as AxiosError
672689
const errorMessage = getApiErrorMessage(error)
673690
dispatch(addErrorNotification(error))
674-
//dispatch(addNewEntriesFailure(errorMessage))
691+
dispatch(modifyLastDeliveredIdFailure(errorMessage))
675692
onFailed?.()
676693
}
677694
}

0 commit comments

Comments
 (0)