|
14 | 14 | // See the License for the specific language governing permissions and |
15 | 15 | // limitations under the License. |
16 | 16 |
|
17 | | -import React, { useRef } from 'react'; |
| 17 | +import React, { useState } from 'react'; |
18 | 18 | import Button from 'cuix/dist/components/Button'; |
19 | | -import DocumentationIcon from '@cloudera/cuix-core/icons/react/DocumentationIcon'; |
| 19 | +import S3Icon from '@cloudera/cuix-core/icons/react/S3Icon'; |
| 20 | +import HDFSIcon from '@cloudera/cuix-core/icons/react/HdfsIcon'; |
| 21 | +import OzoneIcon from '@cloudera/cuix-core/icons/react/OzoneIcon'; |
| 22 | +import GoogleCloudIcon from '@cloudera/cuix-core/icons/react/GoogleCloudIcon'; |
| 23 | +import AdlsIcon from '../../../components/icons/AdlsIcon'; |
| 24 | + |
20 | 25 | import { hueWindow } from 'types/types'; |
21 | 26 |
|
22 | | -import { FileMetaData, ImporterFileSource, LocalFileUploadResponse } from '../types'; |
| 27 | +import LoadingErrorWrapper from '../../../reactComponents/LoadingErrorWrapper/LoadingErrorWrapper'; |
| 28 | +import FileChooserModal from '../../storageBrowser/FileChooserModal/FileChooserModal'; |
| 29 | +import LocalFileUploadOption from './LocalFileUploadOption'; |
| 30 | +import { FILESYSTEMS_API_URL } from '../../storageBrowser/api'; |
| 31 | +import { FileMetaData, ImporterFileSource } from '../types'; |
| 32 | +import { FileSystem } from '../../storageBrowser/types'; |
23 | 33 | import { i18nReact } from '../../../utils/i18nReact'; |
24 | | -import { UPLOAD_LOCAL_FILE_API_URL } from '../api'; |
25 | | -import useSaveData from '../../../utils/hooks/useSaveData/useSaveData'; |
26 | | -import huePubSub from '../../../utils/huePubSub'; |
| 34 | +import useLoadData from '../../../utils/hooks/useLoadData/useLoadData'; |
27 | 35 |
|
28 | 36 | import './ImporterSourceSelector.scss'; |
29 | 37 |
|
| 38 | +const getFileSystems = t => { |
| 39 | + return { |
| 40 | + s3a: { |
| 41 | + icon: <S3Icon />, |
| 42 | + title: t('Amazon S3') |
| 43 | + }, |
| 44 | + hdfs: { |
| 45 | + icon: <HDFSIcon />, |
| 46 | + title: t('HDFS') |
| 47 | + }, |
| 48 | + abfs: { |
| 49 | + icon: <AdlsIcon />, |
| 50 | + title: t('Azure Storage') |
| 51 | + }, |
| 52 | + ofs: { |
| 53 | + icon: <OzoneIcon />, |
| 54 | + title: t('Ozone') |
| 55 | + }, |
| 56 | + adls: { |
| 57 | + icon: <AdlsIcon />, |
| 58 | + title: t('Azure Storage') |
| 59 | + }, |
| 60 | + gs: { |
| 61 | + icon: <GoogleCloudIcon />, |
| 62 | + title: t('Google Storage') |
| 63 | + } |
| 64 | + }; |
| 65 | +}; |
30 | 66 | interface ImporterSourceSelectorProps { |
31 | 67 | setFileMetaData: (fileMetaData: FileMetaData) => void; |
32 | 68 | } |
33 | 69 |
|
34 | 70 | const ImporterSourceSelector = ({ setFileMetaData }: ImporterSourceSelectorProps): JSX.Element => { |
| 71 | + const [selectedUserHomeDirectory, setSelectedUserHomeDirectory] = useState<string | undefined>( |
| 72 | + undefined |
| 73 | + ); |
| 74 | + const [uploadError, setUploadError] = useState<string | undefined>(undefined); |
35 | 75 | const { t } = i18nReact.useTranslation(); |
36 | | - const uploadRef = useRef<HTMLInputElement>(null); |
37 | | - |
38 | | - const { save: upload } = useSaveData<LocalFileUploadResponse>(UPLOAD_LOCAL_FILE_API_URL); |
| 76 | + const fileSystems = getFileSystems(t); |
39 | 77 |
|
40 | | - const handleUploadClick = () => { |
41 | | - if (!uploadRef || !uploadRef.current) { |
42 | | - return; |
43 | | - } |
44 | | - uploadRef.current.click(); |
45 | | - }; |
| 78 | + const { |
| 79 | + data: fileSystemsData, |
| 80 | + loading, |
| 81 | + error, |
| 82 | + reloadData |
| 83 | + } = useLoadData<FileSystem[]>(FILESYSTEMS_API_URL); |
46 | 84 |
|
47 | | - const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => { |
48 | | - const files = e.target.files; |
49 | | - if (!files) { |
50 | | - return; |
| 85 | + const errorConfig = [ |
| 86 | + { |
| 87 | + enabled: !!error, |
| 88 | + message: t('An error occurred while fetching the filesystem'), |
| 89 | + action: t('Retry'), |
| 90 | + onClick: reloadData |
| 91 | + }, |
| 92 | + { |
| 93 | + enabled: !!uploadError, |
| 94 | + message: uploadError |
51 | 95 | } |
| 96 | + ]; |
52 | 97 |
|
53 | | - const file = files[0]; |
54 | | - |
55 | | - const payload = new FormData(); |
56 | | - payload.append('file', file); |
57 | | - |
58 | | - const file_size = file.size; |
59 | | - if (file_size === 0) { |
60 | | - huePubSub.publish('hue.global.warning', { |
61 | | - message: t('This file is empty, please select another file.') |
62 | | - }); |
63 | | - } else if (file_size > 200 * 1000) { |
64 | | - huePubSub.publish('hue.global.warning', { |
65 | | - message: t( |
66 | | - 'File size exceeds the supported size (200 KB). Please use the S3, ABFS or HDFS browser to upload files.' |
67 | | - ) |
68 | | - }); |
69 | | - } else { |
70 | | - upload(payload, { |
71 | | - onSuccess: data => { |
72 | | - setFileMetaData({ |
73 | | - path: data.file_path, |
74 | | - fileName: file.name, |
75 | | - source: ImporterFileSource.LOCAL |
76 | | - }); |
77 | | - }, |
78 | | - onError: error => { |
79 | | - huePubSub.publish('hue.error', error); |
80 | | - } |
81 | | - }); |
82 | | - } |
| 98 | + const handleFileSelection = async (destinationPath: string) => { |
| 99 | + setFileMetaData({ |
| 100 | + path: destinationPath, |
| 101 | + source: ImporterFileSource.REMOTE |
| 102 | + }); |
83 | 103 | }; |
84 | 104 |
|
85 | 105 | return ( |
86 | | - <div className="hue-importer__source-selector cuix antd"> |
87 | | - <div className="hue-importer__source-selector-title"> |
88 | | - {t('Select a source to import from')} |
89 | | - </div> |
90 | | - <div className="hue-importer__source-selector-options"> |
91 | | - {(window as hueWindow).ENABLE_DIRECT_UPLOAD && ( |
92 | | - <div className="hue-importer__source-selector-option"> |
93 | | - <Button |
94 | | - className="hue-importer__source-selector-option-button" |
95 | | - size="large" |
96 | | - icon={<DocumentationIcon />} |
97 | | - onClick={handleUploadClick} |
98 | | - ></Button> |
99 | | - <span className="hue-importer__source-selector-option-btn-title"> |
100 | | - {t('Upload from File')} |
101 | | - </span> |
102 | | - <input |
103 | | - ref={uploadRef} |
104 | | - type="file" |
105 | | - className="hue-importer__source-selector-option-upload" |
106 | | - onChange={handleFileUpload} |
107 | | - accept=".csv, .xlsx, .xls" |
| 106 | + <LoadingErrorWrapper loading={loading} errors={errorConfig}> |
| 107 | + <div className="hue-importer__source-selector cuix antd"> |
| 108 | + <div className="hue-importer__source-selector-title"> |
| 109 | + {t('Select a source to import from')} |
| 110 | + </div> |
| 111 | + <div className="hue-importer__source-selector-options"> |
| 112 | + {(window as hueWindow).ENABLE_DIRECT_UPLOAD && ( |
| 113 | + <LocalFileUploadOption |
| 114 | + setFileMetaData={setFileMetaData} |
| 115 | + setUploadError={setUploadError} |
108 | 116 | /> |
109 | | - </div> |
110 | | - )} |
| 117 | + )} |
| 118 | + {fileSystemsData?.map(filesystem => ( |
| 119 | + <div className="hue-importer__source-selector-option" key={filesystem.name}> |
| 120 | + <Button |
| 121 | + className="hue-importer__source-selector-option-button" |
| 122 | + aria-label={t(fileSystems[filesystem.name].title)} |
| 123 | + size="large" |
| 124 | + icon={fileSystems[filesystem.name].icon} |
| 125 | + onClick={() => { |
| 126 | + setSelectedUserHomeDirectory(filesystem.userHomeDirectory); |
| 127 | + }} |
| 128 | + ></Button> |
| 129 | + <span className="hue-importer__source-selector-option-btn-title"> |
| 130 | + {t(fileSystems[filesystem.name].title)} |
| 131 | + </span> |
| 132 | + </div> |
| 133 | + ))} |
| 134 | + </div> |
111 | 135 | </div> |
112 | | - </div> |
| 136 | + {selectedUserHomeDirectory && ( |
| 137 | + <FileChooserModal |
| 138 | + onClose={() => { |
| 139 | + setSelectedUserHomeDirectory(undefined); |
| 140 | + }} |
| 141 | + onSubmit={handleFileSelection} |
| 142 | + showModal={true} |
| 143 | + title={t('Import file')} |
| 144 | + sourcePath={selectedUserHomeDirectory} |
| 145 | + isFileSelectionAllowed={true} |
| 146 | + isUploadEnabled={true} |
| 147 | + /> |
| 148 | + )} |
| 149 | + </LoadingErrorWrapper> |
113 | 150 | ); |
114 | 151 | }; |
115 | 152 |
|
|
0 commit comments