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
10 changes: 10 additions & 0 deletions redisinsight/ui/src/assets/img/icons/cheer.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions redisinsight/ui/src/assets/img/icons/module_not_loaded.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 7 additions & 5 deletions redisinsight/ui/src/components/query-card/QueryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,15 @@ const QueryCard = (props: Props) => {
setSelectedViewValue(value)
}

const commonError = CommonErrorResponse(command, result)
const commonError = CommonErrorResponse(id, command, result)

return (
<div className={cx(styles.containerWrapper, {
fullscreen: isFullScreen,
[styles.isOpen]: isOpen
})}
<div
className={cx(styles.containerWrapper, {
fullscreen: isFullScreen,
[styles.isOpen]: isOpen
})}
id={id}
>
<div
className={cx(styles.container)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const QueryCardCliGroupResult = (props: Props) => {
<QueryCardCliDefaultResult
isFullScreen={isFullScreen}
items={flatten(result?.[0]?.response.map((item: any) => {
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])
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -69,8 +67,8 @@ const CommonErrorResponse = (command = '', result?: any) => {
}
const unsupportedModule = checkUnsupportedModuleCommand(modules, commandLine)

if (unsupportedModule === RedisDefaultModules.Search) {
return <ModuleNotLoaded content={RSNotLoadedContent} />
if (unsupportedModule) {
return <ModuleNotLoaded moduleName={unsupportedModule} id={id} />
}

return null
Expand Down
62 changes: 62 additions & 0 deletions redisinsight/ui/src/constants/workbenchResults.ts
Original file line number Diff line number Diff line change
@@ -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',
}
Original file line number Diff line number Diff line change
@@ -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<IProps>()

describe('ModuleNotLoaded', () => {
it('should render', () => {
expect(render(<ModuleNotLoaded content={RSNotLoadedContent} />)).toBeTruthy()
})

it('"output" prop should render', () => {
const { queryByTestId } = render(<ModuleNotLoaded content={RSNotLoadedContent} />)

const outputEl = queryByTestId('query-card-no-module-output')
expect(outputEl).toBeInTheDocument()
})
it('"table" prop should render', () => {
const { container } = render(<ModuleNotLoaded content={RSNotLoadedContent} />)

const tableEl = container.querySelector('[data-test-subj="query-card-no-module-table"]')
expect(tableEl).toBeInTheDocument()
})
it('"createCloudBtn" prop should render', () => {
const { queryByTestId } = render(
<ThemeContext.Provider value={{ ...defaultState }}>
<ModuleNotLoaded content={RSNotLoadedContent} />
</ThemeContext.Provider>
)
const btnEl = queryByTestId('query-card-no-module-button')
expect(btnEl).toBeInTheDocument()
})
it('"summaryText" prop should render', () => {
const { queryByTestId } = render(<ModuleNotLoaded content={RSNotLoadedContent} />)

const summaryTextEl = queryByTestId('query-card-no-module-summary-text')
expect(summaryTextEl).toBeInTheDocument()
})
it('"summaryImgPath" prop should render', () => {
const { queryByTestId } = render(<ModuleNotLoaded content={RSNotLoadedContent} />)

const summaryImgEl = queryByTestId('query-card-no-module-summary-img')
expect(summaryImgEl).toBeInTheDocument()
expect(render(<ModuleNotLoaded {...instance(mockedProps)} />)).toBeTruthy()
})
})
Loading