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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ import {
processUnsupportedCommand,
processUnrepeatableNumber,
processMonitorCommand,
processPSubscribeCommand,
} from 'uiSrc/slices/cli/cli-output'
import { CommandMonitor } from 'uiSrc/constants'
import { CommandMonitor, CommandPSubscribe } from 'uiSrc/constants'
import { getCommandRepeat, isRepeatCountCorrect } from 'uiSrc/utils'
import { ConnectionType } from 'uiSrc/slices/interfaces'
import { ClusterNodeRole } from 'uiSrc/slices/interfaces/cli'
Expand Down Expand Up @@ -78,12 +79,20 @@ const CliBodyWrapper = () => {
return
}

// Flow if monitor command was executed
// Flow if MONITOR command was executed
if (checkUnsupportedCommand([CommandMonitor.toLowerCase()], commandLine)) {
dispatch(processMonitorCommand(commandLine, resetCommand))
return
}

// Flow if PSUBSCRIBE command was executed
if (checkUnsupportedCommand([CommandPSubscribe.toLowerCase()], commandLine)) {
dispatch(processPSubscribeCommand(commandLine, () => {
resetCommand()
}))
return
}

if (unsupportedCommand) {
dispatch(processUnsupportedCommand(commandLine, unsupportedCommand, resetCommand))
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ThemeContext } from 'uiSrc/contexts/themeContext'

import { getOverviewMetrics } from './components/OverviewMetrics'

const TIMEOUT_TO_GET_INFO = process.env.NODE_ENV !== 'development' ? 5000 : 100000
const TIMEOUT_TO_GET_INFO = process.env.NODE_ENV !== 'development' ? 5000 : 10000000

interface IProps { windowDimensions: number }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { EuiTextColor } from '@elastic/eui'
import { CellMeasurer, List, CellMeasurerCache, ListRowProps } from 'react-virtualized'

import { getFormatTime } from 'uiSrc/utils'
import { DEFAULT_TEXT } from 'uiSrc/components/notifications'
import { DEFAULT_ERROR_TEXT } from 'uiSrc/components/notifications'

import styles from 'uiSrc/components/monitor/Monitor/styles.module.scss'
import 'react-virtualized/styles.css'
Expand Down Expand Up @@ -80,7 +80,7 @@ const MonitorOutputList = (props: Props) => {
</>
)}
{isError && (
<EuiTextColor color="danger">{message ?? DEFAULT_TEXT}</EuiTextColor>
<EuiTextColor color="danger">{message ?? DEFAULT_ERROR_TEXT}</EuiTextColor>
)}
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import errorMessages from './error-messages'

import styles from './styles.module.scss'

export const DEFAULT_TEXT = 'Something went wrong.'
export const DEFAULT_ERROR_TEXT = 'Something went wrong.'

const Notifications = () => {
const messagesData = useSelector(messagesSelector)
Expand Down Expand Up @@ -82,7 +82,7 @@ const Notifications = () => {
})

