From 74d8e771fa3d9e24c79d5fe7452f0676cc1d8637 Mon Sep 17 00:00:00 2001 From: Amir Allayarov Date: Fri, 20 May 2022 15:47:13 +0400 Subject: [PATCH 1/3] #RI-2928, RI-2921, RI-2914, RI-2924, RI-2927 --- .../components/range-filter/RangeFilter.tsx | 18 +++--- .../StreamDetails/StreamDetails.tsx | 60 +++++++++++++------ .../stream-details/StreamDetailsWrapper.tsx | 2 +- redisinsight/ui/src/slices/browser/stream.ts | 15 +---- 4 files changed, 51 insertions(+), 44 deletions(-) diff --git a/redisinsight/ui/src/components/range-filter/RangeFilter.tsx b/redisinsight/ui/src/components/range-filter/RangeFilter.tsx index aa69302d8c..a11e13523f 100644 --- a/redisinsight/ui/src/components/range-filter/RangeFilter.tsx +++ b/redisinsight/ui/src/components/range-filter/RangeFilter.tsx @@ -14,6 +14,7 @@ export interface Props { end: number handleChangeStart: (value: number) => void handleChangeEnd: (value: number) => void + handleResetFilter: () => void } function usePrevious(value: any) { @@ -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) @@ -39,15 +40,7 @@ const RangeFilter = (props: Props) => { const maxValRef = useRef(null) const range = useRef(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 } }) => { @@ -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) { @@ -171,7 +167,7 @@ const RangeFilter = (props: Props) => { data-testid="range-filter-btn" className={styles.resetButton} type="button" - onClick={resetFilter} + onClick={handleResetFilter} > {buttonString} diff --git a/redisinsight/ui/src/pages/browser/components/stream-details/StreamDetails/StreamDetails.tsx b/redisinsight/ui/src/pages/browser/components/stream-details/StreamDetails/StreamDetails.tsx index 059d6c3af7..9ebbcee16d 100644 --- a/redisinsight/ui/src/pages/browser/components/stream-details/StreamDetails/StreamDetails.tsx +++ b/redisinsight/ui/src/pages/browser/components/stream-details/StreamDetails/StreamDetails.tsx @@ -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[] @@ -72,17 +84,17 @@ 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, ) @@ -90,6 +102,15 @@ const StreamDetails = (props: Props) => { } } + const loadEntries = () => { + dispatch(fetchStreamEntries( + key, + SCAN_COUNT_DEFAULT, + sortedColumnOrder, + false + )) + } + const onChangeSorting = (column: any, order: SortOrder) => { setSortedColumnName(column) setSortedColumnOrder(order) @@ -100,6 +121,7 @@ const StreamDetails = (props: Props) => { const handleChangeStartFilter = useCallback( (value: number) => { dispatch(updateStart(value.toString())) + loadEntries() }, [] ) @@ -107,6 +129,7 @@ const StreamDetails = (props: Props) => { const handleChangeEndFilter = useCallback( (value: number) => { dispatch(updateEnd(value.toString())) + loadEntries() }, [] ) @@ -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())) @@ -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 ? ( @@ -150,6 +171,7 @@ const StreamDetails = (props: Props) => { end={endNumber} handleChangeStart={handleChangeStartFilter} handleChangeEnd={handleChangeEndFilter} + handleResetFilter={handleResetFilter} /> ) : ( @@ -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, diff --git a/redisinsight/ui/src/pages/browser/components/stream-details/StreamDetailsWrapper.tsx b/redisinsight/ui/src/pages/browser/components/stream-details/StreamDetailsWrapper.tsx index 82ae7b8010..5bcb736f20 100644 --- a/redisinsight/ui/src/pages/browser/components/stream-details/StreamDetailsWrapper.tsx +++ b/redisinsight/ui/src/pages/browser/components/stream-details/StreamDetailsWrapper.tsx @@ -177,7 +177,7 @@ const StreamDetailsWrapper = (props: Props) => { - This Entry will be removed from + Entry {id} will be removed from
{key} diff --git a/redisinsight/ui/src/slices/browser/stream.ts b/redisinsight/ui/src/slices/browser/stream.ts index e3e50137b1..3d2b60486c 100644 --- a/redisinsight/ui/src/slices/browser/stream.ts +++ b/redisinsight/ui/src/slices/browser/stream.ts @@ -1,11 +1,10 @@ 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' @@ -13,7 +12,6 @@ import { AddStreamEntriesDto, AddStreamEntriesResponse, GetStreamEntriesResponse, - StreamEntryDto, } from 'apiSrc/modules/browser/dto/stream.dto' import { AppDispatch, RootState } from '../store' import { StateStream } from '../interfaces/stream' @@ -108,14 +106,6 @@ const streamSlice = createSlice({ state.loading = false state.error = payload }, - removeEntriesFromList: (state, { payload }: PayloadAction) => { - remove(state.data?.entries, (entry: StreamEntryDto) => payload.includes(entry.id)) - - state.data = { - ...state.data, - total: state.data.total - 1, - } - }, updateStart: (state, { payload }: PayloadAction) => { state.range.start = payload }, @@ -145,7 +135,6 @@ export const { removeStreamEntries, removeStreamEntriesSuccess, removeStreamEntriesFailure, - removeEntriesFromList, updateStart, updateEnd, cleanRangeFilter @@ -364,7 +353,7 @@ export function deleteStreamEntry(key: string, entries: string[]) { ) if (isStatusSuccessful(status)) { dispatch(removeStreamEntriesSuccess()) - dispatch(removeEntriesFromList(entries)) + dispatch(refreshStreamEntries(key, false)) dispatch(refreshKeyInfoAction(key)) dispatch(addMessageNotification( successMessages.REMOVED_KEY_VALUE( From fca98ff93c0dc543496769fd2da052434cc00d37 Mon Sep 17 00:00:00 2001 From: Amir Allayarov Date: Fri, 20 May 2022 15:57:54 +0400 Subject: [PATCH 2/3] test fxi --- .../ui/src/components/range-filter/RangeFilter.spec.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/redisinsight/ui/src/components/range-filter/RangeFilter.spec.tsx b/redisinsight/ui/src/components/range-filter/RangeFilter.spec.tsx index 8e3c2d81e7..3469b9e1a2 100644 --- a/redisinsight/ui/src/components/range-filter/RangeFilter.spec.tsx +++ b/redisinsight/ui/src/components/range-filter/RangeFilter.spec.tsx @@ -53,12 +53,10 @@ describe('RangeFilter', () => { }) it('should reset start and end values on press Reset buttons', () => { const handleChangeEnd = jest.fn() - const handleChangeStart = jest.fn() render( { fireEvent.click(resetBtn) - expect(handleChangeEnd).toBeCalledWith(120) - expect(handleChangeStart).toBeCalledWith(1) + expect(handleChangeEnd).toBeCalledTimes(1) }) }) From 4acefec3c05a353182514583919cf3949830203a Mon Sep 17 00:00:00 2001 From: Amir Allayarov Date: Fri, 20 May 2022 16:05:32 +0400 Subject: [PATCH 3/3] fix filter test --- .../ui/src/components/range-filter/RangeFilter.spec.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/redisinsight/ui/src/components/range-filter/RangeFilter.spec.tsx b/redisinsight/ui/src/components/range-filter/RangeFilter.spec.tsx index 3469b9e1a2..b8452159f0 100644 --- a/redisinsight/ui/src/components/range-filter/RangeFilter.spec.tsx +++ b/redisinsight/ui/src/components/range-filter/RangeFilter.spec.tsx @@ -51,13 +51,13 @@ describe('RangeFilter', () => { ) expect(handleChangeEnd).toBeCalledTimes(1) }) - it('should reset start and end values on press Reset buttons', () => { - const handleChangeEnd = jest.fn() + it('should call handleResetFilter onClick reset button', () => { + const handleResetFilter = jest.fn() render( { fireEvent.click(resetBtn) - expect(handleChangeEnd).toBeCalledTimes(1) + expect(handleResetFilter).toBeCalledTimes(1) }) })