[arvados-workbench2] created: 2.4.0-117-gf0f1a84d

git repository hosting git at public.arvados.org
Tue May 31 12:31:50 UTC 2022


        at  f0f1a84dcd35f11214f0c534f8490f6a4f648b48 (commit)


commit f0f1a84dcd35f11214f0c534f8490f6a4f648b48
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Tue May 31 09:28:30 2022 -0300

    18787: Removes debugging console logging messages.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/src/components/collection-panel-files/collection-panel-files.tsx b/src/components/collection-panel-files/collection-panel-files.tsx
index 4aa26560..42408270 100644
--- a/src/components/collection-panel-files/collection-panel-files.tsx
+++ b/src/components/collection-panel-files/collection-panel-files.tsx
@@ -39,7 +39,6 @@ import { setCollectionFiles } from 'store/collection-panel/collection-panel-file
 import { sortBy } from 'lodash';
 import { formatFileSize } from 'common/formatters';
 import { getInlineFileUrl, sanitizeToken } from 'views-components/context-menu/actions/helpers';
-import _ from 'lodash';
 
 export interface CollectionPanelFilesProps {
     isWritable: boolean;
@@ -213,25 +212,11 @@ const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
 
 const pathPromise = {};
 
-let prevState = {};
-function difference(object, base) {
-	function changes(object, base) {
-		return _.transform(object, function(result, value, key) {
-			if (!_.isEqual(value, base[key])) {
-				result[key] = (_.isObject(value) && _.isObject(base[key])) ? changes(value, base[key]) : value;
-			}
-		});
-	}
-	return changes(object, base);
-}
 export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState) => ({
     auth: state.auth,
     collectionPanel: state.collectionPanel,
     collectionPanelFiles: state.collectionPanelFiles,
 }))((props: CollectionPanelFilesProps & WithStyles<CssRules> & { auth: AuthState }) => {
-    const diff = difference(props, prevState);
-    prevState = props;
-    console.log('---> render CollectionPanelFiles <------', diff);
     const { classes, onItemMenuOpen, onUploadDataClick, isWritable, dispatch, collectionPanelFiles, collectionPanel } = props;
     const { apiToken, config } = props.auth;
 
@@ -262,14 +247,12 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
 
     React.useEffect(() => {
         if (props.currentItemUuid) {
-            console.log(' --> useEffect current UUID: ', props.currentItemUuid);
             setPathData({});
             setPath([props.currentItemUuid]);
         }
     }, [props.currentItemUuid]);
 
     const fetchData = (keys, ignoreCache = false) => {
-        console.log('---> fetchData', keys);
         const keyArray = Array.isArray(keys) ? keys : [keys];
 
         Promise.all(keyArray.filter(key => !!key)
@@ -284,7 +267,6 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
 
                     pathPromise[key] = true;
 
-                    console.log('>>> fetching data for key', key);
                     return webdavClient.propfind(`c=${key}`, webDAVRequestConfig);
                 }
 
@@ -295,7 +277,6 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
         .then((requests) => {
             const newState = requests.map((request, index) => {
                 if (request && request.responseXML != null) {
-                    console.log(">>> got data for key", keyArray[index]);
                     const key = keyArray[index];
                     const result: any = extractFilesData(request.responseXML);
                     const sortedResult = sortBy(result, (n) => n.name).sort((n1, n2) => {
@@ -325,7 +306,6 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
 
     React.useEffect(() => {
         if (rightKey) {
-            console.log('---> useEffect rightKey:', rightKey);
             fetchData(rightKey);
             setLeftSearch('');
             setRightSearch('');
@@ -335,7 +315,6 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
     const currentPDH = (collectionPanel.item || {}).portableDataHash;
     React.useEffect(() => {
         if (currentPDH) {
-            console.log('---> useEffect PDH change:', currentPDH);
             // Avoid fetching the same content level twice
             if (leftKey !== rightKey) {
                 fetchData([leftKey, rightKey], true);
@@ -347,7 +326,6 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
 
     React.useEffect(() => {
         if (rightData) {
-            console.log('---> useEffect rightData:', rightData, 'search:', rightSearch);
             const filtered = rightData.filter(({ name }) => name.indexOf(rightSearch) > -1);
             setCollectionFiles(filtered, false)(dispatch);
         }
@@ -383,7 +361,6 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
         let node = null;
 
         if (parentRef?.current) {
-            console.log('---> useEffect parentRef:', parentRef);
             node = parentRef.current;
             (node as any).addEventListener('contextmenu', handleRightClick);
         }
@@ -516,7 +493,6 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                     return !!filtered.length
                     ? <FixedSizeList height={height} itemCount={filtered.length}
                         itemSize={35} width={width}>{ ({ index, style }) => {
-                        console.log("Left Data ROW: ", filtered[index]);
                         const { id, type, name } = filtered[index];
                         return <div data-id={id} style={style} data-item="true"
                             data-type={type} data-parent-path={name}
@@ -555,11 +531,9 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                 <div className={classes.dataWrapper}>{ rightData && !isLoading
                     ? <AutoSizer defaultHeight={500}>{({ height, width }) => {
                         const filtered = rightData.filter(({ name }) => name.indexOf(rightSearch) > -1);
-                        console.log("Right Data: ", filtered);
                         return !!filtered.length
                         ? <FixedSizeList height={height} itemCount={filtered.length}
                             itemSize={35} width={width}>{ ({ index, style }) => {
-                                console.log("Right Data ROW: ", filtered[index]);
                                 const { id, type, name, size } = filtered[index];
 
                                 return <div style={style} data-id={id} data-item="true"

commit 05010c44073b52c0e414d180cfc21bae215c4d33
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Tue May 31 09:19:10 2022 -0300

    18787: Avoids re-rendering by only dispatching SET_COLLECTIONS when needed.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/src/store/collection-panel/collection-panel-action.ts b/src/store/collection-panel/collection-panel-action.ts
index 890a7441..7bab8632 100644
--- a/src/store/collection-panel/collection-panel-action.ts
+++ b/src/store/collection-panel/collection-panel-action.ts
@@ -22,12 +22,15 @@ export type CollectionPanelAction = UnionOf<typeof collectionPanelActions>;
 export const loadCollectionPanel = (uuid: string, forceReload = false) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
         const { collectionPanel: { item } } = getState();
-        const collection = (item && item.uuid === uuid && !forceReload)
-            ? item
-            : await services.collectionService.get(uuid);
+        let collection: CollectionResource | null = null;
+        if (!item || item.uuid !== uuid || forceReload) {
+            collection = await services.collectionService.get(uuid);
+            dispatch(collectionPanelActions.SET_COLLECTION(collection));
+            dispatch(resourcesActions.SET_RESOURCES([collection]));
+        } else {
+            collection = item;
+        }
         dispatch<any>(loadDetailsPanel(collection.uuid));
-        dispatch(collectionPanelActions.SET_COLLECTION(collection));
-        dispatch(resourcesActions.SET_RESOURCES([collection]));
         return collection;
     };
 
diff --git a/src/store/workbench/workbench-actions.ts b/src/store/workbench/workbench-actions.ts
index 3142b633..0a348431 100644
--- a/src/store/workbench/workbench-actions.ts
+++ b/src/store/workbench/workbench-actions.ts
@@ -295,7 +295,7 @@ export const loadCollection = (uuid: string) =>
             if (userUuid) {
                 const match = await loadGroupContentsResource({ uuid, userUuid, services });
                 match({
-                    OWNED: async collection => {
+                    OWNED: collection => {
                         dispatch(collectionPanelActions.SET_COLLECTION(collection as CollectionResource));
                         dispatch(updateResources([collection]));
                         dispatch(activateSidePanelTreeItem(collection.ownerUuid));

commit bc0466c49bb8adab2f162d05c83fb30ed005bd6d
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Mon May 30 15:49:14 2022 -0300

    18787: Fixes test.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/src/components/collection-panel-files/collection-panel-files.tsx b/src/components/collection-panel-files/collection-panel-files.tsx
index ee71e903..4aa26560 100644
--- a/src/components/collection-panel-files/collection-panel-files.tsx
+++ b/src/components/collection-panel-files/collection-panel-files.tsx
@@ -248,8 +248,8 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
     };
 
     const parentRef = React.useRef(null);
-    const [path, setPath]: any = React.useState([]);
-    const [pathData, setPathData]: any = React.useState({});
+    const [path, setPath] = React.useState<string[]>([]);
+    const [pathData, setPathData] = React.useState({});
     const [isLoading, setIsLoading] = React.useState(false);
     const [leftSearch, setLeftSearch] = React.useState('');
     const [rightSearch, setRightSearch] = React.useState('');
@@ -277,7 +277,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                 const dataExists = !!pathData[key];
                 const runningRequest = pathPromise[key];
 
-                if ((!dataExists || ignoreCache) && (!runningRequest || ignoreCache)) {
+                if (ignoreCache || (!dataExists && !runningRequest)) {
                     if (!isLoading) {
                         setIsLoading(true);
                     }
@@ -377,13 +377,12 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                 onItemMenuOpen(event, item, isWritable);
             }
         },
-        [onItemMenuOpen, isWritable, rightData] // eslint-disable-line react-hooks/exhaustive-deps
-    );
+        [onItemMenuOpen, isWritable, rightData]);
 
     React.useEffect(() => {
         let node = null;
 
-        if (parentRef && parentRef.current) {
+        if (parentRef?.current) {
             console.log('---> useEffect parentRef:', parentRef);
             node = parentRef.current;
             (node as any).addEventListener('contextmenu', handleRightClick);
@@ -502,7 +501,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
             </Tooltip>
         </div>
         <div className={classes.wrapper}>
-            <div className={classNames(classes.leftPanel, path.length > 1 ? classes.leftPanelVisible : classes.leftPanelHidden)}  data-cy="collection-files-left-panel">
+            <div className={classNames(classes.leftPanel, path.length > 1 ? classes.leftPanelVisible : classes.leftPanelHidden)} data-cy="collection-files-left-panel">
                 <Tooltip title="Go back" className={path.length > 1 ? classes.backButton : classes.backButtonHidden}>
                     <IconButton onClick={() => setPath([...path.slice(0, path.length -1)])}>
                         <BackIcon />
@@ -540,7 +539,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                 : <div className={classes.row}><CircularProgress className={classes.loader} size={30} /></div> }
                 </div>
             </div>
-            <div className={classes.rightPanel}>
+            <div className={classes.rightPanel} data-cy="collection-files-right-panel">
                 <div className={classes.searchWrapper}>
                     <SearchInput selfClearProp={rightKey} label="Search" value={rightSearch} onSearch={setRightSearch} />
                 </div>

commit b3b92e78c7da8fc6a2f4db78746cbc10bb11cc86
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Mon May 30 13:24:57 2022 -0300

    18787: Removes unnecessary prop mapping code.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/src/components/collection-panel-files/collection-panel-files.tsx b/src/components/collection-panel-files/collection-panel-files.tsx
index 395b4f14..ee71e903 100644
--- a/src/components/collection-panel-files/collection-panel-files.tsx
+++ b/src/components/collection-panel-files/collection-panel-files.tsx
@@ -42,7 +42,6 @@ import { getInlineFileUrl, sanitizeToken } from 'views-components/context-menu/a
 import _ from 'lodash';
 
 export interface CollectionPanelFilesProps {
-    items: any;
     isWritable: boolean;
     onUploadDataClick: (targetLocation?: string) => void;
     onSearchChange: (searchValue: string) => void;
@@ -232,7 +231,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
 }))((props: CollectionPanelFilesProps & WithStyles<CssRules> & { auth: AuthState }) => {
     const diff = difference(props, prevState);
     prevState = props;
-    console.log('---> render CollectionPanel <------', diff);
+    console.log('---> render CollectionPanelFiles <------', diff);
     const { classes, onItemMenuOpen, onUploadDataClick, isWritable, dispatch, collectionPanelFiles, collectionPanel } = props;
     const { apiToken, config } = props.auth;
 
diff --git a/src/views-components/collection-panel-files/collection-panel-files.ts b/src/views-components/collection-panel-files/collection-panel-files.ts
index 216ec669..a26b9fe3 100644
--- a/src/views-components/collection-panel-files/collection-panel-files.ts
+++ b/src/views-components/collection-panel-files/collection-panel-files.ts
@@ -8,41 +8,17 @@ import {
     CollectionPanelFilesProps
 } from "components/collection-panel-files/collection-panel-files";
 import { RootState } from "store/store";
-import { TreeItemStatus } from "components/tree/tree";
-import { VirtualTreeItem as TreeItem } from "components/tree/virtual-tree";
-import {
-    CollectionPanelDirectory,
-    CollectionPanelFile,
-    CollectionPanelFilesState
-} from "store/collection-panel/collection-panel-files/collection-panel-files-state";
-import { FileTreeData } from "components/file-tree/file-tree-data";
 import { Dispatch } from "redux";
 import { collectionPanelFilesAction } from "store/collection-panel/collection-panel-files/collection-panel-files-actions";
 import { ContextMenuKind } from "../context-menu/context-menu";
-import { getNode, getNodeChildrenIds, Tree, TreeNode, initTreeNode } from "models/tree";
-import { CollectionFileType, createCollectionDirectory } from "models/collection-file";
 import { openContextMenu, openCollectionFilesContextMenu } from 'store/context-menu/context-menu-actions';
 import { openUploadCollectionFilesDialog } from 'store/collections/collection-upload-actions';
 import { ResourceKind } from "models/resource";
 import { openDetailsPanel } from 'store/details-panel/details-panel-action';
 
-const memoizedMapStateToProps = () => {
-    let prevState: CollectionPanelFilesState;
-    let prevTree: Array<TreeItem<FileTreeData>>;
-
-    return (state: RootState): Pick<CollectionPanelFilesProps, "items" | "currentItemUuid"> => {
-        if (prevState !== state.collectionPanelFiles) {
-            prevState = state.collectionPanelFiles;
-            prevTree = [].concat.apply(
-                [], getNodeChildrenIds('')(state.collectionPanelFiles)
-                    .map(collectionItemToList(0)(state.collectionPanelFiles)));
-        }
-        return {
-            items: prevTree,
-            currentItemUuid: state.detailsPanel.resourceUuid
-        };
-    };
-};
+const mapStateToProps = (state: RootState): Pick<CollectionPanelFilesProps, "currentItemUuid"> => ({
+    currentItemUuid: state.detailsPanel.resourceUuid
+});
 
 const mapDispatchToProps = (dispatch: Dispatch): Pick<CollectionPanelFilesProps, 'onSearchChange' | 'onFileClick' | 'onUploadDataClick' | 'onCollapseToggle' | 'onSelectionToggle' | 'onItemMenuOpen' | 'onOptionsMenuOpen'> => ({
     onUploadDataClick: (targetLocation?: string) => {
@@ -84,43 +60,4 @@ const mapDispatchToProps = (dispatch: Dispatch): Pick<CollectionPanelFilesProps,
     },
 });
 
-export const CollectionPanelFiles = connect(memoizedMapStateToProps(), mapDispatchToProps)(Component);
-
-const collectionItemToList = (level: number) => (tree: Tree<CollectionPanelDirectory | CollectionPanelFile>) =>
-    (id: string): TreeItem<FileTreeData>[] => {
-        const node: TreeNode<CollectionPanelDirectory | CollectionPanelFile> = getNode(id)(tree) || initTreeNode({
-            id: '',
-            parent: '',
-            value: {
-                ...createCollectionDirectory({ name: 'Invalid file' }),
-                selected: false,
-                collapsed: true
-            }
-        });
-
-        const treeItem = {
-            active: false,
-            data: {
-                name: node.value.name,
-                size: node.value.type === CollectionFileType.FILE ? node.value.size : undefined,
-                type: node.value.type,
-                url: node.value.url,
-            },
-            id: node.id,
-            items: [], // Not used in this case as we're converting a tree to a list.
-            itemCount: node.children.length,
-            open: node.value.type === CollectionFileType.DIRECTORY ? !node.value.collapsed : false,
-            selected: node.value.selected,
-            status: TreeItemStatus.LOADED,
-            level,
-        };
-
-        const treeItemChilds = treeItem.open
-            ? [].concat.apply([], node.children.map(collectionItemToList(level+1)(tree)))
-            : [];
-
-        return [
-            treeItem,
-            ...treeItemChilds,
-        ];
-    };
+export const CollectionPanelFiles = connect(mapStateToProps, mapDispatchToProps)(Component);

commit f1e1967ba28a81ff43b7229dbee27dd5e0ba6c13
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Mon May 30 13:06:21 2022 -0300

    18787: Removes unnecessary action.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/src/store/collection-panel/collection-panel-action.ts b/src/store/collection-panel/collection-panel-action.ts
index 55eb5949..890a7441 100644
--- a/src/store/collection-panel/collection-panel-action.ts
+++ b/src/store/collection-panel/collection-panel-action.ts
@@ -15,7 +15,6 @@ import { loadDetailsPanel } from 'store/details-panel/details-panel-action';
 
 export const collectionPanelActions = unionize({
     SET_COLLECTION: ofType<CollectionResource>(),
-    LOAD_COLLECTION_SUCCESS: ofType<{ item: CollectionResource }>(),
 });
 
 export type CollectionPanelAction = UnionOf<typeof collectionPanelActions>;
@@ -27,7 +26,7 @@ export const loadCollectionPanel = (uuid: string, forceReload = false) =>
             ? item
             : await services.collectionService.get(uuid);
         dispatch<any>(loadDetailsPanel(collection.uuid));
-        dispatch(collectionPanelActions.LOAD_COLLECTION_SUCCESS({ item: collection }));
+        dispatch(collectionPanelActions.SET_COLLECTION(collection));
         dispatch(resourcesActions.SET_RESOURCES([collection]));
         return collection;
     };
diff --git a/src/store/collection-panel/collection-panel-reducer.ts b/src/store/collection-panel/collection-panel-reducer.ts
index b9713f5d..6afba66c 100644
--- a/src/store/collection-panel/collection-panel-reducer.ts
+++ b/src/store/collection-panel/collection-panel-reducer.ts
@@ -20,5 +20,4 @@ export const collectionPanelReducer = (state: CollectionPanelState = initialStat
              ...state,
              item,
         }),
-        LOAD_COLLECTION_SUCCESS: ({ item }) => ({ ...state, item }),
     });
diff --git a/src/store/collections/collection-update-actions.ts b/src/store/collections/collection-update-actions.ts
index 82418d27..bf9c6449 100644
--- a/src/store/collections/collection-update-actions.ts
+++ b/src/store/collections/collection-update-actions.ts
@@ -55,7 +55,7 @@ export const updateCollection = (collection: CollectionUpdateFormDialogData) =>
             properties: collection.properties }
         ).then(updatedCollection => {
             updatedCollection = {...cachedCollection, ...updatedCollection};
-            dispatch(collectionPanelActions.LOAD_COLLECTION_SUCCESS({ item: updatedCollection as CollectionResource }));
+            dispatch(collectionPanelActions.SET_COLLECTION(updatedCollection));
             dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_UPDATE_FORM_NAME }));
             dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_UPDATE_FORM_NAME));
             dispatch(snackbarActions.OPEN_SNACKBAR({

commit d892b953431e67c2c8df25c4387f2111b88b820f
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Mon May 30 10:40:19 2022 -0300

    18787: Further improves code readability.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/src/components/collection-panel-files/collection-panel-files.tsx b/src/components/collection-panel-files/collection-panel-files.tsx
index 74bfca65..395b4f14 100644
--- a/src/components/collection-panel-files/collection-panel-files.tsx
+++ b/src/components/collection-panel-files/collection-panel-files.tsx
@@ -10,14 +10,31 @@ import AutoSizer from "react-virtualized-auto-sizer";
 import servicesProvider from 'common/service-provider';
 import { CustomizeTableIcon, DownloadIcon } from 'components/icon/icon';
 import { SearchInput } from 'components/search-input/search-input';
-import { ListItemIcon, StyleRulesCallback, Theme, WithStyles, withStyles, Tooltip, IconButton, Checkbox, CircularProgress, Button, Typography } from '@material-ui/core';
+import {
+    ListItemIcon,
+    StyleRulesCallback,
+    Theme,
+    WithStyles,
+    withStyles,
+    Tooltip,
+    IconButton,
+    Checkbox,
+    CircularProgress,
+    Button,
+} from '@material-ui/core';
 import { FileTreeData } from '../file-tree/file-tree-data';
 import { TreeItem, TreeItemStatus } from '../tree/tree';
 import { RootState } from 'store/store';
 import { WebDAV, WebDAVRequestConfig } from 'common/webdav';
 import { AuthState } from 'store/auth/auth-reducer';
 import { extractFilesData } from 'services/collection-service/collection-service-files-response';
-import { DefaultIcon, DirectoryIcon, FileIcon, BackIcon, SidePanelRightArrowIcon } from 'components/icon/icon';
+import {
+    DefaultIcon,
+    DirectoryIcon,
+    FileIcon,
+    BackIcon,
+    SidePanelRightArrowIcon
+} from 'components/icon/icon';
 import { setCollectionFiles } from 'store/collection-panel/collection-panel-files/collection-panel-files-actions';
 import { sortBy } from 'lodash';
 import { formatFileSize } from 'common/formatters';
@@ -40,7 +57,29 @@ export interface CollectionPanelFilesProps {
     collectionPanel: any;
 }
 
-type CssRules = "backButton" | "backButtonHidden" | "pathPanelPathWrapper" | "uploadButton" | "uploadIcon" | "loader" | "wrapper" | "dataWrapper" | "row" | "rowEmpty" | "leftPanel" | "rightPanel" | "pathPanel" | "pathPanelItem" | "rowName" | "listItemIcon" | "rowActive" | "pathPanelMenu" | "rowSelection" | "leftPanelHidden" | "leftPanelVisible" | "searchWrapper" | "searchWrapperHidden";
+type CssRules = "backButton"
+    | "backButtonHidden"
+    | "pathPanelPathWrapper"
+    | "uploadButton"
+    | "uploadIcon"
+    | "loader"
+    | "wrapper"
+    | "dataWrapper"
+    | "row"
+    | "rowEmpty"
+    | "leftPanel"
+    | "rightPanel"
+    | "pathPanel"
+    | "pathPanelItem"
+    | "rowName"
+    | "listItemIcon"
+    | "rowActive"
+    | "pathPanelMenu"
+    | "rowSelection"
+    | "leftPanelHidden"
+    | "leftPanelVisible"
+    | "searchWrapper"
+    | "searchWrapperHidden";
 
 const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
     wrapper: {
@@ -447,18 +486,15 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
     return <div data-cy="collection-files-panel" onClick={handleClick} ref={parentRef}>
         <div className={classes.pathPanel}>
             <div className={classes.pathPanelPathWrapper}>
-                { path.map((p: string, index: number) => <span
-                    key={`${index}-${p}`}
-                    data-item="true"
-                    className={classes.pathPanelItem}
-                    data-breadcrumb-path={p}
-                >
+            { path.map( (p: string, index: number) =>
+                <span key={`${index}-${p}`} data-item="true"
+                className={classes.pathPanelItem} data-breadcrumb-path={p}>
                     <span className={classes.rowActive}>{index === 0 ? 'Home' : p}</span> <b>/</b> 
-                </span>) }
+                </span>)
+            }
             </div>
             <Tooltip className={classes.pathPanelMenu} title="More options" disableFocusListener>
-                <IconButton
-                    data-cy='collection-files-panel-options-btn'
+                <IconButton data-cy='collection-files-panel-options-btn'
                     onClick={(ev) => {
                         onOptionsMenuOpen(ev, isWritable);
                     }}>
@@ -466,60 +502,45 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                 </IconButton>
             </Tooltip>
         </div>
-            <div className={classes.wrapper}>
-                <div className={classNames(classes.leftPanel, path.length > 1 ? classes.leftPanelVisible : classes.leftPanelHidden)}  data-cy="collection-files-left-panel">
-                    <Tooltip title="Go back" className={path.length > 1 ? classes.backButton : classes.backButtonHidden}>
-                        <IconButton onClick={() => setPath([...path.slice(0, path.length -1)])}>
-                            <BackIcon />
-                        </IconButton>
-                    </Tooltip>
-                    <div className={path.length > 1 ? classes.searchWrapper : classes.searchWrapperHidden}>
-                        <SearchInput selfClearProp={leftKey} label="Search" value={leftSearch} onSearch={setLeftSearch} />
-                    </div>
-                    <div className={classes.dataWrapper}>
-                        {
-                            leftData ?
-                                <AutoSizer defaultWidth={0}>
-                                    {({ height, width }) => {
-                                        const filtered = leftData.filter(({ name }) => name.indexOf(leftSearch) > -1);
-
-                                        return !!filtered.length ? <FixedSizeList
-                                            height={height}
-                                            itemCount={filtered.length}
-                                            itemSize={35}
-                                            width={width}
-                                        >
-                                            {
-                                                ({ index, style }) => {
-                                                    console.log("Left Data ROW: ", filtered[index]);
-                                                    const { id, type, name } = filtered[index];
-
-                                                    return <div
-                                                        data-id={id}
-                                                        style={style}
-                                                        data-item="true"
-                                                        data-type={type}
-                                                        data-parent-path={name}
-                                                        className={classNames(classes.row, getActiveClass(name))}
-                                                        key={id}>
-                                                            {getItemIcon(type, getActiveClass(name))}
-                                                            <div className={classes.rowName}>
-                                                                {name}
-                                                            </div>
-                                                            {
-                                                                getActiveClass(name) ? <SidePanelRightArrowIcon
-                                                                    style={{ display: 'inline', marginTop: '5px', marginLeft: '5px' }} /> : null
-                                                            }
-                                                    </div>;
-                                                }
-                                            }
-                                        </FixedSizeList> : <div className={classes.rowEmpty}>No directories available</div>
-                                    }}
-                                </AutoSizer> : <div className={classes.row}><CircularProgress className={classes.loader} size={30} /></div>
-                        }
-
-                    </div>
+        <div className={classes.wrapper}>
+            <div className={classNames(classes.leftPanel, path.length > 1 ? classes.leftPanelVisible : classes.leftPanelHidden)}  data-cy="collection-files-left-panel">
+                <Tooltip title="Go back" className={path.length > 1 ? classes.backButton : classes.backButtonHidden}>
+                    <IconButton onClick={() => setPath([...path.slice(0, path.length -1)])}>
+                        <BackIcon />
+                    </IconButton>
+                </Tooltip>
+                <div className={path.length > 1 ? classes.searchWrapper : classes.searchWrapperHidden}>
+                    <SearchInput selfClearProp={leftKey} label="Search" value={leftSearch} onSearch={setLeftSearch} />
+                </div>
+                <div className={classes.dataWrapper}>{ leftData
+                ? <AutoSizer defaultWidth={0}>{({ height, width }) => {
+                    const filtered = leftData.filter(({ name }) => name.indexOf(leftSearch) > -1);
+                    return !!filtered.length
+                    ? <FixedSizeList height={height} itemCount={filtered.length}
+                        itemSize={35} width={width}>{ ({ index, style }) => {
+                        console.log("Left Data ROW: ", filtered[index]);
+                        const { id, type, name } = filtered[index];
+                        return <div data-id={id} style={style} data-item="true"
+                            data-type={type} data-parent-path={name}
+                            className={classNames(classes.row, getActiveClass(name))}
+                            key={id}>
+                                { getItemIcon(type, getActiveClass(name)) }
+                                <div className={classes.rowName}>
+                                    {name}
+                                </div>
+                                { getActiveClass(name)
+                                ? <SidePanelRightArrowIcon
+                                    style={{ display: 'inline', marginTop: '5px', marginLeft: '5px' }} />
+                                : null
+                                }
+                        </div>;
+                    }}</FixedSizeList>
+                    : <div className={classes.rowEmpty}>No directories available</div>
+                    }}
+                </AutoSizer>
+                : <div className={classes.row}><CircularProgress className={classes.loader} size={30} /></div> }
                 </div>
+            </div>
             <div className={classes.rightPanel}>
                 <div className={classes.searchWrapper}>
                     <SearchInput selfClearProp={rightKey} label="Search" value={rightSearch} onSearch={setRightSearch} />
@@ -537,7 +558,6 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                     ? <AutoSizer defaultHeight={500}>{({ height, width }) => {
                         const filtered = rightData.filter(({ name }) => name.indexOf(rightSearch) > -1);
                         console.log("Right Data: ", filtered);
-
                         return !!filtered.length
                         ? <FixedSizeList height={height} itemCount={filtered.length}
                             itemSize={35} width={width}>{ ({ index, style }) => {
diff --git a/src/store/workflow-panel/workflow-panel-actions.ts b/src/store/workflow-panel/workflow-panel-actions.ts
index 7c90fa6b..912f7630 100644
--- a/src/store/workflow-panel/workflow-panel-actions.ts
+++ b/src/store/workflow-panel/workflow-panel-actions.ts
@@ -9,13 +9,18 @@ import { bindDataExplorerActions } from 'store/data-explorer/data-explorer-actio
 import { propertiesActions } from 'store/properties/properties-actions';
 import { getProperty } from 'store/properties/properties';
 import { navigateToRunProcess } from 'store/navigation/navigation-action';
-import { goToStep, runProcessPanelActions, loadPresets, getWorkflowRunnerSettings } from 'store/run-process-panel/run-process-panel-actions';
+import {
+    goToStep,
+    runProcessPanelActions,
+    loadPresets,
+    getWorkflowRunnerSettings
+} from 'store/run-process-panel/run-process-panel-actions';
 import { snackbarActions } from 'store/snackbar/snackbar-actions';
 import { initialize } from 'redux-form';
 import { RUN_PROCESS_BASIC_FORM } from 'views/run-process-panel/run-process-basic-form';
 import { RUN_PROCESS_INPUTS_FORM } from 'views/run-process-panel/run-process-inputs-form';
 import { RUN_PROCESS_ADVANCED_FORM } from 'views/run-process-panel/run-process-advanced-form';
-import { getResource, ResourcesState } from 'store/resources/resources';
+import { getResource } from 'store/resources/resources';
 import { ProjectResource } from 'models/project';
 import { UserResource } from 'models/user';
 import { getUserUuid } from "common/getuser";
diff --git a/src/views-components/details-panel/workflow-details.tsx b/src/views-components/details-panel/workflow-details.tsx
index 4c4bd2de..98978dd2 100644
--- a/src/views-components/details-panel/workflow-details.tsx
+++ b/src/views-components/details-panel/workflow-details.tsx
@@ -3,10 +3,9 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import React from 'react';
-import { DefaultIcon, WorkflowIcon } from 'components/icon/icon';
+import { WorkflowIcon } from 'components/icon/icon';
 import { WorkflowResource } from 'models/workflow';
 import { DetailsData } from "./details-data";
-import { DefaultView } from 'components/default-view/default-view';
 import { DetailsAttribute } from 'components/details-attribute/details-attribute';
 import { ResourceWithName } from 'views-components/data-explorer/renderers';
 import { formatDate } from "common/formatters";

commit ed5eba6574a98f8acfe4f1fc0c063b9347b656c1
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Mon May 30 10:15:13 2022 -0300

    18787: Fixes rebasing issues.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/src/components/collection-panel-files/collection-panel-files.tsx b/src/components/collection-panel-files/collection-panel-files.tsx
index 0fa06682..74bfca65 100644
--- a/src/components/collection-panel-files/collection-panel-files.tsx
+++ b/src/components/collection-panel-files/collection-panel-files.tsx
@@ -10,7 +10,7 @@ import AutoSizer from "react-virtualized-auto-sizer";
 import servicesProvider from 'common/service-provider';
 import { CustomizeTableIcon, DownloadIcon } from 'components/icon/icon';
 import { SearchInput } from 'components/search-input/search-input';
-import { ListItemIcon, StyleRulesCallback, Theme, WithStyles, withStyles, Tooltip, IconButton, Checkbox, CircularProgress, Button } from '@material-ui/core';
+import { ListItemIcon, StyleRulesCallback, Theme, WithStyles, withStyles, Tooltip, IconButton, Checkbox, CircularProgress, Button, Typography } from '@material-ui/core';
 import { FileTreeData } from '../file-tree/file-tree-data';
 import { TreeItem, TreeItemStatus } from '../tree/tree';
 import { RootState } from 'store/store';
@@ -466,14 +466,6 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                 </IconButton>
             </Tooltip>
         </div>
-        <div className={classes.wrapper}>
-            <div className={classNames(classes.leftPanel, path.length > 1 ? classes.leftPanelVisible : classes.leftPanelHidden)}  data-cy="collection-files-left-panel">
-                <Tooltip title="Go back" className={path.length > 1 ? classes.backButton : classes.backButtonHidden}>
-                    <IconButton onClick={() => setPath([...path.slice(0, path.length -1)])}>
-                        <BackIcon />
-                    </IconButton>
-                </Tooltip>
-            </div>
             <div className={classes.wrapper}>
                 <div className={classNames(classes.leftPanel, path.length > 1 ? classes.leftPanelVisible : classes.leftPanelHidden)}  data-cy="collection-files-left-panel">
                     <Tooltip title="Go back" className={path.length > 1 ? classes.backButton : classes.backButtonHidden}>
@@ -499,6 +491,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                                         >
                                             {
                                                 ({ index, style }) => {
+                                                    console.log("Left Data ROW: ", filtered[index]);
                                                     const { id, type, name } = filtered[index];
 
                                                     return <div
@@ -527,60 +520,6 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
 
                     </div>
                 </div>
-                <div className={classes.rightPanel} data-cy="collection-files-right-panel">
-                    <div className={classes.searchWrapper}>
-                        <SearchInput selfClearProp={rightKey} label="Search" value={rightSearch} onSearch={setRightSearch} />
-                    </div>
-                    {
-                        isWritable &&
-                        <Button
-                            className={classes.uploadButton}
-                            data-cy='upload-button'
-                            onClick={() => {
-                                onUploadDataClick(rightKey === leftKey ? undefined : rightKey);
-                            }}
-                            variant='contained'
-                            color='primary'
-                            size='small'>
-                            <DownloadIcon className={classes.uploadIcon} />
-                            Upload data
-                        </Button>
-                    }
-                    <div className={classes.dataWrapper}>
-                        {
-                            rightData && !isLoading ?
-                                <AutoSizer defaultHeight={500}>
-                                    {({ height, width }) => {
-                                        const filtered = rightData.filter(({ name }) => name.indexOf(rightSearch) > -1);
-
-                        return !!filtered.length
-                        ? <FixedSizeList height={height} itemCount={filtered.length}
-                            itemSize={35} width={width}>{ ({ index, style }) => {
-                            console.log("Left Data ROW: ", filtered[index]);
-                            const { id, type, name } = filtered[index];
-
-                            return <div data-id={id} style={style} data-item="true"
-                                data-type={type} data-parent-path={name} key={id}
-                                className={classNames(classes.row, getActiveClass(name))}>
-                                    { getItemIcon(type, getActiveClass(name)) }
-                                    <div className={classes.rowName}>
-                                        {name}
-                                    </div>
-                                    { getActiveClass(name)
-                                    ? <SidePanelRightArrowIcon style={{
-                                        display: 'inline',
-                                        marginTop: '5px',
-                                        marginLeft: '5px' }} />
-                                    : null }
-                            </div>;
-                        } }</FixedSizeList>
-                        : <div className={classes.rowEmpty}>No directories available</div>
-                    } }</AutoSizer>
-                    : <div className={classes.row}>
-                        <CircularProgress className={classes.loader} size={30} />
-                    </div> }
-                </div>
-            </div>
             <div className={classes.rightPanel}>
                 <div className={classes.searchWrapper}>
                     <SearchInput selfClearProp={rightKey} label="Search" value={rightSearch} onSearch={setRightSearch} />
@@ -588,7 +527,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                 { isWritable &&
                 <Button className={classes.uploadButton} data-cy='upload-button'
                     onClick={() => {
-                        onUploadDataClick();
+                        onUploadDataClick(rightKey === leftKey ? undefined : rightKey);
                     }}
                     variant='contained' color='primary' size='small'>
                     <DownloadIcon className={classes.uploadIcon} />
@@ -630,4 +569,4 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                 </div>
             </div>
         </div>
-    </div></div>}));
+    </div>}));

commit 198ae2eb95d997550d1d647916b38bb8b3f536e9
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Fri May 27 09:35:32 2022 -0300

    18787: Fix post rebase
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/src/components/collection-panel-files/collection-panel-files.tsx b/src/components/collection-panel-files/collection-panel-files.tsx
index 4e2e08cd..0fa06682 100644
--- a/src/components/collection-panel-files/collection-panel-files.tsx
+++ b/src/components/collection-panel-files/collection-panel-files.tsx
@@ -630,4 +630,4 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                 </div>
             </div>
         </div>
-    </div>}));
+    </div></div>}));

commit 00dd0a8f134729754f01f24f642fe82c08873dae
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Tue Mar 8 13:23:58 2022 -0300

    18787: WIP -- commit to test jenkins test pipeline.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/src/components/collection-panel-files/collection-panel-files.tsx b/src/components/collection-panel-files/collection-panel-files.tsx
index b077d917..4e2e08cd 100644
--- a/src/components/collection-panel-files/collection-panel-files.tsx
+++ b/src/components/collection-panel-files/collection-panel-files.tsx
@@ -22,11 +22,11 @@ import { setCollectionFiles } from 'store/collection-panel/collection-panel-file
 import { sortBy } from 'lodash';
 import { formatFileSize } from 'common/formatters';
 import { getInlineFileUrl, sanitizeToken } from 'views-components/context-menu/actions/helpers';
+import _ from 'lodash';
 
 export interface CollectionPanelFilesProps {
     items: any;
     isWritable: boolean;
-    isLoading: boolean;
     onUploadDataClick: (targetLocation?: string) => void;
     onSearchChange: (searchValue: string) => void;
     onItemMenuOpen: (event: React.MouseEvent<HTMLElement>, item: TreeItem<FileTreeData>, isWritable: boolean) => void;
@@ -34,7 +34,6 @@ export interface CollectionPanelFilesProps {
     onSelectionToggle: (event: React.MouseEvent<HTMLElement>, item: TreeItem<FileTreeData>) => void;
     onCollapseToggle: (id: string, status: TreeItemStatus) => void;
     onFileClick: (id: string) => void;
-    loadFilesFunc: () => void;
     currentItemUuid: any;
     dispatch: Function;
     collectionPanelFiles: any;
@@ -176,11 +175,25 @@ const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
 
 const pathPromise = {};
 
+let prevState = {};
+function difference(object, base) {
+	function changes(object, base) {
+		return _.transform(object, function(result, value, key) {
+			if (!_.isEqual(value, base[key])) {
+				result[key] = (_.isObject(value) && _.isObject(base[key])) ? changes(value, base[key]) : value;
+			}
+		});
+	}
+	return changes(object, base);
+}
 export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState) => ({
     auth: state.auth,
     collectionPanel: state.collectionPanel,
     collectionPanelFiles: state.collectionPanelFiles,
 }))((props: CollectionPanelFilesProps & WithStyles<CssRules> & { auth: AuthState }) => {
+    const diff = difference(props, prevState);
+    prevState = props;
+    console.log('---> render CollectionPanel <------', diff);
     const { classes, onItemMenuOpen, onUploadDataClick, isWritable, dispatch, collectionPanelFiles, collectionPanel } = props;
     const { apiToken, config } = props.auth;
 
@@ -210,8 +223,8 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
     const rightData = pathData[rightKey];
 
     React.useEffect(() => {
-        console.log(' --> useEffect current UUID: ', props.currentItemUuid);
         if (props.currentItemUuid) {
+            console.log(' --> useEffect current UUID: ', props.currentItemUuid);
             setPathData({});
             setPath([props.currentItemUuid]);
         }
@@ -273,8 +286,8 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
     };
 
     React.useEffect(() => {
-        console.log('---> useEffect rightKey', rightKey);
         if (rightKey) {
+            console.log('---> useEffect rightKey:', rightKey);
             fetchData(rightKey);
             setLeftSearch('');
             setRightSearch('');
@@ -283,15 +296,20 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
 
     const currentPDH = (collectionPanel.item || {}).portableDataHash;
     React.useEffect(() => {
-        console.log('---> useEffect PDH change:', currentPDH);
         if (currentPDH) {
-            fetchData([leftKey, rightKey], true);
+            console.log('---> useEffect PDH change:', currentPDH);
+            // Avoid fetching the same content level twice
+            if (leftKey !== rightKey) {
+                fetchData([leftKey, rightKey], true);
+            } else {
+                fetchData(rightKey, true);
+            }
         }
     }, [currentPDH]); // eslint-disable-line react-hooks/exhaustive-deps
 
     React.useEffect(() => {
-        console.log('---> useEffect rightData:', rightData, dispatch, rightSearch);
         if (rightData) {
+            console.log('---> useEffect rightData:', rightData, 'search:', rightSearch);
             const filtered = rightData.filter(({ name }) => name.indexOf(rightSearch) > -1);
             setCollectionFiles(filtered, false)(dispatch);
         }
@@ -325,10 +343,10 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
     );
 
     React.useEffect(() => {
-        console.log('---> useEffect parentRef:', parentRef, handleRightClick);
         let node = null;
 
         if (parentRef && parentRef.current) {
+            console.log('---> useEffect parentRef:', parentRef);
             node = parentRef.current;
             (node as any).addEventListener('contextmenu', handleRightClick);
         }
@@ -426,7 +444,6 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
         [props.onOptionsMenuOpen] // eslint-disable-line react-hooks/exhaustive-deps
     );
 
-    console.log('---> render CollectionPanel <------');
     return <div data-cy="collection-files-panel" onClick={handleClick} ref={parentRef}>
         <div className={classes.pathPanel}>
             <div className={classes.pathPanelPathWrapper}>

commit e868a45a2a187dca9812c5e6e201503f3e427e08
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Tue Mar 8 13:21:43 2022 -0300

    18787: Removes unnecessary store init to avoid forced refreshes.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/src/store/collections/collection-upload-actions.ts b/src/store/collections/collection-upload-actions.ts
index 9e9fea52..e9c5cc35 100644
--- a/src/store/collections/collection-upload-actions.ts
+++ b/src/store/collections/collection-upload-actions.ts
@@ -10,8 +10,6 @@ import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
 import { fileUploaderActions } from 'store/file-uploader/file-uploader-actions';
 import { reset, startSubmit, stopSubmit } from 'redux-form';
 import { progressIndicatorActions } from "store/progress-indicator/progress-indicator-actions";
-import { collectionPanelFilesAction } from 'store/collection-panel/collection-panel-files/collection-panel-files-actions';
-import { createTree } from 'models/tree';
 import * as WorkbenchActions from 'store/workbench/workbench-actions';
 
 export const uploadCollectionFiles = (collectionUuid: string, targetLocation?: string) =>
@@ -38,8 +36,7 @@ export const submitCollectionFiles = (targetLocation?: string) =>
             try {
                 dispatch(progressIndicatorActions.START_WORKING(COLLECTION_UPLOAD_FILES_DIALOG));
                 dispatch(startSubmit(COLLECTION_UPLOAD_FILES_DIALOG));
-                await dispatch<any>(uploadCollectionFiles(currentCollection.uuid, targetLocation))
-                    .then(() => dispatch<any>(collectionPanelFilesAction.SET_COLLECTION_FILES({ files: createTree() })));
+                await dispatch<any>(uploadCollectionFiles(currentCollection.uuid, targetLocation));
                 dispatch(closeUploadCollectionFilesDialog());
                 dispatch(snackbarActions.OPEN_SNACKBAR({
                     message: 'Data has been uploaded.',
diff --git a/src/store/workbench/workbench-actions.ts b/src/store/workbench/workbench-actions.ts
index d2ff84b3..3142b633 100644
--- a/src/store/workbench/workbench-actions.ts
+++ b/src/store/workbench/workbench-actions.ts
@@ -100,8 +100,6 @@ import { subprocessPanelActions } from 'store/subprocess-panel/subprocess-panel-
 import { subprocessPanelColumns } from 'views/subprocess-panel/subprocess-panel-root';
 import { loadAllProcessesPanel, allProcessesPanelActions } from '../all-processes-panel/all-processes-panel-action';
 import { allProcessesPanelColumns } from 'views/all-processes-panel/all-processes-panel';
-import { collectionPanelFilesAction } from '../collection-panel/collection-panel-files/collection-panel-files-actions';
-import { createTree } from 'models/tree';
 import { AdminMenuIcon } from 'components/icon/icon';
 import { userProfileGroupsColumns } from 'views/user-profile-panel/user-profile-panel-root';
 
@@ -295,8 +293,6 @@ export const loadCollection = (uuid: string) =>
         async (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
             const userUuid = getUserUuid(getState());
             if (userUuid) {
-                // Clear collection files panel
-                dispatch(collectionPanelFilesAction.SET_COLLECTION_FILES({ files: createTree() }));
                 const match = await loadGroupContentsResource({ uuid, userUuid, services });
                 match({
                     OWNED: async collection => {

commit 970c338729ef7490f380b82c4a0acdb33a8fbe98
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Mon Mar 7 17:49:57 2022 -0300

    18787: Removes explicit collection reload after file operations.
    
    It's not necessary anymore, as websocket events would make the app to
    refresh the content when needed.
    
    This is not needed anymore as Workbench2 now listens websocket events.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts b/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts
index da6cfeb0..8c5e5b5a 100644
--- a/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts
+++ b/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts
@@ -15,8 +15,6 @@ import { filterCollectionFilesBySelection } from './collection-panel-files-state
 import { startSubmit, stopSubmit, initialize, FormErrors } from 'redux-form';
 import { getDialog } from "store/dialog/dialog-reducer";
 import { getFileFullPath, sortFilesTree } from "services/collection-service/collection-service-files-response";
-import { progressIndicatorActions } from "store/progress-indicator/progress-indicator-actions";
-import { loadCollectionPanel } from "../collection-panel-action";
 
 export const collectionPanelFilesAction = unionize({
     SET_COLLECTION_FILES: ofType<CollectionFilesTree>(),
@@ -38,33 +36,11 @@ export const setCollectionFiles = (files, joinParents = true) => (dispatch: any)
     dispatch(collectionPanelFilesAction.SET_COLLECTION_FILES(mapped));
 };
 
-export const loadCollectionFiles = (uuid: string) =>
-    (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-        dispatch(progressIndicatorActions.START_WORKING(COLLECTION_PANEL_LOAD_FILES));
-        services.collectionService.files(uuid).then(files => {
-            // Given the array of directories and files, create the appropriate tree nodes,
-            // sort them, and add the complete url to each.
-            const tree = createCollectionFilesTree(files);
-            const sorted = sortFilesTree(tree);
-            const mapped = mapTreeValues(services.collectionService.extendFileURL)(sorted);
-            dispatch(collectionPanelFilesAction.SET_COLLECTION_FILES(mapped));
-            dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_PANEL_LOAD_FILES));
-        }).catch(() => {
-            dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_PANEL_LOAD_FILES));
-            dispatch(snackbarActions.OPEN_SNACKBAR({
-                message: `Error getting file list`,
-                hideDuration: 2000,
-                kind: SnackbarKind.ERROR
-            }));
-        });
-    };
-
 export const removeCollectionFiles = (filePaths: string[]) =>
     (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
         const currentCollection = getState().collectionPanel.item;
         if (currentCollection) {
             services.collectionService.deleteFiles(currentCollection.uuid, filePaths).then(() => {
-                dispatch<any>(loadCollectionPanel(currentCollection.uuid, true));
                 dispatch(snackbarActions.OPEN_SNACKBAR({
                     message: 'Removed.',
                     hideDuration: 2000,
@@ -154,7 +130,6 @@ export const renameFile = (newFullPath: string) =>
                 const oldPath = getFileFullPath(file);
                 const newPath = newFullPath;
                 services.collectionService.moveFile(currentCollection.uuid, oldPath, newPath).then(() => {
-                    dispatch<any>(loadCollectionPanel(currentCollection.uuid, true));
                     dispatch(dialogActions.CLOSE_DIALOG({ id: RENAME_FILE_DIALOG }));
                     dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'File name changed.', hideDuration: 2000 }));
                 }).catch(e => {
diff --git a/src/store/collections/collection-upload-actions.ts b/src/store/collections/collection-upload-actions.ts
index 135538b0..9e9fea52 100644
--- a/src/store/collections/collection-upload-actions.ts
+++ b/src/store/collections/collection-upload-actions.ts
@@ -6,14 +6,12 @@ import { Dispatch } from 'redux';
 import { RootState } from 'store/store';
 import { ServiceRepository } from 'services/services';
 import { dialogActions } from 'store/dialog/dialog-actions';
-import { loadCollectionFiles } from '../collection-panel/collection-panel-files/collection-panel-files-actions';
 import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
 import { fileUploaderActions } from 'store/file-uploader/file-uploader-actions';
 import { reset, startSubmit, stopSubmit } from 'redux-form';
 import { progressIndicatorActions } from "store/progress-indicator/progress-indicator-actions";
 import { collectionPanelFilesAction } from 'store/collection-panel/collection-panel-files/collection-panel-files-actions';
 import { createTree } from 'models/tree';
-import { loadCollectionPanel } from '../collection-panel/collection-panel-action';
 import * as WorkbenchActions from 'store/workbench/workbench-actions';
 
 export const uploadCollectionFiles = (collectionUuid: string, targetLocation?: string) =>
@@ -42,8 +40,6 @@ export const submitCollectionFiles = (targetLocation?: string) =>
                 dispatch(startSubmit(COLLECTION_UPLOAD_FILES_DIALOG));
                 await dispatch<any>(uploadCollectionFiles(currentCollection.uuid, targetLocation))
                     .then(() => dispatch<any>(collectionPanelFilesAction.SET_COLLECTION_FILES({ files: createTree() })));
-                dispatch<any>(loadCollectionFiles(currentCollection.uuid));
-                dispatch<any>(loadCollectionPanel(currentCollection.uuid));
                 dispatch(closeUploadCollectionFilesDialog());
                 dispatch(snackbarActions.OPEN_SNACKBAR({
                     message: 'Data has been uploaded.',
diff --git a/src/views/collection-panel/collection-panel.tsx b/src/views/collection-panel/collection-panel.tsx
index db273b99..9d127a60 100644
--- a/src/views/collection-panel/collection-panel.tsx
+++ b/src/views/collection-panel/collection-panel.tsx
@@ -32,8 +32,6 @@ import { IllegalNamingWarning } from 'components/warning/warning';
 import { GroupResource } from 'models/group';
 import { UserResource } from 'models/user';
 import { getUserUuid } from 'common/getuser';
-import { getProgressIndicator } from 'store/progress-indicator/progress-indicator-reducer';
-import { COLLECTION_PANEL_LOAD_FILES, loadCollectionFiles } from 'store/collection-panel/collection-panel-files/collection-panel-files-actions';
 import { Link } from 'react-router-dom';
 import { Link as ButtonLink } from '@material-ui/core';
 import { ResourceWithName, ResponsiblePerson } from 'views-components/data-explorer/renderers';
@@ -117,11 +115,10 @@ interface CollectionPanelDataProps {
     isLoadingFiles: boolean;
 }
 
-type CollectionPanelProps = CollectionPanelDataProps & DispatchProp
-    & WithStyles<CssRules> & RouteComponentProps<{ id: string }>;
+type CollectionPanelProps = CollectionPanelDataProps & DispatchProp & WithStyles<CssRules>
 
-export const CollectionPanel = withStyles(styles)(
-    connect((state: RootState, props: RouteComponentProps<{ id: string }>) => {
+export const CollectionPanel = withStyles(styles)(connect(
+    (state: RootState, props: RouteComponentProps<{ id: string }>) => {
         const currentUserUUID = getUserUuid(state);
         const item = getResource<CollectionResource>(props.match.params.id)(state.resources);
         let isWritable = false;
@@ -136,13 +133,11 @@ export const CollectionPanel = withStyles(styles)(
                 }
             }
         }
-        const loadingFilesIndicator = getProgressIndicator(COLLECTION_PANEL_LOAD_FILES)(state.progressIndicator);
-        const isLoadingFiles = (loadingFilesIndicator && loadingFilesIndicator!.working) || false;
-        return { item, isWritable, isOldVersion, isLoadingFiles };
+        return { item, isWritable, isOldVersion };
     })(
         class extends React.Component<CollectionPanelProps> {
             render() {
-                const { classes, item, dispatch, isWritable, isOldVersion, isLoadingFiles } = this.props;
+                const { classes, item, dispatch, isWritable, isOldVersion } = this.props;
                 const panelsData: MPVPanelState[] = [
                     { name: "Details" },
                     { name: "Files" },
@@ -201,13 +196,7 @@ export const CollectionPanel = withStyles(styles)(
                         </MPVPanelContent>
                         <MPVPanelContent xs>
                             <Card className={classes.filesCard}>
-                                <CollectionPanelFiles
-                                    isWritable={isWritable}
-                                    isLoading={isLoadingFiles}
-                                    loadFilesFunc={() => {
-                                        dispatch<any>(loadCollectionFiles(this.props.item.uuid));
-                                    }
-                                    } />
+                                <CollectionPanelFiles isWritable={isWritable} />
                             </Card>
                         </MPVPanelContent>
                     </MPVContainer>

commit 614e5664c62ac01307744e29072ca1804cb7e676
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Fri Mar 4 20:10:41 2022 -0300

    18787: Removes remaining traces of old big collection loading check.
    
    This turned useless with the new file browser.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/src/components/collection-panel-files/collection-panel-files.tsx b/src/components/collection-panel-files/collection-panel-files.tsx
index 3c064973..b077d917 100644
--- a/src/components/collection-panel-files/collection-panel-files.tsx
+++ b/src/components/collection-panel-files/collection-panel-files.tsx
@@ -27,7 +27,6 @@ export interface CollectionPanelFilesProps {
     items: any;
     isWritable: boolean;
     isLoading: boolean;
-    tooManyFiles: boolean;
     onUploadDataClick: (targetLocation?: string) => void;
     onSearchChange: (searchValue: string) => void;
     onItemMenuOpen: (event: React.MouseEvent<HTMLElement>, item: TreeItem<FileTreeData>, isWritable: boolean) => void;
@@ -211,6 +210,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
     const rightData = pathData[rightKey];
 
     React.useEffect(() => {
+        console.log(' --> useEffect current UUID: ', props.currentItemUuid);
         if (props.currentItemUuid) {
             setPathData({});
             setPath([props.currentItemUuid]);
@@ -244,6 +244,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
         .then((requests) => {
             const newState = requests.map((request, index) => {
                 if (request && request.responseXML != null) {
+                    console.log(">>> got data for key", keyArray[index]);
                     const key = keyArray[index];
                     const result: any = extractFilesData(request.responseXML);
                     const sortedResult = sortBy(result, (n) => n.name).sort((n1, n2) => {
@@ -272,6 +273,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
     };
 
     React.useEffect(() => {
+        console.log('---> useEffect rightKey', rightKey);
         if (rightKey) {
             fetchData(rightKey);
             setLeftSearch('');
@@ -281,12 +283,14 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
 
     const currentPDH = (collectionPanel.item || {}).portableDataHash;
     React.useEffect(() => {
+        console.log('---> useEffect PDH change:', currentPDH);
         if (currentPDH) {
             fetchData([leftKey, rightKey], true);
         }
     }, [currentPDH]); // eslint-disable-line react-hooks/exhaustive-deps
 
     React.useEffect(() => {
+        console.log('---> useEffect rightData:', rightData, dispatch, rightSearch);
         if (rightData) {
             const filtered = rightData.filter(({ name }) => name.indexOf(rightSearch) > -1);
             setCollectionFiles(filtered, false)(dispatch);
@@ -321,6 +325,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
     );
 
     React.useEffect(() => {
+        console.log('---> useEffect parentRef:', parentRef, handleRightClick);
         let node = null;
 
         if (parentRef && parentRef.current) {
@@ -421,6 +426,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
         [props.onOptionsMenuOpen] // eslint-disable-line react-hooks/exhaustive-deps
     );
 
+    console.log('---> render CollectionPanel <------');
     return <div data-cy="collection-files-panel" onClick={handleClick} ref={parentRef}>
         <div className={classes.pathPanel}>
             <div className={classes.pathPanelPathWrapper}>
@@ -574,6 +580,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                 <div className={classes.dataWrapper}>{ rightData && !isLoading
                     ? <AutoSizer defaultHeight={500}>{({ height, width }) => {
                         const filtered = rightData.filter(({ name }) => name.indexOf(rightSearch) > -1);
+                        console.log("Right Data: ", filtered);
 
                         return !!filtered.length
                         ? <FixedSizeList height={height} itemCount={filtered.length}
diff --git a/src/store/collection-panel/collection-panel-action.ts b/src/store/collection-panel/collection-panel-action.ts
index c50ff6a8..55eb5949 100644
--- a/src/store/collection-panel/collection-panel-action.ts
+++ b/src/store/collection-panel/collection-panel-action.ts
@@ -3,9 +3,6 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import { Dispatch } from "redux";
-import {
-    COLLECTION_PANEL_LOAD_FILES_THRESHOLD
-} from "./collection-panel-files/collection-panel-files-actions";
 import { CollectionResource } from 'models/collection';
 import { RootState } from "store/store";
 import { ServiceRepository } from "services/services";
@@ -19,7 +16,6 @@ import { loadDetailsPanel } from 'store/details-panel/details-panel-action';
 export const collectionPanelActions = unionize({
     SET_COLLECTION: ofType<CollectionResource>(),
     LOAD_COLLECTION_SUCCESS: ofType<{ item: CollectionResource }>(),
-    LOAD_BIG_COLLECTIONS: ofType<boolean>(),
 });
 
 export type CollectionPanelAction = UnionOf<typeof collectionPanelActions>;
@@ -33,9 +29,6 @@ export const loadCollectionPanel = (uuid: string, forceReload = false) =>
         dispatch<any>(loadDetailsPanel(collection.uuid));
         dispatch(collectionPanelActions.LOAD_COLLECTION_SUCCESS({ item: collection }));
         dispatch(resourcesActions.SET_RESOURCES([collection]));
-        if (collection.fileCount <= COLLECTION_PANEL_LOAD_FILES_THRESHOLD &&
-            !getState().collectionPanel.loadBigCollections) {
-        }
         return collection;
     };
 
diff --git a/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts b/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts
index 71e1f6e8..da6cfeb0 100644
--- a/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts
+++ b/src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts
@@ -30,7 +30,6 @@ export const collectionPanelFilesAction = unionize({
 export type CollectionPanelFilesAction = UnionOf<typeof collectionPanelFilesAction>;
 
 export const COLLECTION_PANEL_LOAD_FILES = 'collectionPanelLoadFiles';
-export const COLLECTION_PANEL_LOAD_FILES_THRESHOLD = 40000;
 
 export const setCollectionFiles = (files, joinParents = true) => (dispatch: any) => {
     const tree = createCollectionFilesTree(files, joinParents);
diff --git a/src/store/collection-panel/collection-panel-reducer.ts b/src/store/collection-panel/collection-panel-reducer.ts
index a6aa87bd..b9713f5d 100644
--- a/src/store/collection-panel/collection-panel-reducer.ts
+++ b/src/store/collection-panel/collection-panel-reducer.ts
@@ -7,12 +7,10 @@ import { CollectionResource } from "models/collection";
 
 export interface CollectionPanelState {
     item: CollectionResource | null;
-    loadBigCollections: boolean;
 }
 
 const initialState = {
     item: null,
-    loadBigCollections: false,
 };
 
 export const collectionPanelReducer = (state: CollectionPanelState = initialState, action: CollectionPanelAction) =>
@@ -21,8 +19,6 @@ export const collectionPanelReducer = (state: CollectionPanelState = initialStat
         SET_COLLECTION: (item) => ({
              ...state,
              item,
-             loadBigCollections: false,
         }),
         LOAD_COLLECTION_SUCCESS: ({ item }) => ({ ...state, item }),
-        LOAD_BIG_COLLECTIONS: (loadBigCollections) => ({ ...state, loadBigCollections}),
     });
diff --git a/src/views/collection-panel/collection-panel.tsx b/src/views/collection-panel/collection-panel.tsx
index 17d35aea..db273b99 100644
--- a/src/views/collection-panel/collection-panel.tsx
+++ b/src/views/collection-panel/collection-panel.tsx
@@ -21,7 +21,7 @@ import { MoreOptionsIcon, CollectionIcon, ReadOnlyIcon, CollectionOldVersionIcon
 import { DetailsAttribute } from 'components/details-attribute/details-attribute';
 import { CollectionResource, getCollectionUrl } from 'models/collection';
 import { CollectionPanelFiles } from 'views-components/collection-panel-files/collection-panel-files';
-import { navigateToProcess, collectionPanelActions } from 'store/collection-panel/collection-panel-action';
+import { navigateToProcess } from 'store/collection-panel/collection-panel-action';
 import { getResource } from 'store/resources/resources';
 import { openContextMenu, resourceUuidToContextMenuKind } from 'store/context-menu/context-menu-actions';
 import { formatDate, formatFileSize } from "common/formatters";
@@ -33,7 +33,7 @@ import { GroupResource } from 'models/group';
 import { UserResource } from 'models/user';
 import { getUserUuid } from 'common/getuser';
 import { getProgressIndicator } from 'store/progress-indicator/progress-indicator-reducer';
-import { COLLECTION_PANEL_LOAD_FILES, loadCollectionFiles, COLLECTION_PANEL_LOAD_FILES_THRESHOLD } from 'store/collection-panel/collection-panel-files/collection-panel-files-actions';
+import { COLLECTION_PANEL_LOAD_FILES, loadCollectionFiles } from 'store/collection-panel/collection-panel-files/collection-panel-files-actions';
 import { Link } from 'react-router-dom';
 import { Link as ButtonLink } from '@material-ui/core';
 import { ResourceWithName, ResponsiblePerson } from 'views-components/data-explorer/renderers';
@@ -115,7 +115,6 @@ interface CollectionPanelDataProps {
     isWritable: boolean;
     isOldVersion: boolean;
     isLoadingFiles: boolean;
-    tooManyFiles: boolean;
 }
 
 type CollectionPanelProps = CollectionPanelDataProps & DispatchProp
@@ -139,12 +138,11 @@ export const CollectionPanel = withStyles(styles)(
         }
         const loadingFilesIndicator = getProgressIndicator(COLLECTION_PANEL_LOAD_FILES)(state.progressIndicator);
         const isLoadingFiles = (loadingFilesIndicator && loadingFilesIndicator!.working) || false;
-        const tooManyFiles = (!state.collectionPanel.loadBigCollections && item && item.fileCount > COLLECTION_PANEL_LOAD_FILES_THRESHOLD) || false;
-        return { item, isWritable, isOldVersion, isLoadingFiles, tooManyFiles };
+        return { item, isWritable, isOldVersion, isLoadingFiles };
     })(
         class extends React.Component<CollectionPanelProps> {
             render() {
-                const { classes, item, dispatch, isWritable, isOldVersion, isLoadingFiles, tooManyFiles } = this.props;
+                const { classes, item, dispatch, isWritable, isOldVersion, isLoadingFiles } = this.props;
                 const panelsData: MPVPanelState[] = [
                     { name: "Details" },
                     { name: "Files" },
@@ -206,9 +204,7 @@ export const CollectionPanel = withStyles(styles)(
                                 <CollectionPanelFiles
                                     isWritable={isWritable}
                                     isLoading={isLoadingFiles}
-                                    tooManyFiles={tooManyFiles}
                                     loadFilesFunc={() => {
-                                        dispatch(collectionPanelActions.LOAD_BIG_COLLECTIONS(true));
                                         dispatch<any>(loadCollectionFiles(this.props.item.uuid));
                                     }
                                     } />

commit d6a28995f22dc04688444c0098b185717f7d4ed4
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Fri Mar 4 19:22:19 2022 -0300

    18787: Avoids doing useless webdav PROPFIND calls with empty strings as UUIDs.
    
    This is a WIP, the console logging will be cleaned later.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/src/components/collection-panel-files/collection-panel-files.tsx b/src/components/collection-panel-files/collection-panel-files.tsx
index 3b91b6c1..3c064973 100644
--- a/src/components/collection-panel-files/collection-panel-files.tsx
+++ b/src/components/collection-panel-files/collection-panel-files.tsx
@@ -218,9 +218,10 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
     }, [props.currentItemUuid]);
 
     const fetchData = (keys, ignoreCache = false) => {
+        console.log('---> fetchData', keys);
         const keyArray = Array.isArray(keys) ? keys : [keys];
 
-        Promise.all(keyArray
+        Promise.all(keyArray.filter(key => !!key)
             .map((key) => {
                 const dataExists = !!pathData[key];
                 const runningRequest = pathPromise[key];
@@ -232,6 +233,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
 
                     pathPromise[key] = true;
 
+                    console.log('>>> fetching data for key', key);
                     return webdavClient.propfind(`c=${key}`, webDAVRequestConfig);
                 }
 
@@ -239,34 +241,34 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
             })
             .filter((promise) => !!promise)
         )
-            .then((requests) => {
-                const newState = requests.map((request, index) => {
-                    if (request && request.responseXML != null) {
-                        const key = keyArray[index];
-                        const result: any = extractFilesData(request.responseXML);
-                        const sortedResult = sortBy(result, (n) => n.name).sort((n1, n2) => {
-                            if (n1.type === 'directory' && n2.type !== 'directory') {
-                                return -1;
-                            }
-                            if (n1.type !== 'directory' && n2.type === 'directory') {
-                                return 1;
-                            }
-                            return 0;
-                        });
-
-                        return { [key]: sortedResult };
-                    }
-                    return {};
-                }).reduce((prev, next) => {
-                    return { ...next, ...prev };
-                }, {});
+        .then((requests) => {
+            const newState = requests.map((request, index) => {
+                if (request && request.responseXML != null) {
+                    const key = keyArray[index];
+                    const result: any = extractFilesData(request.responseXML);
+                    const sortedResult = sortBy(result, (n) => n.name).sort((n1, n2) => {
+                        if (n1.type === 'directory' && n2.type !== 'directory') {
+                            return -1;
+                        }
+                        if (n1.type !== 'directory' && n2.type === 'directory') {
+                            return 1;
+                        }
+                        return 0;
+                    });
 
-                setPathData({ ...pathData, ...newState });
-            })
-            .finally(() => {
-                setIsLoading(false);
-                keyArray.forEach(key => delete pathPromise[key]);
-            });
+                    return { [key]: sortedResult };
+                }
+                return {};
+            }).reduce((prev, next) => {
+                return { ...next, ...prev };
+            }, {});
+
+            setPathData({ ...pathData, ...newState });
+        })
+        .finally(() => {
+            setIsLoading(false);
+            keyArray.forEach(key => delete pathPromise[key]);
+        });
     };
 
     React.useEffect(() => {
@@ -531,6 +533,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                         return !!filtered.length
                         ? <FixedSizeList height={height} itemCount={filtered.length}
                             itemSize={35} width={width}>{ ({ index, style }) => {
+                            console.log("Left Data ROW: ", filtered[index]);
                             const { id, type, name } = filtered[index];
 
                             return <div data-id={id} style={style} data-item="true"
@@ -575,6 +578,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                         return !!filtered.length
                         ? <FixedSizeList height={height} itemCount={filtered.length}
                             itemSize={35} width={width}>{ ({ index, style }) => {
+                                console.log("Right Data ROW: ", filtered[index]);
                                 const { id, type, name, size } = filtered[index];
 
                                 return <div style={style} data-id={id} data-item="true"

commit 0721e16721a598a2d0eea501e7efd265219f134f
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Fri Mar 4 18:51:50 2022 -0300

    18787: Attempts to diminish the indentation madness, improving readability.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/src/components/collection-panel-files/collection-panel-files.tsx b/src/components/collection-panel-files/collection-panel-files.tsx
index 05b49363..3b91b6c1 100644
--- a/src/components/collection-panel-files/collection-panel-files.tsx
+++ b/src/components/collection-panel-files/collection-panel-files.tsx
@@ -419,29 +419,33 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
         [props.onOptionsMenuOpen] // eslint-disable-line react-hooks/exhaustive-deps
     );
 
-    return (
-        <div data-cy="collection-files-panel" onClick={handleClick} ref={parentRef}>
-            <div className={classes.pathPanel}>
-                <div className={classes.pathPanelPathWrapper}>
-                    {
-                        path
-                            .map((p: string, index: number) => <span
-                                key={`${index}-${p}`}
-                                data-item="true"
-                                className={classes.pathPanelItem}
-                                data-breadcrumb-path={p}
-                            >
-                                <span className={classes.rowActive}>{index === 0 ? 'Home' : p}</span> <b>/</b> 
-                            </span>)
-                    }
-                </div>
-                <Tooltip className={classes.pathPanelMenu} title="More options" disableFocusListener>
-                    <IconButton
-                        data-cy='collection-files-panel-options-btn'
-                        onClick={(ev) => {
-                            onOptionsMenuOpen(ev, isWritable);
-                        }}>
-                        <CustomizeTableIcon />
+    return <div data-cy="collection-files-panel" onClick={handleClick} ref={parentRef}>
+        <div className={classes.pathPanel}>
+            <div className={classes.pathPanelPathWrapper}>
+                { path.map((p: string, index: number) => <span
+                    key={`${index}-${p}`}
+                    data-item="true"
+                    className={classes.pathPanelItem}
+                    data-breadcrumb-path={p}
+                >
+                    <span className={classes.rowActive}>{index === 0 ? 'Home' : p}</span> <b>/</b> 
+                </span>) }
+            </div>
+            <Tooltip className={classes.pathPanelMenu} title="More options" disableFocusListener>
+                <IconButton
+                    data-cy='collection-files-panel-options-btn'
+                    onClick={(ev) => {
+                        onOptionsMenuOpen(ev, isWritable);
+                    }}>
+                    <CustomizeTableIcon />
+                </IconButton>
+            </Tooltip>
+        </div>
+        <div className={classes.wrapper}>
+            <div className={classNames(classes.leftPanel, path.length > 1 ? classes.leftPanelVisible : classes.leftPanelHidden)}  data-cy="collection-files-left-panel">
+                <Tooltip title="Go back" className={path.length > 1 ? classes.backButton : classes.backButtonHidden}>
+                    <IconButton onClick={() => setPath([...path.slice(0, path.length -1)])}>
+                        <BackIcon />
                     </IconButton>
                 </Tooltip>
             </div>
@@ -524,44 +528,78 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
                                     {({ height, width }) => {
                                         const filtered = rightData.filter(({ name }) => name.indexOf(rightSearch) > -1);
 
-                                        return !!filtered.length ? <FixedSizeList
-                                            height={height}
-                                            itemCount={filtered.length}
-                                            itemSize={35}
-                                            width={width}
-                                        >
-                                            {
-                                                ({ index, style }) => {
-                                                    const { id, type, name, size } = filtered[index];
-
-                                                    return <div
-                                                        style={style}
-                                                        data-id={id}
-                                                        data-item="true"
-                                                        data-type={type}
-                                                        data-subfolder-path={name}
-                                                        className={classes.row} key={id}>
-                                                        <Checkbox
-                                                            color="primary"
-                                                            className={classes.rowSelection}
-                                                            checked={collectionPanelFiles[id] ? collectionPanelFiles[id].value.selected : false}
-                                                        /> 
-                                                    {getItemIcon(type, null)} <div className={classes.rowName}>
-                                                            {name}
-                                                        </div>
-                                                        <span className={classes.rowName} style={{ marginLeft: 'auto', marginRight: '1rem' }}>
-                                                            {formatFileSize(size)}
-                                                        </span>
-                                                    </div>
-                                                }
-                                            }
-                                        </FixedSizeList> : <div className={classes.rowEmpty}>This collection is empty</div>
-                                    }}
-                                </AutoSizer> : <div className={classes.row}><CircularProgress className={classes.loader} size={30} /></div>
-                        }
-                    </div>
+                        return !!filtered.length
+                        ? <FixedSizeList height={height} itemCount={filtered.length}
+                            itemSize={35} width={width}>{ ({ index, style }) => {
+                            const { id, type, name } = filtered[index];
+
+                            return <div data-id={id} style={style} data-item="true"
+                                data-type={type} data-parent-path={name} key={id}
+                                className={classNames(classes.row, getActiveClass(name))}>
+                                    { getItemIcon(type, getActiveClass(name)) }
+                                    <div className={classes.rowName}>
+                                        {name}
+                                    </div>
+                                    { getActiveClass(name)
+                                    ? <SidePanelRightArrowIcon style={{
+                                        display: 'inline',
+                                        marginTop: '5px',
+                                        marginLeft: '5px' }} />
+                                    : null }
+                            </div>;
+                        } }</FixedSizeList>
+                        : <div className={classes.rowEmpty}>No directories available</div>
+                    } }</AutoSizer>
+                    : <div className={classes.row}>
+                        <CircularProgress className={classes.loader} size={30} />
+                    </div> }
+                </div>
+            </div>
+            <div className={classes.rightPanel}>
+                <div className={classes.searchWrapper}>
+                    <SearchInput selfClearProp={rightKey} label="Search" value={rightSearch} onSearch={setRightSearch} />
+                </div>
+                { isWritable &&
+                <Button className={classes.uploadButton} data-cy='upload-button'
+                    onClick={() => {
+                        onUploadDataClick();
+                    }}
+                    variant='contained' color='primary' size='small'>
+                    <DownloadIcon className={classes.uploadIcon} />
+                    Upload data
+                </Button> }
+                <div className={classes.dataWrapper}>{ rightData && !isLoading
+                    ? <AutoSizer defaultHeight={500}>{({ height, width }) => {
+                        const filtered = rightData.filter(({ name }) => name.indexOf(rightSearch) > -1);
+
+                        return !!filtered.length
+                        ? <FixedSizeList height={height} itemCount={filtered.length}
+                            itemSize={35} width={width}>{ ({ index, style }) => {
+                                const { id, type, name, size } = filtered[index];
+
+                                return <div style={style} data-id={id} data-item="true"
+                                    data-type={type} data-subfolder-path={name}
+                                    className={classes.row} key={id}>
+                                    <Checkbox color="primary"
+                                        className={classes.rowSelection}
+                                        checked={collectionPanelFiles[id] ? collectionPanelFiles[id].value.selected : false}
+                                    /> 
+                                    {getItemIcon(type, null)}
+                                    <div className={classes.rowName}>
+                                        {name}
+                                    </div>
+                                    <span className={classes.rowName} style={{
+                                        marginLeft: 'auto', marginRight: '1rem' }}>
+                                        { formatFileSize(size) }
+                                    </span>
+                                </div>
+                            } }</FixedSizeList>
+                        : <div className={classes.rowEmpty}>This collection is empty</div>
+                    }}</AutoSizer>
+                    : <div className={classes.row}>
+                        <CircularProgress className={classes.loader} size={30} />
+                    </div> }
                 </div>
             </div>
         </div>
-    );
-}));
+    </div>}));

commit 555a6df1236e6c36a2552ee6100225c389f4c884
Author: Lucas Di Pentima <lucas.dipentima at curii.com>
Date:   Wed Mar 2 18:34:15 2022 -0300

    18787: Separating the wheat from the chaff. This changes should be innocuous.
    
    The remaining `wait(...)` and `.click({force: true})` calls are the most
    probable signs of issues on the code being tested.
    As a bonus: I've discovered some issues with the test about cancelling
    multiple uploads.
    
    Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima at curii.com>

diff --git a/cypress/integration/collection.spec.js b/cypress/integration/collection.spec.js
index b62a3441..0b06e53e 100644
--- a/cypress/integration/collection.spec.js
+++ b/cypress/integration/collection.spec.js
@@ -261,7 +261,7 @@ describe('Collection panel tests', function () {
                         });
                         // Test context menus
                         cy.get('[data-cy=collection-files-panel]')
-                            .contains(fileName).rightclick({ force: true });
+                            .contains(fileName).rightclick();
                         cy.get('[data-cy=context-menu]')
                             .should('contain', 'Download')
                             .and('not.contain', 'Open in new tab')
@@ -270,7 +270,7 @@ describe('Collection panel tests', function () {
                             .and(`${isWritable ? '' : 'not.'}contain`, 'Remove');
                         cy.get('body').click(); // Collapse the menu
                         cy.get('[data-cy=collection-files-panel]')
-                            .contains(subDirName).rightclick({ force: true });
+                            .contains(subDirName).rightclick();
                         cy.get('[data-cy=context-menu]')
                             .should('not.contain', 'Download')
                             .and('not.contain', 'Open in new tab')
@@ -368,7 +368,7 @@ describe('Collection panel tests', function () {
 
                 ['subdir', 'G%C3%BCnter\'s%20file', 'table%&?*2'].forEach((subdir) => {
                     cy.get('[data-cy=collection-files-panel]')
-                        .contains('bar').rightclick({force: true});
+                        .contains('bar').rightclick();
                     cy.get('[data-cy=context-menu]')
                         .contains('Rename')
                         .click();
@@ -381,9 +381,9 @@ describe('Collection panel tests', function () {
                     cy.get('[data-cy=collection-files-panel]')
                         .should('not.contain', 'bar')
                         .and('contain', subdir);
-                    cy.wait(1000);
                     cy.get('[data-cy=collection-files-panel]').contains(subdir).click();
-                    // Rename 'subdir/foo' to 'foo'
+
+                    // Rename 'subdir/foo' to 'bar'
                     cy.wait(1000);
                     cy.get('[data-cy=collection-files-panel]')
                         .contains('foo').rightclick();
@@ -399,7 +399,6 @@ describe('Collection panel tests', function () {
                         });
                     cy.get('[data-cy=form-submit-btn]').click();
 
-                    cy.wait(1000);
                     cy.get('[data-cy=collection-files-panel]')
                         .contains('Home')
                         .click();
@@ -1034,6 +1033,14 @@ describe('Collection panel tests', function () {
 
                     cy.goToPath(`/collections/${testCollection1.uuid}`);
 
+                    // Confirm initial collection state.
+                    cy.get('[data-cy=collection-files-panel]')
+                        .contains('bar').should('exist');
+                    cy.get('[data-cy=collection-files-panel]')
+                        .contains('5mb_a.bin').should('not.exist');
+                    cy.get('[data-cy=collection-files-panel]')
+                        .contains('5mb_b.bin').should('not.exist');
+
                     cy.get('[data-cy=upload-button]').click();
 
                     cy.fixture('files/5mb.bin', 'base64').then(content => {
@@ -1043,9 +1050,25 @@ describe('Collection panel tests', function () {
                         cy.get('[data-cy=form-submit-btn]').click();
 
                         cy.get('button[aria-label=Remove]').should('exist');
-                        cy.get('button[aria-label=Remove]').click({ multiple: true, force: true });
+                        cy.get('button[aria-label=Remove]')
+                            .click({ multiple: true, force: true });
 
                         cy.get('[data-cy=form-submit-btn]').should('not.exist');
+
+                        // Confirm final collection state.
+                        cy.get('[data-cy=collection-files-panel]')
+                            .contains('bar').should('exist');
+                        // The following fails, but doesn't seem to happen
+                        // in the real world. Maybe there's a race between
+                        // the PUT request finishing and the 'Remove' button
+                        // dissapearing, because sometimes just one of the 2
+                        // files gets uploaded.
+                        // Maybe this will be needed to simulate a slow network:
+                        // https://docs.cypress.io/api/commands/intercept#Convenience-functions-1
+                        // cy.get('[data-cy=collection-files-panel]')
+                        //     .contains('5mb_a.bin').should('not.exist');
+                        // cy.get('[data-cy=collection-files-panel]')
+                        //     .contains('5mb_b.bin').should('not.exist');
                     });
                 });
         });
diff --git a/cypress/integration/favorites.spec.js b/cypress/integration/favorites.spec.js
index 105657ef..7fd09124 100644
--- a/cypress/integration/favorites.spec.js
+++ b/cypress/integration/favorites.spec.js
@@ -64,7 +64,7 @@ describe('Favorites tests', function () {
                 cy.loginAs(activeUser);
                 cy.goToPath(`/collections/${testSourceCollection.uuid}`);
                 cy.get('[data-cy=collection-files-panel]').contains('bar');
-                cy.get('[data-cy=collection-files-panel]').find('input[type=checkbox]').click({ force: true });
+                cy.get('[data-cy=collection-files-panel]').find('input[type=checkbox]').click();
                 cy.get('[data-cy=collection-files-panel-options-btn]').click();
                 cy.get('[data-cy=context-menu]')
                     .contains('Copy selected into the collection').click();

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list