X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/852a6a393297d03ca5259ddb6aa7aedff4a000ea..2a7fd99c212c33a1ec9911f8529fa5afc59a7bb2:/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 42408270c0..fb36ebce54 100644 --- a/src/components/collection-panel-files/collection-panel-files.tsx +++ b/src/components/collection-panel-files/collection-panel-files.tsx @@ -8,7 +8,7 @@ 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 { CustomizeTableIcon, DownloadIcon, MoreOptionsIcon } from 'components/icon/icon'; import { SearchInput } from 'components/search-input/search-input'; import { ListItemIcon, @@ -60,6 +60,8 @@ type CssRules = "backButton" | "pathPanelPathWrapper" | "uploadButton" | "uploadIcon" + | "moreOptionsButton" + | "moreOptions" | "loader" | "wrapper" | "dataWrapper" @@ -83,7 +85,7 @@ const styles: StyleRulesCallback = (theme: Theme) => ({ wrapper: { display: 'flex', minHeight: '600px', - color: 'rgba(0, 0, 0, 0.87)', + color: 'rgba(0,0,0,0.87)', fontSize: '0.875rem', fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', fontWeight: 400, @@ -152,8 +154,8 @@ const styles: StyleRulesCallback = (theme: Theme) => ({ marginTop: '-15px', }, pathPanel: { - padding: '1rem', - marginBottom: '1rem', + 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%)', }, @@ -162,7 +164,7 @@ const styles: StyleRulesCallback = (theme: Theme) => ({ }, leftPanel: { flex: 0, - padding: '1rem', + padding: '0 1rem 1rem', marginRight: '1rem', whiteSpace: 'nowrap', position: 'relative', @@ -193,8 +195,8 @@ const styles: StyleRulesCallback = (theme: Theme) => ({ rightPanel: { flex: '50%', padding: '1rem', - paddingTop: '2rem', - marginTop: '-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%)', @@ -207,7 +209,18 @@ const styles: StyleRulesCallback = (theme: Theme) => ({ }, uploadButton: { 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 = {}; @@ -220,11 +233,12 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState 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 webdavClient = new WebDAV({ + baseURL: config.keepWebServiceUrl, + headers: { + Authorization: `Bearer ${apiToken}` + }, + }); const webDAVRequestConfig: WebDAVRequestConfig = { headers: { @@ -295,8 +309,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState }).reduce((prev, next) => { return { ...next, ...prev }; }, {}); - - setPathData({ ...pathData, ...newState }); + setPathData((state) => ({ ...state, ...newState })); }) .finally(() => { setIsLoading(false); @@ -315,12 +328,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState const currentPDH = (collectionPanel.item || {}).portableDataHash; React.useEffect(() => { if (currentPDH) { - // Avoid fetching the same content level twice - if (leftKey !== rightKey) { - fetchData([leftKey, rightKey], true); - } else { - fetchData(rightKey, true); - } + fetchData([leftKey, rightKey], true); } }, [currentPDH]); // eslint-disable-line react-hooks/exhaustive-deps @@ -375,22 +383,28 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState const handleClick = React.useCallback( (event: any) => { let isCheckbox = false; + let isMoreButton = false; let elem = event.target; 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; + } while (elem && elem.dataset && !elem.dataset.item) { elem = elem.parentNode; } - if (elem && elem.dataset && !isCheckbox) { + if (elem && elem.dataset && !isCheckbox && !isMoreButton) { const { parentPath, subfolderPath, breadcrumbPath, type } = elem.dataset; if (breadcrumbPath) { const index = path.indexOf(breadcrumbPath); - setPath([...path.slice(0, index + 1)]); + setPath((state) => ([...state.slice(0, index + 1)])); } if (parentPath && type === 'directory') { @@ -398,11 +412,11 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState path.pop() } - setPath([...path, parentPath]); + setPath((state) => ([...state, parentPath])); } if (subfolderPath && type === 'directory') { - setPath([...path, subfolderPath]); + setPath((state) => ([...state, subfolderPath])); } if (elem.dataset.id && type === 'file') { @@ -418,6 +432,14 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState 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 ); @@ -480,7 +502,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState
1 ? classes.leftPanelVisible : classes.leftPanelHidden)} data-cy="collection-files-left-panel"> 1 ? classes.backButton : classes.backButtonHidden}> - setPath([...path.slice(0, path.length -1)])}> + setPath((state) => ([...state.slice(0, state.length -1)]))}> @@ -512,7 +534,7 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState :
No directories available
}} - :
} + :
}
@@ -551,6 +573,15 @@ export const CollectionPanelFiles = withStyles(styles)(connect((state: RootState marginLeft: 'auto', marginRight: '1rem' }}> { formatFileSize(size) } + + + + +
} } :
This collection is empty