Skip to content

Commit e075507

Browse files
authored
RI-7066: replace eui radio group and eui SuperSelect, RI-7067 (#4645)
* add RadioGroup.tsx * replace EuiRadioGroup with RiRadioGroup * add redis-ui select * replace in EuiSuperSelect with RiSelect
1 parent 1320c70 commit e075507

File tree

62 files changed

+1013
-762
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+1013
-762
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { RadioGroup } from '@redis-ui/components'
2+
3+
export { RadioGroup as RiRadioGroup } from '@redis-ui/components'
4+
5+
export const RiRadioGroupRoot = RadioGroup.Compose
6+
export const RiRadioGroupItemRoot = RadioGroup.Item.Compose
7+
export const RiRadioGroupItemLabel = RadioGroup.Item.Label
8+
export const RiRadioGroupItemIndicator = RadioGroup.Item.Indicator
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Import the original type but don't re-export it
2+
import type { SelectOption, SelectValueRender } from '@redis-ui/components'
3+
import React from 'react'
4+
5+
export { Select as RiSelect } from '@redis-ui/components'
6+
export type { SelectOption, SelectValueRender } from '@redis-ui/components'
7+
8+
// Define our extended type
9+
export type RiSelectOption = SelectOption & {
10+
'data-test-subj'?: string
11+
dropdownDisplay?: string | JSX.Element | null
12+
inputDisplay?: string | JSX.Element | null
13+
}
14+
15+
export const defaultValueRender: SelectValueRender<RiSelectOption> = ({
16+
option,
17+
isOptionValue,
18+
}) => {
19+
if (!option.inputDisplay) {
20+
return option.label ?? option.value
21+
}
22+
23+
if (isOptionValue) {
24+
// render dropdown list item
25+
if (option.dropdownDisplay && typeof option.dropdownDisplay !== 'string') {
26+
// allow for custom dropdown display element
27+
return option.dropdownDisplay
28+
}
29+
return (
30+
<span
31+
data-test-subj={option['data-test-subj']}
32+
data-testid={option['data-test-subj']}
33+
>
34+
{option.dropdownDisplay ?? option.inputDisplay}
35+
</span>
36+
)
37+
}
38+
// allow for custom input display element
39+
if (typeof option.inputDisplay !== 'string') {
40+
return option.inputDisplay
41+
}
42+
return (
43+
<span
44+
data-test-subj={`${option['data-test-subj']}-prompt`}
45+
data-testid={`${option['data-test-subj']}-prompt`}
46+
>
47+
{option.inputDisplay}
48+
</span>
49+
)
50+
}

redisinsight/ui/src/components/command-helper/components/command-helper-search/CHSearchFilter/CHSearchFilter.spec.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react'
2-
import { render, screen, fireEvent } from 'uiSrc/utils/test-utils'
2+
import { render, screen, userEvent } from 'uiSrc/utils/test-utils'
33
import { GROUP_TYPES_DISPLAY } from 'uiSrc/constants'
44
import CHSearchFilter from './CHSearchFilter'
55

@@ -23,17 +23,18 @@ describe('CHSearchFilter', () => {
2323
expect(render(<CHSearchFilter submitFilter={jest.fn()} />)).toBeTruthy()
2424
})
2525

26-
it('should call submitFilter after choose options', () => {
26+
it('should call submitFilter after choose options', async () => {
2727
const submitFilter = jest.fn()
28-
const { queryByText } = render(
29-
<CHSearchFilter submitFilter={submitFilter} />,
30-
)
28+
render(<CHSearchFilter submitFilter={submitFilter} />)
3129
const testGroup = commandGroupsMock[0]
32-
fireEvent.click(screen.getByTestId('select-filter-group-type'))
33-
fireEvent.click(
34-
queryByText((GROUP_TYPES_DISPLAY as any)[testGroup]) || document,
30+
const dropdownButton = screen.getByTestId('select-filter-group-type')
31+
await userEvent.click(dropdownButton)
32+
33+
await userEvent.click(
34+
(await screen.findByText((GROUP_TYPES_DISPLAY as any)[testGroup])) ||
35+
document,
3536
)
3637

37-
expect(submitFilter).toBeCalledWith(testGroup)
38+
expect(submitFilter).toHaveBeenCalledWith(testGroup)
3839
})
3940
})

redisinsight/ui/src/components/command-helper/components/command-helper-search/CHSearchFilter/CHSearchFilter.tsx

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import React, { useEffect, useState } from 'react'
22
import cx from 'classnames'
3-
import { EuiIcon, EuiSuperSelect, EuiSuperSelectOption } from '@elastic/eui'
3+
import { EuiIcon } from '@elastic/eui'
44
import { useSelector } from 'react-redux'
55

66
import { GROUP_TYPES_DISPLAY } from 'uiSrc/constants'
77
import { appRedisCommandsSelector } from 'uiSrc/slices/app/redis-commands'
88
import { cliSettingsSelector } from 'uiSrc/slices/cli/cli-settings'
9-
import { OutsideClickDetector } from 'uiSrc/components/base/utils'
109
import { Text } from 'uiSrc/components/base/text'
1110

11+
import { RiSelect } from 'uiSrc/components/base/forms/select/RiSelect'
1212
import styles from './styles.module.scss'
1313

1414
export interface Props {
@@ -21,7 +21,6 @@ const CHSearchFilter = ({ submitFilter, isLoading }: Props) => {
2121
const { isEnteringCommand, matchedCommand, searchingCommandFilter } =
2222
useSelector(cliSettingsSelector)
2323

24-
const [isSelectOpen, setIsSelectOpen] = useState<boolean>(false)
2524
const [typeSelected, setTypeSelected] = useState<string>(
2625
searchingCommandFilter,
2726
)
@@ -41,56 +40,64 @@ const CHSearchFilter = ({ submitFilter, isLoading }: Props) => {
4140
value: group,
4241
}))
4342

44-
const options: EuiSuperSelectOption<string>[] = groupOptions.map((item) => {
43+
const options = groupOptions.map((item) => {
4544
const { value, text } = item
4645
return {
46+
label: text,
4747
value,
4848
inputDisplay: (
49-
<Text className={cx(styles.selectedType, 'text-capitalize')} size="s">
49+
<Text
50+
data-test-subj={`filter-option-group-type-${value}`}
51+
className={cx(styles.selectedType, 'text-capitalize')}
52+
size="s"
53+
>
54+
{text}
55+
</Text>
56+
),
57+
dropdownDisplay: (
58+
<Text
59+
data-test-subj={`filter-option-group-type-${value}`}
60+
className="text-capitalize"
61+
>
5062
{text}
5163
</Text>
5264
),
53-
dropdownDisplay: <Text className="text-capitalize">{text}</Text>,
54-
'data-test-subj': `filter-option-group-type-${value}`,
5565
}
5666
})
5767

5868
const onChangeType = (initValue: string) => {
5969
const value = typeSelected === initValue ? '' : initValue
6070
setTypeSelected(value)
61-
setIsSelectOpen(false)
6271
submitFilter(value)
6372
}
6473

6574
return (
66-
<OutsideClickDetector onOutsideClick={() => setIsSelectOpen(false)}>
67-
<div className={cx(styles.container)}>
68-
{!typeSelected && (
69-
<div
70-
className={styles.allTypes}
71-
onClick={() => !isLoading && setIsSelectOpen(!isSelectOpen)}
72-
role="presentation"
73-
>
75+
<div className={cx(styles.container)}>
76+
<RiSelect
77+
loading={isLoading}
78+
disabled={isLoading}
79+
options={options}
80+
allowReset
81+
placeholder={
82+
<div role="presentation">
7483
<EuiIcon
7584
type="controlsVertical"
7685
data-testid="filter-option--group-type-default"
77-
className={cx(styles.controlsIcon, styles.allTypesIcon)}
86+
className={styles.controlsIcon}
7887
/>
7988
</div>
80-
)}
81-
<EuiSuperSelect
82-
disabled={isLoading}
83-
isLoading={isLoading}
84-
fullWidth
85-
itemClassName={cx('withColorDefinition', styles.filterKeyType)}
86-
options={options}
87-
isOpen={isSelectOpen}
88-
valueOfSelected={typeSelected}
89-
onChange={(value: string) => onChangeType(value)}
90-
data-testid="select-filter-group-type"
91-
/>
92-
</div>
93-
</OutsideClickDetector>
89+
}
90+
value={typeSelected}
91+
data-testid="select-filter-group-type"
92+
onChange={(value: string) => onChangeType(value)}
93+
valueRender={({ option, isOptionValue }) => {
94+
if (isOptionValue) {
95+
return option.inputDisplay
96+
}
97+
return option.dropdownDisplay
98+
}}
99+
/>
100+
</div>
94101
)
95102
}
96103

redisinsight/ui/src/components/command-helper/components/command-helper-search/CHSearchFilter/styles.module.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
margin-left: 3px;
5353
height: 20px !important;
5454
width: 20px !important;
55-
&:global(.euiIcon) {
55+
&:global(svg) {
5656
color: var(--inputTextColor) !important;
5757
}
5858
}
@@ -68,7 +68,7 @@
6868

6969
.allTypes {
7070
position: absolute;
71-
top: 0;
71+
top: 5px;
7272
display: flex;
7373
align-items: center;
7474

redisinsight/ui/src/components/monaco-editor/components/dedicated-editor/DedicatedEditor.tsx

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import React, { useContext, useEffect, useRef, useState } from 'react'
2+
import styled from 'styled-components'
23
import { compact, findIndex, first, merge } from 'lodash'
34
import AutoSizer, { Size } from 'react-virtualized-auto-sizer'
45
import ReactMonacoEditor, { monaco as monacoEditor } from 'react-monaco-editor'
56
import { Rnd } from 'react-rnd'
67
import cx from 'classnames'
7-
import { EuiSuperSelect, EuiSuperSelectOption } from '@elastic/eui'
88

99
import {
1010
decoration,
@@ -25,8 +25,24 @@ import { ThemeContext } from 'uiSrc/contexts/themeContext'
2525

2626
import { IconButton } from 'uiSrc/components/base/forms/buttons'
2727
import { CancelSlimIcon, CheckThinIcon } from 'uiSrc/components/base/icons'
28+
import { RiSelect } from 'uiSrc/components/base/forms/select/RiSelect'
2829
import styles from './styles.module.scss'
2930

31+
const LangSelect = styled(RiSelect)`
32+
appearance: none;
33+
border: 0 none;
34+
outline: none;
35+
background-color: transparent;
36+
max-width: 200px;
37+
max-height: 26px;
38+
&:active,
39+
&:focus,
40+
&:hover,
41+
&[data-state='open'] {
42+
background-color: transparent;
43+
}
44+
`
45+
3046
export interface Props {
3147
query?: string
3248
langId?: DSL
@@ -67,15 +83,14 @@ const DedicatedEditor = (props: Props) => {
6783
const [selectedLang, setSelectedLang] = useState(
6884
DEDICATED_EDITOR_LANGUAGES[!langs.length ? langId! : first(langs)!],
6985
)
70-
7186
const monacoObjects = useRef<Nullable<IEditorMount>>(null)
7287
const rndRef = useRef<Nullable<any>>(null)
7388

7489
const { theme } = useContext(ThemeContext)
7590

76-
const optionsLangs: EuiSuperSelectOption<DSL>[] = langs.map((lang) => ({
91+
const optionsLangs = langs.map((lang) => ({
7792
value: lang,
78-
inputDisplay: DEDICATED_EDITOR_LANGUAGES[lang]?.name,
93+
label: DEDICATED_EDITOR_LANGUAGES[lang]?.name,
7994
}))
8095

8196
let disposeCompletionItemProvider = () => {}
@@ -154,7 +169,10 @@ const DedicatedEditor = (props: Props) => {
154169
editor: monacoEditor.editor.IStandaloneCodeEditor,
155170
monaco: typeof monacoEditor,
156171
) => {
157-
monacoObjects.current = { editor, monaco }
172+
monacoObjects.current = {
173+
editor,
174+
monaco,
175+
}
158176

159177
setTimeout(() => editor.focus(), 0)
160178

@@ -285,12 +303,11 @@ const DedicatedEditor = (props: Props) => {
285303
<div className={cx(styles.actions)}>
286304
{langs?.length < 2 && <span>{selectedLang?.name}</span>}
287305
{langs?.length >= 2 && (
288-
<EuiSuperSelect
306+
<LangSelect
289307
name="dedicated-editor-language-select"
290308
placeholder="Select language"
291-
valueOfSelected={selectedLang.id}
309+
value={selectedLang.id}
292310
options={optionsLangs}
293-
className={styles.selectLanguage}
294311
onChange={onChangeLanguageSelect}
295312
data-testid="dedicated-editor-language-select"
296313
/>

redisinsight/ui/src/components/oauth/oauth-select-account-dialog/OAuthSelectAccountDialog.tsx

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
import React, { useCallback } from 'react'
2-
import {
3-
EuiModal,
4-
EuiModalBody,
5-
EuiRadioGroup,
6-
EuiRadioGroupOption,
7-
} from '@elastic/eui'
2+
import { EuiModal, EuiModalBody } from '@elastic/eui'
83
import { useDispatch, useSelector } from 'react-redux'
94
import { useFormik } from 'formik'
105
import { useHistory } from 'react-router-dom'
@@ -43,6 +38,13 @@ import {
4338
} from 'uiSrc/components/base/forms/buttons'
4439
import { Title } from 'uiSrc/components/base/text/Title'
4540
import { ColorText, Text } from 'uiSrc/components/base/text'
41+
import {
42+
RiRadioGroupItemIndicator,
43+
RiRadioGroupItemLabel,
44+
RiRadioGroupItemRoot,
45+
RiRadioGroupRoot,
46+
} from 'uiSrc/components/base/forms/radio-group/RadioGroup'
47+
import { Spacer } from 'uiSrc/components/base/layout/spacer'
4648
import styles from './styles.module.scss'
4749

4850
interface FormValues {
@@ -168,12 +170,14 @@ const OAuthSelectAccountDialog = () => {
168170
formik.setFieldValue('accountId', value)
169171
}
170172

171-
const radios: EuiRadioGroupOption[] = accounts.map(({ id, name = '' }) => ({
173+
const radios = accounts.map(({ id, name = '' }) => ({
172174
id: `${id}`,
173175
label: (
174-
<ColorText className={styles.label}>
176+
<ColorText color="subdued">
175177
{name}
176-
<span>{id}</span>
178+
<ColorText color="accent" style={{ paddingLeft: 6 }}>
179+
{id}
180+
</ColorText>
177181
</ColorText>
178182
),
179183
}))
@@ -192,13 +196,18 @@ const OAuthSelectAccountDialog = () => {
192196
<Text className={styles.subTitle}>
193197
Select an account to connect to:
194198
</Text>
195-
<EuiRadioGroup
196-
options={radios}
197-
className={styles.radios}
198-
idSelected={formik.values.accountId ?? ''}
199+
<Spacer size="xl" />
200+
<RiRadioGroupRoot
201+
value={formik.values.accountId ?? ''}
199202
onChange={(id) => handleChangeAccountIdFormat(id)}
200-
name="radio accounts group"
201-
/>
203+
>
204+
{radios.map(({ id, label }) => (
205+
<RiRadioGroupItemRoot value={id} key={id}>
206+
<RiRadioGroupItemIndicator />
207+
<RiRadioGroupItemLabel>{label}</RiRadioGroupItemLabel>
208+
</RiRadioGroupItemRoot>
209+
))}
210+
</RiRadioGroupRoot>
202211
</section>
203212
<div className={styles.footer}>
204213
<SecondaryButton

0 commit comments

Comments
 (0)