return "Group";
case ResourceKind.VIRTUAL_MACHINE:
return "Virtual Machine";
+ case ResourceKind.WORKFLOW:
+ return "Workflow";
default:
return "Unknown";
}
import { loadFileViewersConfig } from 'store/file-viewers/file-viewers-actions';
import { filterGroupAdminActionSet, projectAdminActionSet } from 'views-components/context-menu/action-sets/project-admin-action-set';
import { permissionEditActionSet } from 'views-components/context-menu/action-sets/permission-edit-action-set';
+import { workflowActionSet } from 'views-components/context-menu/action-sets/workflow-action-set';
import { snackbarActions, SnackbarKind } from "store/snackbar/snackbar-actions";
import { openNotFoundDialog } from './store/not-found-panel/not-found-panel-action';
import { storeRedirects } from './common/redirect-to';
addMenuActionSet(ContextMenuKind.PROJECT_ADMIN, projectAdminActionSet);
addMenuActionSet(ContextMenuKind.FILTER_GROUP_ADMIN, filterGroupAdminActionSet);
addMenuActionSet(ContextMenuKind.PERMISSION_EDIT, permissionEditActionSet);
+addMenuActionSet(ContextMenuKind.WORKFLOW, workflowActionSet);
storeRedirects();
import { ProcessResource } from "./process";
import { EmptyResource } from "./empty";
import { CollectionFile, CollectionDirectory } from 'models/collection-file';
+import { WorkflowResource } from 'models/workflow';
-export type DetailsResource = ProjectResource | CollectionResource | ProcessResource | EmptyResource | CollectionFile | CollectionDirectory;
+export type DetailsResource = ProjectResource | CollectionResource | ProcessResource | EmptyResource | CollectionFile | CollectionDirectory | WorkflowResource;
return ContextMenuKind.ROOT_PROJECT;
case ResourceKind.LINK:
return ContextMenuKind.LINK;
+ case ResourceKind.WORKFLOW:
+ return ContextMenuKind.WORKFLOW;
default:
return;
}
import { SidePanelTreeCategory } from '../side-panel-tree/side-panel-tree-actions';
import { Routes, getGroupUrl, getNavUrl, getUserProfileUrl } from 'routes/routes';
import { RootState } from 'store/store';
+import { openDetailsPanel } from 'store/details-panel/details-panel-action';
import { ServiceRepository } from 'services/services';
import { pluginConfig } from 'plugins';
import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
case ResourceKind.VIRTUAL_MACHINE:
dispatch<any>(navigateToAdminVirtualMachines);
return;
+ case ResourceKind.WORKFLOW:
+ dispatch<any>(openDetailsPanel(uuid));
+ return;
}
switch (uuid) {
PROJECT = 'Project',
PROCESS = 'Process',
COLLECTION = 'Data collection',
+ WORKFLOW = 'Workflow',
}
export enum GroupTypeFilter {
initFilter(ObjectTypeFilter.PROJECT),
initFilter(ObjectTypeFilter.PROCESS),
initFilter(ObjectTypeFilter.COLLECTION),
+ initFilter(ObjectTypeFilter.WORKFLOW),
);
// Using pipe() with more than 7 arguments makes the return type be 'any',
initFilter(CollectionTypeFilter.INTERMEDIATE_COLLECTION, ObjectTypeFilter.COLLECTION),
initFilter(CollectionTypeFilter.LOG_COLLECTION, ObjectTypeFilter.COLLECTION),
),
+ initFilter(ObjectTypeFilter.WORKFLOW)
+
);
export const getInitialProcessTypeFilters = pipe(
return ResourceKind.PROCESS;
case ObjectTypeFilter.COLLECTION:
return ResourceKind.COLLECTION;
+ case ObjectTypeFilter.WORKFLOW:
+ return ResourceKind.WORKFLOW;
}
};
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { ContextMenuActionSet } from "views-components/context-menu/context-menu-action-set";
+import { openRunProcess } from "store/workflow-panel/workflow-panel-actions";
+
+export const workflowActionSet: ContextMenuActionSet = [[
+ {
+ name: "Run",
+ execute: (dispatch, resource) => {
+ dispatch<any>(openRunProcess(resource.uuid, resource.ownerUuid, resource.name));
+ }
+ },
+]];
const emptyActionSet: ContextMenuActionSet = [];
const getMenuActionSet = (resource?: ContextMenuResource): ContextMenuActionSet => (
- resource ? menuActionSets.get(resource.menuKind) || emptyActionSet : emptyActionSet
+ resource ? menuActionSets.get(resource.menuKind) || emptyActionSet : emptyActionSet
);
export enum ContextMenuKind {
GROUP_MEMBER = "GroupMember",
PERMISSION_EDIT = "PermissionEdit",
LINK = "Link",
+ WORKFLOW = "Workflow",
}
import { CollectionDetails } from "./collection-details";
import { ProcessDetails } from "./process-details";
import { EmptyDetails } from "./empty-details";
+import { WorkflowDetails } from "./workflow-details";
import { DetailsData } from "./details-data";
import { DetailsResource } from "models/details";
import { Config } from 'common/config';
return new CollectionDetails(res);
case ResourceKind.PROCESS:
return new ProcessDetails(res);
+ case ResourceKind.WORKFLOW:
+ return new WorkflowDetails(res);
default:
return new EmptyDetails(res);
}
let shouldShowInlinePreview = false;
if (!('kind' in res)) {
shouldShowInlinePreview = isInlineFileUrlSafe(
- res ? res.url : "",
- authConfig.keepWebServiceUrl,
- authConfig.keepWebInlineServiceUrl
+ res ? res.url : "",
+ authConfig.keepWebServiceUrl,
+ authConfig.keepWebInlineServiceUrl
) || authConfig.clusterConfig.Collections.TrustAllContent;
}
</Grid>
<Grid item>
<Tabs onChange={this.handleChange}
- value={(item.getTabLabels().length >= tabNr+1) ? tabNr : 0}>
- { item.getTabLabels().map((tabLabel, idx) =>
+ value={(item.getTabLabels().length >= tabNr + 1) ? tabNr : 0}>
+ {item.getTabLabels().map((tabLabel, idx) =>
<Tab key={`tab-label-${idx}`} disableRipple label={tabLabel} />)
}
</Tabs>
</Grid>
<Grid item xs className={this.props.classes.tabContainer} >
- {item.getDetails({tabNr, showPreview: shouldShowInlinePreview})}
+ {item.getDetails({ tabNr, showPreview: shouldShowInlinePreview })}
</Grid>
</Grid >;
}
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import React from 'react';
+import { DefaultIcon, 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 { ResourceOwnerWithName } from 'views-components/data-explorer/renderers';
+import { formatDate } from "common/formatters";
+import { Grid } from '@material-ui/core';
+import { withStyles, StyleRulesCallback, WithStyles, Button } from '@material-ui/core';
+import { openRunProcess } from "store/workflow-panel/workflow-panel-actions";
+import { Dispatch } from 'redux';
+import { connect } from 'react-redux';
+import { ArvadosTheme } from 'common/custom-theme';
+
+export interface WorkflowDetailsCardDataProps {
+ workflow?: WorkflowResource;
+}
+
+export interface WorkflowDetailsCardActionProps {
+ onClick: (wf: WorkflowResource) => () => void;
+}
+
+const mapDispatchToProps = (dispatch: Dispatch) => ({
+ onClick: (wf: WorkflowResource) =>
+ () => wf && dispatch<any>(openRunProcess(wf.uuid, wf.ownerUuid, wf.name)),
+});
+
+type CssRules = 'runButton';
+
+const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
+ runButton: {
+ boxShadow: 'none',
+ padding: '2px 10px 2px 5px',
+ fontSize: '0.75rem'
+ },
+});
+
+export const WorkflowDetailsAttributes = connect(null, mapDispatchToProps)(
+ withStyles(styles)(
+ ({ workflow, onClick, classes }: WorkflowDetailsCardDataProps & WorkflowDetailsCardActionProps & WithStyles<CssRules>) => {
+ return <Grid container>
+ <Button onClick={workflow && onClick(workflow)} className={classes.runButton} variant='contained'
+ data-cy='details-panel-run-btn' color='primary' size='small'>
+ Run
+ </Button>
+ {workflow && workflow.description !== "" && <Grid item xs={12} >
+ <DetailsAttribute
+ label={"Description"}
+ value={workflow?.description} />
+ </Grid>}
+ <Grid item xs={12} >
+ <DetailsAttribute
+ label={"Workflow UUID"}
+ linkToUuid={workflow?.uuid} />
+ </Grid>
+ <Grid item xs={12} >
+ <DetailsAttribute
+ label='Owner' linkToUuid={workflow?.ownerUuid}
+ uuidEnhancer={(uuid: string) => <ResourceOwnerWithName uuid={uuid} />} />
+ </Grid>
+ <Grid item xs={12}>
+ <DetailsAttribute label='Created at' value={formatDate(workflow?.createdAt)} />
+ </Grid>
+ <Grid item xs={12}>
+ <DetailsAttribute label='Last modified' value={formatDate(workflow?.modifiedAt)} />
+ </Grid>
+ <Grid item xs={12} >
+ <DetailsAttribute
+ label='Last modified by user' linkToUuid={workflow?.modifiedByUserUuid}
+ uuidEnhancer={(uuid: string) => <ResourceOwnerWithName uuid={uuid} />} />
+ </Grid>
+ </Grid >;
+ }));
+
+export class WorkflowDetails extends DetailsData<WorkflowResource> {
+ getIcon(className?: string) {
+ return <WorkflowIcon className={className} />;
+ }
+
+ getDetails() {
+ return <WorkflowDetailsAttributes workflow={this.item} />;
+ }
+}
TableCell,
TableBody,
TableRow,
- Grid,
} from '@material-ui/core';
import { ArvadosTheme } from 'common/custom-theme';
import { WorkflowIcon } from 'components/icon/icon';
import { DataTableDefaultView } from 'components/data-table-default-view/data-table-default-view';
+import { parseWorkflowDefinition, getWorkflowInputs, getInputLabel, stringifyInputType } from 'models/workflow';
+import { WorkflowDetailsCardDataProps, WorkflowDetailsAttributes } from 'views-components/details-panel/workflow-details';
import { WorkflowResource, parseWorkflowDefinition, getWorkflowInputs, getInputLabel, stringifyInputType } from 'models/workflow';
import { DetailsAttribute } from 'components/details-attribute/details-attribute';
import { ResourceOwnerWithName } from 'views-components/data-explorer/renderers';
},
});
-interface WorkflowDetailsCardDataProps {
- workflow?: WorkflowResource;
-}
-
type WorkflowDetailsCardProps = WorkflowDetailsCardDataProps & WithStyles<CssRules>;
export const WorkflowDetailsCard = withStyles(styles)(
</Table>;
}
});
-
-export const WorkflowDetailsAttributes = ({ workflow }: WorkflowDetailsCardDataProps) => {
- return <Grid container>
- <Grid item xs={12} >
- <DetailsAttribute
- label={"Workflow UUID"}
- linkToUuid={workflow?.uuid} />
- </Grid>
- <Grid item xs={12} >
- <DetailsAttribute
- label='Owner' linkToUuid={workflow?.ownerUuid}
- uuidEnhancer={(uuid: string) => <ResourceOwnerWithName uuid={uuid} />} />
- </Grid>
- <Grid item xs={12}>
- <DetailsAttribute label='Created at' value={formatDate(workflow?.createdAt)} />
- </Grid>
- <Grid item xs={12}>
- <DetailsAttribute label='Last modified' value={formatDate(workflow?.modifiedAt)} />
- </Grid>
- <Grid item xs={12} >
- <DetailsAttribute
- label='Last modified by user' linkToUuid={workflow?.modifiedByUserUuid}
- uuidEnhancer={(uuid: string) => <ResourceOwnerWithName uuid={uuid} />} />
- </Grid>
- </Grid >;
-};