Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,13 @@ describe('RangeFilter', () => {
)
expect(handleChangeEnd).toBeCalledTimes(1)
})
it('should reset start and end values on press Reset buttons', () => {
const handleChangeEnd = jest.fn()
const handleChangeStart = jest.fn()
it('should call handleResetFilter onClick reset button', () => {
const handleResetFilter = jest.fn()

render(
<RangeFilter
{...instance(mockedProps)}
handleChangeStart={handleChangeStart}
handleChangeEnd={handleChangeEnd}
handleResetFilter={handleResetFilter}
start={1}
end={100}
min={1}
Expand All @@ -70,7 +68,6 @@ describe('RangeFilter', () => {

fireEvent.click(resetBtn)

expect(handleChangeEnd).toBeCalledWith(120)
expect(handleChangeStart).toBeCalledWith(1)
expect(handleResetFilter).toBeCalledTimes(1)
})
})
18 changes: 7 additions & 11 deletions redisinsight/ui/src/components/range-filter/RangeFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface Props {
end: number
handleChangeStart: (value: number) => void
handleChangeEnd: (value: number) => void
handleResetFilter: () => void
}

function usePrevious(value: any) {
Expand All @@ -25,7 +26,7 @@ function usePrevious(value: any) {
}

const RangeFilter = (props: Props) => {
const { max, min, start, end, handleChangeStart, handleChangeEnd } = props
const { max, min, start, end, handleChangeStart, handleChangeEnd, handleResetFilter } = props

const [startVal, setStartVal] = useState(start)
const [endVal, setEndVal] = useState(end)
Expand All @@ -39,15 +40,7 @@ const RangeFilter = (props: Props) => {
const maxValRef = useRef<HTMLInputElement>(null)
const range = useRef<HTMLInputElement>(null)

const prevValue = usePrevious({ max }) ?? { max: 0 }

const resetFilter = useCallback(
() => {
handleChangeStart(min)
handleChangeEnd(max)
},
[min, max]
)
const prevValue = usePrevious({ max, min }) ?? { max: 0, min: 0 }

const onChangeStart = useCallback(
({ target: { value } }) => {
Expand Down Expand Up @@ -112,6 +105,9 @@ const RangeFilter = (props: Props) => {
if (max && prevValue && prevValue.max !== max && end === prevValue.max) {
handleChangeEnd(max)
}
if (min && prevValue && prevValue.min !== min && start === prevValue.min) {
handleChangeStart(min)
}
}, [prevValue])

if (start === 0 && end === 0) {
Expand Down Expand Up @@ -171,7 +167,7 @@ const RangeFilter = (props: Props) => {
data-testid="range-filter-btn"
className={styles.resetButton}
type="button"
onClick={resetFilter}
onClick={handleResetFilter}
>
{buttonString}
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,25 @@ const headerHeight = 60
const rowHeight = 54
const actionsWidth = 54
const minColumnWidth = 190
const xrangeIdPrefix = '('
const noItemsMessageString = 'There are no Entries in the Stream.'
const noItemsMessageInEmptyStream = 'There are no Entries in the Stream.'
const noItemsMessageInRange = 'No results found.'

interface IStreamEntry extends StreamEntryDto {
editing: boolean
}

const getNextId = (id: string, sortOrder: SortOrder): string => {
const splittedId = id.split('-')
// if we don't have prefix
if (splittedId.length === 1) {
return `${id}-1`
}
if (sortOrder === SortOrder.DESC) {
return splittedId[1] === '0' ? `${parseInt(splittedId[0], 10) - 1}` : `${splittedId[0]}-${+splittedId[1] - 1}`
}
return `${splittedId[0]}-${+splittedId[1] + 1}`
}

export interface Props {
data: IStreamEntry[]
columns: ITableColumn[]
Expand Down Expand Up @@ -72,24 +84,33 @@ const StreamDetails = (props: Props) => {
return false
}
return sortedColumnOrder === SortOrder.ASC
? lastLoadedEntryTimeStamp > lastRangeEntryTimestamp
: lastLoadedEntryTimeStamp < firstRangeEntryTimestamp
? lastLoadedEntryTimeStamp <= lastRangeEntryTimestamp
: lastLoadedEntryTimeStamp >= firstRangeEntryTimestamp
}
const previousLoadedString = `${xrangeIdPrefix + lastLoadedEntryId}`
const nextId = getNextId(lastLoadedEntryId, sortedColumnOrder)

if (shouldLoadMore()) {
dispatch(
fetchMoreStreamEntries(
key,
sortedColumnOrder === SortOrder.DESC ? start : previousLoadedString,
sortedColumnOrder === SortOrder.DESC ? previousLoadedString : end,
sortedColumnOrder === SortOrder.DESC ? start : nextId,
sortedColumnOrder === SortOrder.DESC ? nextId : end,
SCAN_COUNT_DEFAULT,
sortedColumnOrder,
)
)
}
}

const loadEntries = () => {
dispatch(fetchStreamEntries(
key,
SCAN_COUNT_DEFAULT,
sortedColumnOrder,
false
))
}

const onChangeSorting = (column: any, order: SortOrder) => {
setSortedColumnName(column)
setSortedColumnOrder(order)
Expand All @@ -100,13 +121,15 @@ const StreamDetails = (props: Props) => {
const handleChangeStartFilter = useCallback(
(value: number) => {
dispatch(updateStart(value.toString()))
loadEntries()
},
[]
)

const handleChangeEndFilter = useCallback(
(value: number) => {
dispatch(updateEnd(value.toString()))
loadEntries()
},
[]
)
Expand All @@ -117,6 +140,15 @@ const StreamDetails = (props: Props) => {
const startNumber = useMemo(() => (start === '' ? 0 : parseInt(start, 10)), [start])
const endNumber = useMemo(() => (end === '' ? 0 : parseInt(end, 10)), [end])

const handleResetFilter = useCallback(
() => {
dispatch(updateStart(firstEntryTimeStamp.toString()))
dispatch(updateEnd(lastEntryTimeStamp.toString()))
loadEntries()
},
[lastEntryTimeStamp, firstEntryTimeStamp]
)

useEffect(() => {
if (start === '' && firstEntry?.id !== '') {
dispatch(updateStart(firstEntryTimeStamp.toString()))
Expand All @@ -129,17 +161,6 @@ const StreamDetails = (props: Props) => {
}
}, [lastEntryTimeStamp])

useEffect(() => {
if (start !== '' && end !== '') {
dispatch(fetchStreamEntries(
key,
SCAN_COUNT_DEFAULT,
sortedColumnOrder,
false
))
}
}, [start, end])

return (
<>
{shouldFilterRender ? (
Expand All @@ -150,6 +171,7 @@ const StreamDetails = (props: Props) => {
end={endNumber}
handleChangeStart={handleChangeStartFilter}
handleChangeEnd={handleChangeEndFilter}
handleResetFilter={handleResetFilter}
/>
)
: (
Expand Down Expand Up @@ -191,7 +213,7 @@ const StreamDetails = (props: Props) => {
totalItemsCount={total}
onWheel={onClosePopover}
onChangeSorting={onChangeSorting}
noItemsMessage={noItemsMessageString}
noItemsMessage={isNull(firstEntry) && isNull(lastEntry) ? noItemsMessageInEmptyStream : noItemsMessageInRange}
tableWidth={columns.length * minColumnWidth - actionsWidth}
sortedColumn={entries?.length ? {
column: sortedColumnName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ const StreamDetailsWrapper = (props: Props) => {
<PopoverDelete
text={(
<>
This Entry will be removed from
Entry {id} will be removed from
<br />
{key}
</>
Expand Down
15 changes: 2 additions & 13 deletions redisinsight/ui/src/slices/browser/stream.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import axios, { AxiosError, CancelTokenSource } from 'axios'
import { remove } from 'lodash'

import { apiService } from 'uiSrc/services'
import { SCAN_COUNT_DEFAULT } from 'uiSrc/constants/api'
import { ApiEndpoints, SortOrder } from 'uiSrc/constants'
import { fetchKeyInfo, refreshKeyInfoAction, } from 'uiSrc/slices/browser/keys'
import { refreshKeyInfoAction, } from 'uiSrc/slices/browser/keys'
import { getApiErrorMessage, getUrl, isStatusSuccessful, Maybe, Nullable } from 'uiSrc/utils'
import { getStreamRangeStart, getStreamRangeEnd } from 'uiSrc/utils/streamUtils'
import successMessages from 'uiSrc/components/notifications/success-messages'
import {
AddStreamEntriesDto,
AddStreamEntriesResponse,
GetStreamEntriesResponse,
StreamEntryDto,
} from 'apiSrc/modules/browser/dto/stream.dto'
import { AppDispatch, RootState } from '../store'
import { StateStream } from '../interfaces/stream'
Expand Down Expand Up @@ -108,14 +106,6 @@ const streamSlice = createSlice({
state.loading = false
state.error = payload
},
removeEntriesFromList: (state, { payload }: PayloadAction<string[]>) => {
remove(state.data?.entries, (entry: StreamEntryDto) => payload.includes(entry.id))

state.data = {
...state.data,
total: state.data.total - 1,
}
},
updateStart: (state, { payload }: PayloadAction<string>) => {
state.range.start = payload
},
Expand Down Expand Up @@ -145,7 +135,6 @@ export const {
removeStreamEntries,
removeStreamEntriesSuccess,
removeStreamEntriesFailure,
removeEntriesFromList,
updateStart,
updateEnd,
cleanRangeFilter
Expand Down Expand Up @@ -364,7 +353,7 @@ export function deleteStreamEntry(key: string, entries: string[]) {
)
if (isStatusSuccessful(status)) {
dispatch(removeStreamEntriesSuccess())
dispatch(removeEntriesFromList(entries))
dispatch<any>(refreshStreamEntries(key, false))
dispatch<any>(refreshKeyInfoAction(key))
dispatch(addMessageNotification(
successMessages.REMOVED_KEY_VALUE(
Expand Down