import { setTokenDialogApiHost } from "store/token-dialog/token-dialog-actions";
import {
processResourceActionSet,
+ runningProcessResourceActionSet,
processResourceAdminActionSet,
+ runningProcessResourceAdminActionSet,
readOnlyProcessResourceActionSet,
} from "views-components/context-menu/action-sets/process-resource-action-set";
import { progressIndicatorActions } from "store/progress-indicator/progress-indicator-actions";
addMenuActionSet(ContextMenuKind.OLD_VERSION_COLLECTION, oldCollectionVersionActionSet);
addMenuActionSet(ContextMenuKind.TRASHED_COLLECTION, trashedCollectionActionSet);
addMenuActionSet(ContextMenuKind.PROCESS_RESOURCE, processResourceActionSet);
+addMenuActionSet(ContextMenuKind.RUNNING_PROCESS_RESOURCE, runningProcessResourceActionSet);
addMenuActionSet(ContextMenuKind.READONLY_PROCESS_RESOURCE, readOnlyProcessResourceActionSet);
addMenuActionSet(ContextMenuKind.TRASH, trashActionSet);
addMenuActionSet(ContextMenuKind.REPOSITORY, repositoryActionSet);
addMenuActionSet(ContextMenuKind.GROUP_MEMBER, groupMemberActionSet);
addMenuActionSet(ContextMenuKind.COLLECTION_ADMIN, collectionAdminActionSet);
addMenuActionSet(ContextMenuKind.PROCESS_ADMIN, processResourceAdminActionSet);
+addMenuActionSet(ContextMenuKind.RUNNING_PROCESS_ADMIN, runningProcessResourceAdminActionSet);
addMenuActionSet(ContextMenuKind.PROJECT_ADMIN, projectAdminActionSet);
addMenuActionSet(ContextMenuKind.FROZEN_PROJECT, frozenActionSet);
addMenuActionSet(ContextMenuKind.FROZEN_PROJECT_ADMIN, frozenAdminActionSet);
import { UserResource } from "models/user";
import { isSidePanelTreeCategory } from "store/side-panel-tree/side-panel-tree-actions";
import { extractUuidKind, ResourceKind, EditableResource, Resource } from "models/resource";
-import { Process } from "store/processes/process";
+import { Process, isProcessCancelable } from "store/processes/process";
import { RepositoryResource } from "models/repositories";
import { SshKeyResource } from "models/ssh-key";
import { VirtualMachinesResource } from "models/virtual-machines";
import { LinkResource } from "models/link";
import { resourceIsFrozen } from "common/frozen-resources";
import { ProjectResource } from "models/project";
+import { getProcess } from "store/processes/process";
import { filterCollectionFilesBySelection } from "store/collection-panel/collection-panel-files/collection-panel-files-state";
export const contextMenuActions = unionize({
description: res.description,
outputUuid: res.outputUuid || "",
workflowUuid: res.properties.template_uuid || "",
- menuKind: ContextMenuKind.PROCESS_RESOURCE,
+ menuKind: isProcessCancelable(process) ? ContextMenuKind.RUNNING_PROCESS_RESOURCE : ContextMenuKind.PROCESS_RESOURCE
})
);
}
: ContextMenuKind.READONLY_COLLECTION;
case ResourceKind.PROCESS:
return isAdminUser && isEditable
- ? ContextMenuKind.PROCESS_ADMIN
+ ? resource && isProcessCancelable(getProcess(resource.uuid)(getState().resources) as Process)
+ ? ContextMenuKind.RUNNING_PROCESS_ADMIN
+ : ContextMenuKind.PROCESS_ADMIN
: readonly
? ContextMenuKind.READONLY_PROCESS_RESOURCE
+ : resource && isProcessCancelable(getProcess(resource.uuid)(getState().resources) as Process)
+ ? ContextMenuKind.RUNNING_PROCESS_RESOURCE
: ContextMenuKind.PROCESS_RESOURCE;
case ResourceKind.USER:
return ContextMenuKind.ROOT_PROJECT;
OutputIcon,
AdvancedIcon,
OpenIcon,
+ StopIcon,
} from "components/icon/icon";
import { favoritePanelActions } from "store/favorite-panel/favorite-panel-action";
import { openMoveProcessDialog } from "store/processes/process-move-actions";
import { togglePublicFavorite } from "store/public-favorites/public-favorites-actions";
import { publicFavoritePanelActions } from "store/public-favorites-panel/public-favorites-action";
import { openInNewTabAction } from "store/open-in-new-tab/open-in-new-tab.actions";
+import { cancelRunningWorkflow } from "store/processes/processes-actions";
export const readOnlyProcessResourceActionSet: ContextMenuActionSet = [
[
],
];
+const runningProcessOnlyActionSet: ContextMenuActionSet = [
+ [
+ {
+ name: "CANCEL",
+ icon: StopIcon,
+ execute: (dispatch, resources) => {
+ dispatch<any>(cancelRunningWorkflow(resources[0].uuid));
+ },
+ },
+ ]
+];
+
export const processResourceAdminActionSet: ContextMenuActionSet = [
[
...processResourceActionSet.reduce((prev, next) => prev.concat(next), []),
},
],
];
+
+export const runningProcessResourceActionSet = [
+ [
+ ...processResourceActionSet.reduce((prev, next) => prev.concat(next), []),
+ ...runningProcessOnlyActionSet.reduce((prev, next) => prev.concat(next), []),
+ ],
+];
+
+export const runningProcessResourceAdminActionSet: ContextMenuActionSet = [
+ [
+ ...processResourceAdminActionSet.reduce((prev, next) => prev.concat(next), []),
+ ...runningProcessOnlyActionSet.reduce((prev, next) => prev.concat(next), []),
+ ],
+];
//
// SPDX-License-Identifier: AGPL-3.0
-import React from 'react';
-import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
+import React from "react";
+import { StyleRulesCallback, WithStyles, withStyles } from "@material-ui/core";
import { DataExplorer } from "views-components/data-explorer/data-explorer";
-import { connect, DispatchProp } from 'react-redux';
-import { DataColumns } from 'components/data-table/data-table';
-import { RouteComponentProps } from 'react-router';
-import { DataTableFilterItem } from 'components/data-table-filters/data-table-filters';
-import { SortDirection } from 'components/data-table/data-column';
-import { ResourceKind } from 'models/resource';
-import { ArvadosTheme } from 'common/custom-theme';
-import { ALL_PROCESSES_PANEL_ID } from 'store/all-processes-panel/all-processes-panel-action';
+import { connect, DispatchProp } from "react-redux";
+import { DataColumns } from "components/data-table/data-table";
+import { RouteComponentProps } from "react-router";
+import { DataTableFilterItem } from "components/data-table-filters/data-table-filters";
+import { SortDirection } from "components/data-table/data-column";
+import { ResourceKind } from "models/resource";
+import { ArvadosTheme } from "common/custom-theme";
+import { ALL_PROCESSES_PANEL_ID } from "store/all-processes-panel/all-processes-panel-action";
import {
ProcessStatus,
ResourceName,
ResourceOwnerWithName,
ResourceType,
ContainerRunTime,
- ResourceCreatedAtDate
-} from 'views-components/data-explorer/renderers';
-import { ProcessIcon } from 'components/icon/icon';
-import { openProcessContextMenu } from 'store/context-menu/context-menu-actions';
-import { loadDetailsPanel } from 'store/details-panel/details-panel-action';
-import { navigateTo } from 'store/navigation/navigation-action';
+ ResourceCreatedAtDate,
+} from "views-components/data-explorer/renderers";
+import { ProcessIcon } from "components/icon/icon";
+import { openProcessContextMenu } from "store/context-menu/context-menu-actions";
+import { loadDetailsPanel } from "store/details-panel/details-panel-action";
+import { navigateTo } from "store/navigation/navigation-action";
import { ContainerRequestResource, ContainerRequestState } from "models/container-request";
-import { RootState } from 'store/store';
-import { createTree } from 'models/tree';
-import { getInitialProcessStatusFilters, getInitialProcessTypeFilters } from 'store/resource-type-filters/resource-type-filters';
-import { getProcess } from 'store/processes/process';
-import { ResourcesState } from 'store/resources/resources';
+import { RootState } from "store/store";
+import { createTree } from "models/tree";
+import { getInitialProcessStatusFilters, getInitialProcessTypeFilters } from "store/resource-type-filters/resource-type-filters";
+import { getProcess } from "store/processes/process";
+import { ResourcesState } from "store/resources/resources";
type CssRules = "toolbar" | "button" | "root";
const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
toolbar: {
paddingBottom: theme.spacing.unit * 3,
- textAlign: "right"
+ textAlign: "right",
},
button: {
- marginLeft: theme.spacing.unit
+ marginLeft: theme.spacing.unit,
},
root: {
- width: '100%',
- }
+ width: "100%",
+ },
});
export enum AllProcessesPanelColumnNames {
TYPE = "Type",
OWNER = "Owner",
CREATED_AT = "Created at",
- RUNTIME = "Run Time"
+ RUNTIME = "Run Time",
}
export interface AllProcessesPanelFilter extends DataTableFilterItem {
name: AllProcessesPanelColumnNames.NAME,
selected: true,
configurable: true,
- sort: {direction: SortDirection.NONE, field: "name"},
+ sort: { direction: SortDirection.NONE, field: "name" },
filters: createTree(),
- render: uuid => <ResourceName uuid={uuid} />
+ render: uuid => <ResourceName uuid={uuid} />,
},
{
name: AllProcessesPanelColumnNames.STATUS,
configurable: true,
mutuallyExclusiveFilters: true,
filters: getInitialProcessStatusFilters(),
- render: uuid => <ProcessStatus uuid={uuid} />
+ render: uuid => <ProcessStatus uuid={uuid} />,
},
{
name: AllProcessesPanelColumnNames.TYPE,
selected: true,
configurable: true,
filters: getInitialProcessTypeFilters(),
- render: uuid => <ResourceType uuid={uuid} />
+ render: uuid => <ResourceType uuid={uuid} />,
},
{
name: AllProcessesPanelColumnNames.OWNER,
selected: true,
configurable: true,
filters: createTree(),
- render: uuid => <ResourceOwnerWithName uuid={uuid} />
+ render: uuid => <ResourceOwnerWithName uuid={uuid} />,
},
{
name: AllProcessesPanelColumnNames.CREATED_AT,
selected: true,
configurable: true,
- sort: {direction: SortDirection.DESC, field: "createdAt"},
+ sort: { direction: SortDirection.DESC, field: "createdAt" },
filters: createTree(),
- render: uuid => <ResourceCreatedAtDate uuid={uuid} />
+ render: uuid => <ResourceCreatedAtDate uuid={uuid} />,
},
{
name: AllProcessesPanelColumnNames.RUNTIME,
selected: true,
configurable: true,
filters: createTree(),
- render: uuid => <ContainerRunTime uuid={uuid} />
- }
+ render: uuid => <ContainerRunTime uuid={uuid} />,
+ },
];
interface AllProcessesPanelDataProps {
onDialogOpen: (ownerUuid: string) => void;
onItemDoubleClick: (item: string) => void;
}
-const mapStateToProps = (state : RootState): AllProcessesPanelDataProps => ({
- resources: state.resources
+const mapStateToProps = (state: RootState): AllProcessesPanelDataProps => ({
+ resources: state.resources,
});
-type AllProcessesPanelProps = AllProcessesPanelDataProps & AllProcessesPanelActionProps & DispatchProp
- & WithStyles<CssRules> & RouteComponentProps<{ id: string }>;
+type AllProcessesPanelProps = AllProcessesPanelDataProps &
+ AllProcessesPanelActionProps &
+ DispatchProp &
+ WithStyles<CssRules> &
+ RouteComponentProps<{ id: string }>;
export const AllProcessesPanel = withStyles(styles)(
connect(mapStateToProps)(
this.props.dispatch<any>(openProcessContextMenu(event, process));
}
this.props.dispatch<any>(loadDetailsPanel(resourceUuid));
- }
+ };
handleRowDoubleClick = (uuid: string) => {
this.props.dispatch<any>(navigateTo(uuid));
- }
+ };
handleRowClick = (uuid: string) => {
this.props.dispatch<any>(loadDetailsPanel(uuid));
- }
+ };
render() {
- return <div className={this.props.classes.root}><DataExplorer
- id={ALL_PROCESSES_PANEL_ID}
- onRowClick={this.handleRowClick}
- onRowDoubleClick={this.handleRowDoubleClick}
- onContextMenu={this.handleContextMenu}
- contextMenuColumn={true}
- defaultViewIcon={ProcessIcon}
- defaultViewMessages={['Processes list empty.']} />
- </div>
+ return (
+ <div className={this.props.classes.root}>
+ <DataExplorer
+ id={ALL_PROCESSES_PANEL_ID}
+ onRowClick={this.handleRowClick}
+ onRowDoubleClick={this.handleRowDoubleClick}
+ onContextMenu={this.handleContextMenu}
+ contextMenuColumn={true}
+ defaultViewIcon={ProcessIcon}
+ defaultViewMessages={["Processes list empty."]}
+ />
+ </div>
+ );
}
}
)