const getErrorsToasts = (errors: IError[]) =>
errors.map(({ id = '', message = DEFAULT_TEXT, instanceId = '', name }) => {
errors.map(({ id = '', message = DEFAULT_ERROR_TEXT, instanceId = '', name }) => {
if (ApiEncryptionErrors.includes(name)) {
return errorMessages.ENCRYPTION(id, () => removeToast({ id }), instanceId)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import React from 'react'
import { useSelector } from 'react-redux'
import { useParams } from 'react-router-dom'
import {
checkUnsupportedCommand,
checkUnsupportedModuleCommand,
cliParseTextResponse,
CliPrefix,
getCommandRepeat,
isRepeatCountCorrect
} from 'uiSrc/utils'
import { cliTexts, SelectCommand } from 'uiSrc/constants/cliOutput'
import { CommandMonitor } from 'uiSrc/constants'
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'
Expand All @@ -18,17 +20,29 @@ import { connectedInstanceSelector } from 'uiSrc/slices/instances/instances'
import ModuleNotLoaded from 'uiSrc/pages/workbench/components/module-not-loaded'

const CommonErrorResponse = (command = '', result?: any) => {
const { instanceId = '' } = useParams<{ instanceId: string }>()
const { unsupportedCommands: cliUnsupportedCommands, blockingCommands } = useSelector(cliSettingsSelector)
const { modules } = useSelector(connectedInstanceSelector)
const unsupportedCommands = [SelectCommand.toLowerCase(), ...cliUnsupportedCommands, ...blockingCommands]
const [commandLine, countRepeat] = getCommandRepeat(command)

// Flow if monitor command was executed
// Flow if MONITOR command was executed
if (checkUnsupportedCommand([CommandMonitor.toLowerCase()], commandLine)) {
return cliParseTextResponse(
cliTexts.MONITOR_COMMAND,
commandLine,
CommandExecutionStatus.Fail,
CliPrefix.QueryCard,
)
}
// Flow if PSUBSCRIBE command was executed
if (checkUnsupportedCommand([CommandPSubscribe.toLowerCase()], commandLine)) {
return cliParseTextResponse(
cliTexts.PSUBSCRIBE_COMMAND(Pages.pubSub(instanceId)),
commandLine,
CommandExecutionStatus.Fail,
CliPrefix.QueryCard,
true,
)
}

Expand All @@ -39,6 +53,7 @@ const CommonErrorResponse = (command = '', result?: any) => {
cliTexts.UNABLE_TO_DECRYPT,
'',
CommandExecutionStatus.Fail,
CliPrefix.QueryCard,
)
}

Expand All @@ -47,6 +62,7 @@ const CommonErrorResponse = (command = '', result?: any) => {
cliTexts.REPEAT_COUNT_INVALID,
commandLine,
CommandExecutionStatus.Fail,
CliPrefix.QueryCard,
)
}

Expand Down
2 changes: 2 additions & 0 deletions redisinsight/ui/src/constants/cliOutput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export const cliTexts = {
REPEAT_COUNT_INVALID: 'Invalid repeat command option value',
CONNECTION_CLOSED: 'Client connection previously closed. Run the command after the connection is re-created.',
MONITOR_COMMAND: 'Use the "Profiler" tool to see all the requests processed by the server.',
PSUBSCRIBE_COMMAND: (href: string = '') =>
'Use Pub/Sub to see the messages published to all channels in your database.',
UNABLE_TO_DECRYPT: 'Unable to decrypt. Check the system keychain or re-run the command.',
CLI_ERROR_MESSAGE: (message: string) => (
[
Expand Down
1 change: 1 addition & 0 deletions redisinsight/ui/src/constants/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export enum CommandPrefix {
}

export const CommandMonitor = 'MONITOR'
export const CommandPSubscribe = 'PSUBSCRIBE'

export enum CommandRediSearch {
Search = 'FT.SEARCH',
Expand Down
2 changes: 1 addition & 1 deletion redisinsight/ui/src/constants/workbenchResults.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const bulkReplyCommands = ['LOLWUT', 'INFO', 'CLIENT', 'CLUSTER', 'MEMORY', 'MONITOR']
export const bulkReplyCommands = ['LOLWUT', 'INFO', 'CLIENT', 'CLUSTER', 'MEMORY', 'MONITOR', 'PSUBSCRIBE']
4 changes: 2 additions & 2 deletions redisinsight/ui/src/pages/pubSub/PubSubPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react'
import InstanceHeader from 'uiSrc/components/instance-header'
import { SubscriptionType } from 'uiSrc/constants/pubSub'

import { MessagesList, SubscriptionPanel } from './components'
import { MessagesListWrapper, SubscriptionPanel } from './components'

import styles from './styles.module.scss'

Expand All @@ -23,7 +23,7 @@ const PubSubPage = () => {
<SubscriptionPanel />
</div>
<div className={styles.tableWrapper}>
<MessagesList />
<MessagesListWrapper />
</div>
</div>
<div className={styles.footerPanel}>
Expand Down

This file was deleted.

6 changes: 3 additions & 3 deletions redisinsight/ui/src/pages/pubSub/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import SubscriptionPanel from './SubscriptionPanel'
import MessagesList from './MessagesList'
import SubscriptionPanel from './subscription-panel'
import MessagesListWrapper from './messages-list'

export {
SubscriptionPanel,
MessagesList
MessagesListWrapper,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react'
import { ConnectionType } from 'uiSrc/slices/interfaces'
import { render } from 'uiSrc/utils/test-utils'

import EmptyMessagesList from './EmptyMessagesList'

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

it('should render cluster info for Cluster connection type', () => {
const { queryByTestId } = render(<EmptyMessagesList connectionType={ConnectionType.Cluster} />)

expect(queryByTestId('empty-messages-list-cluster')).toBeInTheDocument()
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react'
import { EuiIcon, EuiText } from '@elastic/eui'
import cx from 'classnames'

import { ConnectionType } from 'uiSrc/slices/interfaces'

import styles from './styles.module.scss'

export interface Props {
connectionType?: ConnectionType
}

const EmptyMessagesList = ({ connectionType }: Props) => (
<div className={styles.container} data-testid="empty-messages-list">
<div className={cx(styles.content, { [styles.contentCluster]: connectionType === ConnectionType.Cluster })}>
<EuiText className={styles.title}>No messages to display</EuiText>
<EuiText className={styles.summary}>
Subscribe to the Channel to see all the messages published to your database
</EuiText>
<EuiText className={styles.alert}>
<EuiIcon type="alert" className={styles.alertIcon} />
Running in production may decrease performance and memory available
</EuiText>
{connectionType === ConnectionType.Cluster && (
<>
<div className={styles.separator} />
<EuiText className={styles.cluster} data-testid="empty-messages-list-cluster">
{'Messages published with '}
<span className={styles.badge}>
SPUBLISH
</span>
{' will not appear in this channel'}
</EuiText>
</>
)}
</div>
</div>
)

export default EmptyMessagesList
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import EmptyMessagesList from './EmptyMessagesList'

export default EmptyMessagesList
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
@import "@elastic/eui/src/global_styling/mixins/helpers";
@import "@elastic/eui/src/components/table/mixins";
@import "@elastic/eui/src/global_styling/index";

.container {
@include euiScrollBar;
display: flex;
justify-content: center;
overflow: auto;

width: 100%;
height: 100%;
}

.content {
display: flex;
flex-direction: column;
align-items: center;
margin: auto;

width: 530px;
height: 110px;

&Cluster {
height: 184px;
}

.title {
font-size: 16px !important;
line-height: 24px !important;
letter-spacing: 0px !important;
padding-bottom: 24px;
}

.summary {
font-size: 13px !important;
line-height: 18px !important;
letter-spacing: -0.13px !important;
color: var(--euiColorMediumShade) !important;
padding-bottom: 18px;
}

.alert {
font-size: 13px !important;
line-height: 18px !important;
letter-spacing: -0.13px !important;
color: var(--euiColorWarningLight) !important;
}

.cluster {
font-size: 13px !important;
line-height: 18px !important;
letter-spacing: -0.13px !important;
color: var(--textColorShade) !important;
}

.alertIcon {
margin-right: 6px;
margin-top: -3px;
}

.badge {
font-size: 12px;
font-weight: 500;
line-height: 18px;
padding: 0 8px;
display: inline-block;
text-decoration: none;
border-radius: 4px;
white-space: nowrap;
vertical-align: middle;
cursor: default;
max-width: 100%;
text-align: left;
color: var(--htmlColor);
background-color: var(--separatorColor);
}

.separator {
height: 0px;
width: 192px;
border: 1px solid var(--separatorColor);
margin: 30px 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react'
import { instance, mock } from 'ts-mockito'
import { render } from 'uiSrc/utils/test-utils'

import MessagesList, { Props } from './MessagesList'

const mockedProps = mock<Props>()

describe('MessagesList', () => {
it('should render', () => {
expect(
render(<MessagesList {...instance(mockedProps)} />)
).toBeTruthy()
})
})
Loading