From 1e739d02814ba4ce0088752c65675cdf0fed38a1 Mon Sep 17 00:00:00 2001 From: Pavel Angelov Date: Mon, 9 Jun 2025 14:25:25 +0300 Subject: [PATCH 01/10] change label --- .../change-editor-type-button/ChangeEditorTypeButton.spec.tsx | 2 +- .../change-editor-type-button/ChangeEditorTypeButton.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.spec.tsx b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.spec.tsx index ae97c1de04..3708792bea 100644 --- a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.spec.tsx +++ b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.spec.tsx @@ -37,7 +37,7 @@ describe('ChangeEditorTypeButton', () => { await userEvent.hover(button) expect( - await screen.findByText('This JSON is too large to edit'), + await screen.findByText('This JSON document is too large to view or edit in full.'), ).toBeInTheDocument() }) diff --git a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.tsx b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.tsx index 6243117d94..e202a80882 100644 --- a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.tsx +++ b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.tsx @@ -19,7 +19,7 @@ const ChangeEditorTypeButton = ({ const isDisabled = isReadMode const tooltip = isReadMode - ? 'This JSON is too large to edit' + ? 'This JSON document is too large to view or edit in full.' : 'Edit value in text editor' return ( From 7824b871f341eb005396a125ae48ccc478e72a6c Mon Sep 17 00:00:00 2001 From: Pavel Angelov Date: Mon, 9 Jun 2025 18:01:51 +0300 Subject: [PATCH 02/10] introduce isWithinThreshold --- .../ChangeEditorTypeButton.tsx | 4 ++-- .../change-editor-type-button/useChangeEditorType.tsx | 4 ++-- redisinsight/ui/src/slices/browser/keys.ts | 11 +++++++++-- redisinsight/ui/src/slices/browser/rejson.ts | 5 +++++ redisinsight/ui/src/slices/interfaces/instances.ts | 1 + 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.tsx b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.tsx index e202a80882..8db3d7da5c 100644 --- a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.tsx +++ b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.tsx @@ -14,10 +14,10 @@ export type ChangeEditorTypeButtonProps = { const ChangeEditorTypeButton = ({ mode = ButtonMode.editable, }: ChangeEditorTypeButtonProps) => { - const { switchEditorType } = useChangeEditorType() + const { switchEditorType, isWithinThreshold } = useChangeEditorType() const isReadMode = mode === ButtonMode.readOnly - const isDisabled = isReadMode + const isDisabled = isReadMode || !isWithinThreshold const tooltip = isReadMode ? 'This JSON document is too large to view or edit in full.' : 'Edit value in text editor' diff --git a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/useChangeEditorType.tsx b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/useChangeEditorType.tsx index 1c77b1dca4..41d265a155 100644 --- a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/useChangeEditorType.tsx +++ b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/useChangeEditorType.tsx @@ -5,7 +5,7 @@ import { EditorType } from 'uiSrc/slices/interfaces' export const useChangeEditorType = () => { const dispatch = useDispatch() - const { editorType } = useSelector(rejsonSelector) + const { editorType, isWithinThreshold } = useSelector(rejsonSelector) const switchEditorType = useCallback(() => { const opposite = @@ -13,5 +13,5 @@ export const useChangeEditorType = () => { dispatch(setEditorType(opposite)) }, [dispatch, editorType]) - return { switchEditorType, editorType } + return { switchEditorType, editorType, isWithinThreshold } } diff --git a/redisinsight/ui/src/slices/browser/keys.ts b/redisinsight/ui/src/slices/browser/keys.ts index 1fe94a77c0..edbebacc33 100644 --- a/redisinsight/ui/src/slices/browser/keys.ts +++ b/redisinsight/ui/src/slices/browser/keys.ts @@ -1,7 +1,6 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit' import { cloneDeep, remove, get, isUndefined } from 'lodash' import axios, { AxiosError, CancelTokenSource } from 'axios' -import { useSelector } from 'react-redux' import { apiService, localStorageService } from 'uiSrc/services' import { ApiEndpoints, @@ -62,7 +61,12 @@ import { refreshZsetMembersAction, } from './zset' import { fetchSetMembers, refreshSetMembersAction } from './set' -import { fetchReJSON, setEditorType } from './rejson' +import { + fetchReJSON, + JSON_LENGTH_TO_FORCE_RETRIEVE, + setEditorType, + setIsWithinThreshold, +} from './rejson' import { setHashInitialState, fetchHashFields, @@ -808,6 +812,9 @@ export function fetchKeyInfo( if (data.type === KeyTypes.ReJSON) { dispatch(fetchReJSON(key, '$', data.length, resetData)) dispatch(setEditorType(EditorType.Default)) + dispatch( + setIsWithinThreshold(data.length <= JSON_LENGTH_TO_FORCE_RETRIEVE), + ) } if (data.type === KeyTypes.Stream) { const { viewType } = state.browser.stream diff --git a/redisinsight/ui/src/slices/browser/rejson.ts b/redisinsight/ui/src/slices/browser/rejson.ts index e9b648883a..2537efa922 100644 --- a/redisinsight/ui/src/slices/browser/rejson.ts +++ b/redisinsight/ui/src/slices/browser/rejson.ts @@ -48,6 +48,7 @@ export const initialState: InitialStateRejson = { type: '', }, editorType: EditorType.Default, + isWithinThreshold: true, } // A slice for recipes @@ -114,6 +115,9 @@ const rejsonSlice = createSlice({ setEditorType: (state, { payload }: PayloadAction) => { state.editorType = payload }, + setIsWithinThreshold: (state, { payload }: PayloadAction) => { + state.isWithinThreshold = payload + }, }, }) @@ -132,6 +136,7 @@ export const { removeRejsonKeySuccess, removeRejsonKeyFailure, setEditorType, + setIsWithinThreshold, } = rejsonSlice.actions // A selector diff --git a/redisinsight/ui/src/slices/interfaces/instances.ts b/redisinsight/ui/src/slices/interfaces/instances.ts index 4d6dd7f8c8..9d90aaa0de 100644 --- a/redisinsight/ui/src/slices/interfaces/instances.ts +++ b/redisinsight/ui/src/slices/interfaces/instances.ts @@ -497,6 +497,7 @@ export interface InitialStateRejson { error: Nullable data: GetRejsonRlResponse editorType: EditorType + isWithinThreshold: boolean } export interface ICredentialsRedisCluster { From eca4772b3da833fa160d6111a3d3d7a80228f6c9 Mon Sep 17 00:00:00 2001 From: Pavel Angelov Date: Tue, 10 Jun 2025 17:04:16 +0300 Subject: [PATCH 03/10] display the button when content is within threshold --- .../ChangeEditorTypeButton.tsx | 20 ++++--------------- .../change-editor-type-button/index.ts | 1 - .../useChangeEditorType.tsx | 9 ++++++++- .../rejson-details/RejsonDetails.tsx | 20 +++---------------- 4 files changed, 15 insertions(+), 35 deletions(-) diff --git a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.tsx b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.tsx index 8db3d7da5c..f1ed5317b9 100644 --- a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.tsx +++ b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.tsx @@ -2,23 +2,11 @@ import React from 'react' import { EuiButtonIcon, EuiToolTip } from '@elastic/eui' import { useChangeEditorType } from './useChangeEditorType' -export enum ButtonMode { - editable = 'editable', - readOnly = 'readOnly', -} - -export type ChangeEditorTypeButtonProps = { - mode?: ButtonMode -} - -const ChangeEditorTypeButton = ({ - mode = ButtonMode.editable, -}: ChangeEditorTypeButtonProps) => { - const { switchEditorType, isWithinThreshold } = useChangeEditorType() - const isReadMode = mode === ButtonMode.readOnly +const ChangeEditorTypeButton = () => { + const { switchEditorType, isTextEditorDisabled } = useChangeEditorType() - const isDisabled = isReadMode || !isWithinThreshold - const tooltip = isReadMode + const isDisabled = isTextEditorDisabled + const tooltip = isTextEditorDisabled ? 'This JSON document is too large to view or edit in full.' : 'Edit value in text editor' diff --git a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/index.ts b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/index.ts index 1f50dcadb4..a3834f345f 100644 --- a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/index.ts +++ b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/index.ts @@ -1,5 +1,4 @@ import ChangeEditorTypeButton from './ChangeEditorTypeButton' -export { ButtonMode as ChangeEditorTypeButtonMode } from './ChangeEditorTypeButton' export { useChangeEditorType } from './useChangeEditorType' export default ChangeEditorTypeButton diff --git a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/useChangeEditorType.tsx b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/useChangeEditorType.tsx index 41d265a155..893b13ce30 100644 --- a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/useChangeEditorType.tsx +++ b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/useChangeEditorType.tsx @@ -1,11 +1,18 @@ import { useCallback } from 'react' import { useSelector, useDispatch } from 'react-redux' +import { FeatureFlags } from 'uiSrc/constants' +import { appFeatureFlagsFeaturesSelector } from 'uiSrc/slices/app/features' import { rejsonSelector, setEditorType } from 'uiSrc/slices/browser/rejson' import { EditorType } from 'uiSrc/slices/interfaces' export const useChangeEditorType = () => { const dispatch = useDispatch() const { editorType, isWithinThreshold } = useSelector(rejsonSelector) + const { [FeatureFlags.envDependent]: envDependentFeature } = useSelector( + appFeatureFlagsFeaturesSelector, + ) + + const isTextEditorDisabled = !isWithinThreshold && !envDependentFeature?.flag const switchEditorType = useCallback(() => { const opposite = @@ -13,5 +20,5 @@ export const useChangeEditorType = () => { dispatch(setEditorType(opposite)) }, [dispatch, editorType]) - return { switchEditorType, editorType, isWithinThreshold } + return { switchEditorType, editorType, isTextEditorDisabled } } diff --git a/redisinsight/ui/src/pages/browser/modules/key-details/components/rejson-details/rejson-details/RejsonDetails.tsx b/redisinsight/ui/src/pages/browser/modules/key-details/components/rejson-details/rejson-details/RejsonDetails.tsx index 7a60ec4107..148e404795 100644 --- a/redisinsight/ui/src/pages/browser/modules/key-details/components/rejson-details/rejson-details/RejsonDetails.tsx +++ b/redisinsight/ui/src/pages/browser/modules/key-details/components/rejson-details/rejson-details/RejsonDetails.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import { useDispatch } from 'react-redux' import { EuiButtonIcon } from '@elastic/eui' import cx from 'classnames' import { @@ -9,16 +9,12 @@ import { setReJSONDataAction, } from 'uiSrc/slices/browser/rejson' import { RedisResponseBuffer } from 'uiSrc/slices/interfaces' -import { appFeatureFlagsFeaturesSelector } from 'uiSrc/slices/app/features' -import { FeatureFlags } from 'uiSrc/constants' import { getBrackets, isRealArray, isRealObject, wrapPath } from '../utils' import { BaseProps, ObjectTypes } from '../interfaces' import RejsonDynamicTypes from '../rejson-dynamic-types' import { AddItem } from '../components' -import ChangeEditorTypeButton, { - ChangeEditorTypeButtonMode, -} from '../../change-editor-type-button' +import ChangeEditorTypeButton from '../../change-editor-type-button' import styles from '../styles.module.scss' @@ -36,10 +32,6 @@ const RejsonDetails = (props: BaseProps) => { const [addRootKVPair, setAddRootKVPair] = useState(false) - const { [FeatureFlags.envDependent]: envDependentFeature } = useSelector( - appFeatureFlagsFeaturesSelector, - ) - const dispatch = useDispatch() const handleFetchVisualisationResults = ( @@ -104,13 +96,7 @@ const RejsonDetails = (props: BaseProps) => { 'start', )} - + )} Date: Tue, 10 Jun 2025 17:49:13 +0300 Subject: [PATCH 04/10] add hook tests --- .../useChangeEditorType.spec.ts | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/useChangeEditorType.spec.ts b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/useChangeEditorType.spec.ts index 77a05620d7..2200e59b8b 100644 --- a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/useChangeEditorType.spec.ts +++ b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/useChangeEditorType.spec.ts @@ -1,6 +1,8 @@ import * as reactRedux from 'react-redux' import { renderHook, act } from '@testing-library/react-hooks' import { EditorType } from 'uiSrc/slices/interfaces' +import { FeatureFlags } from 'uiSrc/constants' + import { useChangeEditorType } from './useChangeEditorType' jest.mock('react-redux', () => ({ @@ -56,4 +58,62 @@ describe('useChangeEditorType', () => { payload: EditorType.Default, }) }) + + describe('isTextEditorDisabled', () => { + it('should be false when isWithinThreshold is true', () => { + mockedUseSelector + .mockImplementationOnce(() => ({ + editorType: EditorType.Default, + isWithinThreshold: true, + })) + .mockImplementationOnce(() => ({ + [FeatureFlags.envDependent]: { flag: false }, + })) + + const { result } = renderHook(() => useChangeEditorType()) + expect(result.current.isTextEditorDisabled).toBe(false) + }) + + it('should be false when not within threshold but feature flag is true', () => { + mockedUseSelector + .mockImplementationOnce(() => ({ + editorType: EditorType.Default, + isWithinThreshold: false, + })) + .mockImplementationOnce(() => ({ + [FeatureFlags.envDependent]: { flag: true }, + })) + + const { result } = renderHook(() => useChangeEditorType()) + expect(result.current.isTextEditorDisabled).toBe(false) + }) + + it('should be true when not within threshold and feature flag is false', () => { + mockedUseSelector + .mockImplementationOnce(() => ({ + editorType: EditorType.Default, + isWithinThreshold: false, + })) + .mockImplementationOnce(() => ({ + [FeatureFlags.envDependent]: { flag: false }, + })) + + const { result } = renderHook(() => useChangeEditorType()) + expect(result.current.isTextEditorDisabled).toBe(true) + }) + + it('should be true when envDependentFeature is undefined', () => { + mockedUseSelector + .mockImplementationOnce(() => ({ + editorType: EditorType.Default, + isWithinThreshold: false, + })) + .mockImplementationOnce(() => ({ + [FeatureFlags.envDependent]: undefined, + })) + + const { result } = renderHook(() => useChangeEditorType()) + expect(result.current.isTextEditorDisabled).toBe(true) + }) + }) }) From 279aa9194d92fc059b8552a590a78ed8e99c9e38 Mon Sep 17 00:00:00 2001 From: Pavel Angelov Date: Tue, 10 Jun 2025 17:53:06 +0300 Subject: [PATCH 05/10] fix tests --- .../ChangeEditorTypeButton.spec.tsx | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.spec.tsx b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.spec.tsx index 3708792bea..cf34b98d66 100644 --- a/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.spec.tsx +++ b/redisinsight/ui/src/pages/browser/modules/key-details/components/change-editor-type-button/ChangeEditorTypeButton.spec.tsx @@ -1,12 +1,16 @@ import React from 'react' import { render, screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' -import ChangeEditorTypeButton, { ButtonMode } from './ChangeEditorTypeButton' + +import ChangeEditorTypeButton from './ChangeEditorTypeButton' const mockSwitchEditorType = jest.fn() +let mockIsTextEditorDisabled = false + jest.mock('./useChangeEditorType', () => ({ useChangeEditorType: () => ({ switchEditorType: mockSwitchEditorType, + isTextEditorDisabled: mockIsTextEditorDisabled, }), })) @@ -16,32 +20,38 @@ describe('ChangeEditorTypeButton', () => { }) it('should render an enabled button with default tooltip', async () => { + mockIsTextEditorDisabled = false + render() const button = screen.getByRole('button', { name: /change editor type/i }) expect(button).toBeEnabled() await userEvent.hover(button) - expect( await screen.findByText('Edit value in text editor'), ).toBeInTheDocument() }) - it('should render a disabled button with read-only tooltip', async () => { - render() + it('should render a disabled button with a tooltip', async () => { + mockIsTextEditorDisabled = true + + render() const button = screen.getByRole('button', { name: /change editor type/i }) expect(button).toBeDisabled() await userEvent.hover(button) - expect( - await screen.findByText('This JSON document is too large to view or edit in full.'), + await screen.findByText( + 'This JSON document is too large to view or edit in full.', + ), ).toBeInTheDocument() }) it('should call switchEditorType on click when not disabled', async () => { + mockIsTextEditorDisabled = false + render() const button = screen.getByRole('button', { name: /change editor type/i }) @@ -51,7 +61,9 @@ describe('ChangeEditorTypeButton', () => { }) it('should not call switchEditorType when disabled', async () => { - render() + mockIsTextEditorDisabled = true + + render() const button = screen.getByRole('button', { name: /change editor type/i }) await userEvent.click(button) From 92e00f62566bc1b7beec87d66eb0dc42f7cb8ac6 Mon Sep 17 00:00:00 2001 From: Pavel Angelov Date: Tue, 10 Jun 2025 17:58:35 +0300 Subject: [PATCH 06/10] add keys tests --- .../ui/src/slices/tests/browser/keys.spec.ts | 56 ++++++++++++++++++- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/redisinsight/ui/src/slices/tests/browser/keys.spec.ts b/redisinsight/ui/src/slices/tests/browser/keys.spec.ts index 6a5bf392eb..9d8caf353b 100644 --- a/redisinsight/ui/src/slices/tests/browser/keys.spec.ts +++ b/redisinsight/ui/src/slices/tests/browser/keys.spec.ts @@ -3,7 +3,6 @@ import { AxiosError } from 'axios' import { configureStore } from '@reduxjs/toolkit' import { BrowserColumns, - DEFAULT_SHOWN_COLUMNS, KeyTypes, KeyValueFormat, ModulesKeyTypes, @@ -19,7 +18,6 @@ import { clearStoreActions, initialStateDefault, mockedStore, - mockStore, } from 'uiSrc/utils/test-utils' import { addErrorNotification, @@ -33,7 +31,11 @@ import { } from 'uiSrc/slices/app/context' import { MOCK_TIMESTAMP } from 'uiSrc/mocks/data/dateNow' import { rootReducer } from 'uiSrc/slices/store' -import { setEditorType } from 'uiSrc/slices/browser/rejson' +import { + JSON_LENGTH_TO_FORCE_RETRIEVE, + setEditorType, + setIsWithinThreshold, +} from 'uiSrc/slices/browser/rejson' import { EditorType } from 'uiSrc/slices/interfaces' import { CreateHashWithExpireDto } from 'apiSrc/modules/browser/hash/dto' import { @@ -1400,6 +1402,54 @@ describe('keys slice', () => { ]), ) }) + + it('should set isWithinThreshold to true when length is within threshold', async () => { + // Arrange + const data = { + name: stringToBuffer('rejson'), + type: KeyTypes.ReJSON, + ttl: -1, + size: 10, + length: JSON_LENGTH_TO_FORCE_RETRIEVE - 1, + } + const responsePayload = { data, status: 200 } + + apiService.post = jest.fn().mockResolvedValue(responsePayload) + + // Act + await store.dispatch(fetchKeyInfo(data.name)) + + // Assert + expect(store.getActions()).toEqual( + expect.arrayContaining([ + expect.objectContaining(setIsWithinThreshold(true)), + ]), + ) + }) + + it('should set isWithinThreshold to false when length exceeds threshold', async () => { + // Arrange + const data = { + name: stringToBuffer('rejson'), + type: KeyTypes.ReJSON, + ttl: -1, + size: 10, + length: JSON_LENGTH_TO_FORCE_RETRIEVE + 1, + } + const responsePayload = { data, status: 200 } + + apiService.post = jest.fn().mockResolvedValue(responsePayload) + + // Act + await store.dispatch(fetchKeyInfo(data.name)) + + // Assert + expect(store.getActions()).toEqual( + expect.arrayContaining([ + expect.objectContaining(setIsWithinThreshold(false)), + ]), + ) + }) }) describe('refreshKeyInfoAction', () => { From 30a842c944a74e9b1b3ee3e5f82bb5be84e86ed7 Mon Sep 17 00:00:00 2001 From: Pavel Angelov Date: Tue, 10 Jun 2025 17:59:08 +0300 Subject: [PATCH 07/10] change the default value --- redisinsight/ui/src/slices/browser/rejson.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redisinsight/ui/src/slices/browser/rejson.ts b/redisinsight/ui/src/slices/browser/rejson.ts index 2537efa922..ef7e49ddb3 100644 --- a/redisinsight/ui/src/slices/browser/rejson.ts +++ b/redisinsight/ui/src/slices/browser/rejson.ts @@ -48,7 +48,7 @@ export const initialState: InitialStateRejson = { type: '', }, editorType: EditorType.Default, - isWithinThreshold: true, + isWithinThreshold: false, } // A slice for recipes From 7d31152ac689c2b90fc5cbe660717813c772f96a Mon Sep 17 00:00:00 2001 From: Pavel Angelov Date: Wed, 11 Jun 2025 13:12:14 +0300 Subject: [PATCH 08/10] fix tests --- .../rejson-details/monaco-editor/MonacoEditor.spec.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/redisinsight/ui/src/pages/browser/modules/key-details/components/rejson-details/monaco-editor/MonacoEditor.spec.tsx b/redisinsight/ui/src/pages/browser/modules/key-details/components/rejson-details/monaco-editor/MonacoEditor.spec.tsx index e6fe514993..479f2042a0 100644 --- a/redisinsight/ui/src/pages/browser/modules/key-details/components/rejson-details/monaco-editor/MonacoEditor.spec.tsx +++ b/redisinsight/ui/src/pages/browser/modules/key-details/components/rejson-details/monaco-editor/MonacoEditor.spec.tsx @@ -10,6 +10,11 @@ const mockStore = configureStore({ browser: { rejson: {}, }, + app: { + features: { + featureFlags: { features: { envDependent: { flag: true } } }, + }, + }, }), }) From d71124af21333597b28a80534a3216b9559ec170 Mon Sep 17 00:00:00 2001 From: Pavel Angelov Date: Wed, 11 Jun 2025 16:35:12 +0300 Subject: [PATCH 09/10] use size instead of length --- redisinsight/ui/src/slices/browser/keys.ts | 2 +- redisinsight/ui/src/slices/tests/browser/keys.spec.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/redisinsight/ui/src/slices/browser/keys.ts b/redisinsight/ui/src/slices/browser/keys.ts index edbebacc33..4aeff847c4 100644 --- a/redisinsight/ui/src/slices/browser/keys.ts +++ b/redisinsight/ui/src/slices/browser/keys.ts @@ -813,7 +813,7 @@ export function fetchKeyInfo( dispatch(fetchReJSON(key, '$', data.length, resetData)) dispatch(setEditorType(EditorType.Default)) dispatch( - setIsWithinThreshold(data.length <= JSON_LENGTH_TO_FORCE_RETRIEVE), + setIsWithinThreshold(data.size <= JSON_LENGTH_TO_FORCE_RETRIEVE), ) } if (data.type === KeyTypes.Stream) { diff --git a/redisinsight/ui/src/slices/tests/browser/keys.spec.ts b/redisinsight/ui/src/slices/tests/browser/keys.spec.ts index 9d8caf353b..fd82659116 100644 --- a/redisinsight/ui/src/slices/tests/browser/keys.spec.ts +++ b/redisinsight/ui/src/slices/tests/browser/keys.spec.ts @@ -1409,8 +1409,8 @@ describe('keys slice', () => { name: stringToBuffer('rejson'), type: KeyTypes.ReJSON, ttl: -1, - size: 10, - length: JSON_LENGTH_TO_FORCE_RETRIEVE - 1, + size: JSON_LENGTH_TO_FORCE_RETRIEVE, + length: JSON_LENGTH_TO_FORCE_RETRIEVE + 100, // just to make sure this isn't used instead of size } const responsePayload = { data, status: 200 } @@ -1433,8 +1433,8 @@ describe('keys slice', () => { name: stringToBuffer('rejson'), type: KeyTypes.ReJSON, ttl: -1, - size: 10, - length: JSON_LENGTH_TO_FORCE_RETRIEVE + 1, + size: JSON_LENGTH_TO_FORCE_RETRIEVE + 1, + length: JSON_LENGTH_TO_FORCE_RETRIEVE, // just to make sure this isn't used instead of size } const responsePayload = { data, status: 200 } From 2ff0637ac3eb55e6c052ea52a5309d4aad00252c Mon Sep 17 00:00:00 2001 From: Pavel Angelov Date: Wed, 11 Jun 2025 17:16:44 +0300 Subject: [PATCH 10/10] add env variable for precise config --- redisinsight/ui/src/config/default.ts | 4 ++++ redisinsight/ui/src/slices/browser/keys.ts | 14 +++++++------- .../ui/src/slices/tests/browser/keys.spec.ts | 13 ++++++++----- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/redisinsight/ui/src/config/default.ts b/redisinsight/ui/src/config/default.ts index efacc5591b..70b3c9305f 100644 --- a/redisinsight/ui/src/config/default.ts +++ b/redisinsight/ui/src/config/default.ts @@ -84,6 +84,10 @@ export const defaultConfig = { 'RI_DATABASE_OVERVIEW_MINIMUM_REFRESH_INTERVAL', 1, ), + rejsonMonacoEditorMaxThreshold: intEnv( + 'RI_REJSON_MONACO_EDITOR_MAX_THRESHOLD', + 10_000, + ), }, features: { envDependent: { diff --git a/redisinsight/ui/src/slices/browser/keys.ts b/redisinsight/ui/src/slices/browser/keys.ts index 4aeff847c4..bb09aec495 100644 --- a/redisinsight/ui/src/slices/browser/keys.ts +++ b/redisinsight/ui/src/slices/browser/keys.ts @@ -2,6 +2,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit' import { cloneDeep, remove, get, isUndefined } from 'lodash' import axios, { AxiosError, CancelTokenSource } from 'axios' import { apiService, localStorageService } from 'uiSrc/services' +import { getConfig } from 'uiSrc/config' import { ApiEndpoints, BrowserStorageItem, @@ -61,12 +62,7 @@ import { refreshZsetMembersAction, } from './zset' import { fetchSetMembers, refreshSetMembersAction } from './set' -import { - fetchReJSON, - JSON_LENGTH_TO_FORCE_RETRIEVE, - setEditorType, - setIsWithinThreshold, -} from './rejson' +import { fetchReJSON, setEditorType, setIsWithinThreshold } from './rejson' import { setHashInitialState, fetchHashFields, @@ -108,6 +104,8 @@ import { AppDispatch, RootState } from '../store' import { StreamViewType } from '../interfaces/stream' import { EditorType, RedisResponseBuffer, RedisString } from '../interfaces' +const riConfig = getConfig() + const defaultViewFormat = KeyValueFormat.Unicode export const initialState: KeysStore = { @@ -813,7 +811,9 @@ export function fetchKeyInfo( dispatch(fetchReJSON(key, '$', data.length, resetData)) dispatch(setEditorType(EditorType.Default)) dispatch( - setIsWithinThreshold(data.size <= JSON_LENGTH_TO_FORCE_RETRIEVE), + setIsWithinThreshold( + data.size <= riConfig.browser.rejsonMonacoEditorMaxThreshold, + ), ) } if (data.type === KeyTypes.Stream) { diff --git a/redisinsight/ui/src/slices/tests/browser/keys.spec.ts b/redisinsight/ui/src/slices/tests/browser/keys.spec.ts index fd82659116..075b67cb7a 100644 --- a/redisinsight/ui/src/slices/tests/browser/keys.spec.ts +++ b/redisinsight/ui/src/slices/tests/browser/keys.spec.ts @@ -1,6 +1,7 @@ import { cloneDeep } from 'lodash' import { AxiosError } from 'axios' import { configureStore } from '@reduxjs/toolkit' +import { getConfig } from 'uiSrc/config' import { BrowserColumns, KeyTypes, @@ -32,7 +33,6 @@ import { import { MOCK_TIMESTAMP } from 'uiSrc/mocks/data/dateNow' import { rootReducer } from 'uiSrc/slices/store' import { - JSON_LENGTH_TO_FORCE_RETRIEVE, setEditorType, setIsWithinThreshold, } from 'uiSrc/slices/browser/rejson' @@ -111,6 +111,9 @@ import reducer, { refreshKey, } from '../../browser/keys' +const riConfig = getConfig() +const REJSON_THRESHOLD = riConfig.browser.rejsonMonacoEditorMaxThreshold + jest.mock('uiSrc/services', () => ({ ...jest.requireActual('uiSrc/services'), })) @@ -1409,8 +1412,8 @@ describe('keys slice', () => { name: stringToBuffer('rejson'), type: KeyTypes.ReJSON, ttl: -1, - size: JSON_LENGTH_TO_FORCE_RETRIEVE, - length: JSON_LENGTH_TO_FORCE_RETRIEVE + 100, // just to make sure this isn't used instead of size + size: REJSON_THRESHOLD, + length: REJSON_THRESHOLD + 100, // just to make sure this isn't used instead of size } const responsePayload = { data, status: 200 } @@ -1433,8 +1436,8 @@ describe('keys slice', () => { name: stringToBuffer('rejson'), type: KeyTypes.ReJSON, ttl: -1, - size: JSON_LENGTH_TO_FORCE_RETRIEVE + 1, - length: JSON_LENGTH_TO_FORCE_RETRIEVE, // just to make sure this isn't used instead of size + size: REJSON_THRESHOLD + 1, + length: REJSON_THRESHOLD, // just to make sure this isn't used instead of size } const responsePayload = { data, status: 200 }