Skip to content

Commit c04aac9

Browse files
authored
RI-7713: polish import from file forms (#5186)
* fix the footer button location and sizes * fix import text and spacing between elements * remove info icons next to submit buttons and remove unused import found * Fix footer button sizes and alignment * revert the submit button info icon * finalize styling for main import file db form and error form * extract import table result constants * replace hard coded values with defined constants; remove scss styles and files * add sizing for table result index column; add some spacings in the component * add import db result type enum * apply proper styling and refactor the results log component * Ok -> OK * add padding to the container instead changing box-shadow -> border * add maxHeight to table result, beyond which a scroll will appear * use rems instead of pixels * show only sections with items > 0 * decrease max table height * remove custom margin * remove unneded collapsible nav title; calculate navState once per item, not three times * extract the results data config in a separate file; use useMemo for the filtering * update tests since id is changed from failed-* to fail-* to match the type
1 parent 55023a5 commit c04aac9

File tree

13 files changed

+170
-294
lines changed

13 files changed

+170
-294
lines changed

redisinsight/ui/src/components/import-file-modal/ImportFileModal.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react'
22

33
import { Nullable } from 'uiSrc/utils'
44
import { RiFilePicker, UploadWarning } from 'uiSrc/components'
5-
import { Col, FlexItem } from 'uiSrc/components/base/layout/flex'
5+
import { Col, FlexItem, Row } from 'uiSrc/components/base/layout/flex'
66
import { ColorText, Text } from 'uiSrc/components/base/text'
77
import { Loader, Modal } from 'uiSrc/components/base/display'
88
import { RiIcon } from 'uiSrc/components/base/icons/RiIcon'
@@ -137,7 +137,7 @@ const ImportFileModal = <T,>({
137137
<Modal.Content.Footer.Compose>
138138
<Modal.Content.Footer.Group>
139139
{isShowForm && (
140-
<>
140+
<Row gap="m" justify="end">
141141
<SecondaryButton
142142
size="l"
143143
onClick={onClose}
@@ -153,7 +153,7 @@ const ImportFileModal = <T,>({
153153
>
154154
{submitBtnText || 'Import'}
155155
</PrimaryButton>
156-
</>
156+
</Row>
157157
)}
158158
{data && <PrimaryButton onClick={onClose}>OK</PrimaryButton>}
159159
</Modal.Content.Footer.Group>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export enum ImportTableResultColumn {
2+
Index = 'index',
3+
Host = 'host',
4+
Errors = 'errors',
5+
}
6+
7+
export const TABLE_IMPORT_RESULT_COLUMN_ID_HEADER_MAP = new Map<
8+
ImportTableResultColumn,
9+
string
10+
>([
11+
[ImportTableResultColumn.Index, '#'],
12+
[ImportTableResultColumn.Host, 'Host:Port'],
13+
[ImportTableResultColumn.Errors, 'Result'],
14+
])
15+
16+
export enum ImportDatabaseResultType {
17+
Success = 'success',
18+
Partial = 'partial',
19+
Fail = 'fail',
20+
}

redisinsight/ui/src/constants/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,5 @@ export * from './datetime'
3636
export * from './sorting'
3737
export * from './databaseList'
3838
export * from './rdiList'
39+
export * from './importDatabasesTableResult'
3940
export { ApiEndpoints, BrowserStorageItem, ApiStatusCode, apiErrors }

redisinsight/ui/src/pages/home/components/cluster-connection/cluster-connection-form/ClusterConnectionForm.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import {
1616
PrimaryButton,
1717
SecondaryButton,
1818
} from 'uiSrc/components/base/forms/buttons'
19-
import { InfoIcon } from 'uiSrc/components/base/icons'
2019
import {
2120
FormField,
2221
RiInfoIconProps,
@@ -163,7 +162,6 @@ const ClusterConnectionForm = (props: Props) => {
163162
onClick={onClick}
164163
disabled={submitIsDisabled}
165164
loading={loading}
166-
icon={submitIsDisabled ? InfoIcon : undefined}
167165
data-testid="btn-submit"
168166
>
169167
Submit

redisinsight/ui/src/pages/home/components/import-database/ImportDatabase.tsx

Lines changed: 40 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useEffect, useState } from 'react'
22
import { useDispatch, useSelector } from 'react-redux'
33
import ReactDOM from 'react-dom'
4+
45
import {
56
fetchInstancesAction,
67
importInstancesSelector,
@@ -9,22 +10,19 @@ import {
910
} from 'uiSrc/slices/instances/instances'
1011
import { Nullable } from 'uiSrc/utils'
1112
import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry'
12-
import { RiTooltip, UploadWarning, RiFilePicker } from 'uiSrc/components'
13+
import { RiFilePicker, RiTooltip, UploadWarning } from 'uiSrc/components'
1314
import { useModalHeader } from 'uiSrc/contexts/ModalTitleProvider'
1415
import { Col, FlexItem, Row } from 'uiSrc/components/base/layout/flex'
15-
import { Spacer } from 'uiSrc/components/base/layout/spacer'
1616
import {
1717
PrimaryButton,
1818
SecondaryButton,
1919
} from 'uiSrc/components/base/forms/buttons'
20-
import { InfoIcon } from 'uiSrc/components/base/icons'
20+
import { InfoIcon, RiIcon } from 'uiSrc/components/base/icons'
2121
import { Title } from 'uiSrc/components/base/text/Title'
2222
import { ColorText, Text } from 'uiSrc/components/base/text'
2323
import { Loader } from 'uiSrc/components/base/display'
24-
import { RiIcon } from 'uiSrc/components/base/icons/RiIcon'
2524
import ResultsLog from './components/ResultsLog'
2625

27-
import styles from './styles.module.scss'
2826
import { ScrollableWrapper } from '../styles.module'
2927

3028
export interface Props {
@@ -102,53 +100,47 @@ const ImportDatabase = (props: Props) => {
102100

103101
if (error) {
104102
return ReactDOM.createPortal(
105-
<div className="footerAddDatabase">
103+
<Row justify="end" gap="m" data-testid="footer-import-database">
106104
<PrimaryButton
107-
size="s"
108105
color="secondary"
109106
onClick={onClickRetry}
110107
data-testid="btn-retry"
111108
>
112109
Retry
113110
</PrimaryButton>
114-
</div>,
111+
</Row>,
115112
footerEl,
116113
)
117114
}
118115

119116
if (data) {
120117
return ReactDOM.createPortal(
121-
<div className="footerAddDatabase">
118+
<Row justify="end" gap="m" data-testid="footer-import-database">
122119
<PrimaryButton
123-
size="s"
124120
type="submit"
125121
onClick={handleOnClose}
126122
data-testid="btn-close"
127123
>
128-
Ok
124+
OK
129125
</PrimaryButton>
130-
</div>,
126+
</Row>,
131127
footerEl,
132128
)
133129
}
134130

135131
return ReactDOM.createPortal(
136-
<div className="footerAddDatabase">
132+
<Row justify="end" gap="m" data-testid="footer-import-database">
137133
<SecondaryButton
138-
size="s"
139134
className="btn-cancel"
140135
onClick={handleOnClose}
141-
style={{ marginRight: 12 }}
142136
>
143137
Cancel
144138
</SecondaryButton>
145139
<RiTooltip
146140
position="top"
147-
anchorClassName="euiToolTip__btn-disabled"
148141
content={isSubmitDisabled ? 'Upload a file' : undefined}
149142
>
150143
<PrimaryButton
151-
size="s"
152144
type="submit"
153145
onClick={onSubmit}
154146
loading={loading}
@@ -159,7 +151,7 @@ const ImportDatabase = (props: Props) => {
159151
Submit
160152
</PrimaryButton>
161153
</RiTooltip>
162-
</div>,
154+
</Row>,
163155
footerEl,
164156
)
165157
}
@@ -169,70 +161,70 @@ const ImportDatabase = (props: Props) => {
169161
return (
170162
<>
171163
<ScrollableWrapper data-testid="add-db_import">
172-
<Col>
173-
<FlexItem grow>
164+
<Col gap="xl">
165+
<Col grow gap="xl">
174166
{isShowForm && (
175-
<>
176-
<Text color="subdued" size="s">
167+
<Col gap="xl">
168+
<Text>
177169
Use a JSON file to import your database connections. Ensure
178170
that you only use files from trusted sources to prevent the
179171
risk of automatically executing malicious code.
180172
</Text>
181-
<Spacer />
182173

183174
<RiFilePicker
184175
id="import-file-modal-filepicker"
185176
initialPromptText="Select or drag and drop a file"
186-
className={styles.fileDrop}
187177
isInvalid={isInvalid}
188178
onChange={onFileChange}
189179
display="large"
190180
data-testid="import-file-modal-filepicker"
191181
aria-label="Select or drag and drop file"
192182
/>
183+
193184
{isInvalid && (
194-
<ColorText
195-
color="danger"
196-
className={styles.errorFileMsg}
197-
data-testid="input-file-error-msg"
198-
>
185+
<ColorText color="danger" data-testid="input-file-error-msg">
199186
{`File should not exceed ${MAX_MB_FILE} MB`}
200187
</ColorText>
201188
)}
202-
</>
189+
</Col>
203190
)}
204191
{loading && (
205-
<div
206-
className={styles.loading}
192+
<Col
193+
justify="center"
194+
gap="l"
195+
align="center"
207196
data-testid="file-loading-indicator"
208197
>
209198
<Loader size="xl" />
210-
<Text color="subdued" style={{ marginTop: 12 }}>
211-
Uploading...
212-
</Text>
213-
</div>
199+
<Text>Uploading...</Text>
200+
</Col>
214201
)}
215202
{error && (
216-
<div className={styles.result} data-testid="result-failed">
217-
<RiIcon type="ToastCancelIcon" color="danger600" size="xxl" />
218-
<Text color="subdued" style={{ marginTop: 16 }}>
219-
Failed to add database connections
220-
</Text>
221-
<Text color="subdued">{error}</Text>
222-
</div>
203+
<Col
204+
align="center"
205+
gap="l"
206+
justify="center"
207+
data-testid="result-failed"
208+
>
209+
<RiIcon
210+
type="IndicatorXIcon"
211+
color="danger600"
212+
customSize="5rem"
213+
/>
214+
<Text>Failed to add database connections</Text>
215+
<Text>{error}</Text>
216+
</Col>
223217
)}
224-
</FlexItem>
218+
</Col>
225219
{isShowForm && (
226-
<FlexItem grow className={styles.uploadWarningContainer}>
220+
<FlexItem>
227221
<UploadWarning />
228222
</FlexItem>
229223
)}
230224
</Col>
231225
{data && (
232226
<Row justify="center">
233-
<FlexItem grow style={{ maxWidth: '100%' }}>
234-
<ResultsLog data={data} />
235-
</FlexItem>
227+
<ResultsLog data={data} />
236228
</Row>
237229
)}
238230
</ScrollableWrapper>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import styled from 'styled-components'
2+
3+
import { Col } from 'uiSrc/components/base/layout/flex'
4+
5+
// Ideally this should not be needed, but the section component
6+
// will not let the parent cut the border, more precisely the box-shadow,
7+
// so we need to add padding to the parent container
8+
export const StyledColWrapper = styled(Col)`
9+
padding: ${({ theme }) => theme.core.space.space025};
10+
`
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { ImportDatabaseResultType } from 'uiSrc/constants'
2+
import { TableResultData } from './ResultsLog'
3+
4+
export const RESULTS_DATA_CONFIG: TableResultData[] = [
5+
{
6+
type: ImportDatabaseResultType.Success,
7+
title: 'Fully imported',
8+
},
9+
{
10+
type: ImportDatabaseResultType.Partial,
11+
title: 'Partially imported',
12+
},
13+
{
14+
type: ImportDatabaseResultType.Fail,
15+
title: 'Failed to import',
16+
},
17+
]

redisinsight/ui/src/pages/home/components/import-database/components/ResultsLog/ResultsLog.spec.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ describe('ResultsLog', () => {
2727

2828
expect(screen.getByTestId('success-results-closed')).toBeInTheDocument()
2929
expect(screen.getByTestId('partial-results-closed')).toBeInTheDocument()
30-
expect(screen.getByTestId('failed-results-closed')).toBeInTheDocument()
30+
expect(screen.getByTestId('fail-results-closed')).toBeInTheDocument()
3131
})
3232

3333
it('should open and collapse other groups', () => {
@@ -45,12 +45,12 @@ describe('ResultsLog', () => {
4545
expect(screen.getByTestId('success-results-open')).toBeInTheDocument()
4646

4747
expect(screen.getByTestId('partial-results-closed')).toBeInTheDocument()
48-
expect(screen.getByTestId('failed-results-closed')).toBeInTheDocument()
48+
expect(screen.getByTestId('fail-results-closed')).toBeInTheDocument()
4949

5050
fireEvent.click(
51-
within(screen.getByTestId('failed-results-closed')).getByRole('button'),
51+
within(screen.getByTestId('fail-results-closed')).getByRole('button'),
5252
)
53-
expect(screen.getByTestId('failed-results-open')).toBeInTheDocument()
53+
expect(screen.getByTestId('fail-results-open')).toBeInTheDocument()
5454

5555
expect(screen.getByTestId('partial-results-closed')).toBeInTheDocument()
5656
expect(screen.getByTestId('success-results-closed')).toBeInTheDocument()
@@ -60,7 +60,7 @@ describe('ResultsLog', () => {
6060
)
6161
expect(screen.getByTestId('partial-results-open')).toBeInTheDocument()
6262

63-
expect(screen.getByTestId('failed-results-closed')).toBeInTheDocument()
63+
expect(screen.getByTestId('fail-results-closed')).toBeInTheDocument()
6464
expect(screen.getByTestId('success-results-closed')).toBeInTheDocument()
6565
})
6666

@@ -87,7 +87,7 @@ describe('ResultsLog', () => {
8787
),
8888
).toHaveTextContent('1')
8989
expect(
90-
within(screen.getByTestId('failed-results-closed')).getByTestId(
90+
within(screen.getByTestId('fail-results-closed')).getByTestId(
9191
'number-of-dbs',
9292
),
9393
).toHaveTextContent('1')

0 commit comments

Comments
 (0)