Browse Source

[ui-storagebrowser] refreshes file stats when file is edited (#3920)

* [ui-storagebrowser] refreshes file stats when file is edited
Ram Prasad Agarwal 11 months ago
parent
commit
fe17f6ad2a

+ 6 - 2
desktop/core/src/desktop/js/apps/storageBrowser/StorageBrowserTab/StorageBrowserTab.tsx

@@ -46,7 +46,11 @@ const StorageBrowserTab = ({ homeDir, testId }: StorageBrowserTabProps): JSX.Ele
 
 
   const { t } = i18nReact.useTranslation();
   const { t } = i18nReact.useTranslation();
 
 
-  const { data: fileStats, loading } = useLoadData<FileStats>(FILE_STATS_API_URL, {
+  const {
+    data: fileStats,
+    loading,
+    reloadData
+  } = useLoadData<FileStats>(FILE_STATS_API_URL, {
     params: {
     params: {
       path: filePath
       path: filePath
     },
     },
@@ -89,7 +93,7 @@ const StorageBrowserTab = ({ homeDir, testId }: StorageBrowserTabProps): JSX.Ele
           <StorageDirectoryPage fileStats={fileStats} onFilePathChange={setFilePath} />
           <StorageDirectoryPage fileStats={fileStats} onFilePathChange={setFilePath} />
         )}
         )}
         {fileStats?.type === BrowserViewType.file && (
         {fileStats?.type === BrowserViewType.file && (
-          <StorageFilePage fileName={fileName} fileStats={fileStats} />
+          <StorageFilePage fileName={fileName} fileStats={fileStats} onReload={reloadData} />
         )}
         )}
       </div>
       </div>
     </Spin>
     </Spin>

+ 5 - 3
desktop/core/src/desktop/js/apps/storageBrowser/StorageDirectoryPage/StorageDirectoryPage.tsx

@@ -186,9 +186,11 @@ const StorageDirectoryPage = ({
   const onRowClicked = (record: StorageDirectoryTableData) => {
   const onRowClicked = (record: StorageDirectoryTableData) => {
     return {
     return {
       onClick: () => {
       onClick: () => {
-        onFilePathChange(record.path);
-        if (record.type === 'dir') {
-          setPageNumber(1);
+        if (selectedFiles.length === 0) {
+          onFilePathChange(record.path);
+          if (record.type === 'dir') {
+            setPageNumber(1);
+          }
         }
         }
       }
       }
     };
     };

+ 36 - 10
desktop/core/src/desktop/js/apps/storageBrowser/StorageFilePage/StorageFilePage.test.tsx

@@ -64,6 +64,7 @@ const mockFileStats: FileStats = {
   type: BrowserViewType.file
   type: BrowserViewType.file
 };
 };
 const mockFileName = 'file.txt';
 const mockFileName = 'file.txt';
+const mockReload = jest.fn();
 
 
 describe('StorageFilePage', () => {
 describe('StorageFilePage', () => {
   let oldShowDownloadButton: boolean;
   let oldShowDownloadButton: boolean;
@@ -80,7 +81,9 @@ describe('StorageFilePage', () => {
   });
   });
 
 
   it('should render file metadata and content', () => {
   it('should render file metadata and content', () => {
-    render(<StorageFilePage fileName={mockFileName} fileStats={mockFileStats} />);
+    render(
+      <StorageFilePage fileName={mockFileName} fileStats={mockFileStats} onReload={mockReload} />
+    );
 
 
     expect(screen.getByText('Size')).toBeInTheDocument();
     expect(screen.getByText('Size')).toBeInTheDocument();
     expect(screen.getByText('120.56 KB')).toBeInTheDocument();
     expect(screen.getByText('120.56 KB')).toBeInTheDocument();
@@ -100,7 +103,9 @@ describe('StorageFilePage', () => {
 
 
   // TODO: fix this test when mocking of useLoadData onSuccess callback is mproperly mocked
   // TODO: fix this test when mocking of useLoadData onSuccess callback is mproperly mocked
   it.skip('should show edit button and hides save/cancel buttons initially', () => {
   it.skip('should show edit button and hides save/cancel buttons initially', () => {
-    render(<StorageFilePage fileName={mockFileName} fileStats={mockFileStats} />);
+    render(
+      <StorageFilePage fileName={mockFileName} fileStats={mockFileStats} onReload={mockReload} />
+    );
 
 
     expect(screen.getByRole('button', { name: 'Edit' })).toBeVisible();
     expect(screen.getByRole('button', { name: 'Edit' })).toBeVisible();
     expect(screen.queryByRole('button', { name: 'Save' })).toBeNull();
     expect(screen.queryByRole('button', { name: 'Save' })).toBeNull();
@@ -113,14 +118,18 @@ describe('StorageFilePage', () => {
       contents: 'Initial file content',
       contents: 'Initial file content',
       compression: 'zip'
       compression: 'zip'
     }));
     }));
-    render(<StorageFilePage fileName={mockFileName} fileStats={mockFileStats} />);
+    render(
+      <StorageFilePage fileName={mockFileName} fileStats={mockFileStats} onReload={mockReload} />
+    );
 
 
     expect(screen.queryByRole('button', { name: 'Edit' })).toBeNull();
     expect(screen.queryByRole('button', { name: 'Edit' })).toBeNull();
   });
   });
 
 
   it('should show save and cancel buttons when editing', async () => {
   it('should show save and cancel buttons when editing', async () => {
     const user = userEvent.setup();
     const user = userEvent.setup();
-    render(<StorageFilePage fileName={mockFileName} fileStats={mockFileStats} />);
+    render(
+      <StorageFilePage fileName={mockFileName} fileStats={mockFileStats} onReload={mockReload} />
+    );
 
 
     expect(screen.getByRole('button', { name: 'Edit' })).toBeVisible();
     expect(screen.getByRole('button', { name: 'Edit' })).toBeVisible();
     expect(screen.queryByRole('button', { name: 'Save' })).toBeNull();
     expect(screen.queryByRole('button', { name: 'Save' })).toBeNull();
@@ -138,7 +147,9 @@ describe('StorageFilePage', () => {
 
 
   it('should update textarea value and calls handleSave', async () => {
   it('should update textarea value and calls handleSave', async () => {
     const user = userEvent.setup();
     const user = userEvent.setup();
-    render(<StorageFilePage fileName={mockFileName} fileStats={mockFileStats} />);
+    render(
+      <StorageFilePage fileName={mockFileName} fileStats={mockFileStats} onReload={mockReload} />
+    );
 
 
     await user.click(screen.getByRole('button', { name: 'Edit' }));
     await user.click(screen.getByRole('button', { name: 'Edit' }));
 
 
@@ -160,7 +171,9 @@ describe('StorageFilePage', () => {
 
 
   it('should cancel editing and reverts textarea value', async () => {
   it('should cancel editing and reverts textarea value', async () => {
     const user = userEvent.setup();
     const user = userEvent.setup();
-    render(<StorageFilePage fileName={mockFileName} fileStats={mockFileStats} />);
+    render(
+      <StorageFilePage fileName={mockFileName} fileStats={mockFileStats} onReload={mockReload} />
+    );
 
 
     await user.click(screen.getByRole('button', { name: 'Edit' }));
     await user.click(screen.getByRole('button', { name: 'Edit' }));
 
 
@@ -180,7 +193,9 @@ describe('StorageFilePage', () => {
 
 
   it('should download a file when download button is clicked', async () => {
   it('should download a file when download button is clicked', async () => {
     const user = userEvent.setup();
     const user = userEvent.setup();
-    render(<StorageFilePage fileName={mockFileName} fileStats={mockFileStats} />);
+    render(
+      <StorageFilePage fileName={mockFileName} fileStats={mockFileStats} onReload={mockReload} />
+    );
 
 
     await user.click(screen.getByRole('button', { name: 'Download' }));
     await user.click(screen.getByRole('button', { name: 'Download' }));
 
 
@@ -194,7 +209,9 @@ describe('StorageFilePage', () => {
 
 
   it('should download a file when download button is clicked', async () => {
   it('should download a file when download button is clicked', async () => {
     const user = userEvent.setup();
     const user = userEvent.setup();
-    render(<StorageFilePage fileName={mockFileName} fileStats={mockFileStats} />);
+    render(
+      <StorageFilePage fileName={mockFileName} fileStats={mockFileStats} onReload={mockReload} />
+    );
 
 
     await user.click(screen.getByRole('button', { name: 'Download' }));
     await user.click(screen.getByRole('button', { name: 'Download' }));
 
 
@@ -209,7 +226,9 @@ describe('StorageFilePage', () => {
   it('should not render the download button when show_download_button is false', () => {
   it('should not render the download button when show_download_button is false', () => {
     (window as hueWindow).SHOW_DOWNLOAD_BUTTON = false;
     (window as hueWindow).SHOW_DOWNLOAD_BUTTON = false;
 
 
-    render(<StorageFilePage fileName={mockFileName} fileStats={mockFileStats} />);
+    render(
+      <StorageFilePage fileName={mockFileName} fileStats={mockFileStats} onReload={mockReload} />
+    );
 
 
     expect(screen.queryByRole('button', { name: 'Download' })).toBeNull();
     expect(screen.queryByRole('button', { name: 'Download' })).toBeNull();
     expect(screen.queryByRole('link', { name: 'Download' })).toBeNull();
     expect(screen.queryByRole('link', { name: 'Download' })).toBeNull();
@@ -217,7 +236,9 @@ describe('StorageFilePage', () => {
 
 
   // TODO: fix this test when mocking of useLoadData onSuccess callback is mproperly mocked
   // TODO: fix this test when mocking of useLoadData onSuccess callback is mproperly mocked
   it.skip('should render a textarea for text files', () => {
   it.skip('should render a textarea for text files', () => {
-    render(<StorageFilePage fileName={mockFileName} fileStats={mockFileStats} />);
+    render(
+      <StorageFilePage fileName={mockFileName} fileStats={mockFileStats} onReload={mockReload} />
+    );
 
 
     const textarea = screen.getByRole('textbox');
     const textarea = screen.getByRole('textbox');
     expect(textarea).toBeInTheDocument();
     expect(textarea).toBeInTheDocument();
@@ -229,6 +250,7 @@ describe('StorageFilePage', () => {
       <StorageFilePage
       <StorageFilePage
         fileName="imagefile.png"
         fileName="imagefile.png"
         fileStats={{ ...mockFileStats, path: '/path/to/imagefile.png' }}
         fileStats={{ ...mockFileStats, path: '/path/to/imagefile.png' }}
+        onReload={mockReload}
       />
       />
     );
     );
 
 
@@ -242,6 +264,7 @@ describe('StorageFilePage', () => {
       <StorageFilePage
       <StorageFilePage
         fileName="documentfile.pdf"
         fileName="documentfile.pdf"
         fileStats={{ ...mockFileStats, path: '/path/to/documentfile.pdf' }}
         fileStats={{ ...mockFileStats, path: '/path/to/documentfile.pdf' }}
+        onReload={mockReload}
       />
       />
     );
     );
 
 
@@ -253,6 +276,7 @@ describe('StorageFilePage', () => {
       <StorageFilePage
       <StorageFilePage
         fileName="audiofile.mp3"
         fileName="audiofile.mp3"
         fileStats={{ ...mockFileStats, path: '/path/to/audiofile.mp3' }}
         fileStats={{ ...mockFileStats, path: '/path/to/audiofile.mp3' }}
+        onReload={mockReload}
       />
       />
     );
     );
 
 
@@ -266,6 +290,7 @@ describe('StorageFilePage', () => {
       <StorageFilePage
       <StorageFilePage
         fileName="videofile.mp4"
         fileName="videofile.mp4"
         fileStats={{ ...mockFileStats, path: '/path/to/videofile.mp4' }}
         fileStats={{ ...mockFileStats, path: '/path/to/videofile.mp4' }}
+        onReload={mockReload}
       />
       />
     );
     );
 
 
@@ -282,6 +307,7 @@ describe('StorageFilePage', () => {
           path: '/path/to/unsupportedfile.xyz'
           path: '/path/to/unsupportedfile.xyz'
         }}
         }}
         fileName="unsupportedfile.xyz"
         fileName="unsupportedfile.xyz"
+        onReload={mockReload}
       />
       />
     );
     );
 
 

+ 3 - 1
desktop/core/src/desktop/js/apps/storageBrowser/StorageFilePage/StorageFilePage.tsx

@@ -41,11 +41,12 @@ import { Spin } from 'antd';
 import useLoadData from '../../../utils/hooks/useLoadData';
 import useLoadData from '../../../utils/hooks/useLoadData';
 
 
 interface StorageFilePageProps {
 interface StorageFilePageProps {
+  onReload: () => void;
   fileName: string;
   fileName: string;
   fileStats: FileStats;
   fileStats: FileStats;
 }
 }
 
 
-const StorageFilePage = ({ fileName, fileStats }: StorageFilePageProps): JSX.Element => {
+const StorageFilePage = ({ fileName, fileStats, onReload }: StorageFilePageProps): JSX.Element => {
   const { t } = i18nReact.useTranslation();
   const { t } = i18nReact.useTranslation();
   const [isEditing, setIsEditing] = useState<boolean>(false);
   const [isEditing, setIsEditing] = useState<boolean>(false);
   const [fileContent, setFileContent] = useState<FilePreview['contents']>();
   const [fileContent, setFileContent] = useState<FilePreview['contents']>();
@@ -90,6 +91,7 @@ const StorageFilePage = ({ fileName, fileStats }: StorageFilePageProps): JSX.Ele
           setIsEditing(true);
           setIsEditing(true);
         },
         },
         onSuccess: () => {
         onSuccess: () => {
+          onReload();
           huePubSub.publish('hue.global.info', { message: t('Changes saved!') });
           huePubSub.publish('hue.global.info', { message: t('Changes saved!') });
         }
         }
       }
       }