Skip to content

Commit 3746c48

Browse files
authored
Merge pull request #2881 from RedisInsight/fe/feature/RI-5228-upload-large-files
import large files
2 parents e4d1cb8 + 44170b5 commit 3746c48

File tree

4 files changed

+61
-15
lines changed

4 files changed

+61
-15
lines changed

redisinsight/ui/src/pages/browser/components/bulk-actions/BulkUpload/BulkUpload.spec.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import { render, screen, fireEvent, act, mockedStore, cleanup } from 'uiSrc/util
55
import {
66
bulkActionsUploadOverviewSelector,
77
bulkUpload,
8-
setBulkUploadStartAgain
8+
setBulkUploadStartAgain,
9+
uploadController
910
} from 'uiSrc/slices/browser/bulkActions'
1011
import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry'
1112
import { BulkActionsType } from 'uiSrc/constants'
@@ -24,6 +25,9 @@ jest.mock('uiSrc/slices/browser/bulkActions', () => ({
2425
}),
2526
bulkActionsUploadOverviewSelector: jest.fn().mockReturnValue(null),
2627
bulkActionsUploadSummarySelector: jest.fn().mockReturnValue(null),
28+
uploadController: {
29+
abort: jest.fn()
30+
}
2731
}))
2832

2933
let store: typeof mockedStore
@@ -47,6 +51,18 @@ describe('BulkUpload', () => {
4751
expect(onCancel).toBeCalled()
4852
})
4953

