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
3 changes: 2 additions & 1 deletion redisinsight/ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Router from './Router'
import store from './slices/store'
import { Theme } from './constants'
import { themeService } from './services'
import { NavigationMenu, Notifications, Config } from './components'
import { NavigationMenu, Notifications, Config, ShortcutsFlyout } from './components'
import { ThemeProvider } from './contexts/themeContext'
import MainComponent from './components/main/MainComponent'

Expand All @@ -32,6 +32,7 @@ const App = ({ children }: { children?: ReactElement }) => (
</EuiPageBody>
</EuiPage>
<Notifications />
<ShortcutsFlyout />
</div>
</Router>
</ThemeProvider>
Expand Down
4 changes: 3 additions & 1 deletion redisinsight/ui/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Config from './config'
import AdvancedSettings from './advanced-settings/AdvancedSettings'
import { ConsentsSettings, ConsentsSettingsPopup } from './consents-settings'
import KeyboardShortcut from './keyboard-shortcut/KeyboardShortcut'
import ShortcutsFlyout from './shortcuts-flyout/ShortcutsFlyout'

export {
NavigationMenu,
Expand All @@ -30,5 +31,6 @@ export {
ConsentsSettings,
ConsentsSettingsPopup,
AdvancedSettings,
KeyboardShortcut
KeyboardShortcut,
ShortcutsFlyout
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import React from 'react'
import { isString } from 'lodash'
import cx from 'classnames'
import { EuiBadge, EuiText } from '@elastic/eui'

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

export interface Props {
items: string[],
separator?: string
items: (string | JSX.Element)[];
separator?: string;
transparent?: boolean;
}

const KeyboardShortcut = ({ items = [], separator = '' }: Props) => (
const KeyboardShortcut = ({ items = [], separator = '', transparent = false }: Props) => (
<div className={styles.container}>
{
items.map((item: string, index: number) => (
<div key={item}>
items.map((item: string | JSX.Element, index: number) => (
<div key={isString(item) ? item : item?.props?.children}>
{ (index !== 0) && <div className={styles.separator}>{separator}</div> }
<EuiBadge className={styles.badge}>
<EuiBadge className={cx(styles.badge, { [styles.transparent]: transparent })}>
<EuiText size="s">{item}</EuiText>
</EuiBadge>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,10 @@

.badge {
background-color: var(--euiTooltipBackgroundColor) !important;
border: 1px solid var(--euiToastSuccessBtnColor) !important;;
border: 1px solid var(--euiToastSuccessBtnColor) !important;
}

.transparent {
background-color: transparent !important;
border-color: var(--separatorColor) !important;
}
32 changes: 21 additions & 11 deletions redisinsight/ui/src/components/navigation-menu/NavigationMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
import { PageNames, Pages } from 'uiSrc/constants'
import { getRouterLinkProps } from 'uiSrc/services'
import { connectedInstanceSelector } from 'uiSrc/slices/instances'
import { setReleaseNotesViewed, appElectronInfoSelector } from 'uiSrc/slices/app/info'
import { setReleaseNotesViewed, appElectronInfoSelector, setShortcutsFlyoutState } from 'uiSrc/slices/app/info'
import LogoSVG from 'uiSrc/assets/img/logo.svg'
import SettingsSVG from 'uiSrc/assets/img/sidebar/settings.svg'
import SettingsActiveSVG from 'uiSrc/assets/img/sidebar/settings_active.svg'
Expand Down Expand Up @@ -71,6 +71,11 @@ const NavigationMenu = () => {
history.push(Pages.browser(connectedInstanceId))
}

const onKeyboardShortcutClick = () => {
setIsHelpMenuActive(false)
dispatch(setShortcutsFlyoutState(true))
}

const privateRoutes: INavigations[] = [
{
tooltipText: 'Browser',
Expand Down Expand Up @@ -177,16 +182,21 @@ const NavigationMenu = () => {
</EuiLink>
</EuiFlexItem>

<EuiFlexItem className={cx(styles.helpMenuItem, styles.helpMenuItemDisabled)}>
<EuiIcon type="keyboardShortcut" size="xl" />
<EuiSpacer size="s" />
<EuiText
size="xs"
textAlign="center"
className={styles.helpMenuText}
>
Keyboard Shortcuts
</EuiText>
<EuiFlexItem
className={styles.helpMenuItem}
onClick={() => onKeyboardShortcutClick()}
>
<div className={styles.helpMenuItemLink}>
<EuiIcon type="keyboardShortcut" size="xl" />
<EuiSpacer size="s" />
<EuiText
size="xs"
textAlign="center"
className={styles.helpMenuText}
>
Keyboard Shortcuts
</EuiText>
</div>
</EuiFlexItem>

<EuiFlexItem className={styles.helpMenuItem}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,23 +103,25 @@ $sideBarWidth: 60px;

.helpMenuItem {
align-items: center;
cursor: pointer;

:global(.euiButtonIcon), :global(.euiIcon) {
color: var(--euiTooltipTextColor) !important;
}

.helpMenuItemLink {
&:global(.euiLink) {
text-decoration: none !important;
display: flex;
flex-direction: column;
align-items: center;
transition: transform 0.3s ease;
text-decoration: none !important;
display: flex;
flex-direction: column;
align-items: center;
transition: transform 0.3s ease;

&:hover {
transform: translateY(-1px);
}
&:hover {
transform: translateY(-1px);
}

&:global(.euiLink) {
text-decoration: none !important;
&:focus {
animation: none !important;
}
Expand All @@ -128,6 +130,7 @@ $sideBarWidth: 60px;
}

.helpMenuItemDisabled {
cursor: auto;
:global(.euiIcon), div {
color: var(--buttonSecondaryDisabledTextColor) !important;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react'
import { cloneDeep } from 'lodash'
import { cleanup, mockedStore, render } from 'uiSrc/utils/test-utils'
import ShortcutsFlyout from './ShortcutsFlyout'
import { SHORTCUTS, ShortcutGroup } from './schema'

let store: typeof mockedStore
beforeEach(() => {
cleanup()
store = cloneDeep(mockedStore)
store.clearActions()
})

const appInfoSlicesPath = 'uiSrc/slices/app/info'

jest.mock(appInfoSlicesPath, () => ({
...jest.requireActual(appInfoSlicesPath),
appInfoSelector: jest.fn().mockReturnValue({
...jest.requireActual(appInfoSlicesPath).appInfoSelector,
isShortcutsFlyoutOpen: true
}),
}))

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

it('should render groups', () => {
render(<ShortcutsFlyout />)

SHORTCUTS.forEach((group: ShortcutGroup) => {
expect(
document.querySelector(`[data-test-subj="shortcut-title-${group.name}"]`)
).toBeInTheDocument()
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from 'react'
import cx from 'classnames'
import { useDispatch, useSelector } from 'react-redux'
import {
EuiBasicTableColumn,
EuiFlyout,
EuiFlyoutBody,
EuiInMemoryTable,
EuiSpacer,
EuiTitle
} from '@elastic/eui'
import { appInfoSelector, setShortcutsFlyoutState } from 'uiSrc/slices/app/info'
import { KeyboardShortcut } from 'uiSrc/components'
import { SHORTCUTS, ShortcutGroup, separator } from './schema'

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

const ShortcutsFlyout = () => {
const { isShortcutsFlyoutOpen } = useSelector(appInfoSelector)

const dispatch = useDispatch()

const tableColumns: EuiBasicTableColumn<any>[] = [
{
name: '',
field: 'description',
width: '60%'
},
{
name: '',
field: 'keys',
width: '40%',
render: (items: string[]) => <KeyboardShortcut items={items} separator={separator} transparent />
}
]

const ShortcutsTable = ({ name, items }: ShortcutGroup) => (
<div key={name}>
<EuiTitle size="xxs" data-test-subj={`shortcut-title-${name}`}>
<h6>{name}</h6>
</EuiTitle>
<EuiSpacer size="m" />
<EuiInMemoryTable
className={cx('inMemoryTableDefault', styles.table)}
columns={tableColumns}
items={items}
responsive={false}
/>
<EuiSpacer size="xl" />
</div>
)

return isShortcutsFlyoutOpen ? (
<EuiFlyout
ownFocus
size="538px"
onClose={() => dispatch(setShortcutsFlyoutState(false))}
>
<EuiFlyoutBody>
<EuiTitle size="s" className={styles.title}>
<h4>Shortcuts</h4>
</EuiTitle>
<EuiSpacer size="m" />
{SHORTCUTS.map(ShortcutsTable)}
</EuiFlyoutBody>
</EuiFlyout>
) : null
}

export default ShortcutsFlyout
42 changes: 42 additions & 0 deletions redisinsight/ui/src/components/shortcuts-flyout/schema.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { KEYBOARD_SHORTCUTS } from 'uiSrc/constants'

export interface Shortcut {
label?: string
description: string
keys: (string | JSX.Element)[]
}

export interface ShortcutGroup {
name: string
items: Shortcut[]
}

export const separator = KEYBOARD_SHORTCUTS._separator

export const SHORTCUTS: ShortcutGroup[] = [
{
name: 'Desktop application',
items: [
KEYBOARD_SHORTCUTS.desktop.newWindow,
KEYBOARD_SHORTCUTS.desktop.reloadPage,
]
},
{
name: 'CLI',
items: [
KEYBOARD_SHORTCUTS.cli.autocompleteNext,
KEYBOARD_SHORTCUTS.cli.autocompletePrev,
KEYBOARD_SHORTCUTS.cli.clearSearch,
KEYBOARD_SHORTCUTS.cli.prevCommand,
KEYBOARD_SHORTCUTS.cli.nextCommand,
]
},
{
name: 'Workbench',
items: [
KEYBOARD_SHORTCUTS.workbench.runQuery,
KEYBOARD_SHORTCUTS.workbench.nextLine,
KEYBOARD_SHORTCUTS.workbench.listOfCommands
]
},
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.title {
font-size: 18px;
font-weight: 600 !important;
}
.table {
:global(thead) {
display: none;
}
&:global(.inMemoryTableDefault .euiTableCellContent span) {
padding-top: 0 !important;
white-space: normal;

}
:global(.euiBadge) {
height: 22px;
min-width: 34px !important;
display: flex;
justify-content: center;
align-items: center;

:global(.euiText) {
font-weight: 500;
}

:global(.badgeArrowUp), :global(.badgeArrowDown), :global(.shiftSymbol) {
position: relative;
top: -3px
}

:global(.shiftSymbol) {
top: -2px
}

:global(.cmdSymbol) {
font-size: 12px;
}
}
}
24 changes: 0 additions & 24 deletions redisinsight/ui/src/constants/keyboardShortcuts.ts

This file was deleted.

Loading