Explorar el Código

[ui-storagebrowser] change label of HDFS root from / to hdfs (#4069)

Ram Prasad Agarwal hace 8 meses
padre
commit
02c2b2d1e7
Se han modificado 19 ficheros con 158 adiciones y 94 borrados
  1. 1 6
      desktop/core/src/desktop/js/apps/storageBrowser/FileChooserModal/FileChooserModal.tsx
  2. 7 10
      desktop/core/src/desktop/js/apps/storageBrowser/StorageBrowserTab/StorageBrowserTab.tsx
  3. 8 6
      desktop/core/src/desktop/js/apps/storageBrowser/StorageDirectoryPage/StorageDirectoryActions/FileAndFolder/ChangeOwnerAndGroupModal/ChangeOwnerAndGroupModal.tsx
  4. 2 1
      desktop/core/src/desktop/js/apps/storageBrowser/StorageDirectoryPage/StorageDirectoryPage.tsx
  5. 8 11
      desktop/core/src/desktop/js/apps/storageBrowser/StorageFilePage/StorageFilePage.tsx
  6. 1 1
      desktop/core/src/desktop/js/reactComponents/FileChooser/FileChooserModal/FileChooserModal.tsx
  7. 7 0
      desktop/core/src/desktop/js/reactComponents/LoadingErrorWrapper/LoadingErrorWrapper.scss
  8. 1 1
      desktop/core/src/desktop/js/reactComponents/LoadingErrorWrapper/LoadingErrorWrapper.test.tsx
  9. 9 7
      desktop/core/src/desktop/js/reactComponents/LoadingErrorWrapper/LoadingErrorWrapper.tsx
  10. 1 1
      desktop/core/src/desktop/js/reactComponents/PathBrowser/Breadcrumb/Breadcrumb.tsx
  11. 0 0
      desktop/core/src/desktop/js/reactComponents/PathBrowser/OverflowingItem/OverflowTooltip.tsx
  12. 0 0
      desktop/core/src/desktop/js/reactComponents/PathBrowser/OverflowingItem/OverflowingItem.scss
  13. 0 0
      desktop/core/src/desktop/js/reactComponents/PathBrowser/OverflowingItem/OverflowingItem.tsx
  14. 9 5
      desktop/core/src/desktop/js/reactComponents/PathBrowser/PathBrowser.scss
  15. 15 15
      desktop/core/src/desktop/js/reactComponents/PathBrowser/PathBrowser.test.tsx
  16. 24 22
      desktop/core/src/desktop/js/reactComponents/PathBrowser/PathBrowser.tsx
  17. 52 4
      desktop/core/src/desktop/js/reactComponents/PathBrowser/PathBrowser.util.test.ts
  18. 10 1
      desktop/core/src/desktop/js/reactComponents/PathBrowser/PathBrowser.util.ts
  19. 3 3
      desktop/core/src/desktop/js/utils/storageBrowserUtils.ts

+ 1 - 6
desktop/core/src/desktop/js/apps/storageBrowser/FileChooserModal/FileChooserModal.tsx

@@ -146,12 +146,7 @@ const FileChooserModal = ({
     >
       <div className="hue-filechooser-modal__body">
         <div className="hue-filechooser-modal__path-browser-panel">
-          <PathBrowser
-            filePath={destPath}
-            onFilepathChange={setDestPath}
-            seperator={'/'}
-            showIcon={false}
-          />
+          <PathBrowser filePath={destPath} onFilepathChange={setDestPath} showIcon={false} />
         </div>
         <Input
           className="hue-filechooser-modal__search"

+ 7 - 10
desktop/core/src/desktop/js/apps/storageBrowser/StorageBrowserTab/StorageBrowserTab.tsx

@@ -32,7 +32,10 @@ import { BorderlessButton } from 'cuix/dist/components/Button';
 import StorageFilePage from '../StorageFilePage/StorageFilePage';
 import changeURL from '../../../utils/url/changeURL';
 import LoadingErrorWrapper from '../../../reactComponents/LoadingErrorWrapper/LoadingErrorWrapper';
-import { getFileSystemAndPath } from '../../../reactComponents/PathBrowser/PathBrowser.util';
+import {
+  getLastDirOrFileNameFromPath,
+  getFileSystemAndPath
+} from '../../../reactComponents/PathBrowser/PathBrowser.util';
 import { inTrash } from '../../../utils/storageBrowserUtils';
 
 import './StorageBrowserTab.scss';
@@ -55,8 +58,7 @@ const StorageBrowserTab = ({ fileSystem, testId }: StorageBrowserTabProps): JSX.
     urlFileSystem === fileSystem.name ? urlFilePath : fileSystem.userHomeDirectory;
 
   const [filePath, setFilePath] = useState<string>(initialFilePath);
-  const fileName =
-    filePath.split('/').pop() !== '' ? (filePath.split('/').pop() ?? '') : filePath.split('://')[0];
+  const fileName = getLastDirOrFileNameFromPath(filePath);
 
   const { t } = i18nReact.useTranslation();
 
@@ -188,12 +190,7 @@ const StorageBrowserTab = ({ fileSystem, testId }: StorageBrowserTabProps): JSX.
           className="hue-storage-browser-tab__path-browser-container"
           data-testid={`${testId}-path-browser-panel`}
         >
-          <PathBrowser
-            filePath={filePath}
-            onFilepathChange={setFilePath}
-            seperator={'/'}
-            showIcon={false}
-          />
+          <PathBrowser filePath={filePath} onFilepathChange={setFilePath} />
         </div>
         {fileStats?.type === BrowserViewType.dir && !isLoading && (
           <StorageDirectoryPage
@@ -204,7 +201,7 @@ const StorageBrowserTab = ({ fileSystem, testId }: StorageBrowserTabProps): JSX.
           />
         )}
         {fileStats?.type === BrowserViewType.file && !isLoading && (
-          <StorageFilePage fileName={fileName} fileStats={fileStats} onReload={reloadData} />
+          <StorageFilePage fileStats={fileStats} onReload={reloadData} />
         )}
       </div>
     </LoadingErrorWrapper>

+ 8 - 6
desktop/core/src/desktop/js/apps/storageBrowser/StorageDirectoryPage/StorageDirectoryActions/FileAndFolder/ChangeOwnerAndGroupModal/ChangeOwnerAndGroupModal.tsx

@@ -19,15 +19,15 @@ import Modal from 'cuix/dist/components/Modal';
 import { i18nReact } from '../../../../../../utils/i18nReact';
 import useSaveData from '../../../../../../utils/hooks/useSaveData/useSaveData';
 import { Checkbox, Input, Select } from 'antd';
-import { ListDirectory, StorageDirectoryTableData } from '../../../../types';
+import { HDFSFileSystemConfig, StorageDirectoryTableData } from '../../../../types';
 import { BULK_CHANGE_OWNER_API_URL } from '../../../../api';
 import './ChangeOwnerAndGroupModal.scss';
 
 interface ChangeOwnerAndGroupModalProps {
-  superUser?: ListDirectory['superuser'];
-  superGroup?: ListDirectory['supergroup'];
-  users?: ListDirectory['users'];
-  groups?: ListDirectory['groups'];
+  superUser?: HDFSFileSystemConfig['superuser'];
+  superGroup?: HDFSFileSystemConfig['supergroup'];
+  users?: HDFSFileSystemConfig['users'];
+  groups?: HDFSFileSystemConfig['groups'];
   isOpen?: boolean;
   files: StorageDirectoryTableData[];
   setLoading: (value: boolean) => void;
@@ -37,7 +37,9 @@ interface ChangeOwnerAndGroupModalProps {
 }
 
 const OTHERS_KEY = 'others';
-const getDropdownOptions = (entity: ListDirectory['users'] | ListDirectory['groups']) => {
+const getDropdownOptions = (
+  entity: HDFSFileSystemConfig['users'] | HDFSFileSystemConfig['groups']
+) => {
   return [...entity, OTHERS_KEY].map(user => ({
     value: user,
     label: user

+ 2 - 1
desktop/core/src/desktop/js/apps/storageBrowser/StorageDirectoryPage/StorageDirectoryPage.tsx

@@ -48,6 +48,7 @@ import PaginatedTable, {
   SortOrder,
   ColumnProps
 } from '../../../reactComponents/PaginatedTable/PaginatedTable';
+import { getLastDirOrFileNameFromPath } from '../../../reactComponents/PathBrowser/PathBrowser.util';
 
 interface StorageDirectoryPageProps {
   fileStats: FileStats;
@@ -110,7 +111,7 @@ const StorageDirectoryPage = ({
     }
 
     return filesData?.files?.map(file => ({
-      name: file.path.split('/').pop() ?? '',
+      name: getLastDirOrFileNameFromPath(file.path),
       size: file.type === BrowserViewType.file ? formatBytes(file.size) : '',
       user: file.user,
       group: file.group,

+ 8 - 11
desktop/core/src/desktop/js/apps/storageBrowser/StorageFilePage/StorageFilePage.tsx

@@ -33,15 +33,16 @@ import useLoadData from '../../../utils/hooks/useLoadData/useLoadData';
 import { getLastKnownConfig } from '../../../config/hueConfig';
 import LoadingErrorWrapper from '../../../reactComponents/LoadingErrorWrapper/LoadingErrorWrapper';
 import { inTrash } from '../../../utils/storageBrowserUtils';
+import { getLastDirOrFileNameFromPath } from '../../../reactComponents/PathBrowser/PathBrowser.util';
 
 interface StorageFilePageProps {
   onReload: () => void;
-  fileName: string;
   fileStats: FileStats;
 }
 
-const StorageFilePage = ({ fileName, fileStats, onReload }: StorageFilePageProps): JSX.Element => {
+const StorageFilePage = ({ fileStats, onReload }: StorageFilePageProps): JSX.Element => {
   const config = getLastKnownConfig();
+  const fileName = getLastDirOrFileNameFromPath(fileStats.path);
   const fileType = getFileType(fileName);
 
   const { t } = i18nReact.useTranslation();
@@ -54,11 +55,7 @@ const StorageFilePage = ({ fileName, fileStats, onReload }: StorageFilePageProps
 
   const { loading: isSaving, save } = useSaveData(SAVE_FILE_API_URL);
 
-  const {
-    data: fileData,
-    loading: loadingPreview,
-    error: errorPreview
-  } = useLoadData<FilePreview>(FILE_PREVIEW_API_URL, {
+  const { data, loading, error } = useLoadData<FilePreview>(FILE_PREVIEW_API_URL, {
     params: {
       path: fileStats.path,
       offset: pageOffset,
@@ -80,7 +77,7 @@ const StorageFilePage = ({ fileName, fileStats, onReload }: StorageFilePageProps
 
   const handleCancel = () => {
     setIsEditing(false);
-    setFileContent(fileData?.contents);
+    setFileContent(data?.contents);
   };
 
   const handleSave = () => {
@@ -126,7 +123,7 @@ const StorageFilePage = ({ fileName, fileStats, onReload }: StorageFilePageProps
 
   const errorConfig = [
     {
-      enabled: !!errorPreview,
+      enabled: !!error,
       message: t('An error occurred while fetching file content for path "{{path}}".', {
         path: fileStats.path
       }),
@@ -151,7 +148,7 @@ const StorageFilePage = ({ fileName, fileStats, onReload }: StorageFilePageProps
           ))}
         </div>
 
-        <LoadingErrorWrapper loading={loadingPreview || isSaving} errors={errorConfig}>
+        <LoadingErrorWrapper loading={loading || isSaving} errors={errorConfig} hideChildren>
           <div className="preview">
             <div className="preview__title-bar">
               {t('Content')}
@@ -171,7 +168,7 @@ const StorageFilePage = ({ fileName, fileStats, onReload }: StorageFilePageProps
                       data-testid="preview--save--button"
                       data-event=""
                       onClick={handleSave}
-                      disabled={fileContent === fileData?.contents}
+                      disabled={fileContent === data?.contents}
                     >
                       {t('Save')}
                     </PrimaryButton>

+ 1 - 1
desktop/core/src/desktop/js/reactComponents/FileChooser/FileChooserModal/FileChooserModal.tsx

@@ -104,7 +104,7 @@ const FileChooserModal: React.FC<FileProps> = ({ show, onCancel, title, okText }
                   <PathBrowser
                     filePath={filePath}
                     onFilepathChange={setFilePath}
-                    seperator={'>'}
+                    separator={'>'}
                     showIcon={true}
                   />
                 )}

+ 7 - 0
desktop/core/src/desktop/js/reactComponents/LoadingErrorWrapper/LoadingErrorWrapper.scss

@@ -22,3 +22,10 @@
   align-items: center;
   gap: 16px;
 }
+
+.antd.cuix {
+  .loading-error-wrapper__spinner {
+    // this overrides the max-height: 400px in antd library
+    max-height: 100% !important;
+  }
+}

+ 1 - 1
desktop/core/src/desktop/js/reactComponents/LoadingErrorWrapper/LoadingErrorWrapper.test.tsx

@@ -15,7 +15,7 @@ describe('LoadingErrorWrapper', () => {
       <LoadingErrorWrapper {...defaultProps} loading={true} />
     );
 
-    expect(getAllByTestId('loading-error-wrapper__sppiner')).toHaveLength(2);
+    expect(getAllByTestId('loading-error-wrapper__spinner')).toHaveLength(2);
     expect(queryByText('Children Content')).toBeInTheDocument();
   });
 

+ 9 - 7
desktop/core/src/desktop/js/reactComponents/LoadingErrorWrapper/LoadingErrorWrapper.tsx

@@ -30,21 +30,23 @@ interface LoadingErrorWrapperProps {
   loading: boolean;
   errors: WrapperError[];
   children: React.ReactNode;
+  hideChildren?: boolean;
 }
 
 const LoadingErrorWrapper = ({
   loading,
   errors,
-  children
+  children,
+  hideChildren = false
 }: LoadingErrorWrapperProps): JSX.Element => {
   if (loading) {
-    // TODO: discuss in UI meeting, if we need to render children while loading
-    // Initial thoughts:
-    // -- On first render -> hide children
-    // -- On re-render -> render children
     return (
-      <Spin spinning={loading} data-testid="loading-error-wrapper__sppiner">
-        {children}
+      <Spin
+        spinning={loading}
+        data-testid="loading-error-wrapper__spinner"
+        className="loading-error-wrapper__spinner"
+      >
+        {hideChildren === false && children}
       </Spin>
     );
   }

+ 1 - 1
desktop/core/src/desktop/js/reactComponents/PathBrowser/Breadcrumb/Breadcrumb.tsx

@@ -16,7 +16,7 @@
 
 import React from 'react';
 
-import OverflowingItem from '../OverflowingItem';
+import OverflowingItem from '../OverflowingItem/OverflowingItem';
 import './Breadcrumb.scss';
 
 interface BreadcrumbProps {

+ 0 - 0
desktop/core/src/desktop/js/reactComponents/PathBrowser/OverflowTooltip.tsx → desktop/core/src/desktop/js/reactComponents/PathBrowser/OverflowingItem/OverflowTooltip.tsx


+ 0 - 0
desktop/core/src/desktop/js/reactComponents/PathBrowser/OverflowingItem.scss → desktop/core/src/desktop/js/reactComponents/PathBrowser/OverflowingItem/OverflowingItem.scss


+ 0 - 0
desktop/core/src/desktop/js/reactComponents/PathBrowser/OverflowingItem.tsx → desktop/core/src/desktop/js/reactComponents/PathBrowser/OverflowingItem/OverflowingItem.tsx


+ 9 - 5
desktop/core/src/desktop/js/reactComponents/PathBrowser/PathBrowser.scss

@@ -25,10 +25,14 @@ $icon-height: 24px;
     display: contents;
 
     .hue-path-browser__file-system-icon {
-      object-fit: cover;
-      width: $icon-width;
-      height: $icon-height;
-      margin: 0 vars.$fluidx-spacing-xs;
+      margin-right: vars.$fluidx-spacing-xs;
+
+      svg {
+        vertical-align: middle;
+        width: $icon-width;
+        height: $icon-height;
+
+      }
     }
   }
 
@@ -55,7 +59,7 @@ $icon-height: 24px;
     }
   }
 
-  .hue-path-browser__breadcrumb-seperator {
+  .hue-path-browser__breadcrumb-separator {
     display: flex;
     justify-content: center;
     align-items: center;

+ 15 - 15
desktop/core/src/desktop/js/reactComponents/PathBrowser/PathBrowser.test.tsx

@@ -30,31 +30,31 @@ describe('Pathbrowser', () => {
   const mockFilePath = 'abfs://test/folder';
   const mockLongFilePath = 'abfs://path/to/nested1/nested2/nested3/folder';
   describe('Pathbrowser breadcrumbs', () => {
-    it('should render the specified seperator to seperate the breadcrumbs', () => {
+    it('should render the specified separator to separate the breadcrumbs', () => {
       render(
         <PathBrowser
           filePath={mockFilePath}
           onFilepathChange={onFilepathChangeMock}
-          seperator={'%'}
+          separator={'%'}
           showIcon
         />
       );
-      const seperator = screen.getAllByText('%');
-      expect(seperator).not.toBeNull();
+      const separator = screen.getAllByText('%');
+      expect(separator).not.toBeNull();
     });
 
-    it('should not render a different seperator than specified to seperate the breadcrumbs', () => {
+    it('should not render a different separator than specified to separate the breadcrumbs', () => {
       render(
         <PathBrowser
           testId="pathbroswer"
           filePath={mockFilePath}
           onFilepathChange={onFilepathChangeMock}
-          seperator={'%'}
+          separator={'%'}
           showIcon
         />
       );
       screen
-        .getAllByTestId('pathbroswer-breadcrumb-seperator')
+        .getAllByTestId('pathbroswer-breadcrumb-separator')
         .slice(1)
         .forEach(element => {
           expect(element).toBeVisible();
@@ -67,7 +67,7 @@ describe('Pathbrowser', () => {
         <PathBrowser
           filePath={mockFilePath}
           onFilepathChange={onFilepathChangeMock}
-          seperator={'/'}
+          separator={'/'}
           showIcon
         />
       );
@@ -79,7 +79,7 @@ describe('Pathbrowser', () => {
         <PathBrowser
           onFilepathChange={onFilepathChangeMock}
           filePath={mockLongFilePath}
-          seperator={'/'}
+          separator={'/'}
           showIcon
         />
       );
@@ -92,7 +92,7 @@ describe('Pathbrowser', () => {
         <PathBrowser
           onFilepathChange={onFilepathChangeMock}
           filePath={mockLongFilePath}
-          seperator={'/'}
+          separator={'/'}
           showIcon
         />
       );
@@ -109,7 +109,7 @@ describe('Pathbrowser', () => {
         <PathBrowser
           onFilepathChange={onFilepathChangeMock}
           filePath={mockFilePath}
-          seperator={'/'}
+          separator={'/'}
           showIcon={false}
         />
       );
@@ -124,7 +124,7 @@ describe('Pathbrowser', () => {
         <PathBrowser
           onFilepathChange={onFilepathChangeMock}
           filePath={mockFilePath}
-          seperator={'/'}
+          separator={'/'}
           showIcon
         />
       );
@@ -137,7 +137,7 @@ describe('Pathbrowser', () => {
         <PathBrowser
           onFilepathChange={onFilepathChangeMock}
           filePath={mockFilePath}
-          seperator={'/'}
+          separator={'/'}
           showIcon={false}
         />
       );
@@ -152,7 +152,7 @@ describe('Pathbrowser', () => {
         <PathBrowser
           onFilepathChange={onFilepathChangeMock}
           filePath={mockFilePath}
-          seperator={'/'}
+          separator={'/'}
           showIcon
         />
       );
@@ -165,7 +165,7 @@ describe('Pathbrowser', () => {
         <PathBrowser
           onFilepathChange={onFilepathChangeMock}
           filePath={mockFilePath}
-          seperator={'/'}
+          separator={'/'}
           showIcon
         />
       );

+ 24 - 22
desktop/core/src/desktop/js/reactComponents/PathBrowser/PathBrowser.tsx

@@ -29,11 +29,14 @@ import Breadcrumb from './Breadcrumb/Breadcrumb';
 import './PathBrowser.scss';
 import { getBreadcrumbs, getFileSystemAndPath, BreadcrumbData } from './PathBrowser.util';
 
+const DEFAULT_URL_SCHEMA_SEPARATOR = '://';
+const DEFAULT_PATH_SEPARATOR = '/';
+
 interface PathBrowserProps {
   filePath: string;
   onFilepathChange: (path: string) => void;
-  seperator: string;
-  showIcon: boolean;
+  separator?: string;
+  showIcon?: boolean;
   testId?: string;
 }
 
@@ -44,8 +47,8 @@ const defaultProps = {
 const PathBrowser = ({
   filePath,
   onFilepathChange,
-  seperator,
-  showIcon,
+  separator = DEFAULT_PATH_SEPARATOR,
+  showIcon = false,
   testId
 }: PathBrowserProps): JSX.Element => {
   const [isEditMode, setIsEditMode] = useState(false);
@@ -53,12 +56,11 @@ const PathBrowser = ({
   const icons = {
     hdfs: <HdfsIcon />,
     abfs: <AdlsIcon />,
-    s3: <S3Icon />
+    s3a: <S3Icon />
   };
 
   const { fileSystem, path } = getFileSystemAndPath(filePath);
   const breadcrumbs = getBreadcrumbs(fileSystem, path);
-  const URISchemeSeparator = fileSystem === 'hdfs' ? seperator : '://';
 
   const useOutsideAlerter = (ref: RefObject<HTMLDivElement>) => {
     useEffect(() => {
@@ -113,12 +115,12 @@ const PathBrowser = ({
     return (
       <div className="hue-path-browser" data-testid={`${testId}`}>
         {showIcon && (
-          <div
-            className="hue-path-browser__file-system-icon"
+          <span
             data-testid={`${testId}__file-system-icon`}
+            className="hue-path-browser__file-system-icon"
           >
             {icons[fileSystem]}
-          </div>
+          </span>
         )}
         <div className="hue-path-browser__breadcrumbs" data-testid={`${testId}-breadcrumb`}>
           {breadcrumbs.length <= 3 ? (
@@ -131,12 +133,12 @@ const PathBrowser = ({
                     url={item.url}
                     onFilepathChange={onFilepathChange}
                   />
-                  {index != breadcrumbs.length - 1 && (
+                  {(index === 0 || index != breadcrumbs.length - 1) && (
                     <div
-                      className="hue-path-browser__breadcrumb-seperator"
-                      data-testid={`${testId}-breadcrumb-seperator`}
+                      className="hue-path-browser__breadcrumb-separator"
+                      data-testid={`${testId}-breadcrumb-separator`}
                     >
-                      {index === 0 ? URISchemeSeparator : seperator}
+                      {index === 0 ? DEFAULT_URL_SCHEMA_SEPARATOR : separator}
                     </div>
                   )}
                 </React.Fragment>
@@ -151,10 +153,10 @@ const PathBrowser = ({
                 key={breadcrumbs[0].url}
               />
               <div
-                className="hue-path-browser__breadcrumb-seperator"
-                data-testid={`${testId}-breadcrumb-seperator`}
+                className="hue-path-browser__breadcrumb-separator"
+                data-testid={`${testId}-breadcrumb-separator`}
               >
-                {URISchemeSeparator}
+                {DEFAULT_URL_SCHEMA_SEPARATOR}
               </div>
               <Dropdown
                 overlayClassName="hue-path-browser__dropdown cuix antd"
@@ -175,10 +177,10 @@ const PathBrowser = ({
                 </BorderlessButton>
               </Dropdown>
               <div
-                className="hue-path-browser__breadcrumb-seperator"
-                data-testid={`${testId}-breadcrumb-seperator`}
+                className="hue-path-browser__breadcrumb-separator"
+                data-testid={`${testId}-breadcrumb-separator`}
               >
-                {seperator}
+                {separator}
               </div>
               <Breadcrumb
                 key={breadcrumbs[breadcrumbs.length - 2].url}
@@ -187,10 +189,10 @@ const PathBrowser = ({
                 onFilepathChange={onFilepathChange}
               />
               <div
-                className="hue-path-browser__breadcrumb-seperator"
-                data-testid={`${testId}-breadcrumb-seperator`}
+                className="hue-path-browser__breadcrumb-separator"
+                data-testid={`${testId}-breadcrumb-separator`}
               >
-                {seperator}
+                {separator}
               </div>
               <Breadcrumb
                 key={breadcrumbs[breadcrumbs.length - 1].url}

+ 52 - 4
desktop/core/src/desktop/js/reactComponents/PathBrowser/PathBrowser.util.test.ts

@@ -14,7 +14,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import { getBreadcrumbs, getFileSystemAndPath } from './PathBrowser.util';
+import {
+  getBreadcrumbs,
+  getLastDirOrFileNameFromPath,
+  getFileSystemAndPath
+} from './PathBrowser.util';
 
 describe('PathBrowser utils', () => {
   describe('getFileSystemAndPath', () => {
@@ -65,7 +69,7 @@ describe('PathBrowser utils', () => {
       const result = getBreadcrumbs('hdfs', hdfsPath);
 
       expect(result).toEqual([
-        { url: '/', label: '/' },
+        { url: '/', label: 'hdfs' },
         { url: '/test', label: 'test' },
         { url: '/test/folder', label: 'folder' }
       ]);
@@ -87,7 +91,7 @@ describe('PathBrowser utils', () => {
       const result = getBreadcrumbs('hdfs', pathWithTrailingSlash);
 
       expect(result).toEqual([
-        { url: '/', label: '/' },
+        { url: '/', label: 'hdfs' },
         { url: '/folder', label: 'folder' },
         { url: '/folder/with', label: 'with' },
         { url: '/folder/with/trailing', label: 'trailing' },
@@ -100,7 +104,7 @@ describe('PathBrowser utils', () => {
       const result = getBreadcrumbs('hdfs', pathWithLeadingSlash);
 
       expect(result).toEqual([
-        { url: '/', label: '/' },
+        { url: '/', label: 'hdfs' },
         { url: '/path', label: 'path' },
         { url: '/path/to', label: 'to' },
         { url: '/path/to/file', label: 'file' }
@@ -129,4 +133,48 @@ describe('PathBrowser utils', () => {
       ]);
     });
   });
+
+  describe('getLastDirOrFileNameFromPath', () => {
+    it('should return the correct fileName for a valid path', () => {
+      const path = '/user/documents/file.txt';
+      const result = getLastDirOrFileNameFromPath(path);
+      expect(result).toBe('file.txt');
+    });
+
+    it('should return the correct fileName for a valid path with double file extension', () => {
+      const path = '/user/documents/file.tar.gz';
+      const result = getLastDirOrFileNameFromPath(path);
+      expect(result).toBe('file.tar.gz');
+    });
+
+    it('should return an correct fileName for a path ending with a slash', () => {
+      const path = '/user/documents/file.txt/';
+      const result = getLastDirOrFileNameFromPath(path);
+      expect(result).toBe('file.txt');
+    });
+
+    it('should return correct directoryName for S3A path', () => {
+      const path = 's3a://example/hue/';
+      const result = getLastDirOrFileNameFromPath(path);
+      expect(result).toBe('hue');
+    });
+
+    it('should return correct directoryName when path is root S3A', () => {
+      const path = 's3a://';
+      const result = getLastDirOrFileNameFromPath(path);
+      expect(result).toBe('s3a');
+    });
+
+    it('should return correct directoryName when path is root HDFS', () => {
+      const path = '/';
+      const result = getLastDirOrFileNameFromPath(path);
+      expect(result).toBe('hdfs');
+    });
+
+    it('should return empty string when path is empty string', () => {
+      const path = '';
+      const result = getLastDirOrFileNameFromPath(path);
+      expect(result).toBe('');
+    });
+  });
 });

+ 10 - 1
desktop/core/src/desktop/js/reactComponents/PathBrowser/PathBrowser.util.ts

@@ -47,7 +47,7 @@ export const getFileSystemAndPath = (
 export const getBreadcrumbs = (fileSystem: string, path: string): BreadcrumbData[] => {
   const pathParts = path.split('/').filter(Boolean);
   const rootUrl = fileSystem === 'hdfs' ? '/' : `${fileSystem}://`;
-  const rootlabel = fileSystem === 'hdfs' ? '/' : fileSystem;
+  const rootlabel = fileSystem === 'hdfs' ? 'hdfs' : fileSystem;
   const rootNode = {
     url: rootUrl,
     label: rootlabel
@@ -62,3 +62,12 @@ export const getBreadcrumbs = (fileSystem: string, path: string): BreadcrumbData
     [rootNode]
   );
 };
+
+export const getLastDirOrFileNameFromPath = (inputPath: string): string => {
+  if (inputPath === '') {
+    return inputPath;
+  }
+  const { fileSystem, path } = getFileSystemAndPath(inputPath);
+  const sanitizedPath = path.endsWith('/') ? path.slice(0, -1) : path;
+  return sanitizedPath.split('/').pop() || fileSystem;
+};

+ 3 - 3
desktop/core/src/desktop/js/utils/storageBrowserUtils.ts

@@ -17,7 +17,7 @@
 const fileSysteRoot = {
   hdfs: ['/', 'hdfs'],
   ofs: ['ofs://'],
-  s3: ['s3a://'],
+  s3a: ['s3a://'],
   gs: ['gs://'],
   abfs: ['abfs://']
 };
@@ -41,7 +41,7 @@ export const isOFS = (path: string): boolean => {
 };
 
 export const isS3 = (path: string): boolean => {
-  return checkFileSystem(path, fileSysteRoot.s3);
+  return checkFileSystem(path, fileSysteRoot.s3a);
 };
 
 export const isGS = (path: string): boolean => {
@@ -53,7 +53,7 @@ export const isABFS = (path: string): boolean => {
 };
 
 export const isS3Root = (path: string): boolean => {
-  return checkFileSystemRoot(path, fileSysteRoot.s3);
+  return checkFileSystemRoot(path, fileSysteRoot.s3a);
 };
 
 export const isGSRoot = (path: string): boolean => {