X-Git-Url: https://git.arvados.org/arvados-workbench2.git/blobdiff_plain/d6a28995f22dc04688444c0098b185717f7d4ed4..5d6640046afef7dc3714b784430e18bf2f2153fe:/src/components/collection-panel-files/collection-panel-files.tsx diff --git a/src/components/collection-panel-files/collection-panel-files.tsx b/src/components/collection-panel-files/collection-panel-files.tsx index 3c064973..f1e50e0f 100644 --- a/src/components/collection-panel-files/collection-panel-files.tsx +++ b/src/components/collection-panel-files/collection-panel-files.tsx @@ -2,32 +2,41 @@ // // SPDX-License-Identifier: AGPL-3.0 -import React from 'react'; -import classNames from 'classnames'; -import { connect } from 'react-redux'; +import React from "react"; +import classNames from "classnames"; +import { connect } from "react-redux"; import { FixedSizeList } from "react-window"; 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 { 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 { setCollectionFiles } from 'store/collection-panel/collection-panel-files/collection-panel-files-actions'; -import { sortBy } from 'lodash'; -import { formatFileSize } from 'common/formatters'; -import { getInlineFileUrl, sanitizeToken } from 'views-components/context-menu/actions/helpers'; +import servicesProvider from "common/service-provider"; +import { DownloadIcon, MoreHorizontalIcon, MoreVerticalIcon } 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 { 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 { setCollectionFiles } from "store/collection-panel/collection-panel-files/collection-panel-files-actions"; +import { sortBy } from "lodash"; +import { formatFileSize } from "common/formatters"; +import { getInlineFileUrl, sanitizeToken } from "views-components/context-menu/actions/helpers"; +import { extractUuidKind, ResourceKind } from "models/resource"; export interface CollectionPanelFilesProps { - items: any; isWritable: boolean; - isLoading: boolean; - tooManyFiles: boolean; onUploadDataClick: (targetLocation?: string) => void; onSearchChange: (searchValue: string) => void; onItemMenuOpen: (event: React.MouseEvent, item: TreeItem, isWritable: boolean) => void; @@ -35,575 +44,665 @@ export interface CollectionPanelFilesProps { onSelectionToggle: (event: React.MouseEvent, item: TreeItem) => void; onCollapseToggle: (id: string, status: TreeItemStatus) => void; onFileClick: (id: string) => void; - loadFilesFunc: () => void; currentItemUuid: any; dispatch: Function; collectionPanelFiles: any; 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" + | "moreOptionsButton" + | "moreOptions" + | "loader" + | "wrapper" + | "dataWrapper" + | "row" + | "rowEmpty" + | "leftPanel" + | "rightPanel" + | "pathPanel" + | "pathPanelItem" + | "rowName" + | "listItemIcon" + | "rowActive" + | "pathPanelMenu" + | "rowSelection" + | "leftPanelHidden" + | "leftPanelVisible" + | "searchWrapper" + | "searchWrapperHidden"; const styles: StyleRulesCallback = (theme: Theme) => ({ wrapper: { - display: 'flex', - minHeight: '600px', - color: 'rgba(0, 0, 0, 0.87)', - fontSize: '0.875rem', + display: "flex", + minHeight: "600px", + color: "rgba(0,0,0,0.87)", + fontSize: "0.875rem", fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', fontWeight: 400, - lineHeight: '1.5', - letterSpacing: '0.01071em' + lineHeight: "1.5", + letterSpacing: "0.01071em", }, backButton: { - color: '#00bfa5', - cursor: 'pointer', - float: 'left', + color: "#00bfa5", + cursor: "pointer", + float: "left", }, backButtonHidden: { - display: 'none', + display: "none", }, dataWrapper: { - minHeight: '500px' + minHeight: "500px", }, row: { - display: 'flex', - marginTop: '0.5rem', - marginBottom: '0.5rem', - cursor: 'pointer', + display: "flex", + marginTop: "0.5rem", + marginBottom: "0.5rem", + cursor: "pointer", "&:hover": { - backgroundColor: 'rgba(0, 0, 0, 0.08)', - } + backgroundColor: "rgba(0, 0, 0, 0.08)", + }, }, rowEmpty: { - top: '40%', - width: '100%', - textAlign: 'center', - position: 'absolute' + top: "40%", + width: "100%", + textAlign: "center", + position: "absolute", }, loader: { - top: '50%', - left: '50%', - marginTop: '-15px', - marginLeft: '-15px', - position: 'absolute' + top: "50%", + left: "50%", + marginTop: "-15px", + marginLeft: "-15px", + position: "absolute", }, rowName: { - display: 'inline-flex', - flexDirection: 'column', - justifyContent: 'center' + display: "inline-flex", + flexDirection: "column", + justifyContent: "center", }, searchWrapper: { - display: 'inline-block', - marginBottom: '1rem', - marginLeft: '1rem', + display: "inline-block", + marginBottom: "1rem", + marginLeft: "1rem", }, searchWrapperHidden: { - width: '0px' + width: "0px", }, rowSelection: { - padding: '0px', + padding: "0px", }, rowActive: { color: `${theme.palette.primary.main} !important`, }, listItemIcon: { - display: 'inline-flex', - flexDirection: 'column', - justifyContent: 'center' + display: "inline-flex", + flexDirection: "column", + justifyContent: "center", }, pathPanelMenu: { - float: 'right', - marginTop: '-15px', + float: "right", + marginTop: "-15px", }, pathPanel: { - padding: '1rem', - marginBottom: '1rem', - backgroundColor: '#fff', - boxShadow: '0px 1px 3px 0px rgb(0 0 0 / 20%), 0px 1px 1px 0px rgb(0 0 0 / 14%), 0px 2px 1px -1px rgb(0 0 0 / 12%)', + padding: "0.5rem", + marginBottom: "0.5rem", + backgroundColor: "#fff", + boxShadow: "0px 1px 3px 0px rgb(0 0 0 / 20%), 0px 1px 1px 0px rgb(0 0 0 / 14%), 0px 2px 1px -1px rgb(0 0 0 / 12%)", }, pathPanelPathWrapper: { - display: 'inline-block', + display: "inline-block", }, leftPanel: { flex: 0, - padding: '1rem', - marginRight: '1rem', - whiteSpace: 'nowrap', - position: 'relative', - backgroundColor: '#fff', - boxShadow: '0px 3px 3px 0px rgb(0 0 0 / 20%), 0px 3px 1px 0px rgb(0 0 0 / 14%), 0px 3px 1px -1px rgb(0 0 0 / 12%)', + padding: "0 1rem 1rem", + marginRight: "1rem", + whiteSpace: "nowrap", + position: "relative", + backgroundColor: "#fff", + boxShadow: "0px 3px 3px 0px rgb(0 0 0 / 20%), 0px 3px 1px 0px rgb(0 0 0 / 14%), 0px 3px 1px -1px rgb(0 0 0 / 12%)", }, leftPanelVisible: { opacity: 1, - flex: '50%', - animation: `animateVisible 1000ms ${theme.transitions.easing.easeOut}` + flex: "50%", + animation: `animateVisible 1000ms ${theme.transitions.easing.easeOut}`, }, leftPanelHidden: { opacity: 0, - flex: 'initial', - padding: '0', - marginRight: '0', + flex: "initial", + padding: "0", + marginRight: "0", }, "@keyframes animateVisible": { "0%": { opacity: 0, - flex: 'initial', + flex: "initial", }, "100%": { opacity: 1, - flex: '50%', - } + flex: "50%", + }, }, rightPanel: { - flex: '50%', - padding: '1rem', - paddingTop: '2rem', - marginTop: '-1rem', - position: 'relative', - backgroundColor: '#fff', - boxShadow: '0px 3px 3px 0px rgb(0 0 0 / 20%), 0px 3px 1px 0px rgb(0 0 0 / 14%), 0px 3px 1px -1px rgb(0 0 0 / 12%)', + flex: "50%", + padding: "1rem", + paddingTop: "0.5rem", + marginTop: "-0.5rem", + position: "relative", + backgroundColor: "#fff", + boxShadow: "0px 3px 3px 0px rgb(0 0 0 / 20%), 0px 3px 1px 0px rgb(0 0 0 / 14%), 0px 3px 1px -1px rgb(0 0 0 / 12%)", }, pathPanelItem: { - cursor: 'pointer', + cursor: "pointer", }, uploadIcon: { - transform: 'rotate(180deg)' + transform: "rotate(180deg)", }, uploadButton: { - float: 'right', - } + float: "right", + }, + moreOptionsButton: { + width: theme.spacing.unit * 3, + height: theme.spacing.unit * 3, + marginRight: theme.spacing.unit, + marginTop: "auto", + marginBottom: "auto", + justifyContent: "center", + }, + moreOptions: { + position: "absolute", + }, }); const pathPromise = {}; -export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState) => ({ - auth: state.auth, - collectionPanel: state.collectionPanel, - collectionPanelFiles: state.collectionPanelFiles, -}))((props: CollectionPanelFilesProps & WithStyles & { auth: AuthState }) => { - const { classes, onItemMenuOpen, onUploadDataClick, isWritable, dispatch, collectionPanelFiles, collectionPanel } = props; - const { apiToken, config } = props.auth; - - const webdavClient = new WebDAV(); - webdavClient.defaults.baseURL = config.keepWebServiceUrl; - webdavClient.defaults.headers = { - Authorization: `Bearer ${apiToken}` - }; - - const webDAVRequestConfig: WebDAVRequestConfig = { - headers: { - Depth: '1', - }, - }; - - const parentRef = React.useRef(null); - const [path, setPath]: any = React.useState([]); - const [pathData, setPathData]: any = React.useState({}); - const [isLoading, setIsLoading] = React.useState(false); - const [leftSearch, setLeftSearch] = React.useState(''); - const [rightSearch, setRightSearch] = React.useState(''); - - const leftKey = (path.length > 1 ? path.slice(0, path.length - 1) : path).join('/'); - const rightKey = path.join('/'); - - const leftData = pathData[leftKey] || []; - const rightData = pathData[rightKey]; - - React.useEffect(() => { - if (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) - .map((key) => { - const dataExists = !!pathData[key]; - const runningRequest = pathPromise[key]; - - if ((!dataExists || ignoreCache) && (!runningRequest || ignoreCache)) { - if (!isLoading) { - setIsLoading(true); - } +export const CollectionPanelFiles = withStyles(styles)( + connect((state: RootState) => ({ + auth: state.auth, + collectionPanel: state.collectionPanel, + collectionPanelFiles: state.collectionPanelFiles, + }))((props: CollectionPanelFilesProps & WithStyles & { auth: AuthState }) => { + const { classes, onItemMenuOpen, onUploadDataClick, isWritable, dispatch, collectionPanelFiles, collectionPanel } = props; + const { apiToken, config } = props.auth; + + const webdavClient = new WebDAV({ + baseURL: config.keepWebServiceUrl, + headers: { + Authorization: `Bearer ${apiToken}`, + }, + }); - pathPromise[key] = true; + const webDAVRequestConfig: WebDAVRequestConfig = { + headers: { + Depth: "1", + }, + }; - console.log('>>> fetching data for key', key); - return webdavClient.propfind(`c=${key}`, webDAVRequestConfig); - } + const parentRef = React.useRef(null); + const [path, setPath] = React.useState([]); + const [pathData, setPathData] = React.useState({}); + const [isLoading, setIsLoading] = React.useState(false); + const [leftSearch, setLeftSearch] = React.useState(""); + const [rightSearch, setRightSearch] = React.useState(""); - return Promise.resolve(null); - }) - .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; - }); + const leftKey = (path.length > 1 ? path.slice(0, path.length - 1) : path).join("/"); + const rightKey = path.join("/"); - return { [key]: sortedResult }; - } - return {}; - }).reduce((prev, next) => { - return { ...next, ...prev }; - }, {}); - - setPathData({ ...pathData, ...newState }); - }) - .finally(() => { - setIsLoading(false); - keyArray.forEach(key => delete pathPromise[key]); - }); - }; - - React.useEffect(() => { - if (rightKey) { - fetchData(rightKey); - setLeftSearch(''); - setRightSearch(''); - } - }, [rightKey]); // eslint-disable-line react-hooks/exhaustive-deps - - const currentPDH = (collectionPanel.item || {}).portableDataHash; - React.useEffect(() => { - if (currentPDH) { - fetchData([leftKey, rightKey], true); - } - }, [currentPDH]); // eslint-disable-line react-hooks/exhaustive-deps - - React.useEffect(() => { - if (rightData) { - const filtered = rightData.filter(({ name }) => name.indexOf(rightSearch) > -1); - setCollectionFiles(filtered, false)(dispatch); - } - }, [rightData, dispatch, rightSearch]); - - const handleRightClick = React.useCallback( - (event) => { - event.preventDefault(); - let elem = event.target; - - while (elem && elem.dataset && !elem.dataset.item) { - elem = elem.parentNode; - } + const leftData = pathData[leftKey] || []; + const rightData = pathData[rightKey]; - if (!elem || !elem.dataset) { - return; + React.useEffect(() => { + if (props.currentItemUuid && extractUuidKind(props.currentItemUuid) === ResourceKind.COLLECTION) { + setPathData({}); + setPath([props.currentItemUuid]); } + }, [props.currentItemUuid]); - const { id } = elem.dataset; + const fetchData = (keys, ignoreCache = false) => { + const keyArray = Array.isArray(keys) ? keys : [keys]; - const item: any = { - id, - data: rightData.find((elem) => elem.id === id), - }; + Promise.all( + keyArray + .filter(key => !!key) + .map(key => { + const dataExists = !!pathData[key]; + const runningRequest = pathPromise[key]; - if (id) { - onItemMenuOpen(event, item, isWritable); - } - }, - [onItemMenuOpen, isWritable, rightData] // eslint-disable-line react-hooks/exhaustive-deps - ); + if (ignoreCache || (!dataExists && !runningRequest)) { + if (!isLoading) { + setIsLoading(true); + } - React.useEffect(() => { - let node = null; + pathPromise[key] = true; - if (parentRef && parentRef.current) { - node = parentRef.current; - (node as any).addEventListener('contextmenu', handleRightClick); - } + return webdavClient.propfind(`c=${key}`, webDAVRequestConfig); + } - return () => { - if (node) { - (node as any).removeEventListener('contextmenu', handleRightClick); - } + return Promise.resolve(null); + }) + .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 }; + }, {}); + setPathData(state => ({ ...state, ...newState })); + }, () => { + // Nothing to do + }) + .finally(() => { + setIsLoading(false); + keyArray.forEach(key => delete pathPromise[key]); + }); }; - }, [parentRef, handleRightClick]); - const handleClick = React.useCallback( - (event: any) => { - let isCheckbox = false; - let elem = event.target; + React.useEffect(() => { + if (rightKey) { + fetchData(rightKey); + setLeftSearch(""); + setRightSearch(""); + } + }, [rightKey, rightData]); // eslint-disable-line react-hooks/exhaustive-deps - if (elem.type === 'checkbox') { - isCheckbox = true; + const currentPDH = (collectionPanel.item || {}).portableDataHash; + React.useEffect(() => { + if (currentPDH) { + fetchData([leftKey, rightKey], true); } + }, [currentPDH]); // eslint-disable-line react-hooks/exhaustive-deps - while (elem && elem.dataset && !elem.dataset.item) { - elem = elem.parentNode; + React.useEffect(() => { + if (rightData) { + const filtered = rightData.filter(({ name }) => name.indexOf(rightSearch) > -1); + setCollectionFiles(filtered, false)(dispatch); } + }, [rightData, dispatch, rightSearch]); - if (elem && elem.dataset && !isCheckbox) { - const { parentPath, subfolderPath, breadcrumbPath, type } = elem.dataset; + const handleRightClick = React.useCallback( + event => { + event.preventDefault(); + let elem = event.target; - if (breadcrumbPath) { - const index = path.indexOf(breadcrumbPath); - setPath([...path.slice(0, index + 1)]); + while (elem && elem.dataset && !elem.dataset.item) { + elem = elem.parentNode; } - if (parentPath && type === 'directory') { - if (path.length > 1) { - path.pop() - } + if (!elem || !elem.dataset) { + return; + } + + const { id } = elem.dataset; + + const item: any = { + id, + data: rightData.find(elem => elem.id === id), + }; - setPath([...path, parentPath]); + if (id) { + onItemMenuOpen(event, item, isWritable); } + }, + [onItemMenuOpen, isWritable, rightData] + ); + + React.useEffect(() => { + let node = null; + + if (parentRef?.current) { + node = parentRef.current; + (node as any).addEventListener("contextmenu", handleRightClick); + } - if (subfolderPath && type === 'directory') { - setPath([...path, subfolderPath]); + return () => { + if (node) { + (node as any).removeEventListener("contextmenu", handleRightClick); } + }; + }, [parentRef, handleRightClick]); + + const handleClick = React.useCallback( + (event: any) => { + let isCheckbox = false; + let isMoreButton = false; + let elem = event.target; - if (elem.dataset.id && type === 'file') { - const item = rightData.find(({id}) => id === elem.dataset.id) || leftData.find(({ id }) => id === elem.dataset.id); - const enhancedItem = servicesProvider.getServices().collectionService.extendFileURL(item); - const fileUrl = sanitizeToken(getInlineFileUrl(enhancedItem.url, config.keepWebServiceUrl, config.keepWebInlineServiceUrl), true); - window.open(fileUrl, '_blank'); + if (elem.type === "checkbox") { + isCheckbox = true; + } + // The "More options" button click event could be triggered on its + // internal graphic element. + else if ( + (elem.dataset && elem.dataset.id === "moreOptions") || + (elem.parentNode && elem.parentNode.dataset && elem.parentNode.dataset.id === "moreOptions") + ) { + isMoreButton = true; } - } - if (isCheckbox) { - const { id } = elem.dataset; - const item = collectionPanelFiles[id]; - props.onSelectionToggle(event, item); - } - }, - [path, setPath, collectionPanelFiles] // eslint-disable-line react-hooks/exhaustive-deps - ); - - const getItemIcon = React.useCallback( - (type: string, activeClass: string | null) => { - let Icon = DefaultIcon; - - switch (type) { - case 'directory': - Icon = DirectoryIcon; - break; - case 'file': - Icon = FileIcon; - break; - } + while (elem && elem.dataset && !elem.dataset.item) { + elem = elem.parentNode; + } - return ( - - - - ) - }, - [classes] - ); + if (elem && elem.dataset && !isCheckbox && !isMoreButton) { + const { parentPath, subfolderPath, breadcrumbPath, type } = elem.dataset; - const getActiveClass = React.useCallback( - (name) => { - return path[path.length - 1] === name ? classes.rowActive : null; - }, - [path, classes] - ); + if (breadcrumbPath) { + const index = path.indexOf(breadcrumbPath); + setPath(state => [...state.slice(0, index + 1)]); + } - const onOptionsMenuOpen = React.useCallback( - (ev, isWritable) => { - props.onOptionsMenuOpen(ev, isWritable); - }, - [props.onOptionsMenuOpen] // eslint-disable-line react-hooks/exhaustive-deps - ); - - return
-
-
- { path.map((p: string, index: number) => - {index === 0 ? 'Home' : p} /  - ) } -
- - { - onOptionsMenuOpen(ev, isWritable); - }}> - - - -
-
-
1 ? classes.leftPanelVisible : classes.leftPanelHidden)} data-cy="collection-files-left-panel"> - 1 ? classes.backButton : classes.backButtonHidden}> - setPath([...path.slice(0, path.length -1)])}> - - - -
-
-
1 ? classes.leftPanelVisible : classes.leftPanelHidden)} data-cy="collection-files-left-panel"> - 1 ? classes.backButton : classes.backButtonHidden}> - setPath([...path.slice(0, path.length -1)])}> - + if (parentPath && type === "directory") { + if (path.length > 1) { + path.pop(); + } + + setPath(state => [...state, parentPath]); + } + + if (subfolderPath && type === "directory") { + setPath(state => [...state, subfolderPath]); + } + + if (elem.dataset.id && type === "file") { + const item = rightData.find(({ id }) => id === elem.dataset.id) || leftData.find(({ id }) => id === elem.dataset.id); + const enhancedItem = servicesProvider.getServices().collectionService.extendFileURL(item); + const fileUrl = sanitizeToken( + getInlineFileUrl(enhancedItem.url, config.keepWebServiceUrl, config.keepWebInlineServiceUrl), + true + ); + window.open(fileUrl, "_blank"); + } + } + + if (isCheckbox) { + const { id } = elem.dataset; + const item = collectionPanelFiles[id]; + props.onSelectionToggle(event, item); + } + if (isMoreButton) { + const { id } = elem.dataset; + const item: any = { + id, + data: rightData.find(elem => elem.id === id), + }; + onItemMenuOpen(event, item, isWritable); + } + }, + [path, setPath, collectionPanelFiles] // eslint-disable-line react-hooks/exhaustive-deps + ); + + const getItemIcon = React.useCallback( + (type: string, activeClass: string | null) => { + let Icon = DefaultIcon; + + switch (type) { + case "directory": + Icon = DirectoryIcon; + break; + case "file": + Icon = FileIcon; + break; + } + + return ( + + + + ); + }, + [classes] + ); + + const getActiveClass = React.useCallback( + name => { + return path[path.length - 1] === name ? classes.rowActive : null; + }, + [path, classes] + ); + + const onOptionsMenuOpen = React.useCallback( + (ev, isWritable) => { + props.onOptionsMenuOpen(ev, isWritable); + }, + [props.onOptionsMenuOpen] // eslint-disable-line react-hooks/exhaustive-deps + ); + + return ( +
+
+
+ {path.map((p: string, index: number) => ( + + {index === 0 ? "Home" : p} /  + + ))} +
+ + { + onOptionsMenuOpen(ev, isWritable); + }} + > + -
1 ? classes.searchWrapper : classes.searchWrapperHidden}> - -
-
- { - leftData ? +
+
+
1 ? classes.leftPanelVisible : classes.leftPanelHidden)} + data-cy="collection-files-left-panel" + > + 1 ? classes.backButton : classes.backButtonHidden} + > + setPath(state => [...state.slice(0, state.length - 1)])}> + + + +
1 ? classes.searchWrapper : classes.searchWrapperHidden}> + +
+
+ {leftData ? ( {({ height, width }) => { const filtered = leftData.filter(({ name }) => name.indexOf(leftSearch) > -1); - - return !!filtered.length ? - { - ({ index, style }) => { + return !!filtered.length ? ( + + {({ index, style }) => { const { id, type, name } = filtered[index]; - - return
+ return ( +
{getItemIcon(type, getActiveClass(name))} -
- {name} -
- { - getActiveClass(name) ? : null - } -
; - } - } - :
No directories available
+
{name}
+ {getActiveClass(name) ? ( + + ) : null} +
+ ); + }} +
+ ) : ( +
No directories available
+ ); }} -
:
- } - -
-
-
-
- + + ) : ( +
+ +
+ )} +
- { - isWritable && - - } -
- { - rightData && !isLoading ? +
+
+ +
+ {isWritable && ( + + )} +
+ {rightData && !isLoading ? ( {({ height, width }) => { const filtered = rightData.filter(({ name }) => name.indexOf(rightSearch) > -1); - - return !!filtered.length - ? { ({ index, style }) => { - console.log("Left Data ROW: ", filtered[index]); - const { id, type, name } = filtered[index]; - - return
- { getItemIcon(type, getActiveClass(name)) } -
- {name} -
- { getActiveClass(name) - ? - : null } -
; - } }
- :
No directories available
- } }
- :
- -
} -
-
-
-
- -
- { isWritable && - } -
{ rightData && !isLoading - ? {({ height, width }) => { - const filtered = rightData.filter(({ name }) => name.indexOf(rightSearch) > -1); - - return !!filtered.length - ? { ({ index, style }) => { - console.log("Right Data ROW: ", filtered[index]); - const { id, type, name, size } = filtered[index]; - - return
-   - {getItemIcon(type, null)} -
- {name} -
- - { formatFileSize(size) } - + return !!filtered.length ? ( + + {({ index, style }) => { + const { id, type, name, size } = filtered[index]; + + return ( +
+ +   + {getItemIcon(type, null)} +
{name}
+ + {formatFileSize(size)} + + + + + + +
+ ); + }} +
+ ) : ( +
This collection is empty
+ ); + }} + + ) : ( +
+
- } } - :
This collection is empty
- }} - :
- -
} + )} +
+
-
-
})); + ); + }) +);