From dc0ae1676647655658f5c565bf0aa2298fa139b0 Mon Sep 17 00:00:00 2001 From: Amir Allayarov Date: Fri, 3 Mar 2023 11:33:16 +0400 Subject: [PATCH 1/7] #RI-4230 - update workbench module not loaded screens --- .../ui/src/assets/img/icons/cheer.svg | 10 + .../img/icons/mobile_module_not_loaded.svg | 37 +++ .../assets/img/icons/module_not_loaded.svg | 38 +++ .../src/components/query-card/QueryCard.tsx | 12 +- .../QueryCardCliGroupResult.tsx | 2 +- .../CommonErrorResponse.tsx | 8 +- .../ui/src/constants/workbenchResults.ts | 62 +++++ .../ModuleNotLoaded.spec.tsx | 70 +----- .../module-not-loaded/ModuleNotLoaded.tsx | 220 ++++++++---------- .../module-not-loaded/styles.module.scss | 186 +++++++++------ .../ui/src/pages/workbench/constants.ts | 36 +-- .../ui/src/slices/interfaces/instances.ts | 8 + .../themes/dark_theme/_dark_theme.lazy.scss | 1 + .../themes/dark_theme/_theme_color.scss | 1 + .../themes/light_theme/_light_theme.lazy.scss | 1 + .../themes/light_theme/_theme_color.scss | 1 + redisinsight/ui/src/utils/cliHelper.tsx | 49 +++- 17 files changed, 431 insertions(+), 311 deletions(-) create mode 100644 redisinsight/ui/src/assets/img/icons/cheer.svg create mode 100644 redisinsight/ui/src/assets/img/icons/mobile_module_not_loaded.svg create mode 100644 redisinsight/ui/src/assets/img/icons/module_not_loaded.svg diff --git a/redisinsight/ui/src/assets/img/icons/cheer.svg b/redisinsight/ui/src/assets/img/icons/cheer.svg new file mode 100644 index 0000000000..95baa5b9d0 --- /dev/null +++ b/redisinsight/ui/src/assets/img/icons/cheer.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/redisinsight/ui/src/assets/img/icons/mobile_module_not_loaded.svg b/redisinsight/ui/src/assets/img/icons/mobile_module_not_loaded.svg new file mode 100644 index 0000000000..0508b5147e --- /dev/null +++ b/redisinsight/ui/src/assets/img/icons/mobile_module_not_loaded.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/redisinsight/ui/src/assets/img/icons/module_not_loaded.svg b/redisinsight/ui/src/assets/img/icons/module_not_loaded.svg new file mode 100644 index 0000000000..deb7a4d35a --- /dev/null +++ b/redisinsight/ui/src/assets/img/icons/module_not_loaded.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/redisinsight/ui/src/components/query-card/QueryCard.tsx b/redisinsight/ui/src/components/query-card/QueryCard.tsx index 694ed6187b..d5a5e12997 100644 --- a/redisinsight/ui/src/components/query-card/QueryCard.tsx +++ b/redisinsight/ui/src/components/query-card/QueryCard.tsx @@ -153,13 +153,15 @@ const QueryCard = (props: Props) => { setSelectedViewValue(value) } - const commonError = CommonErrorResponse(command, result) + const commonError = CommonErrorResponse(id, command, result) return ( -
{ { - const commonError = CommonErrorResponse(item.command, item.response) + const commonError = CommonErrorResponse(item.id, item.command, item.response) if (React.isValidElement(commonError)) { return ([wbSummaryCommand(item.command), commonError]) } diff --git a/redisinsight/ui/src/components/query-card/QueryCardCommonResult/components/CommonErrorResponse/CommonErrorResponse.tsx b/redisinsight/ui/src/components/query-card/QueryCardCommonResult/components/CommonErrorResponse/CommonErrorResponse.tsx index 7ed1277fdb..c6564c7da4 100644 --- a/redisinsight/ui/src/components/query-card/QueryCardCommonResult/components/CommonErrorResponse/CommonErrorResponse.tsx +++ b/redisinsight/ui/src/components/query-card/QueryCardCommonResult/components/CommonErrorResponse/CommonErrorResponse.tsx @@ -12,15 +12,13 @@ import { import { cliTexts, SelectCommand } from 'uiSrc/constants/cliOutput' import { CommandMonitor, CommandPSubscribe, Pages } from 'uiSrc/constants' import { CommandExecutionStatus } from 'uiSrc/slices/interfaces/cli' -import { RedisDefaultModules } from 'uiSrc/slices/interfaces' -import { RSNotLoadedContent } from 'uiSrc/pages/workbench/constants' import { cliSettingsSelector } from 'uiSrc/slices/cli/cli-settings' import { connectedInstanceSelector } from 'uiSrc/slices/instances/instances' import ModuleNotLoaded from 'uiSrc/pages/workbench/components/module-not-loaded' import { showMonitor } from 'uiSrc/slices/cli/monitor' -const CommonErrorResponse = (command = '', result?: any) => { +const CommonErrorResponse = (id: string, command = '', result?: any) => { const { instanceId = '' } = useParams<{ instanceId: string }>() const { unsupportedCommands: cliUnsupportedCommands, blockingCommands } = useSelector(cliSettingsSelector) const { modules } = useSelector(connectedInstanceSelector) @@ -69,8 +67,8 @@ const CommonErrorResponse = (command = '', result?: any) => { } const unsupportedModule = checkUnsupportedModuleCommand(modules, commandLine) - if (unsupportedModule === RedisDefaultModules.Search) { - return + if (unsupportedModule) { + return } return null diff --git a/redisinsight/ui/src/constants/workbenchResults.ts b/redisinsight/ui/src/constants/workbenchResults.ts index affce8b9e2..4e199b11fb 100644 --- a/redisinsight/ui/src/constants/workbenchResults.ts +++ b/redisinsight/ui/src/constants/workbenchResults.ts @@ -1,3 +1,65 @@ +import { RedisDefaultModules } from 'uiSrc/slices/interfaces' + export const bulkReplyCommands = ['LOLWUT', 'INFO', 'CLIENT', 'CLUSTER', 'MEMORY', 'MONITOR', 'PSUBSCRIBE'] export const EMPTY_COMMAND = 'Encrypted data' + +export const MODULE_NOT_LOADED_CONTENT: { [key in RedisDefaultModules]?: any } = { + [RedisDefaultModules.TimeSeries]: { + text: 'RedisTimeSeries adds a Time Series data structure to Redis. With this capability you can:', + improvements: [ + 'Add sample data', + 'Perform cross-time-series range and aggregation queries', + 'Define compaction rules for economical retention of historical data' + ], + link: 'https://redis.io/docs/stack/timeseries/' + }, + [RedisDefaultModules.Search]: { + text: 'RediSearch adds the capability to:', + improvements: [ + 'Query', + 'Secondary index', + 'Full-text search' + ], + additionalText: 'These features enable multi-field queries, aggregation, exact phrase matching, numeric filtering, geo filtering and vector similarity semantic search on top of text queries.', + link: 'https://redis.io/docs/stack/search/' + }, + [RedisDefaultModules.Graph]: { + text: 'RedisGraph adds a Property Graph data structure to Redis. With this capability you can:', + improvements: [ + 'Create graphs', + 'Query property graphs using the Cypher query language with proprietary extensions' + ], + link: 'https://redis.io/docs/stack/graph/' + }, + [RedisDefaultModules.ReJSON]: { + text: 'RedisJSON adds the capability to:', + improvements: [ + 'Store JSON documents', + 'Update JSON documents', + 'Retrieve JSON documents' + ], + additionalText: 'RedisJSON also works seamlessly with RediSearch to let you index and query JSON documents.', + link: 'https://redis.io/docs/stack/json/' + }, + [RedisDefaultModules.Bloom]: { + text: 'RedisBloom adds a set of probabilistic data structures to Redis, including:', + improvements: [ + 'Bloom filter', + 'Cuckoo filter', + 'Count-min sketch', + 'Top-K', + 'T-digest' + ], + additionalText: 'With this capability you can query streaming data without needing to store all the elements of the stream.', + link: 'https://redis.io/docs/stack/bloom/' + } +} + +export const MODULE_TEXT_VIEW: { [key in RedisDefaultModules]?: string } = { + [RedisDefaultModules.Bloom]: 'RedisBloom', + [RedisDefaultModules.Graph]: 'RedisGraph', + [RedisDefaultModules.ReJSON]: 'RedisJSON', + [RedisDefaultModules.Search]: 'RediSearch', + [RedisDefaultModules.TimeSeries]: 'RedisTimeSeries', +} diff --git a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.spec.tsx b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.spec.tsx index 6bfaedf219..2d0e19e96a 100644 --- a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.spec.tsx +++ b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.spec.tsx @@ -1,72 +1,12 @@ -import { cloneDeep } from 'lodash' import React from 'react' -import { cleanup, mockedStore, render } from 'uiSrc/utils/test-utils' -import { ThemeContext, defaultState } from 'uiSrc/contexts/themeContext' -import ModuleNotLoaded from './ModuleNotLoaded' -import { RSNotLoadedContent } from '../../constants' +import { instance, mock } from 'ts-mockito' +import { render } from 'uiSrc/utils/test-utils' +import ModuleNotLoaded, { IProps } from './ModuleNotLoaded' -let store: typeof mockedStore - -beforeEach(() => { - cleanup() - store = cloneDeep(mockedStore) - store.clearActions() -}) - -jest.mock('uiSrc/services', () => ({ - ...jest.requireActual('uiSrc/services'), - sessionStorageService: { - set: jest.fn(), - get: jest.fn(), - }, -})) - -jest.mock('uiSrc/slices/content/create-redis-buttons', () => ({ - ...jest.requireActual('uiSrc/slices/content/create-redis-buttons'), - contentSelector: jest.fn().mockReturnValue({ - loading: false, - data: { - cloud: { title: 'Limited offer', description: 'Try Redis cloud' } - } - }), -})) +const mockedProps = mock() describe('ModuleNotLoaded', () => { it('should render', () => { - expect(render()).toBeTruthy() - }) - - it('"output" prop should render', () => { - const { queryByTestId } = render() - - const outputEl = queryByTestId('query-card-no-module-output') - expect(outputEl).toBeInTheDocument() - }) - it('"table" prop should render', () => { - const { container } = render() - - const tableEl = container.querySelector('[data-test-subj="query-card-no-module-table"]') - expect(tableEl).toBeInTheDocument() - }) - it('"createCloudBtn" prop should render', () => { - const { queryByTestId } = render( - - - - ) - const btnEl = queryByTestId('query-card-no-module-button') - expect(btnEl).toBeInTheDocument() - }) - it('"summaryText" prop should render', () => { - const { queryByTestId } = render() - - const summaryTextEl = queryByTestId('query-card-no-module-summary-text') - expect(summaryTextEl).toBeInTheDocument() - }) - it('"summaryImgPath" prop should render', () => { - const { queryByTestId } = render() - - const summaryImgEl = queryByTestId('query-card-no-module-summary-img') - expect(summaryImgEl).toBeInTheDocument() + expect(render()).toBeTruthy() }) }) diff --git a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx index 75ec496cc8..b80e9452a7 100644 --- a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx +++ b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx @@ -1,146 +1,116 @@ -import React, { useContext } from 'react' -import { useSelector } from 'react-redux' +import React, { useEffect, useState } from 'react' import cx from 'classnames' import { - EuiBasicTableColumn, - EuiFlexGroup, - EuiFlexItem, - EuiIcon, - EuiInMemoryTable, EuiTextColor, + EuiText, + EuiTitle, + EuiLink, + EuiButton, } from '@elastic/eui' -import parse from 'html-react-parser' -import { ThemeContext } from 'uiSrc/contexts/themeContext' -import { contentSelector } from 'uiSrc/slices/content/create-redis-buttons' -import { Theme } from 'uiSrc/constants' -import PromoLink from 'uiSrc/components/promo-link/PromoLink' -import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry' -import { getPathToResource } from 'uiSrc/services/resourcesService' -import { ContentCreateRedis } from 'uiSrc/slices/interfaces/content' +import { ReactComponent as MobileIcon } from 'uiSrc/assets/img/icons/mobile_module_not_loaded.svg' +import { ReactComponent as DesktopIcon } from 'uiSrc/assets/img/icons/module_not_loaded.svg' +import { ReactComponent as CheerIcon } from 'uiSrc/assets/img/icons/cheer.svg' +import { MODULE_NOT_LOADED_CONTENT as CONTENT, MODULE_TEXT_VIEW } from 'uiSrc/constants' +import { RedisDefaultModules } from 'uiSrc/slices/interfaces' import styles from './styles.module.scss' -interface IContentColumn { - title: string - text: string +export interface IProps { + moduleName: RedisDefaultModules + id: string } -export interface IModuleNotLoadedContent { - output?: string - createCloudBtnText?: string - createCloudBtnHref?: string - summaryText?: string - summaryImgDark?: string - summaryImgLight?: string - summaryImgPath?: string - columns?: IContentColumn[] -} +const MAX_ELEMENT_WIDTH = 1440 -export interface Props { - content: IModuleNotLoadedContent -} +const renderTitle = (width: number, moduleName?: string) => ( + +

+ {`Looks like ${moduleName} is not available`} + {width > MAX_ELEMENT_WIDTH &&
} + for this database +

+
+) -const ModuleNotLoaded = ({ content = {} }: Props) => { - const { - output = '', - summaryText = '', - summaryImgDark = '', - summaryImgLight = '', - summaryImgPath = '', - columns = [] - } = content - const { loading, data: createDbContent } = useSelector(contentSelector) +const renderText = (moduleName?: string) => ( + + {`Create a free Redis Stack database with ${moduleName} which extends the core capabilities of open-source Redis`} + +) - const { theme } = useContext(ThemeContext) +const ListItem = ({ item }: { item: string }) => ( +
  • +
    + +
    + {item} +
  • +) - const columnsSettings: EuiBasicTableColumn[] = columns.map(({ title }, i) => ({ - name: title, - field: `text${i}`, - dataType: 'string', - truncateText: false, - render: (text: any) => parse(text) - })) +const ModuleNotLoaded = ({ moduleName, id }: IProps) => { + const [width, setWidth] = useState(0) - const item = columns.reduce((obj, { text }, i) => ({ ...obj, [`text${i}`]: text }), {}) + const module = MODULE_TEXT_VIEW[moduleName] - const handleClickLink = (event: TelemetryEvent, eventData: any = {}) => { - sendEventTelemetry({ - event, - eventData: { - ...eventData - } - }) - } - const CreateCloudBtn = ({ content }: { content: ContentCreateRedis }) => { - const { title, description, styles, links } = content - // @ts-ignore - const linkStyles = styles ? styles[theme] : {} - return ( - handleClickLink( - links?.redisearch?.event as TelemetryEvent, - { source: 'RediSearch is not loaded' } - )} - styles={{ - ...linkStyles, - backgroundImage: linkStyles?.backgroundImage - ? `url(${getPathToResource(linkStyles.backgroundImage)})` - : undefined - }} - /> - ) - } + useEffect(() => { + const parentEl = document?.getElementById(id) + if (parentEl) { + setWidth(parentEl.offsetWidth) + } + }) return ( -
    - - {!!output && ( - - - - - - {parse(output)} - - - )} - {!!columns?.length && ( - - - - )} - { !loading && createDbContent?.cloud && ( - - - - )} - {(!!summaryText || !!summaryImgPath || !!summaryImgDark || !!summaryImgLight) && ( - -
    - {(!!summaryImgPath || !!summaryImgDark || !!summaryImgLight) && ( - redisearch table - )} - {!!summaryText &&
    {parse(summaryText)}
    } -
    -
    - )} -
    +
    MAX_ELEMENT_WIDTH })}> +
    +
    + {width > MAX_ELEMENT_WIDTH + ? + : } +
    +
    + {renderTitle(width, module)} + {CONTENT[moduleName]?.text} +
      + {CONTENT[moduleName]?.improvements.map((item: string) => ( + + ))} +
    + {!!CONTENT[moduleName]?.additionalText && ( + + {CONTENT[moduleName]?.additionalText} + + )} + {renderText(module)} +
    +
    +
    + + Learn More + + + + Get Started For Free + + +
    ) } diff --git a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss index 82e4e247d3..455def199f 100644 --- a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss +++ b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss @@ -1,97 +1,139 @@ .container { - font-family: 'Graphik', sans-serif !important; - - br { - display: block !important; - content: ""; - margin: 2em; - font-size: 34%; + padding: 41px 30px; + + .title { + font-family: 'Graphik', sans-serif; + font-size: 32px; + font-weight: 600; + word-break: break-word; + margin-bottom: 20px; } - ul { - list-style: disc !important; - padding-left: 20px !important; + .linksWrapper .text, + .text { + font-family: 'Graphik', sans-serif; + font-size: 14px; + line-height: 17px; + word-break: break-word; + color: var(--wbTextColor) !important; + text-decoration: none !important; } - :global(.query-card-output-response-fail) { - padding: 6px 0; - color: var(--euiColorDanger) !important + .bigText { + font-family: 'Graphik', sans-serif; + font-size: 20px; + line-height: 24px; + word-break: break-word; + color: var(--wbTextColor); + margin-bottom: 20px; } -} - -.table { - margin: 0 -20px !important; - :global(.euiTableRowCell) { - background-color: var(--euiPageBackgroundColor) !important; + .flex { + display: flex; + flex-direction: row-reverse; + align-items: center; + justify-content: space-between; + + .icon { + width: 173px; + margin-left: 15px; + } + + .bigIcon { + width: 317px; + } } - br { - font-size: 18%; + .listItem { + display: flex; + margin-bottom: 20px; + + .iconWrapper { + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + background: var(--wbActiveIconColor); + border-radius: 50%; + margin-right: 10px; + } + + .listIcon { + width: 10px; + height: 10px; + + path { + fill: var(--euiPageBackgroundColor); + } + } } - - a { - line-height: 24px; - text-align: left; - text-decoration: underline; - color: var(--buttonSecondaryTextColor); - - &:hover { - text-decoration: none; + + .linksWrapper { + display: flex; + justify-content: flex-end; + align-items: center; + margin-top: 20px; + + .link { + margin-right: 20px; + color: var(-wbTextColor); } } -} + + .marginBottom { + margin-bottom: 20px; + } -.summary { - display: flex; + &.fullScreen { + .flex { + flex-direction: column; + } - > div { - padding-bottom: 10px; - } -} + .contentWrapper { + display: flex; + flex-direction: column; + align-items: center; + } -.alertIconWrapper { - height: 19px; - display: inline-flex; - align-items: center; -} + .title, + .text, + .bigText { + text-align: center; + } -.summaryImg { - width: 468px !important; - height: 174px !important; - margin-right: 22px; -} + .bigText { + width: 586px; + } -@media only screen and (max-width: 700px) { - .summaryImg { - width: 312px !important; - height: 116px !important; - } -} + .additionalText { + width: 620px; + } -@media only screen and (max-width: 1200px) { - .summary { - display: block; - } -} + .list { + display: flex; + justify-content: center; + } -@media only screen and (max-width: 767px) { - .container :global(.euiFlexGroup--responsive .query-card-output-response-fail) { - margin: 10px 0 !important; - } + .listItem { + margin-right: 15px; + + &:last-child { + margin-right: 0; + } + } - .table { - :global(.euiTableRowCell) { - background-color: initial !important; - max-width: 100% !important; - width: 100%; - border-top: 1px solid var(--euiColorLightShade) !important; + .linksWrapper { + justify-content: center; + flex-direction: column-reverse; } - :global(.euiTableRow) { - padding: 0 !important; - border-right: 0 !important; - background-color: var(--euiPageBackgroundColor) !important; + .link { + margin-right: 0; + + &:first-child { + margin-top: 13px; + } } } } diff --git a/redisinsight/ui/src/pages/workbench/constants.ts b/redisinsight/ui/src/pages/workbench/constants.ts index 673c0bce3d..298891f3ce 100644 --- a/redisinsight/ui/src/pages/workbench/constants.ts +++ b/redisinsight/ui/src/pages/workbench/constants.ts @@ -1,8 +1,5 @@ -import RSNotAvailableLightImg from 'uiSrc/assets/img/workbench/RediSearchNotAvailableLight.jpg' -import RSNotAvailableDarkImg from 'uiSrc/assets/img/workbench/RediSearchNotAvailableDark.jpg' import TextViewIconDark from 'uiSrc/assets/img/workbench/text_view_dark.svg' import TextViewIconLight from 'uiSrc/assets/img/workbench/text_view_light.svg' -import { IModuleNotLoadedContent } from './components/module-not-loaded' export const WORKBENCH_HISTORY_WRAPPER_NAME = 'WORKBENCH' export const WORKBENCH_HISTORY_MAX_LENGTH = 30 @@ -57,30 +54,15 @@ const PROFILE_VIEW_TYPE_OPTIONS = [ export const getProfileViewTypeOptions = () => [...PROFILE_VIEW_TYPE_OPTIONS] - export enum ModuleCommandPrefix { RediSearch = 'FT.', -} - -export const RSNotLoadedContent: IModuleNotLoadedContent = { - output: 'RediSearch module is not loaded for this database', - createCloudBtnText: 'Create your free Redis database with RediSearch on Redis Cloud​', - createCloudBtnHref: 'https://redis.com/try-free/?utm_source=redis&utm_medium=app&utm_campaign=redisinsight_redisearch_offer_jan', - summaryText: 'RedisInsight supports RediSearch and allows you to:

    ' - + '
    • Build and execute queries
    • Browse, analyse and export results

    ' - + 'As a benefit you get faster turnarounds when building your application using Redis and RediSearch.', - summaryImgDark: RSNotAvailableDarkImg, - summaryImgLight: RSNotAvailableLightImg, - // summaryImgPath: 'uiSrc/assets/img/workbench/RediSearchNotAvailable.jpg', - columns: [{ - title: 'What is RediSearch?', - text: 'RediSearch is a real-time search engine that enables you to query your Redis data. It implements a secondary index on top of Redis.
    This enables advanced features, such as multi-field queries, aggregation, auto-completion and full text search capabilities.
    These capabilities include exact phrase matching, fuzzy and prefix matching, numeric filtering, geo-spatial filtering, something that is neither possible or efficient with traditional Redis indexing approaches.', - }, { - title: 'Learn more about RediSearch module:', - text: 'RediSearch Quick Start tutorial' - + 'RediSearch Documentation' - + 'RediSearch Commands' - + 'RediSearch in Brief' - + 'RediSearch Benchmarks (blog post)' - }] + JSON = 'JSON.', + TimeSeries = 'TS.', + Graph = 'GRAPH.', + BF = 'BF.', + CF = 'CF.', + CMS = 'CMS.', + TOPK = 'TOPK.', + TDIGEST = 'TDIGEST.', + // RedisBloom = RedisBloom, } diff --git a/redisinsight/ui/src/slices/interfaces/instances.ts b/redisinsight/ui/src/slices/interfaces/instances.ts index e9ff40ed8d..6c052b6548 100644 --- a/redisinsight/ui/src/slices/interfaces/instances.ts +++ b/redisinsight/ui/src/slices/interfaces/instances.ts @@ -175,6 +175,14 @@ export const REDISEARCH_MODULES: string[] = [ RedisDefaultModules.FTL, ] +export const COMMAND_MODULES = { + [RedisDefaultModules.Search]: REDISEARCH_MODULES, + [RedisDefaultModules.ReJSON]: [RedisDefaultModules.ReJSON], + [RedisDefaultModules.TimeSeries]: [RedisDefaultModules.TimeSeries], + [RedisDefaultModules.Graph]: [RedisDefaultModules.Graph], + [RedisDefaultModules.Bloom]: [RedisDefaultModules.Bloom], +} + const RediSearchModulesText = [...REDISEARCH_MODULES].reduce((prev, next) => ({ ...prev, [next]: 'RediSearch' }), {}) // Enums don't allow to use dynamic key diff --git a/redisinsight/ui/src/styles/themes/dark_theme/_dark_theme.lazy.scss b/redisinsight/ui/src/styles/themes/dark_theme/_dark_theme.lazy.scss index 2819808f43..1f1ffb713c 100644 --- a/redisinsight/ui/src/styles/themes/dark_theme/_dark_theme.lazy.scss +++ b/redisinsight/ui/src/styles/themes/dark_theme/_dark_theme.lazy.scss @@ -179,6 +179,7 @@ --wbRunResultsBg: #{$wbRunResultsBg}; --wbHoverIconColor: #{$wbHoverIconColor}; --wbActiveIconColor: #{$wbActiveIconColor}; + --wbTextColor: #{$wbTextColor}; // Pub/Sub --pubSubClientsBadge: #{$pubSubClientsBadge}; diff --git a/redisinsight/ui/src/styles/themes/dark_theme/_theme_color.scss b/redisinsight/ui/src/styles/themes/dark_theme/_theme_color.scss index e42473ee00..f596371d27 100644 --- a/redisinsight/ui/src/styles/themes/dark_theme/_theme_color.scss +++ b/redisinsight/ui/src/styles/themes/dark_theme/_theme_color.scss @@ -139,6 +139,7 @@ $rsSubmitBtn: #1ae26e; $wbRunResultsBg: #000; $wbHoverIconColor: #ffffff; $wbActiveIconColor: #8ba2ff; +$wbTextColor: #dfe5ef; // PubSub $pubSubClientsBadge: #008000; diff --git a/redisinsight/ui/src/styles/themes/light_theme/_light_theme.lazy.scss b/redisinsight/ui/src/styles/themes/light_theme/_light_theme.lazy.scss index ccc938f991..5fdef0de41 100644 --- a/redisinsight/ui/src/styles/themes/light_theme/_light_theme.lazy.scss +++ b/redisinsight/ui/src/styles/themes/light_theme/_light_theme.lazy.scss @@ -181,6 +181,7 @@ --wbRunResultsBg: #{$wbRunResultsBg}; --wbHoverIconColor: #{$wbHoverIconColor}; --wbActiveIconColor: #{$wbActiveIconColor}; + --wbTextColor: #{$wbTextColor}; // Pub/Sub --pubSubClientsBadge: #{$pubSubClientsBadge}; diff --git a/redisinsight/ui/src/styles/themes/light_theme/_theme_color.scss b/redisinsight/ui/src/styles/themes/light_theme/_theme_color.scss index 20c09ec571..670e364b21 100644 --- a/redisinsight/ui/src/styles/themes/light_theme/_theme_color.scss +++ b/redisinsight/ui/src/styles/themes/light_theme/_theme_color.scss @@ -136,6 +136,7 @@ $rsInputWrapperColor: #fff; $wbRunResultsBg: #fff; $wbHoverIconColor: #415681; $wbActiveIconColor: #3163D8; +$wbTextColor: #415681; // Pub/Sub $pubSubClientsBadge: #b5cea8; diff --git a/redisinsight/ui/src/utils/cliHelper.tsx b/redisinsight/ui/src/utils/cliHelper.tsx index 2f24de7954..3f818c1cb2 100644 --- a/redisinsight/ui/src/utils/cliHelper.tsx +++ b/redisinsight/ui/src/utils/cliHelper.tsx @@ -1,4 +1,4 @@ -import React, { Fragment } from 'react' +import React from 'react' import { Dispatch, PayloadAction } from '@reduxjs/toolkit' import parse from 'html-react-parser' @@ -8,10 +8,13 @@ import { resetOutput, updateCliCommandHistory } from 'uiSrc/slices/cli/cli-outpu import { BrowserStorageItem, ICommands } from 'uiSrc/constants' import { ModuleCommandPrefix } from 'uiSrc/pages/workbench/constants' import { SelectCommand } from 'uiSrc/constants/cliOutput' -import { ClusterNode, RedisDefaultModules, REDISEARCH_MODULES } from 'uiSrc/slices/interfaces' +import { + ClusterNode, + RedisDefaultModules, + COMMAND_MODULES, +} from 'uiSrc/slices/interfaces' import { AdditionalRedisModule } from 'apiSrc/modules/database/models/additional.redis.module' -import { Nullable } from './types' import formatToText from './transformers/cliTextFormatter' import { getDbIndex } from './longNames' @@ -139,18 +142,42 @@ const checkUnsupportedCommand = (unsupportedCommands: string[], commandLine: str const checkBlockingCommand = (blockingCommands: string[], commandLine: string) => blockingCommands?.find((command) => commandLine?.trim().toLowerCase().startsWith(command)) +const checkCommandModule = (command: string) => { + switch (true) { + case command.startsWith(ModuleCommandPrefix.RediSearch): { + return RedisDefaultModules.Search + } + case command.startsWith(ModuleCommandPrefix.JSON): { + return RedisDefaultModules.ReJSON + } + case command.startsWith(ModuleCommandPrefix.TimeSeries): { + return RedisDefaultModules.TimeSeries + } + case command.startsWith(ModuleCommandPrefix.Graph): { + return RedisDefaultModules.Graph + } + case command.startsWith(ModuleCommandPrefix.BF): + case command.startsWith(ModuleCommandPrefix.CF): + case command.startsWith(ModuleCommandPrefix.CMS): + case command.startsWith(ModuleCommandPrefix.TDIGEST): + case command.startsWith(ModuleCommandPrefix.TOPK): { + return RedisDefaultModules.Bloom + } + default: { + return null + } + } +} + const checkUnsupportedModuleCommand = (loadedModules: AdditionalRedisModule[], commandLine: string) => { const command = commandLine?.trim().toUpperCase() - let commandModule: Nullable = null - if (command.startsWith(ModuleCommandPrefix.RediSearch)) { - commandModule = RedisDefaultModules.Search + const commandModule = checkCommandModule(command) + if (!commandModule) { + return null } - - const isModuleLoaded = loadedModules?.some(({ name }) => name === commandModule) - // Redisearch has 4 names, need check all - || loadedModules?.some(({ name }) => - REDISEARCH_MODULES.some((search) => name === search)) + const isModuleLoaded = loadedModules?.some(({ name }) => + COMMAND_MODULES[commandModule].some((module) => name === module)) if (isModuleLoaded) { return null From d442927330cd5484d85a14b431f1c790aed0ce76 Mon Sep 17 00:00:00 2001 From: Amir Allayarov Date: Fri, 3 Mar 2023 13:32:56 +0400 Subject: [PATCH 2/7] #RI-4230 - add tests --- redisinsight/ui/src/utils/cliHelper.tsx | 1 + .../ui/src/utils/tests/cliHelper.spec.ts | 70 ++++++++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/redisinsight/ui/src/utils/cliHelper.tsx b/redisinsight/ui/src/utils/cliHelper.tsx index 3f818c1cb2..b65f8ea2d5 100644 --- a/redisinsight/ui/src/utils/cliHelper.tsx +++ b/redisinsight/ui/src/utils/cliHelper.tsx @@ -222,6 +222,7 @@ export { cliCommandWrapper, clearOutput, updateCliHistoryStorage, + checkCommandModule, checkUnsupportedCommand, checkBlockingCommand, checkUnsupportedModuleCommand, diff --git a/redisinsight/ui/src/utils/tests/cliHelper.spec.ts b/redisinsight/ui/src/utils/tests/cliHelper.spec.ts index 515fe6a891..961c7f185e 100644 --- a/redisinsight/ui/src/utils/tests/cliHelper.spec.ts +++ b/redisinsight/ui/src/utils/tests/cliHelper.spec.ts @@ -3,11 +3,16 @@ import { getCommandNameFromQuery, cliParseCommandsGroupResult, CliPrefix, - wbSummaryCommand + wbSummaryCommand, + checkUnsupportedModuleCommand, + checkCommandModule, + checkUnsupportedCommand, + checkBlockingCommand, } from 'uiSrc/utils' import { MOCK_COMMANDS_SPEC } from 'uiSrc/constants' import { render, screen } from 'uiSrc/utils/test-utils' import { CommandExecutionStatus } from 'uiSrc/slices/interfaces/cli' +import { RedisDefaultModules } from 'uiSrc/slices/interfaces' const getDbIndexFromSelectQueryTests = [ { input: 'select 0', expected: 0 }, @@ -21,6 +26,7 @@ const getDbIndexFromSelectQueryTests = [ { input: 'info', expected: new Error('Invalid command') }, { input: 'select "1 1231"', expected: new Error('Parsing error') }, { input: 'select abc', expected: new Error('Parsing error') }, + { input: 'select ', expected: new Error('Parsing error') }, ] describe('getDbIndexFromSelectQuery', () => { @@ -49,6 +55,41 @@ const getCommandNameFromQueryTests = [ input: [`${' '.repeat(20)} CLIENT ${' '.repeat(100)} KILL`, MOCK_COMMANDS_SPEC, 500], expected: 'CLIENT KILL' }, + { input: [1], expected: undefined }, +] + +const checkUnsupportedModuleCommandTests = [ + { input: [[], 'FT.foo bar'], expected: RedisDefaultModules.Search }, + { input: [[{ name: RedisDefaultModules.Search }], 'foo bar'], expected: null }, + { input: [[{ name: RedisDefaultModules.Search }], 'ft.foo bar'], expected: null }, + { input: [[{ name: RedisDefaultModules.SearchLight }], 'ft.foo bar'], expected: null }, + { input: [[{ name: RedisDefaultModules.FT }], ' FT.foo bar'], expected: null }, + { input: [[{ name: RedisDefaultModules.FTL }], ' ft.foo bar'], expected: null }, +] + +const checkCommandModuleTests = [ + { input: 'FT.foo bar', expected: RedisDefaultModules.Search }, + { input: 'JSON.foo bar', expected: RedisDefaultModules.ReJSON }, + { input: 'TS.foo bar', expected: RedisDefaultModules.TimeSeries }, + { input: 'GRAPH.foo bar', expected: RedisDefaultModules.Graph }, + { input: 'BF.foo bar', expected: RedisDefaultModules.Bloom }, + { input: 'CF.foo bar', expected: RedisDefaultModules.Bloom }, + { input: 'CMS.foo bar', expected: RedisDefaultModules.Bloom }, + { input: 'TDIGEST.foo bar', expected: RedisDefaultModules.Bloom }, + { input: 'TOPK.foo bar', expected: RedisDefaultModules.Bloom }, + { input: 'FOO.foo bar', expected: null }, +] + +const checkUnsupportedCommandTests = [ + { input: [['FT'], 'FT.foo bar'], expected: 'FT' }, + { input: [['FT'], ' ft.foo bar '], expected: 'FT' }, + { input: [['FOO', 'BAR'], 'FT.foo bar'], expected: undefined }, +] + +const checkBlockingCommandTests = [ + { input: [['ft'], 'FT.foo bar'], expected: 'ft' }, + { input: [['ft'], ' ft.foo bar '], expected: 'ft' }, + { input: [['foo', 'bar'], 'FT.foo bar'], expected: undefined }, ] describe('getCommandNameFromQuery', () => { @@ -99,3 +140,30 @@ describe('wbSummaryCommand', () => { expect(container).toHaveTextContent(expected) }) }) + +describe('checkUnsupportedModuleCommand', () => { + test.each(checkUnsupportedModuleCommandTests)('%j', ({ input, expected }) => { + // @ts-ignore + expect(checkUnsupportedModuleCommand(...input)).toEqual(expected) + }) +}) + +describe('checkCommandModule', () => { + test.each(checkCommandModuleTests)('%j', ({ input, expected }) => { + expect(checkCommandModule(input)).toEqual(expected) + }) +}) + +describe('checkUnsupportedCommand', () => { + test.each(checkUnsupportedCommandTests)('%j', ({ input, expected }) => { + // @ts-ignore + expect(checkUnsupportedCommand(...input)).toEqual(expected) + }) +}) + +describe('checkBlockingCommand', () => { + test.each(checkBlockingCommandTests)('%j', ({ input, expected }) => { + // @ts-ignore + expect(checkBlockingCommand(...input)).toEqual(expected) + }) +}) From 5da5cbd647dee90dea3fa112cc66ab4e811ac825 Mon Sep 17 00:00:00 2001 From: Amir Allayarov Date: Mon, 6 Mar 2023 14:15:36 +0700 Subject: [PATCH 3/7] #RI-4230 - update --- .../components/module-not-loaded/ModuleNotLoaded.tsx | 2 +- .../components/module-not-loaded/styles.module.scss | 12 ++++++++++++ redisinsight/ui/src/pages/workbench/constants.ts | 1 - 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx index b80e9452a7..37b68e88b7 100644 --- a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx +++ b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx @@ -71,7 +71,7 @@ const ModuleNotLoaded = ({ moduleName, id }: IProps) => {
    {renderTitle(width, module)} {CONTENT[moduleName]?.text} -
      +
        {CONTENT[moduleName]?.improvements.map((item: string) => ( ))} diff --git a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss index 455def199f..2eb7e87a8b 100644 --- a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss +++ b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss @@ -44,12 +44,22 @@ } } + .list.bloomList { + display: flex; + flex-wrap: wrap; + + .listItem { + margin-right: 18px; + } + } + .listItem { display: flex; margin-bottom: 20px; .iconWrapper { display: flex; + flex: 0 0 16px; align-items: center; justify-content: center; width: 16px; @@ -86,6 +96,8 @@ } &.fullScreen { + padding: 89px 77px; + .flex { flex-direction: column; } diff --git a/redisinsight/ui/src/pages/workbench/constants.ts b/redisinsight/ui/src/pages/workbench/constants.ts index 298891f3ce..0df68f333b 100644 --- a/redisinsight/ui/src/pages/workbench/constants.ts +++ b/redisinsight/ui/src/pages/workbench/constants.ts @@ -64,5 +64,4 @@ export enum ModuleCommandPrefix { CMS = 'CMS.', TOPK = 'TOPK.', TDIGEST = 'TDIGEST.', - // RedisBloom = RedisBloom, } From 62a40d2affc3828d9b50a609eac86206e8d252dc Mon Sep 17 00:00:00 2001 From: Amir Allayarov Date: Tue, 7 Mar 2023 18:27:26 +0700 Subject: [PATCH 4/7] #RI-4230 - resolve demo comments --- .../assets/img/icons/module_not_loaded.svg | 29 +++++++++---------- .../module-not-loaded/ModuleNotLoaded.tsx | 2 +- .../module-not-loaded/styles.module.scss | 1 + 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/redisinsight/ui/src/assets/img/icons/module_not_loaded.svg b/redisinsight/ui/src/assets/img/icons/module_not_loaded.svg index deb7a4d35a..e43e747c93 100644 --- a/redisinsight/ui/src/assets/img/icons/module_not_loaded.svg +++ b/redisinsight/ui/src/assets/img/icons/module_not_loaded.svg @@ -1,38 +1,37 @@ - - - - + + + - - + + - - + + - + - + - - + + - + - - + + diff --git a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx index 37b68e88b7..f45505ecb2 100644 --- a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx +++ b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx @@ -26,7 +26,7 @@ const MAX_ELEMENT_WIDTH = 1440 const renderTitle = (width: number, moduleName?: string) => (

        - {`Looks like ${moduleName} is not available`} + {`Looks like ${moduleName} is not available `} {width > MAX_ELEMENT_WIDTH &&
        } for this database

        diff --git a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss index 2eb7e87a8b..e766f791b5 100644 --- a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss +++ b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss @@ -41,6 +41,7 @@ .bigIcon { width: 317px; + margin-bottom: 42px; } } From 4fa5213365f39700085a988b8b7f39955bbf5ae0 Mon Sep 17 00:00:00 2001 From: nmammadli Date: Wed, 8 Mar 2023 18:24:35 +0100 Subject: [PATCH 5/7] add test for https://redislabs.atlassian.net/browse/RI-4230 --- tests/e2e/pageObjects/workbench-page.ts | 2 ++ .../workbench/command-results.e2e.ts | 20 ++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/e2e/pageObjects/workbench-page.ts b/tests/e2e/pageObjects/workbench-page.ts index 9554d85f51..db9b38543f 100644 --- a/tests/e2e/pageObjects/workbench-page.ts +++ b/tests/e2e/pageObjects/workbench-page.ts @@ -29,6 +29,7 @@ export class WorkbenchPage { //*The following categories are ordered alphabetically (Alerts, Buttons, Checkboxes, etc.). //------------------------------------------------------------------------------------------- //BUTTONS + welcomePageTitle = Selector('[data-testid=welcome-page-title]'); submitCommandButton = Selector('[data-testid=btn-submit]'); resizeButtonForScriptingAndResults = Selector('[data-test-subj=resize-btn-scripting-area-and-results]'); collapsePreselectAreaButton = Selector('[data-testid=collapse-enablement-area]'); @@ -181,6 +182,7 @@ export class WorkbenchPage { */ async sendCommandInWorkbench(command: string, speed = 1, paste = true): Promise { await t + .click(this.queryInput) .typeText(this.queryInput, command, { replace: true, speed, paste }) .click(this.submitCommandButton); } diff --git a/tests/e2e/tests/regression/workbench/command-results.e2e.ts b/tests/e2e/tests/regression/workbench/command-results.e2e.ts index ae807aeb0d..860117b3be 100644 --- a/tests/e2e/tests/regression/workbench/command-results.e2e.ts +++ b/tests/e2e/tests/regression/workbench/command-results.e2e.ts @@ -2,7 +2,7 @@ import { acceptLicenseTermsAndAddDatabaseApi } from '../../../helpers/database'; import { WorkbenchPage, MyRedisDatabasePage } from '../../../pageObjects'; import { commonUrl, - ossStandaloneRedisearch + ossStandaloneRedisearch, ossStandaloneV5Config } from '../../../helpers/conf'; import { env, rte } from '../../../helpers/constants'; import { deleteStandaloneDatabaseApi } from '../../../helpers/api/api-database'; @@ -134,3 +134,21 @@ test.before(async t => { // verify table view row count match with text view after client list command await workBenchActions.verifyClientListTableViewRowCount(); }); +// https://redislabs.atlassian.net/browse/RI-4230 +test.only.before(async t => { + await acceptLicenseTermsAndAddDatabaseApi(ossStandaloneV5Config, ossStandaloneV5Config.databaseName); + await t.click(myRedisDatabasePage.workbenchButton); +}).after(async() => { + await deleteStandaloneDatabaseApi(ossStandaloneV5Config); +})('Verify that change screens when capability not available - JSON,RediSearch', async t => { + const commandJSON = 'JSON.ARRAPPEND key value'; + const commandFT = 'FT.LIST'; + await workbenchPage.sendCommandInWorkbench(commandJSON); + // Verify change screens when capability not available - 'Search' + await t.expect(workbenchPage.welcomePageTitle.withText('Looks like RedisJSON is not available').visible) + .ok('Missing RedisJSON title is not visible'); + await workbenchPage.sendCommandInWorkbench(commandFT); + // Verify change screens when capability not available - 'JSON' + await t.expect(workbenchPage.welcomePageTitle.withText('Looks like RediSearch is not available').visible) + .ok('Missing RedisJSON title is not visible'); +}); From 79151323550b27a8914b48261573dd44d48414b5 Mon Sep 17 00:00:00 2001 From: Amir Allayarov Date: Thu, 9 Mar 2023 10:23:15 +0700 Subject: [PATCH 6/7] #RI-4275 - fix styles --- .../ui/src/constants/workbenchResults.ts | 16 ++++++++-------- .../module-not-loaded/ModuleNotLoaded.tsx | 11 +++++++++-- .../module-not-loaded/styles.module.scss | 8 -------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/redisinsight/ui/src/constants/workbenchResults.ts b/redisinsight/ui/src/constants/workbenchResults.ts index 4e199b11fb..75aac0ea1b 100644 --- a/redisinsight/ui/src/constants/workbenchResults.ts +++ b/redisinsight/ui/src/constants/workbenchResults.ts @@ -6,7 +6,7 @@ export const EMPTY_COMMAND = 'Encrypted data' export const MODULE_NOT_LOADED_CONTENT: { [key in RedisDefaultModules]?: any } = { [RedisDefaultModules.TimeSeries]: { - text: 'RedisTimeSeries adds a Time Series data structure to Redis. With this capability you can:', + text: ['RedisTimeSeries adds a Time Series data structure to Redis. ', 'With this capability you can:'], improvements: [ 'Add sample data', 'Perform cross-time-series range and aggregation queries', @@ -15,17 +15,17 @@ export const MODULE_NOT_LOADED_CONTENT: { [key in RedisDefaultModules]?: any } = link: 'https://redis.io/docs/stack/timeseries/' }, [RedisDefaultModules.Search]: { - text: 'RediSearch adds the capability to:', + text: ['RediSearch adds the capability to:'], improvements: [ 'Query', 'Secondary index', 'Full-text search' ], - additionalText: 'These features enable multi-field queries, aggregation, exact phrase matching, numeric filtering, geo filtering and vector similarity semantic search on top of text queries.', + additionalText: ['These features enable multi-field queries, aggregation, exact phrase matching, numeric filtering, ', 'geo filtering and vector similarity semantic search on top of text queries.'], link: 'https://redis.io/docs/stack/search/' }, [RedisDefaultModules.Graph]: { - text: 'RedisGraph adds a Property Graph data structure to Redis. With this capability you can:', + text: ['RedisGraph adds a Property Graph data structure to Redis. ', 'With this capability you can:'], improvements: [ 'Create graphs', 'Query property graphs using the Cypher query language with proprietary extensions' @@ -33,17 +33,17 @@ export const MODULE_NOT_LOADED_CONTENT: { [key in RedisDefaultModules]?: any } = link: 'https://redis.io/docs/stack/graph/' }, [RedisDefaultModules.ReJSON]: { - text: 'RedisJSON adds the capability to:', + text: ['RedisJSON adds the capability to:'], improvements: [ 'Store JSON documents', 'Update JSON documents', 'Retrieve JSON documents' ], - additionalText: 'RedisJSON also works seamlessly with RediSearch to let you index and query JSON documents.', + additionalText: ['RedisJSON also works seamlessly with RediSearch to let you index and query JSON documents.'], link: 'https://redis.io/docs/stack/json/' }, [RedisDefaultModules.Bloom]: { - text: 'RedisBloom adds a set of probabilistic data structures to Redis, including:', + text: ['RedisBloom adds a set of probabilistic data structures to Redis, including:'], improvements: [ 'Bloom filter', 'Cuckoo filter', @@ -51,7 +51,7 @@ export const MODULE_NOT_LOADED_CONTENT: { [key in RedisDefaultModules]?: any } = 'Top-K', 'T-digest' ], - additionalText: 'With this capability you can query streaming data without needing to store all the elements of the stream.', + additionalText: ['With this capability you can query streaming data without needing to store all the elements of the stream.'], link: 'https://redis.io/docs/stack/bloom/' } } diff --git a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx index f45505ecb2..b19cd639a6 100644 --- a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx +++ b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/ModuleNotLoaded.tsx @@ -21,6 +21,7 @@ export interface IProps { id: string } +const MIN_ELEMENT_WIDTH = 1210 const MAX_ELEMENT_WIDTH = 1440 const renderTitle = (width: number, moduleName?: string) => ( @@ -70,7 +71,11 @@ const ModuleNotLoaded = ({ moduleName, id }: IProps) => {
    {renderTitle(width, module)} - {CONTENT[moduleName]?.text} + + {CONTENT[moduleName]?.text.map((item: string) => ( + width > MIN_ELEMENT_WIDTH ? <>{item}
    : item + ))} +
      {CONTENT[moduleName]?.improvements.map((item: string) => ( @@ -78,7 +83,9 @@ const ModuleNotLoaded = ({ moduleName, id }: IProps) => {
    {!!CONTENT[moduleName]?.additionalText && ( - {CONTENT[moduleName]?.additionalText} + {CONTENT[moduleName]?.additionalText.map((item: string) => ( + width > MIN_ELEMENT_WIDTH ? <>{item}
    : item + ))}
    )} {renderText(module)} diff --git a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss index e766f791b5..8268533ff4 100644 --- a/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss +++ b/redisinsight/ui/src/pages/workbench/components/module-not-loaded/styles.module.scss @@ -115,14 +115,6 @@ text-align: center; } - .bigText { - width: 586px; - } - - .additionalText { - width: 620px; - } - .list { display: flex; justify-content: center; From 73b6e465d874008d18b395c67765e4f728efe5a2 Mon Sep 17 00:00:00 2001 From: nmammadli Date: Thu, 9 Mar 2023 12:17:23 +0100 Subject: [PATCH 7/7] delete .only and update name --- tests/e2e/tests/regression/workbench/command-results.e2e.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/tests/regression/workbench/command-results.e2e.ts b/tests/e2e/tests/regression/workbench/command-results.e2e.ts index 860117b3be..a68bba1d54 100644 --- a/tests/e2e/tests/regression/workbench/command-results.e2e.ts +++ b/tests/e2e/tests/regression/workbench/command-results.e2e.ts @@ -135,12 +135,12 @@ test.before(async t => { await workBenchActions.verifyClientListTableViewRowCount(); }); // https://redislabs.atlassian.net/browse/RI-4230 -test.only.before(async t => { +test.before(async t => { await acceptLicenseTermsAndAddDatabaseApi(ossStandaloneV5Config, ossStandaloneV5Config.databaseName); await t.click(myRedisDatabasePage.workbenchButton); }).after(async() => { await deleteStandaloneDatabaseApi(ossStandaloneV5Config); -})('Verify that change screens when capability not available - JSON,RediSearch', async t => { +})('Verify that user can see options on what can be done to work with capabilities in Workbench for docker', async t => { const commandJSON = 'JSON.ARRAPPEND key value'; const commandFT = 'FT.LIST'; await workbenchPage.sendCommandInWorkbench(commandJSON);