X-Git-Url: https://git.arvados.org/arvados-workbench2.git/blobdiff_plain/29280b2ea824414bb703ac8b63cf3f90f72aea62..31e84a9315728c2f58a26bf0e9e1d2b38326fb86:/src/views-components/side-panel-button/side-panel-button.tsx diff --git a/src/views-components/side-panel-button/side-panel-button.tsx b/src/views-components/side-panel-button/side-panel-button.tsx index e39b3782..fb5ea11f 100644 --- a/src/views-components/side-panel-button/side-panel-button.tsx +++ b/src/views-components/side-panel-button/side-panel-button.tsx @@ -5,15 +5,22 @@ import * as React from 'react'; import { connect, DispatchProp } from 'react-redux'; import { RootState } from '~/store/store'; -import { getProperty } from '~/store/properties/properties'; -import { PROJECT_PANEL_CURRENT_UUID } from '~/store/project-panel/project-panel-action'; import { ArvadosTheme } from '~/common/custom-theme'; import { PopoverOrigin } from '@material-ui/core/Popover'; import { StyleRulesCallback, WithStyles, withStyles, Toolbar, Grid, Button, MenuItem, Menu } from '@material-ui/core'; import { AddIcon, CollectionIcon, ProcessIcon, ProjectIcon } from '~/components/icon/icon'; import { openProjectCreateDialog } from '~/store/projects/project-create-actions'; import { openCollectionCreateDialog } from '~/store/collections/collection-create-actions'; +import { navigateToRunProcess } from '~/store/navigation/navigation-action'; +import { runProcessPanelActions } from '~/store/run-process-panel/run-process-panel-actions'; +import { getUserUuid } from '~/common/getuser'; import { matchProjectRoute } from '~/routes/routes'; +import { GroupClass, GroupResource } from '~/models/group'; +import { ResourcesState, getResource } from '~/store/resources/resources'; +import { extractUuidKind, ResourceKind } from '~/models/resource'; +import { pluginConfig } from '~/plugins'; +import { ElementListReducer } from '~/common/plugintypes'; +import { Location } from 'history'; type CssRules = 'button' | 'menuItem' | 'icon'; @@ -33,8 +40,10 @@ const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ }); interface SidePanelDataProps { + location: Location; currentItemId: string; - buttonVisible: boolean; + resources: ResourcesState; + currentUserUUID: string | undefined; } interface SidePanelState { @@ -45,19 +54,25 @@ type SidePanelProps = SidePanelDataProps & DispatchProp & WithStyles; const transformOrigin: PopoverOrigin = { vertical: -50, - horizontal: 45 + horizontal: 0 }; -const isButtonVisible = ({ router }: RootState) => { - const pathname = router.location ? router.location.pathname : ''; - const match = matchProjectRoute(pathname); - return !!match; +export const isProjectTrashed = (proj: GroupResource | undefined, resources: ResourcesState): boolean => { + if (proj === undefined) { return false; } + if (proj.isTrashed) { return true; } + if (extractUuidKind(proj.ownerUuid) === ResourceKind.USER) { return false; } + const parentProj = getResource(proj.ownerUuid)(resources); + return isProjectTrashed(parentProj, resources); }; export const SidePanelButton = withStyles(styles)( connect((state: RootState) => ({ - currentItemId: getProperty(PROJECT_PANEL_CURRENT_UUID)(state.properties), - buttonVisible: isButtonVisible(state) + currentItemId: state.router.location + ? state.router.location.pathname.split('/').slice(-1)[0] + : null, + location: state.router.location, + resources: state.resources, + currentUserUUID: getUserUuid(state), }))( class extends React.Component { @@ -66,12 +81,50 @@ export const SidePanelButton = withStyles(styles)( }; render() { - const { classes, buttonVisible } = this.props; + const { classes, location, resources, currentUserUUID, currentItemId } = this.props; const { anchorEl } = this.state; + let enabled = false; + if (currentItemId === currentUserUUID) { + enabled = true; + } else if (matchProjectRoute(location ? location.pathname : '')) { + const currentProject = getResource(currentItemId)(resources); + if (currentProject && + currentProject.writableBy.indexOf(currentUserUUID || '') >= 0 && + !isProjectTrashed(currentProject, resources) && + currentProject.groupClass !== GroupClass.FILTER) { + enabled = true; + } + } + + for (const enableFn of pluginConfig.enableNewButtonMatchers) { + if (enableFn(location, currentItemId, currentUserUUID, resources)) { + enabled = true; + } + } + + let menuItems = <> + + New collection + + + Run a process + + + New project + + ; + + const reduceItemsFn: (a: React.ReactElement[], b: ElementListReducer) => React.ReactElement[] = + (a, b) => b(a, classes.menuItem); + + menuItems = React.createElement(React.Fragment, null, + pluginConfig.newButtonMenuList.reduce(reduceItemsFn, React.Children.toArray(menuItems.props.children))); + return - {buttonVisible && - -