-
Notifications
You must be signed in to change notification settings - Fork 395
[ui-importer] Add configured filesystems in importer #4131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
✅ Test files were modified. Ensure that the tests cover all relevant changes. ✅ |
465c3d9
to
42dccf4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work.
Please check the comments below.
desktop/core/src/desktop/js/apps/storageBrowser/FileChooserModal/FileChooserModal.tsx
Show resolved
Hide resolved
}} | ||
/> | ||
)} | ||
<InputModal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we refactor the **/StorageDirectoryActions/CreateAndUpload/CreateAndUploadAction.tsx
component to take the create file and folder action to separate component and reuse it here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will be added in a separate PR
desktop/core/src/desktop/js/apps/storageBrowser/FileChooserModal/FileChooserModal.tsx
Outdated
Show resolved
Hide resolved
desktop/core/src/desktop/js/apps/storageBrowser/FileChooserModal/FileChooserModal.tsx
Outdated
Show resolved
Hide resolved
desktop/core/src/desktop/js/apps/newimporter/ImporterSourceSelector/ImporterSourceSelector.tsx
Outdated
Show resolved
Hide resolved
desktop/core/src/desktop/js/apps/newimporter/ImporterSourceSelector/ImporterSourceSelector.tsx
Outdated
Show resolved
Hide resolved
desktop/core/src/desktop/js/apps/newimporter/ImporterSourceSelector/ImporterSourceSelector.tsx
Outdated
Show resolved
Hide resolved
desktop/core/src/desktop/js/apps/newimporter/ImporterSourceSelector/ImporterSourceSelector.tsx
Show resolved
Hide resolved
desktop/core/src/desktop/js/apps/storageBrowser/FileChooserModal/FileChooserModal.tsx
Outdated
Show resolved
Hide resolved
Lots of good feedback from @ramprasadagarwal. I'll hold while you guys sort it out, but I did notice that the screenshot of the drag and drop looks weird where the "drop area" appears behind the action buttons of the modal. |
desktop/core/src/desktop/js/apps/newimporter/ImporterSourceSelector/ImporterSourceSelector.tsx
Outdated
Show resolved
Hide resolved
desktop/core/src/desktop/js/apps/newimporter/ImporterSourceSelector/ImporterSourceSelector.tsx
Outdated
Show resolved
Hide resolved
811ebb9
to
3700a3c
Compare
.../core/src/desktop/js/apps/newimporter/ImporterSourceSelector/ImporterSourceSelector.test.tsx
Outdated
Show resolved
Hide resolved
desktop/core/src/desktop/js/apps/newimporter/ImporterSourceSelector/ImporterSourceSelector.tsx
Outdated
Show resolved
Hide resolved
desktop/core/src/desktop/js/apps/newimporter/ImporterSourceSelector/ImporterSourceSelector.tsx
Show resolved
Hide resolved
desktop/core/src/desktop/js/apps/newimporter/ImporterSourceSelector/ImporterSourceSelector.tsx
Outdated
Show resolved
Hide resolved
...p/core/src/desktop/js/apps/newimporter/ImporterSourceSelector/LocalFileUploadOption.test.tsx
Outdated
Show resolved
Hide resolved
desktop/core/src/desktop/js/apps/storageBrowser/FileChooserModal/FileChooserModal.tsx
Outdated
Show resolved
Hide resolved
desktop/core/src/desktop/js/reactComponents/BottomSlidePanel/BottomSlidePanel.tsx
Outdated
Show resolved
Hide resolved
desktop/core/src/desktop/js/reactComponents/BottomSlidePanel/BottomSlidePanel.tsx
Outdated
Show resolved
Hide resolved
desktop/core/src/desktop/js/reactComponents/BottomSlidePanel/BottomSlidePanel.tsx
Show resolved
Hide resolved
desktop/core/src/desktop/js/reactComponents/BottomSlidePanel/BottomSlidePanel.tsx
Outdated
Show resolved
Hide resolved
3700a3c
to
1e68db6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work. I reviewed the first half of the files. Will continue with the rest later, but you can start addressing the issues.
expect(screen.getByText('Select a source to import from')).toBeInTheDocument(); | ||
expect(screen.queryByText('LocalUpload')).toBeInTheDocument(); | ||
expect(screen.getByText('Amazon S3')).toBeInTheDocument(); | ||
expect(screen.getByText('HDFS')).toBeInTheDocument(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should cover all filesystems defined in ImporterSourceSelector.tsx
|
||
render(<ImporterSourceSelector setFileMetaData={mockSetFileMetaData} />); | ||
|
||
const s3Button = screen.getAllByRole('button')[1]; // second button (first is local upload) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we are forced to use an index to access a button it is often a tell that we need to improve the accessibility of that button.
)} | ||
{fileSystemsData?.map(filesystem => ( | ||
<div className="hue-importer__source-selector-option" key={filesystem.name}> | ||
<Button |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either move the span title inside the button component or add aria-label={t(fileSystems[filesystem.name].title)}
to the button
|
||
render(<ImporterSourceSelector setFileMetaData={mockSetFileMetaData} />); | ||
|
||
expect(screen.getByText('Select a source to import from')).toBeInTheDocument(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this testing the loading state? The 'Select a source to import from' is shown after loading.
const errorConfig = [ | ||
{ | ||
enabled: !!error, | ||
message: t('An error occurred while fetching the filesystem'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we improve this message? Something about "one or more available filesystems". Can you check if we have any useful information from the API about why it failed?
const fileSize = file.size; | ||
if (fileSize === 0) { | ||
setUploadError(t('This file is empty, please select another file.')); | ||
} else if (fileSize > 150 * 1024 * 1024) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of questions:
- The error msg states max is 200 KB, I assume it should be 150 MB and the error msg is wrong or? In that case this should be 150 * 1000 * 100 for MB (1024 is MiB)
- Where is this limit coming from? Is it available as a config value?
Please at least define this value in a const and reuse it in the error msg. There is a util function available to translate sizes into human readable form in a old vue file, I think we should extract that into a ts file, modify it to use Decimal base and start using it.
export const humanSize = (value?: number): string => {
// Use SI decimal units for 1000-based calculations
const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB']; // Stays the same
if (value === 0) {
return '0 B';
}
if (!value) {
return ''; // Or '0 B' depending on desired behavior for undefined/null
}
if (value < 1000) { // Changed here!
return `${value} B`;
}
// Note! Changed base for calculations from 1024 to 1000
const unitIndex = Math.min(Math.floor(Math.log(value) / Math.log(1000)), UNITS.length - 1);
const unitValue = Math.round((value / Math.pow(1000, unitIndex)) * 10) / 10;
return `${unitValue} ${UNITS[unitIndex]}`;
};
} else if (fileSize > 150 * 1024 * 1024) { | ||
setUploadError( | ||
t( | ||
'File size exceeds the supported size (200 KB). Please use the S3, ABFS or HDFS browser to upload files.' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we sending them off to a third party tool? Can't the user upload a larger file using the new storage browser in Hue? If so, lets create an actionable error msg that can take the user there.
const { t } = i18nReact.useTranslation(); | ||
const uploadRef = useRef<HTMLInputElement>(null); | ||
|
||
const { save: upload } = useSaveData<LocalFileUploadResponse>(UPLOAD_LOCAL_FILE_API_URL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To where are we actually uploading this file? The Hue web server? HDFS?
cc @ramprasadagarwal
data-testid="hue-file-input" | ||
className="hue-importer__source-selector-option-upload" | ||
onChange={handleFileUpload} | ||
accept=".csv, .xlsx, .xls" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did we really agree that these are the only supported file formats?
); | ||
}); | ||
|
||
it('should show error for file > 150mb', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: MB
@nidhibhatg I'm also trying out some deep PR review AI prompting using the the copilot chat functionality. Please have a look, I think they make sense. Unfortunately I can't get them to appear as comments in the actual code.
Comment:
ImporterSourceSelector.tsx
Comment:
Comment:
LocalFileUploadOption.test.tsx
Comment: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds support for configured filesystems in the importer and enhances the file chooser with upload and folder-creation capabilities.
- Introduces a reusable
BottomSlidePanel
component for folder creation UI - Extends
FileChooserModal
with drag-and-drop, polling, upload button, and error/retry handling - Updates
ImporterSourceSelector
to fetch and render configured filesystems dynamically
Reviewed Changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.
File | Description |
---|---|
reactComponents/BottomSlidePanel/BottomSlidePanel.tsx | New bottom slide panel component |
apps/storageBrowser/FileChooserModal/FileChooserModal.tsx | File chooser extended to support upload & folder creation |
apps/newimporter/ImporterSourceSelector/ImporterSourceSelector.tsx | Fetch and display configured filesystems |
apps/newimporter/ImporterSourceSelector/LocalFileUploadOption.tsx | Local file upload option with size validation |
Comments suppressed due to low confidence (4)
desktop/core/src/desktop/js/reactComponents/BottomSlidePanel/BottomSlidePanel.tsx:24
- The onPrimaryClick prop is typed as
(unknown) => void
, which is ambiguous. Consider changing it to a clear signature like() => void
or specify the exact argument type.
onPrimaryClick?: (unknown) => void;
desktop/core/src/desktop/js/reactComponents/BottomSlidePanel/BottomSlidePanel.tsx:66
- The mask div has
role="button"
but no accessible name. Addaria-label
oraria-labelledby
(e.g.,aria-label="Close panel"
) so screen readers announce its purpose.
<div className={`hue-bottom-slide-mask ${isOpen ? 'fade-in' : 'fade-out'}`}
desktop/core/src/desktop/js/reactComponents/BottomSlidePanel/BottomSlidePanel.scss:62
- Missing semicolon after the
padding: 16px 24px
property in.hue-bottom-slide-panel__footer
. Add a semicolon to avoid CSS parsing errors.
padding: 16px 24px
desktop/core/src/desktop/js/apps/storageBrowser/FileChooserModal/FileChooserModal.tsx:207
- The variable
name
is undefined here. You probably meant to usecreateFolderValue
or the new folder name returned from the API.
setDestPath(prev => `${prev}/${name}`);
<Input | ||
defaultValue={createFolderValue} | ||
disabled={createFolderLoading} | ||
onPressEnter={() => handleCreate} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The handler () => handleCreate
returns the function instead of invoking it. Change this to onPressEnter={handleCreate}
or onPressEnter={() => handleCreate()}
.
onPressEnter={() => handleCreate} | |
onPressEnter={() => handleCreate()} |
Copilot uses AI. Check for mistakes.
} else if (fileSize > 150 * 1024 * 1024) { | ||
setUploadError( | ||
t( | ||
'File size exceeds the supported size (200 KB). Please use the S3, ABFS or HDFS browser to upload files.' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message references "200 KB" but the code checks fileSize > 150 * 1024 * 1024
(~150 MB). Either update the threshold or correct the message to match.
'File size exceeds the supported size (200 KB). Please use the S3, ABFS or HDFS browser to upload files.' | |
'File size exceeds the supported size (150 MB). Please use the S3, ABFS or HDFS browser to upload files.' |
Copilot uses AI. Check for mistakes.
{fileSystemsData?.map(filesystem => ( | ||
<div className="hue-importer__source-selector-option" key={filesystem.name}> | ||
<Button | ||
className="hue-importer__source-selector-option-button" | ||
size="large" | ||
icon={fileSystems[filesystem.name].icon} | ||
onClick={() => { | ||
setSelectedUserHomeDirectory(filesystem.userHomeDirectory); | ||
}} | ||
></Button> | ||
<span className="hue-importer__source-selector-option-btn-title"> | ||
{t(fileSystems[filesystem.name].title)} | ||
</span> | ||
</div> | ||
))} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indexing fileSystems
by filesystem.name
without checking if the key exists may throw at runtime. Consider filtering unsupported names or providing a fallback icon.
Copilot uses AI. Check for mistakes.
What changes were proposed in this pull request?
How was this patch tested?
Please review Hue Contributing Guide before opening a pull request.