Browse Source

[ui-sb] removes redundant file upload modal (#4227)

Ram Prasad Agarwal 3 tháng trước cách đây
mục cha
commit
469edaa308

+ 34 - 22
desktop/core/src/desktop/js/apps/storageBrowser/StorageDirectoryPage/StorageDirectoryActions/CreateAndUpload/CreateAndUploadAction.test.tsx

@@ -24,6 +24,8 @@ describe('CreateAndUploadAction', () => {
   const mockFilesUpload = jest.fn();
 
   beforeEach(() => {
+    jest.clearAllMocks();
+
     render(
       <CreateAndUploadAction
         currentPath={currentPath}
@@ -35,7 +37,7 @@ describe('CreateAndUploadAction', () => {
   });
 
   it('should render the dropdown with actions', async () => {
-    const newButton = screen.getByText('New');
+    const newButton = screen.getByRole('button', { name: 'New' });
     expect(newButton).toBeInTheDocument();
 
     await act(async () => fireEvent.click(newButton));
@@ -46,75 +48,85 @@ describe('CreateAndUploadAction', () => {
   });
 
   it('should open the folder creation modal when "New Folder" is clicked', async () => {
-    const newButton = screen.getByText('New');
+    const newButton = screen.getByRole('button', { name: 'New' });
     await act(async () => fireEvent.click(newButton));
 
-    const newFolderButton = screen.getByText('New Folder');
+    const newFolderButton = screen.getByRole('menuitem', { name: 'New Folder' });
     await act(async () => fireEvent.click(newFolderButton));
 
-    expect(screen.getByText('Create Folder')).toBeInTheDocument();
+    expect(screen.getByRole('dialog', { name: 'Create Folder' })).toBeInTheDocument();
   });
 
   it('should open the file creation modal when "New File" is clicked', async () => {
-    const newButton = screen.getByText('New');
+    const newButton = screen.getByRole('button', { name: 'New' });
     await act(async () => fireEvent.click(newButton));
 
-    const newFileButton = screen.getByText('New File');
+    const newFileButton = screen.getByRole('menuitem', { name: 'New File' });
     await act(async () => fireEvent.click(newFileButton));
 
-    expect(screen.getByText('Create File')).toBeInTheDocument();
+    expect(screen.getByRole('dialog', { name: 'Create File' })).toBeInTheDocument();
   });
 
-  it('should open the upload file modal when "New Upload" is clicked', async () => {
-    const newButton = screen.getByText('New');
-    await act(async () => fireEvent.click(newButton));
+  it('should render hidden file input for upload functionality', async () => {
+    const fileInput = document.querySelector('input[type="file"]');
+    expect(fileInput).toBeInTheDocument();
+    expect(fileInput).toHaveAttribute('hidden');
+    expect(fileInput).toHaveAttribute('multiple');
+  });
 
-    const newUploadButton = screen.getByText('Upload File');
-    fireEvent.click(newUploadButton);
+  it('should handle file selection and call onFilesUpload', async () => {
+    const fileInput = document.querySelector('input[type="file"]');
+    expect(fileInput).toBeInTheDocument();
+
+    const file1 = new File(['test content 1'], 'test1.txt', { type: 'text/plain' });
+    const file2 = new File(['test content 2'], 'test2.txt', { type: 'text/plain' });
+
+    fireEvent.change(fileInput!, {
+      target: { files: [file1, file2] }
+    });
 
-    // Check if the upload modal is opened
-    expect(screen.getByText('Upload a File')).toBeInTheDocument();
+    expect(mockFilesUpload).toHaveBeenCalledWith([file1, file2]);
   });
 
   it('should call the correct API for creating a folder', async () => {
-    const newButton = screen.getByText('New');
+    const newButton = screen.getByRole('button', { name: 'New' });
     await act(async () => fireEvent.click(newButton));
 
-    const newFolderButton = screen.getByText('New Folder');
+    const newFolderButton = screen.getByRole('menuitem', { name: 'New Folder' });
     await act(async () => fireEvent.click(newFolderButton));
 
     const input = screen.getByRole('textbox');
     fireEvent.change(input, { target: { value: 'Test Folder' } });
 
-    const createButton = screen.getByText('Create');
+    const createButton = screen.getByRole('button', { name: 'Create' });
     fireEvent.click(createButton);
 
     await waitFor(() => {
       expect(mockSave).toHaveBeenCalledWith(
         { path: currentPath, name: 'Test Folder' },
-        { url: CREATE_DIRECTORY_API_URL } // This URL is assumed from the code.
+        { url: CREATE_DIRECTORY_API_URL }
       );
     });
   });
 
   it('should call the correct API for creating a file', async () => {
-    const newButton = screen.getByText('New');
+    const newButton = screen.getByRole('button', { name: 'New' });
     await act(async () => fireEvent.click(newButton));
 
-    const newFileButton = screen.getByText('New File');
+    const newFileButton = screen.getByRole('menuitem', { name: 'New File' });
     await act(async () => fireEvent.click(newFileButton));
 
     // Simulate file name submission
     const input = screen.getByRole('textbox');
     fireEvent.change(input, { target: { value: 'Test File' } });
 
-    const createButton = screen.getByText('Create');
+    const createButton = screen.getByRole('button', { name: 'Create' });
     fireEvent.click(createButton);
 
     await waitFor(() => {
       expect(mockSave).toHaveBeenCalledWith(
         { path: currentPath, name: 'Test File' },
-        { url: CREATE_FILE_API_URL } // This URL is assumed from the code.
+        { url: CREATE_FILE_API_URL }
       );
     });
   });

+ 23 - 17
desktop/core/src/desktop/js/apps/storageBrowser/StorageDirectoryPage/StorageDirectoryActions/CreateAndUpload/CreateAndUploadAction.tsx

@@ -14,10 +14,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import React, { useState } from 'react';
+import React, { useState, useRef } from 'react';
 import { Dropdown } from 'antd';
 import { MenuItemGroupType } from 'antd/lib/menu/hooks/useItems';
-import Modal from 'cuix/dist/components/Modal';
+
 import FolderIcon from '@cloudera/cuix-core/icons/react/ProjectIcon';
 import FileIcon from '@cloudera/cuix-core/icons/react/DocumentationIcon';
 import DropDownIcon from '@cloudera/cuix-core/icons/react/DropdownIcon';
@@ -29,7 +29,6 @@ import { CREATE_DIRECTORY_API_URL, CREATE_FILE_API_URL } from '../../../api';
 import { FileStats } from '../../../types';
 import useSaveData from '../../../../../utils/hooks/useSaveData/useSaveData';
 import InputModal from '../../../../../reactComponents/InputModal/InputModal';
-import DragAndDrop from '../../../../../reactComponents/DragAndDrop/DragAndDrop';
 
 import './CreateAndUploadAction.scss';
 
@@ -53,6 +52,7 @@ const CreateAndUploadAction = ({
   onActionError
 }: CreateAndUploadActionProps): JSX.Element => {
   const { t } = i18nReact.useTranslation();
+  const fileInputRef = useRef<HTMLInputElement>(null);
 
   const [selectedAction, setSelectedAction] = useState<ActionType>();
 
@@ -60,11 +60,6 @@ const CreateAndUploadAction = ({
     setSelectedAction(undefined);
   };
 
-  const onUpload = (files: File[]) => {
-    onModalClose();
-    onFilesUpload(files);
-  };
-
   const onApiSuccess = () => {
     onModalClose();
     onActionSuccess();
@@ -80,6 +75,15 @@ const CreateAndUploadAction = ({
     setSelectedAction(action);
   };
 
+  const onFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
+    if (e.target.files && e.target.files.length > 0) {
+      const filesArray = Array.from(e.target.files);
+      onFilesUpload(filesArray);
+    }
+    // Reset the input value so the same file can be selected again
+    e.target.value = '';
+  };
+
   const newActionsMenuItems: MenuItemGroupType[] = [
     {
       key: 'create',
@@ -109,7 +113,7 @@ const CreateAndUploadAction = ({
           icon: <ImportIcon />,
           key: ActionType.uploadFile,
           label: t('Upload File'),
-          onClick: onActionClick(ActionType.uploadFile)
+          onClick: () => fileInputRef.current?.click()
         }
       ]
     }
@@ -142,6 +146,7 @@ const CreateAndUploadAction = ({
           <DropDownIcon />
         </PrimaryButton>
       </Dropdown>
+
       {(selectedAction === ActionType.createFolder || selectedAction === ActionType.createFile) && (
         <InputModal
           showModal={true}
@@ -156,14 +161,15 @@ const CreateAndUploadAction = ({
           error={error}
         />
       )}
-      <Modal
-        onCancel={onModalClose}
-        className="hue-file-upload-modal cuix antd"
-        open={selectedAction === ActionType.uploadFile}
-        title={t('Upload a File')}
-      >
-        <DragAndDrop onDrop={onUpload} />
-      </Modal>
+
+      <input
+        ref={fileInputRef}
+        type="file"
+        id="file-upload-input"
+        hidden
+        multiple
+        onChange={onFileUpload}
+      />
     </>
   );
 };