54+
it('should call abort controller', () => {
55+
const onCancel = jest.fn()
56+
const abortMock = jest.fn();
57+
(uploadController as any).abort = abortMock
58+
59+
render(<BulkUpload onCancel={onCancel} />)
60+
61+
fireEvent.click(screen.getByTestId('bulk-action-cancel-btn'))
62+
63+
expect(abortMock).toBeCalled()
64+
})
65+
5066
it('submit btn should be disabled without file', () => {
5167
render(<BulkUpload onCancel={jest.fn()} />)
5268

redisinsight/ui/src/pages/browser/components/bulk-actions/BulkUpload/BulkUpload.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ import {
2020
bulkActionsUploadSelector,
2121
bulkActionsUploadSummarySelector,
2222
bulkUploadDataAction,
23-
setBulkUploadStartAgain
23+
setBulkUploadStartAgain,
24+
uploadController
2425
} from 'uiSrc/slices/browser/bulkActions'
2526

2627
import BulkActionsInfo from 'uiSrc/pages/browser/components/bulk-actions/BulkActionsInfo'
@@ -34,7 +35,7 @@ export interface Props {
3435
onCancel: () => void
3536
}
3637

37-
const MAX_MB_FILE = 100
38+
const MAX_MB_FILE = 3_000
3839
const MAX_FILE_SIZE = MAX_MB_FILE * 1024 * 1024
3940

4041
const BulkUpload = (props: Props) => {
@@ -88,6 +89,11 @@ const BulkUpload = (props: Props) => {
8889
}
8990
}
9091

92+
const handleClickCancel = () => {
93+
uploadController?.abort()
94+
onCancel?.()
95+
}
96+
9197
return (
9298
<div className={styles.container} data-testid="bulk-upload-container">
9399
{!isCompleted ? (
@@ -147,7 +153,7 @@ const BulkUpload = (props: Props) => {
147153
<div className={styles.footer}>
148154
<EuiButton
149155
color="secondary"
150-
onClick={onCancel}
156+
onClick={handleClickCancel}
151157
className={styles.cancelBtn}
152158
data-testid="bulk-action-cancel-btn"
153159
>

redisinsight/ui/src/pages/instance/InstancePage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import BottomGroupComponents from 'uiSrc/components/bottom-group-components/Bott
2929
import LiveTimeRecommendations from 'uiSrc/components/live-time-recommendations'
3030
import { monitorSelector, setMonitorInitialState } from 'uiSrc/slices/cli/monitor'
3131
import { setInitialPubSubState } from 'uiSrc/slices/pubsub/pubsub'
32-
import { setBulkActionsInitialState } from 'uiSrc/slices/browser/bulkActions'
32+
import { resetBulkActions } from 'uiSrc/slices/browser/bulkActions'
3333
import { setClusterDetailsInitialState } from 'uiSrc/slices/analytics/clusterDetails'
3434
import { setDatabaseAnalysisInitialState } from 'uiSrc/slices/analytics/dbAnalysis'
3535
import { resetRedisearchKeysData, setRedisearchInitialState } from 'uiSrc/slices/browser/redisearch'
@@ -122,7 +122,7 @@ const InstancePage = ({ routes = [] }: Props) => {
122122
dispatch(resetKeys())
123123
dispatch(setMonitorInitialState())
124124
dispatch(setInitialPubSubState())
125-
dispatch(setBulkActionsInitialState())
125+
dispatch(resetBulkActions())
126126
dispatch(setAppContextInitialState())
127127
dispatch(resetPatternKeysData())
128128
dispatch(resetCliHelperSettings())

redisinsight/ui/src/slices/browser/bulkActions.ts

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
22

3-
import { AxiosError } from 'axios'
3+
import axios, { AxiosError } from 'axios'
44
import { ApiEndpoints, BulkActionsType, MAX_BULK_ACTION_ERRORS_LENGTH } from 'uiSrc/constants'
55
import { apiService } from 'uiSrc/services'
6-
import { getApiErrorMessage, getUrl, isStatusSuccessful } from 'uiSrc/utils'
6+
import { getApiErrorMessage, getUrl, isStatusSuccessful, Maybe, Nullable } from 'uiSrc/utils'
77

88
import { addErrorNotification } from 'uiSrc/slices/app/notifications'
99
import { AppDispatch, RootState } from '../store'
@@ -114,9 +114,12 @@ const bulkActionsSlice = createSlice({
114114
state.bulkUpload.fileName = payload.fileName
115115
},
116116

117-
bulkUploadFailed: (state, { payload }) => {
117+
bulkUploadFailed: (state, { payload }: PayloadAction<Maybe<string>>) => {
118118
state.bulkUpload.loading = false
119-
state.bulkUpload.error = payload
119+
120+
if (payload) {
121+
state.bulkUpload.error = payload
122+
}
120123
},
121124
},
122125
})
@@ -157,6 +160,9 @@ export const bulkActionsUploadSummarySelector = (state: RootState) =>
157160
// The reducer
158161
export default bulkActionsSlice.reducer
159162

163+
// eslint-disable-next-line import/no-mutable-exports
164+
export let uploadController: Nullable<AbortController> = null
165+
160166
// Thunk actions
161167
// Asynchronous thunk action
162168
export function bulkUploadDataAction(
@@ -169,6 +175,9 @@ export function bulkUploadDataAction(
169175
dispatch(bulkUpload())
170176

171177
try {
178+
uploadController?.abort()
179+
uploadController = new AbortController()
180+
172181
const { status, data } = await apiService.post(
173182
getUrl(
174183
id,
@@ -179,19 +188,34 @@ export function bulkUploadDataAction(
179188
headers: {
180189
Accept: 'application/json',
181190
'Content-Type': 'multipart/form-data'
182-
}
191+
},
192+
signal: uploadController.signal
183193
}
184194
)
185195

196+
uploadController = null
197+
186198
if (isStatusSuccessful(status)) {
187199
dispatch(bulkUploadSuccess({ data, fileName: uploadFile.fileName }))
188200
onSuccessAction?.()
189201
}
190202
} catch (error) {
191-
const errorMessage = getApiErrorMessage(error as AxiosError)
192-
dispatch(addErrorNotification(error as AxiosError))
193-
dispatch(bulkUploadFailed(errorMessage))
194-
onFailAction?.()
203+
// show error when request wasn't aborted
204+
if (!axios.isCancel(error)) {
205+
const errorMessage = getApiErrorMessage(error as AxiosError)
206+
dispatch(addErrorNotification(error as AxiosError))
207+
dispatch(bulkUploadFailed(errorMessage))
208+
onFailAction?.()
209+
} else {
210+
dispatch(bulkUploadFailed())
211+
}
195212
}
196213
}
197214
}
215+
216+
export function resetBulkActions() {
217+
return async (dispatch: AppDispatch) => {
218+
uploadController?.abort()
219+
dispatch(setBulkActionsInitialState())
220+
}
221+
}

0 commit comments

Comments
 (0)