|
| 1 | +// Licensed to Cloudera, Inc. under one |
| 2 | +// or more contributor license agreements. See the NOTICE file |
| 3 | +// distributed with this work for additional information |
| 4 | +// regarding copyright ownership. Cloudera, Inc. licenses this file |
| 5 | +// to you under the Apache License, Version 2.0 (the |
| 6 | +// "License"); you may not use this file except in compliance |
| 7 | +// with the License. You may obtain a copy of the License at |
| 8 | +// |
| 9 | +// http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | +// |
| 11 | +// Unless required by applicable law or agreed to in writing, software |
| 12 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | +// See the License for the specific language governing permissions and |
| 15 | +// limitations under the License. |
| 16 | + |
| 17 | +import React, { useEffect, useState } from 'react'; |
| 18 | +import useSaveData from '../../../utils/hooks/useSaveData/useSaveData'; |
| 19 | +import { |
| 20 | + FileFormatResponse, |
| 21 | + FileMetaData, |
| 22 | + GuessFieldTypesResponse, |
| 23 | + ImporterTableData |
| 24 | +} from '../types'; |
| 25 | +import { convertToAntdColumns, convertToDataSource } from '../utils/utils'; |
| 26 | +import { i18nReact } from '../../../utils/i18nReact'; |
| 27 | +import { BorderlessButton, PrimaryButton } from 'cuix/dist/components/Button'; |
| 28 | +import LoadingErrorWrapper from '../../../reactComponents/LoadingErrorWrapper/LoadingErrorWrapper'; |
| 29 | +import useResizeObserver from '../../../utils/hooks/useResizeObserver/useResizeObserver'; |
| 30 | +import PaginatedTable from '../../../reactComponents/PaginatedTable/PaginatedTable'; |
| 31 | +import { GUESS_FORMAT_URL, GUESS_FIELD_TYPES_URL } from '../api'; |
| 32 | + |
| 33 | +import './ImporterFilePreview.scss'; |
| 34 | + |
| 35 | +interface ImporterFilePreviewProps { |
| 36 | + fileMetaData: FileMetaData; |
| 37 | +} |
| 38 | + |
| 39 | +const ImporterFilePreview = ({ fileMetaData }: ImporterFilePreviewProps): JSX.Element => { |
| 40 | + const { t } = i18nReact.useTranslation(); |
| 41 | + const [fileFormat, setFileFormat] = useState<FileFormatResponse | null>(null); |
| 42 | + |
| 43 | + const { save: guessFormat, loading: guessingFormat } = useSaveData<FileFormatResponse>( |
| 44 | + GUESS_FORMAT_URL, |
| 45 | + { |
| 46 | + onSuccess: data => { |
| 47 | + setFileFormat(data); |
| 48 | + } |
| 49 | + } |
| 50 | + ); |
| 51 | + |
| 52 | + const { |
| 53 | + save: guessFields, |
| 54 | + data: previewData, |
| 55 | + loading: guessingFields |
| 56 | + } = useSaveData<GuessFieldTypesResponse>(GUESS_FIELD_TYPES_URL); |
| 57 | + |
| 58 | + useEffect(() => { |
| 59 | + const guessFormatPayload = { |
| 60 | + inputFormat: fileMetaData.source, |
| 61 | + file_type: fileMetaData.type, |
| 62 | + path: fileMetaData.path |
| 63 | + }; |
| 64 | + const guessFormatormData = new FormData(); |
| 65 | + guessFormatormData.append('fileFormat', JSON.stringify(guessFormatPayload)); |
| 66 | + guessFormat(guessFormatormData); |
| 67 | + }, [fileMetaData]); |
| 68 | + |
| 69 | + useEffect(() => { |
| 70 | + if (!fileFormat) { |
| 71 | + return; |
| 72 | + } |
| 73 | + |
| 74 | + const payload = { |
| 75 | + path: fileMetaData.path, |
| 76 | + format: fileFormat, |
| 77 | + inputFormat: fileMetaData.source |
| 78 | + }; |
| 79 | + const formData = new FormData(); |
| 80 | + formData.append('fileFormat', JSON.stringify(payload)); |
| 81 | + guessFields(formData); |
| 82 | + }, [fileMetaData.path, fileFormat]); |
| 83 | + |
| 84 | + const columns = convertToAntdColumns(previewData?.columns ?? []); |
| 85 | + const tableData = convertToDataSource(columns, previewData?.sample); |
| 86 | + |
| 87 | + const [ref, rect] = useResizeObserver(); |
| 88 | + |
| 89 | + return ( |
| 90 | + <div className="hue-importer-preview-page"> |
| 91 | + <div className="hue-importer-preview-page__header"> |
| 92 | + <div className="hue-importer-preview-page__header__title">{t('Preview')}</div> |
| 93 | + <div className="hue-importer-preview-page__header__actions"> |
| 94 | + <BorderlessButton data-testid="hue-importer-preview-page__header__actions__cancel"> |
| 95 | + {t('Cancel')} |
| 96 | + </BorderlessButton> |
| 97 | + <PrimaryButton data-testid="hue-importer-preview-page__header__actions__finish"> |
| 98 | + {t('Finish Import')} |
| 99 | + </PrimaryButton> |
| 100 | + </div> |
| 101 | + </div> |
| 102 | + <div className="hue-importer-preview-page__metadata">{t('DESTINATION')}</div> |
| 103 | + <div className="hue-importer-preview-page__main-section" ref={ref}> |
| 104 | + <LoadingErrorWrapper loading={guessingFormat || guessingFields} errors={[]} hideChildren> |
| 105 | + <PaginatedTable<ImporterTableData> |
| 106 | + data={tableData} |
| 107 | + columns={columns} |
| 108 | + rowKey="importerDataKey" |
| 109 | + scroll={{ |
| 110 | + y: Math.max(rect.height - 60, 100), |
| 111 | + x: true |
| 112 | + }} |
| 113 | + locale={{ emptyText: t('No data available') }} |
| 114 | + /> |
| 115 | + </LoadingErrorWrapper> |
| 116 | + </div> |
| 117 | + </div> |
| 118 | + ); |
| 119 | +}; |
| 120 | + |
| 121 | +export default ImporterFilePreview; |
0 commit comments