Skip to content

Commit 5c5cdca

Browse files
authored
RI-6905: hide db controls begind three dots button (#4439)
* wrap controls in three dots popover * remove unused imports; move the three dots icon from rdi to icons asset folder. fix the import in the rdi component
1 parent 1ae7ec2 commit 5c5cdca

File tree

6 files changed

+117
-27
lines changed

6 files changed

+117
-27
lines changed
File renamed without changes.

redisinsight/ui/src/pages/browser/components/popover-delete/PopoverDelete.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react'
2-
import { EuiButton, EuiButtonIcon, EuiPopover, EuiText, EuiToolTip } from '@elastic/eui'
2+
import { EuiButton, EuiButtonEmpty, EuiButtonIcon, EuiPopover, EuiText, EuiToolTip } from '@elastic/eui'
33

44
import { RedisString } from 'uiSrc/slices/interfaces'
55
import { isTruncatedString } from 'uiSrc/utils'
@@ -20,6 +20,7 @@ export interface Props {
2020
handleButtonClick?: () => void
2121
appendInfo?: JSX.Element | string | null
2222
testid?: string
23+
buttonLabel?: string
2324
}
2425

2526
const PopoverDelete = (props: Props) => {
@@ -37,6 +38,7 @@ const PopoverDelete = (props: Props) => {
3738
handleButtonClick,
3839
appendInfo,
3940
testid = '',
41+
buttonLabel,
4042
} = props
4143

4244
const isDisabled = isTruncatedString(item)
@@ -51,7 +53,17 @@ const PopoverDelete = (props: Props) => {
5153
}
5254
}
5355

54-
const deleteButton = (
56+
const deleteButton = buttonLabel ? (
57+
<EuiButtonEmpty
58+
iconType="trash"
59+
aria-label="Remove field"
60+
color="primary"
61+
disabled={isDisabled || updateLoading}
62+
onClick={isDisabled ? () => {} : onButtonClick}
63+
data-testid={testid ? `${testid}-icon` : 'remove-icon'}
64+
isDisabled={isDisabled}
65+
>{buttonLabel}</EuiButtonEmpty>
66+
) : (
5567
<EuiButtonIcon
5668
iconType="trash"
5769
aria-label="Remove field"

redisinsight/ui/src/pages/home/components/database-list-component/DatabasesListWrapper.test.tsx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,15 +194,35 @@ describe('DatabasesListWrapper', () => {
194194
(sendEventTelemetry as jest.Mock).mockRestore()
195195
})
196196

197+
it('should open controls popover when three dots clicked', async () => {
198+
render(<DatabasesListWrapper {...instance(mockedProps)} instances={mockInstances} onEditInstance={() => {}} />);
199+
200+
await act(() => {
201+
fireEvent.click(screen.getByTestId('controls-button-a0db1bc8-a353-4c43-a856-b72f4811d2d4'));
202+
})
203+
204+
const controlsPopoverId = screen.getByTestId('controls-popover-a0db1bc8-a353-4c43-a856-b72f4811d2d4');
205+
const editBtn = screen.getByTestId('edit-instance-a0db1bc8-a353-4c43-a856-b72f4811d2d4');
206+
const deleteBtn = screen.getByTestId('delete-instance-a0db1bc8-a353-4c43-a856-b72f4811d2d4-icon');
207+
208+
expect(controlsPopoverId).toBeInTheDocument();
209+
expect(editBtn).toBeInTheDocument();
210+
expect(deleteBtn).toBeInTheDocument();
211+
});
212+
197213
it('should call proper telemetry on delete database', async () => {
198214
const sendEventTelemetryMock = jest.fn();
199215

200216
(sendEventTelemetry as jest.Mock).mockImplementation(() => sendEventTelemetryMock)
201217
render(<DatabasesListWrapper {...instance(mockedProps)} instances={mockInstances} />)
202218

219+
await act(() => {
220+
fireEvent.click(screen.getByTestId('controls-button-a0db1bc8-a353-4c43-a856-b72f4811d2d4'));
221+
});
222+
203223
await act(() => {
204224
fireEvent.click(screen.getByTestId('delete-instance-a0db1bc8-a353-4c43-a856-b72f4811d2d4-icon'))
205-
})
225+
});
206226

207227
expect(sendEventTelemetry).toBeCalledWith({
208228
event: TelemetryEvent.CONFIG_DATABASES_SINGLE_DATABASE_DELETE_CLICKED,
@@ -220,6 +240,10 @@ describe('DatabasesListWrapper', () => {
220240
(sendEventTelemetry as jest.Mock).mockImplementation(() => sendEventTelemetryMock)
221241
render(<DatabasesListWrapper {...instance(mockedProps)} instances={mockInstances} onEditInstance={() => {}} />)
222242

243+
await act(() => {
244+
fireEvent.click(screen.getByTestId('controls-button-a0db1bc8-a353-4c43-a856-b72f4811d2d4'));
245+
});
246+
223247
await act(() => {
224248
fireEvent.click(screen.getByTestId('edit-instance-a0db1bc8-a353-4c43-a856-b72f4811d2d4'))
225249
})

redisinsight/ui/src/pages/home/components/database-list-component/DatabasesListWrapper.tsx

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import {
22
Criteria,
3+
EuiButtonEmpty,
34
EuiButtonIcon,
45
EuiIcon,
56
EuiLink,
7+
EuiPopover,
68
EuiResizeObserver,
79
EuiTableFieldDataColumnType,
810
EuiText,
@@ -23,16 +25,16 @@ import RediStackLightMin from 'uiSrc/assets/img/modules/redistack/RediStackLight
2325
import RediStackDarkLogo from 'uiSrc/assets/img/modules/redistack/RedisStackLogoDark.svg'
2426
import RediStackLightLogo from 'uiSrc/assets/img/modules/redistack/RedisStackLogoLight.svg'
2527
import CloudLinkIcon from 'uiSrc/assets/img/oauth/cloud_link.svg?react'
28+
import ThreeDots from 'uiSrc/assets/img/icons/three_dots.svg?react'
2629
import DatabaseListModules from 'uiSrc/components/database-list-modules/DatabaseListModules'
2730
import ItemList from 'uiSrc/components/item-list'
2831
import { BrowserStorageItem, DEFAULT_SORT, FeatureFlags, Pages, Theme } from 'uiSrc/constants'
2932
import { EXTERNAL_LINKS } from 'uiSrc/constants/links'
3033
import { ThemeContext } from 'uiSrc/contexts/themeContext'
3134
import PopoverDelete from 'uiSrc/pages/browser/components/popover-delete/PopoverDelete'
3235
import { localStorageService } from 'uiSrc/services'
33-
import { appContextSelector, resetRdiContext, setAppContextInitialState } from 'uiSrc/slices/app/context'
34-
import { resetKeys } from 'uiSrc/slices/browser/keys'
35-
import { resetRedisearchKeysData } from 'uiSrc/slices/browser/redisearch'
36+
import { appContextSelector, resetRdiContext } from 'uiSrc/slices/app/context'
37+
3638
import {
3739
checkConnectToInstanceAction,
3840
deleteInstancesAction,
@@ -100,6 +102,12 @@ const DatabasesListWrapper = (props: Props) => {
100102
)
101103

102104
const deletingIdRef = useRef('')
105+
const controlsOpenIdRef = useRef('')
106+
107+
const toggleControlsPopover = (instanceId: string) => {
108+
controlsOpenIdRef.current = controlsOpenIdRef.current === instanceId ? '' : instanceId
109+
forceRerender({})
110+
}
103111

104112
const closePopover = () => {
105113
if (deletingIdRef.current) {
@@ -270,6 +278,15 @@ const DatabasesListWrapper = (props: Props) => {
270278
'data-testid': `db-row_${instance?.id}`
271279
})
272280

281+
const controlsButton = (instanceId: string) => (
282+
<EuiButtonIcon
283+
iconType={ThreeDots}
284+
aria-label="Controls icon"
285+
data-testid={`controls-button-${instanceId}`}
286+
onClick={() => toggleControlsPopover(instanceId)}
287+
/>
288+
)
289+
273290
const columns: EuiTableFieldDataColumnType<Instance>[] = [
274291
{
275292
field: 'name',
@@ -450,26 +467,46 @@ const DatabasesListWrapper = (props: Props) => {
450467
</EuiToolTip>
451468
)}
452469
<FeatureFlagComponent name={FeatureFlags.databaseManagement}>
453-
<EuiButtonIcon
454-
iconType="pencil"
455-
className="editInstanceBtn"
456-
aria-label="Edit instance"
457-
data-testid={`edit-instance-${instance.id}`}
458-
onClick={() => handleClickEditInstance(instance)}
459-
/>
460-
<PopoverDelete
461-
header={formatLongName(instance.name, 50, 10, '...')}
462-
text="will be removed from Redis Insight."
463-
item={instance.id}
464-
suffix={suffix}
465-
deleting={deletingIdRef.current}
466-
closePopover={closePopover}
467-
updateLoading={false}
468-
showPopover={showPopover}
469-
handleDeleteItem={() => handleDeleteInstance(instance)}
470-
handleButtonClick={() => handleClickDeleteInstance(instance)}
471-
testid={`delete-instance-${instance.id}`}
472-
/>
470+
<EuiPopover
471+
ownFocus
472+
initialFocus={false}
473+
anchorPosition='leftUp'
474+
isOpen={controlsOpenIdRef.current === instance.id}
475+
closePopover={() => toggleControlsPopover('')}
476+
panelPaddingSize="s"
477+
button={controlsButton(instance.id)}
478+
data-testid={`controls-popover-${instance.id}`}
479+
>
480+
<div className="controlsPopoverContent">
481+
<div>
482+
<EuiButtonEmpty
483+
iconType="pencil"
484+
className="editInstanceBtn"
485+
aria-label="Edit instance"
486+
data-testid={`edit-instance-${instance.id}`}
487+
onClick={() => handleClickEditInstance(instance)}
488+
>
489+
Edit database
490+
</EuiButtonEmpty>
491+
</div>
492+
<div>
493+
<PopoverDelete
494+
header={formatLongName(instance.name, 50, 10, '...')}
495+
text="will be removed from Redis Insight."
496+
item={instance.id}
497+
suffix={suffix}
498+
deleting={deletingIdRef.current}
499+
closePopover={closePopover}
500+
updateLoading={false}
501+
showPopover={showPopover}
502+
handleDeleteItem={() => handleDeleteInstance(instance)}
503+
handleButtonClick={() => handleClickDeleteInstance(instance)}
504+
testid={`delete-instance-${instance.id}`}
505+
buttonLabel="Remove database"
506+
/>
507+
</div>
508+
</div>
509+
</EuiPopover>
473510
</FeatureFlagComponent>
474511
</>
475512
)

redisinsight/ui/src/pages/home/components/database-list-component/styles.module.scss

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,20 @@ $breakpoint-l: 1400px;
109109
}
110110
}
111111
}
112+
113+
:global(.controlsPopoverContent) {
114+
display: flex;
115+
flex-direction: column;
116+
117+
& > div {
118+
display: flex;
119+
120+
button {
121+
flex: 1;
122+
123+
:global(.euiButtonContent) {
124+
justify-content: start;
125+
}
126+
}
127+
}
128+
}

redisinsight/ui/src/pages/rdi/instance/components/header/components/rdi-config-file-action-menu/RdiConfigFileActionMenu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
EuiFlexItem,
88
} from '@elastic/eui'
99
import cx from 'classnames'
10-
import threeDots from 'uiSrc/assets/img/rdi/three_dots.svg?react'
10+
import threeDots from 'uiSrc/assets/img/icons/three_dots.svg?react'
1111
import uploadIcon from 'uiSrc/assets/img/rdi/upload.svg?react'
1212
import UploadModal from 'uiSrc/pages/rdi/pipeline-management/components/upload-modal/UploadModal'
1313
import Download from 'uiSrc/pages/rdi/instance/components/download'

0 commit comments

Comments
 (0)