Skip to content

Commit f3fa47f

Browse files
authored
Merge pull request #1214 from RedisInsight/feature/RI-3479_redis-auto-btn
Feature/ri 3479 redis auto btn
2 parents 6de30e3 + c22f1e5 commit f3fa47f

File tree

23 files changed

+352
-65
lines changed

23 files changed

+352
-65
lines changed

redisinsight/ui/.eslintrc.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,20 @@ module.exports = {
7979
'index',
8080
],
8181
pathGroups: [
82+
{
83+
pattern: 'apiSrc/**',
84+
group: 'internal',
85+
position: 'after'
86+
},
8287
{
8388
pattern: '{.,..}/*.scss', // same directory only
8489
// pattern: '{.,..}/**/*\.scss' // same & outside directories (e.g. import '../foo/foo.scss')
8590
group: 'object',
8691
position: 'after'
8792
}
8893
],
89-
warnOnUnassignedImports: true
94+
warnOnUnassignedImports: true,
95+
pathGroupsExcludedImportTypes: ['builtin']
9096
},
9197
],
9298
},

redisinsight/ui/src/components/query-card/QueryCardCliPlugin/QueryCardCliPlugin.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useContext, useEffect, useRef, useState } from 'react'
22
import { useDispatch, useSelector } from 'react-redux'
33
import cx from 'classnames'
4+
import { v4 as uuidv4 } from 'uuid'
45
import { EuiFlexItem, EuiIcon, EuiLoadingContent, EuiTextColor } from '@elastic/eui'
56
import { pluginApi } from 'uiSrc/services/PluginAPI'
67
import { ThemeContext } from 'uiSrc/contexts/themeContext'
@@ -210,7 +211,7 @@ const QueryCardCliPlugin = (props: Props) => {
210211
useEffect(() => {
211212
const view = visualizations.find((visualization: IPluginVisualization) => visualization.uniqId === id)
212213
if (view) {
213-
generatedIframeNameRef.current = `${view.plugin.name}-${Date.now()}`
214+
generatedIframeNameRef.current = `${view.plugin.name}-${uuidv4()}`
214215
setCurrentView(view)
215216

216217
const { plugin } = view

redisinsight/ui/src/pages/workbench/components/enablement-area/EnablementArea/EnablementArea.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useHistory, useLocation } from 'react-router-dom'
33
import { useSelector, useDispatch } from 'react-redux'
44
import cx from 'classnames'
55
import { EuiListGroup, EuiLoadingContent } from '@elastic/eui'
6+
import { CodeButtonParams, ExecuteButtonMode } from 'uiSrc/pages/workbench/components/enablement-area/interfaces'
67
import { EnablementAreaComponent, IEnablementAreaItem } from 'uiSrc/slices/interfaces'
78
import { EnablementAreaProvider, IInternalPage } from 'uiSrc/pages/workbench/contexts/enablementAreaContext'
89
import { appContextWorkbenchEA, resetWorkbenchEAItem } from 'uiSrc/slices/app/context'
@@ -14,7 +15,7 @@ import {
1415
InternalLink,
1516
LazyCodeButton,
1617
LazyInternalPage,
17-
PlainText
18+
PlainText,
1819
} from './components'
1920

2021
import styles from './styles.module.scss'
@@ -25,7 +26,11 @@ export interface Props {
2526
guides: Record<string, IEnablementAreaItem>
2627
tutorials: Record<string, IEnablementAreaItem>
2728
loading: boolean
28-
openScript: (script: string, path?: string, name?: string) => void
29+
openScript: (
30+
script: string,
31+
execute?: { mode?: ExecuteButtonMode, params?: CodeButtonParams },
32+
file?: { path?: string, name?: string }
33+
) => void
2934
onOpenInternalPage: (page: IInternalPage) => void
3035
isCodeBtnDisabled?: boolean
3136
}

redisinsight/ui/src/pages/workbench/components/enablement-area/EnablementArea/components/Code/Code.spec.tsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import React from 'react'
22
import { instance, mock } from 'ts-mockito'
3-
import { fireEvent, render } from 'uiSrc/utils/test-utils'
4-
import { EnablementAreaProvider, defaultValue } from 'uiSrc/pages/workbench/contexts/enablementAreaContext'
53
import { MONACO_MANUAL } from 'uiSrc/constants'
4+
import { ExecuteButtonMode } from 'uiSrc/pages/workbench/components/enablement-area/interfaces'
5+
import { defaultValue, EnablementAreaProvider } from 'uiSrc/pages/workbench/contexts/enablementAreaContext'
6+
import { fireEvent, render, screen } from 'uiSrc/utils/test-utils'
67

78
import Code, { Props } from './Code'
89

@@ -29,6 +30,21 @@ describe('Code', () => {
2930

3031
const link = queryByTestId(`preselect-${label}`)
3132
fireEvent.click(link as Element)
32-
expect(setScript).toBeCalledWith(MONACO_MANUAL)
33+
expect(setScript).toBeCalledWith(MONACO_MANUAL, {}, undefined)
34+
})
35+
36+
it('should correctly set script with auto execute', () => {
37+
const setScript = jest.fn()
38+
const label = 'Manual'
39+
40+
render(
41+
<EnablementAreaProvider value={{ ...defaultValue, setScript }}>
42+
<Code {...instance(mockedProps)} label={label} mode={ExecuteButtonMode.Auto}>{MONACO_MANUAL}</Code>
43+
</EnablementAreaProvider>
44+
)
45+
46+
screen.debug()
47+
fireEvent.click(screen.queryByTestId(`preselect-auto-${label}`) as Element)
48+
expect(setScript).toBeCalledWith(MONACO_MANUAL, { mode: ExecuteButtonMode.Auto }, undefined)
3349
})
3450
})

redisinsight/ui/src/pages/workbench/components/enablement-area/EnablementArea/components/Code/Code.tsx

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,48 @@
1-
import React, { useContext } from 'react'
21
import { startCase } from 'lodash'
2+
import React, { useContext } from 'react'
33
import { useLocation } from 'react-router-dom'
4-
4+
import { getFileInfo, parseParams } from 'uiSrc/pages/workbench/components/enablement-area/EnablementArea/utils'
5+
import { CodeButtonParams, ExecuteButtonMode } from 'uiSrc/pages/workbench/components/enablement-area/interfaces'
56
import EnablementAreaContext from 'uiSrc/pages/workbench/contexts/enablementAreaContext'
6-
import { getFileInfo } from 'uiSrc/pages/workbench/components/enablement-area/EnablementArea/utils/getFileInfo'
7+
import { Maybe } from 'uiSrc/utils'
78

89
import CodeButton from '../CodeButton'
910

1011
export interface Props {
11-
label: string;
12-
children: string;
12+
label: string
13+
children: string
14+
params?: string
15+
mode?: ExecuteButtonMode
1316
}
1417

15-
const Code = ({ children, ...rest }: Props) => {
18+
const Code = ({ children, params, mode, ...rest }: Props) => {
1619
const { search } = useLocation()
1720
const { setScript, isCodeBtnDisabled } = useContext(EnablementAreaContext)
1821

19-
const loadContent = () => {
22+
const loadContent = (execute: { mode?: ExecuteButtonMode, params?: CodeButtonParams }) => {
2023
const pagePath = new URLSearchParams(search).get('item')
24+
let file: Maybe<{ path: string, name: string }>
25+
2126
if (pagePath) {
2227
const pageInfo = getFileInfo(pagePath)
23-
setScript(children, `${pageInfo.location}/${pageInfo.name}`, startCase(rest.label))
24-
} else {
25-
setScript(children)
28+
file = {
29+
path: `${pageInfo.location}/${pageInfo.name}`,
30+
name: startCase(rest.label)
31+
}
2632
}
33+
34+
setScript(children, execute, file)
2735
}
2836

2937
return (
30-
<CodeButton className="mb-s mt-s" onClick={loadContent} disabled={isCodeBtnDisabled} {...rest} />
38+
<CodeButton
39+
className="mb-s mt-s"
40+
onClick={loadContent}
41+
params={parseParams(params)}
42+
mode={mode}
43+
disabled={isCodeBtnDisabled}
44+
{...rest}
45+
/>
3146
)
3247
}
3348

redisinsight/ui/src/pages/workbench/components/enablement-area/EnablementArea/components/CodeButton/CodeButton.spec.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react'
22
import { instance, mock } from 'ts-mockito'
3+
import { ExecuteButtonMode } from 'uiSrc/pages/workbench/components/enablement-area/interfaces'
34
import { fireEvent, render, screen } from 'uiSrc/utils/test-utils'
45
import CodeButton, { Props } from './CodeButton'
56

@@ -14,6 +15,14 @@ describe('CodeButton', () => {
1415
expect(component).toBeTruthy()
1516
expect(container).toHaveTextContent(label)
1617
})
18+
19+
it('should not render auto-execute button', () => {
20+
const label = 'Manual'
21+
render(<CodeButton {...instance(mockedProps)} label={label} />)
22+
23+
expect(screen.queryByTestId(`preselect-auto-${label}`)).not.toBeInTheDocument()
24+
})
25+
1726
it('should call onClick function', () => {
1827
const onClick = jest.fn()
1928
const label = 'Manual'
@@ -23,4 +32,22 @@ describe('CodeButton', () => {
2332

2433
expect(onClick).toBeCalled()
2534
})
35+
36+
it('should call onClick with auto execute param', () => {
37+
const onClick = jest.fn()
38+
const label = 'Auto'
39+
40+
render(
41+
<CodeButton
42+
{...instance(mockedProps)}
43+
label={label}
44+
onClick={onClick}
45+
mode={ExecuteButtonMode.Auto}
46+
params={{}}
47+
/>
48+
)
49+
fireEvent.click(screen.getByTestId(`preselect-auto-${label}`))
50+
51+
expect(onClick).toBeCalledWith({ mode: ExecuteButtonMode.Auto, params: {} })
52+
})
2653
})
Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,48 @@
1+
import { EuiButton, EuiIcon } from '@elastic/eui'
2+
import cx from 'classnames'
13
import React from 'react'
2-
import { EuiButton } from '@elastic/eui'
4+
import { CodeButtonParams, ExecuteButtonMode } from 'uiSrc/pages/workbench/components/enablement-area/interfaces'
35
import { truncateText } from 'uiSrc/utils'
46

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

79
export interface Props {
8-
onClick: () => void
10+
onClick: (execute: { mode?: ExecuteButtonMode, params?: CodeButtonParams }) => void
911
label: string
1012
isLoading?: boolean
1113
disabled?: boolean
1214
className?: string
15+
params?: CodeButtonParams
16+
mode?: ExecuteButtonMode
17+
}
18+
const CodeButton = ({ onClick, label, isLoading, className, disabled, params, mode, ...rest }: Props) => {
19+
const isAutoExecute = mode === ExecuteButtonMode.Auto
20+
21+
return (
22+
<EuiButton
23+
iconSide="right"
24+
isLoading={isLoading}
25+
size="s"
26+
onClick={() => onClick({ mode, params })}
27+
fullWidth
28+
color="secondary"
29+
className={cx(className, styles.button)}
30+
textProps={{ className: styles.buttonText }}
31+
data-testid={`preselect-${isAutoExecute ? 'auto-' : ''}${label}`}
32+
disabled={disabled}
33+
{...rest}
34+
>
35+
<>
36+
{truncateText(label, 86)}
37+
{isAutoExecute && (
38+
<EuiIcon
39+
className={styles.autoExecuteIcon}
40+
type="playFilled"
41+
/>
42+
)}
43+
</>
44+
</EuiButton>
45+
)
1346
}
14-
const CodeButton = ({ onClick, label, isLoading, className, disabled, ...rest }: Props) => (
15-
<EuiButton
16-
iconSide="right"
17-
isLoading={isLoading}
18-
size="s"
19-
onClick={onClick}
20-
fullWidth
21-
color="secondary"
22-
className={[className, styles.button].join(' ')}
23-
textProps={{ className: styles.buttonText }}
24-
data-testid={`preselect-${label}`}
25-
disabled={disabled}
26-
{...rest}
27-
>
28-
{truncateText(label, 86)}
29-
</EuiButton>
30-
)
3147

3248
export default CodeButton

redisinsight/ui/src/pages/workbench/components/enablement-area/EnablementArea/components/CodeButton/styles.module.scss

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,27 @@
22

33
.button {
44
justify-content: space-between;
5+
position: relative;
56
&[class*='euiButton--secondary']:not([class*='isDisabled']) {
6-
&:hover,
7-
&:focus,
8-
&:focus-within {
7+
&:hover {
98
background-color: var(--euiColorSecondary) !important;
109
border-color: var(--euiColorSecondary) !important;
10+
color: var(--euiColorPrimaryText) !important;
1111
}
1212
}
13-
&:not(:hover) {
14-
span {
15-
color: var(--euiTextSubduedColor);
16-
}
13+
14+
:global(.euiButton__content) {
15+
padding: 0 24px !important;
16+
}
17+
18+
.autoExecuteIcon {
19+
position: absolute;
20+
top: 50%;
21+
right: 4px;
22+
transform: translateY(-50%);
23+
24+
width: 16px;
25+
height: 16px;
1726
}
1827
}
1928

redisinsight/ui/src/pages/workbench/components/enablement-area/EnablementArea/components/LazyCodeButton/LazyCodeButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const LazyCodeButton = ({ path = '', ...rest }: Props) => {
2727
if (isStatusSuccessful(status)) {
2828
setLoading(false)
2929
const pageInfo = getFileInfo(path)
30-
setScript(data, pageInfo.location, startCase(pageInfo.name))
30+
setScript(data, {}, { path: pageInfo.location, name: startCase(pageInfo.name) })
3131
}
3232
} catch (error) {
3333
setLoading(false)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export * from './parseParams'
2+
export * from './getFileInfo'
3+
export * from './remarkImage'
4+
export * from './rehypeLinks'
5+
export * from './remarkRedisCode'

0 commit comments

Comments
 (0)