interface DetailsAttributeDataProps {
label: string;
classLabel?: string;
- value?: string | number;
+ value?: React.ReactNode;
classValue?: string;
lowercaseValue?: boolean;
link?: string;
// SPDX-License-Identifier: AGPL-3.0
import { Resource, ResourceKind } from "./resource";
+import { MountType } from "~/models/mount-types";
+import { RuntimeConstraints } from './runtime-constraints';
+import { SchedulingParameters } from './scheduling-parameters';
export enum ContainerRequestState {
UNCOMMITTED = "Uncommitted",
description: string;
properties: any;
state: ContainerRequestState;
- requestingContainerUuid: string;
- containerUuid: string;
+ requestingContainerUuid: string | null;
+ containerUuid: string | null;
containerCountMax: number;
- mounts: any;
- runtimeConstraints: any;
- schedulingParameters: any;
+ mounts: MountType[];
+ runtimeConstraints: RuntimeConstraints;
+ schedulingParameters: SchedulingParameters;
containerImage: string;
environment: any;
cwd: string;
outputPath: string;
outputName: string;
outputTtl: number;
- priority: number;
+ priority: number | null;
expiresAt: string;
useExisting: boolean;
- logUuid: string;
- outputUuid: string;
+ logUuid: string | null;
+ outputUuid: string | null;
filters: string;
}
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { Resource, ResourceKind } from "./resource";
+import { MountType } from '~/models/mount-types';
+import { RuntimeConstraints } from "~/models/runtime-constraints";
+import { SchedulingParameters } from './scheduling-parameters';
+
+export enum ContainerState {
+ QUEUED = 'Queued',
+ LOCKED = 'Locked',
+ RUNNING = 'Running',
+ COMPLETE = 'Complete',
+ CANCELLED = 'Cancelled',
+}
+
+export interface ContainerResource extends Resource {
+ kind: ResourceKind.CONTAINER;
+ state: string;
+ startedAt: string | null;
+ finishedAt: string | null;
+ log: string | null;
+ environment: {};
+ cwd: string;
+ command: string[];
+ outputPath: string;
+ mounts: MountType[];
+ runtimeConstraints: RuntimeConstraints;
+ schedulingParameters: SchedulingParameters;
+ output: string | null;
+ containerImage: string;
+ progress: number;
+ priority: number;
+ exitCode: number | null;
+ authUuid: string | null;
+ lockedByUuid: string | null;
+}
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+export enum MountKind {
+ COLLECTION = 'collection',
+ GIT_TREE = 'git_tree',
+ TEMPORARY_DIRECTORY = 'tmp',
+ KEEP = 'keep',
+ MOUNTED_FILE = 'file',
+ JSON = 'JSON'
+}
+
+export type MountType =
+ CollectionMount |
+ GitTreeMount |
+ TemporaryDirectoryMount |
+ KeepMount |
+ JSONMount;
+
+export interface CollectionMount {
+ kind: MountKind.COLLECTION;
+ uuid?: string;
+ portableDataHash?: string;
+ path?: string;
+ writable?: boolean;
+}
+
+export interface GitTreeMount {
+ kind: MountKind.GIT_TREE;
+ uuid: string;
+ commit: string;
+ path?: string;
+}
+
+export enum TemporaryDirectoryDeviceType {
+ RAM = 'ram',
+ SSD = 'ssd',
+ DISK = 'disk',
+ NETWORK = 'network',
+}
+
+export interface TemporaryDirectoryMount {
+ kind: MountKind.TEMPORARY_DIRECTORY;
+ capacity: number;
+ deviceType: TemporaryDirectoryDeviceType;
+}
+
+export interface KeepMount {
+ kind: MountKind.KEEP;
+}
+
+export interface JSONMount {
+ kind: MountKind.JSON;
+ content: string;
+}
export enum ResourceKind {
COLLECTION = "arvados#collection",
+ CONTAINER = "arvados#container",
CONTAINER_REQUEST = "arvados#containerRequest",
GROUP = "arvados#group",
PROCESS = "arvados#containerRequest",
PROJECT = "arvados#group",
- WORKFLOW = "arvados#workflow",
USER = "arvados#user",
+ WORKFLOW = "arvados#workflow",
}
export enum ResourceObjectType {
- USER = 'tpzed',
+ COLLECTION = '4zz18',
+ CONTAINER = 'dz642',
+ CONTAINER_REQUEST = 'xvhdp',
GROUP = 'j7d0g',
- COLLECTION = '4zz18'
+ USER = 'tpzed',
}
export const RESOURCE_UUID_PATTERN = '.{5}-.{5}-.{15}';
return ResourceKind.GROUP;
case ResourceObjectType.COLLECTION:
return ResourceKind.COLLECTION;
+ case ResourceObjectType.CONTAINER_REQUEST:
+ return ResourceKind.CONTAINER_REQUEST;
+ case ResourceObjectType.CONTAINER:
+ return ResourceKind.CONTAINER;
default:
return undefined;
}
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+export interface RuntimeConstraints {
+ ram: number;
+ vcpus: number;
+ keepCacheRam: number;
+ API: boolean;
+}
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+export interface SchedulingParameters {
+ partitions: string[];
+ preemptible: boolean;
+ maxRunTime: number;
+}
// SPDX-License-Identifier: AGPL-3.0
import { History, Location } from 'history';
-import { RootStore } from '../store/store';
+import { RootStore } from '~/store/store';
import { matchPath } from 'react-router';
import { ResourceKind, RESOURCE_UUID_PATTERN, extractUuidKind } from '~/models/resource';
import { getProjectUrl } from '../models/project';
import { getCollectionUrl } from '~/models/collection';
-import { loadProject, loadFavorites, loadCollection } from '../store/workbench/workbench-actions';
+import { loadProject, loadFavorites, loadCollection } from '~/store/workbench/workbench-actions';
+import { loadProcess } from '~/store/processes/processes-actions';
export const Routes = {
ROOT: '/',
TOKEN: '/token',
PROJECTS: `/projects/:id(${RESOURCE_UUID_PATTERN})`,
COLLECTIONS: `/collections/:id(${RESOURCE_UUID_PATTERN})`,
- PROCESS: `/processes/:id(${RESOURCE_UUID_PATTERN})`,
+ PROCESSES: `/processes/:id(${RESOURCE_UUID_PATTERN})`,
FAVORITES: '/favorites',
};
}
};
+export const getProcessUrl = (uuid: string) => `/processes/${uuid}`;
+
export const addRouteChangeHandlers = (history: History, store: RootStore) => {
const handler = handleLocationChange(store);
handler(history.location);
export const matchFavoritesRoute = (route: string) =>
matchPath(route, { path: Routes.FAVORITES });
-export interface ProjectRouteParams {
+export interface ResourceRouteParams {
id: string;
}
export const matchProjectRoute = (route: string) =>
- matchPath<ProjectRouteParams>(route, { path: Routes.PROJECTS });
-
-export interface CollectionRouteParams {
- id: string;
-}
+ matchPath<ResourceRouteParams>(route, { path: Routes.PROJECTS });
export const matchCollectionRoute = (route: string) =>
- matchPath<CollectionRouteParams>(route, { path: Routes.COLLECTIONS });
+ matchPath<ResourceRouteParams>(route, { path: Routes.COLLECTIONS });
+
+export const matchProcessRoute = (route: string) =>
+ matchPath<ResourceRouteParams>(route, { path: Routes.PROCESSES });
const handleLocationChange = (store: RootStore) => ({ pathname }: Location) => {
const projectMatch = matchProjectRoute(pathname);
const collectionMatch = matchCollectionRoute(pathname);
const favoriteMatch = matchFavoritesRoute(pathname);
+ const processMatch = matchProcessRoute(pathname);
if (projectMatch) {
store.dispatch(loadProject(projectMatch.params.id));
} else if (collectionMatch) {
store.dispatch(loadCollection(collectionMatch.params.id));
} else if (favoriteMatch) {
store.dispatch(loadFavorites());
+ } else if (processMatch) {
+ store.dispatch(loadProcess(processMatch.params.id));
}
};
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { CommonResourceService } from "~/common/api/common-resource-service";
+import { AxiosInstance } from "axios";
+import { ContainerRequestResource } from '../../models/container-request';
+
+export class ContainerRequestService extends CommonResourceService<ContainerRequestResource> {
+ constructor(serverApi: AxiosInstance) {
+ super(serverApi, "container_requests");
+ }
+}
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { CommonResourceService } from "~/common/api/common-resource-service";
+import { AxiosInstance } from "axios";
+import { ContainerResource } from '../../models/container';
+
+export class ContainerService extends CommonResourceService<ContainerResource> {
+ constructor(serverApi: AxiosInstance) {
+ super(serverApi, "containers");
+ }
+}
import { UserService } from './user-service/user-service';
import { AncestorService } from "~/services/ancestors-service/ancestors-service";
import { ResourceKind } from "~/models/resource";
+import { ContainerRequestService } from './container-request-service/container-request-service';
+import { ContainerService } from './container-service/container-service';
export type ServiceRepository = ReturnType<typeof createServices>;
const webdavClient = new WebDAV();
webdavClient.defaults.baseURL = config.keepWebServiceUrl;
- const authService = new AuthService(apiClient, config.rootUrl);
- const keepService = new KeepService(apiClient);
const groupsService = new GroupsService(apiClient);
- const projectService = new ProjectService(apiClient);
+ const keepService = new KeepService(apiClient);
const linkService = new LinkService(apiClient);
- const favoriteService = new FavoriteService(linkService, groupsService);
- const collectionService = new CollectionService(apiClient, webdavClient, authService);
- const tagService = new TagService(linkService);
- const collectionFilesService = new CollectionFilesService(collectionService);
+ const projectService = new ProjectService(apiClient);
const userService = new UserService(apiClient);
+ const containerRequestService = new ContainerRequestService(apiClient);
+ const containerService = new ContainerService(apiClient);
+
const ancestorsService = new AncestorService(groupsService, userService);
+ const authService = new AuthService(apiClient, config.rootUrl);
+ const collectionService = new CollectionService(apiClient, webdavClient, authService);
+ const collectionFilesService = new CollectionFilesService(collectionService);
+ const favoriteService = new FavoriteService(linkService, groupsService);
+ const tagService = new TagService(linkService);
return {
+ ancestorsService,
apiClient,
- webdavClient,
authService,
- keepService,
+ collectionFilesService,
+ collectionService,
+ containerRequestService,
+ containerService,
+ favoriteService,
groupsService,
- projectService,
+ keepService,
linkService,
- favoriteService,
- collectionService,
+ projectService,
tagService,
- collectionFilesService,
userService,
- ancestorsService,
+ webdavClient,
};
};
import { getProjectUrl } from "~/models/project";
import { SidePanelTreeCategory } from '../side-panel-tree/side-panel-tree-actions';
-import { Routes } from '~/routes/routes';
+import { Routes, getProcessUrl } from '~/routes/routes';
export const navigateTo = (uuid: string) =>
async (dispatch: Dispatch) => {
dispatch<any>(navigateToProject(uuid));
} else if (kind === ResourceKind.COLLECTION) {
dispatch<any>(navigateToCollection(uuid));
+ } else if (kind === ResourceKind.CONTAINER_REQUEST) {
+ dispatch<any>(navigateToProcess(uuid));
}
if (uuid === SidePanelTreeCategory.FAVORITES) {
dispatch<any>(navigateToFavorites);
export const navigateToProject = compose(push, getProjectUrl);
export const navigateToCollection = compose(push, getCollectionUrl);
+
+export const navigateToProcess = compose(push, getProcessUrl);
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { ContainerRequestResource } from '../../models/container-request';
+import { ContainerResource } from '../../models/container';
+import { ResourcesState, getResource } from '~/store/resources/resources';
+import { filterResources } from '../resources/resources';
+import { ResourceKind, Resource } from '~/models/resource';
+
+export interface Process {
+ containerRequest: ContainerRequestResource;
+ container?: ContainerResource;
+}
+
+export const getProcess = (uuid: string) => (resources: ResourcesState): Process | undefined => {
+ const containerRequest = getResource<ContainerRequestResource>(uuid)(resources);
+ if (containerRequest) {
+ if (containerRequest.containerUuid) {
+ const container = getResource<ContainerResource>(containerRequest.containerUuid)(resources);
+ if (container) {
+ return { containerRequest, container };
+ }
+ }
+ return { containerRequest };
+ }
+ return;
+};
+
+export const getSubprocesses = (uuid: string) => (resources: ResourcesState) => {
+ const containerRequests = filterResources(isSubprocess(uuid))(resources) as ContainerRequestResource[];
+ return containerRequests.reduce((subprocesses, { uuid }) => {
+ const process = getProcess(uuid)(resources);
+ return process
+ ? [...subprocesses, process]
+ : subprocesses;
+ }, []);
+};
+
+export const getProcessStatus = (process: Process) =>
+ process.container
+ ? process.container.state
+ : process.containerRequest.state;
+
+const isSubprocess = (uuid: string) => (resource: Resource) =>
+ resource.kind === ResourceKind.CONTAINER_REQUEST
+ && (resource as ContainerRequestResource).requestingContainerUuid === uuid;
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { Dispatch } from "redux";
+import { RootState } from '~/store/store';
+import { ServiceRepository } from '~/services/services';
+import { updateResources } from '~/store/resources/resources-actions';
+import { FilterBuilder } from '~/common/api/filter-builder';
+import { ContainerRequestResource } from '../../models/container-request';
+
+export const loadProcess = (uuid: string) =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const containerRequest = await services.containerRequestService.get(uuid);
+ dispatch<any>(updateResources([containerRequest]));
+ if (containerRequest.containerUuid) {
+ const container = await services.containerService.get(containerRequest.containerUuid);
+ dispatch<any>(updateResources([container]));
+ }
+ };
+
+export const loadSubprocesses = (uuid: string) =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const containerRequests = await dispatch<any>(loadContainerRequests(
+ new FilterBuilder().addEqual('requestingContainerUuid', uuid).getFilters()
+ )) as ContainerRequestResource[];
+
+ const containerUuids: string[] = containerRequests.reduce((uuids, { containerUuid }) =>
+ containerUuid
+ ? [...uuids, containerUuid]
+ : uuids, []);
+
+ if (containerUuids.length > 0) {
+ await dispatch<any>(loadContainers(
+ new FilterBuilder().addIn('uuid', containerUuids).getFilters()
+ ));
+ }
+ };
+
+export const loadContainerRequests = (filters: string) =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const { items } = await services.containerRequestService.list({ filters });
+ dispatch<any>(updateResources(items));
+ return items;
+ };
+
+export const loadContainers = (filters: string) =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ const { items } = await services.containerService.list({ filters });
+ dispatch<any>(updateResources(items));
+ return items;
+ };
export const deleteResource = (id: string) =>
(state: ResourcesState) => {
- const newState = {...state};
+ const newState = { ...state };
delete newState[id];
return newState;
};
(state: ResourcesState) =>
Object
.keys(state)
- .map(id => getResource(id)(state))
+ .reduce((resources, id) => {
+ const resource = getResource(id)(state);
+ return resource
+ ? [...resources, resource]
+ : resources;
+ }, [])
.filter(filter);
export const filterResourcesByKind = (kind: ResourceKind) =>
(state: ResourcesState) =>
filterResources(resource => resource.kind === kind)(state);
-
import * as collectionCopyActions from '~/store/collections/collection-copy-actions';
import * as collectionUpdateActions from '~/store/collections/collection-update-actions';
import * as collectionMoveActions from '~/store/collections/collection-move-actions';
+import * as processesActions from '../processes/processes-actions';
+import { getProcess } from '../processes/process';
export const loadWorkbench = () =>
}
};
+export const loadProcess = (uuid: string) =>
+ async (dispatch: Dispatch, getState: () => RootState) => {
+ await dispatch<any>(processesActions.loadProcess(uuid));
+ const process = getProcess(uuid)(getState().resources);
+ if (process) {
+ await dispatch<any>(activateSidePanelTreeItem(process.containerRequest.ownerUuid));
+ dispatch<any>(setCollectionBreadcrumbs(process.containerRequest.ownerUuid));
+ dispatch(loadDetailsPanel(uuid));
+ }
+ };
+
export const resourceIsNotLoaded = (uuid: string) =>
snackbarActions.OPEN_SNACKBAR({
message: `Resource identified by ${uuid} is not loaded.`
{/* Links but we dont have view */}
<DetailsAttribute label='Outputs' link={this.item.outputPath} value={this.item.outputPath} />
<DetailsAttribute label='UUID' link={this.item.uuid} value={this.item.uuid} />
- <DetailsAttribute label='Container UUID' link={this.item.containerUuid} value={this.item.containerUuid} />
+ <DetailsAttribute label='Container UUID' link={this.item.containerUuid || ''} value={this.item.containerUuid} />
<DetailsAttribute label='Priority' value={this.item.priority} />
- <DetailsAttribute label='Runtime Constraints' value={this.item.runtimeConstraints} />
+ <DetailsAttribute label='Runtime Constraints' value={JSON.stringify(this.item.runtimeConstraints)} />
{/* Link but we dont have view */}
<DetailsAttribute label='Docker Image locator' link={this.item.containerImage} value={this.item.containerImage} />
</div>;
+++ /dev/null
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import { Dispatch } from 'redux';
-import { openProcessContextMenu } from '~/store/context-menu/context-menu-actions';
-import { connect } from 'react-redux';
-import { RootState } from '~/store/store';
-import { ProcessInformationCard as InformationCardComponent, ProcessInformationCardDataProps } from '~/views/process-panel/process-information-card';
-
-type InformationCardActionProps = Pick<ProcessInformationCardDataProps, 'onContextMenu'>;
-
-const mapStateToProps = (state: RootState) => ({
- // todo: change for processPanel
- item: state.collectionPanel.item
-});
-
-const mapDispatchToProps = (dispatch: Dispatch): InformationCardActionProps => ({
- onContextMenu: (event: React.MouseEvent<HTMLElement>) => {
- dispatch<any>(openProcessContextMenu(event));
- }
-});
-
-export const ProcessInformationCard = connect(mapStateToProps, mapDispatchToProps)(InformationCardComponent);
\ No newline at end of file
import { ArvadosTheme } from '~/common/custom-theme';
import { MoreOptionsIcon, ProcessIcon } from '~/components/icon/icon';
import { DetailsAttribute } from '~/components/details-attribute/details-attribute';
+import { Process } from '~/store/processes/process';
+import { getProcessStatus } from '../../store/processes/process';
type CssRules = 'card' | 'iconHeader' | 'label' | 'value' | 'chip' | 'headerText' | 'link' | 'content' | 'title' | 'avatar';
});
export interface ProcessInformationCardDataProps {
- item: any;
+ process: Process;
onContextMenu: (event: React.MouseEvent<HTMLElement>) => void;
}
type ProcessInformationCardProps = ProcessInformationCardDataProps & WithStyles<CssRules>;
export const ProcessInformationCard = withStyles(styles)(
- ({ classes, onContextMenu }: ProcessInformationCardProps) =>
+ ({ classes, process, onContextMenu }: ProcessInformationCardProps) =>
<Card className={classes.card}>
<CardHeader
classes={{
avatar={<ProcessIcon className={classes.iconHeader} />}
action={
<div>
- <Chip label="Complete" className={classes.chip} />
+ <Chip label={getProcessStatus(process)} className={classes.chip} />
<IconButton
aria-label="More options"
onClick={event => onContextMenu(event)}>
</div>
}
title={
- <Tooltip title="Pipeline template that generates a config file from a template">
+ <Tooltip title={process.containerRequest.name}>
<Typography noWrap variant="title">
- Pipeline template that generates a config file from a template
+ {process.containerRequest.name}
</Typography>
</Tooltip>
}
- subheader="(no-description)" />
+ subheader={process.containerRequest.description} />
<CardContent className={classes.content}>
<Grid container>
<Grid item xs={6}>
<DetailsAttribute classLabel={classes.label} classValue={classes.value}
- label='From' value="1:25 PM 3/23/2018" />
+ label='From' value={process.container ? process.container.startedAt : 'N/A'} />
<DetailsAttribute classLabel={classes.label} classValue={classes.value}
- label='To' value='1:25 PM 3/23/2018' />
+ label='To' value={process.container ? process.container.finishedAt : 'N/A'} />
<DetailsAttribute classLabel={classes.label} classValue={classes.link}
- label='Workflow' value='FastQC MultiQC' />
+ label='Workflow' value='???' />
</Grid>
<Grid item xs={6}>
<DetailsAttribute classLabel={classes.link} label='Outputs' />
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { Grid } from '@material-ui/core';
+import { ProcessInformationCard } from './process-information-card';
+import { DefaultView } from '~/components/default-view/default-view';
+import { ProcessIcon } from '~/components/icon/icon';
+import { Process } from '~/store/processes/process';
+import { SubprocessesCard } from './subprocesses-card';
+
+export interface ProcessPanelRootDataProps {
+ process?: Process;
+}
+
+export interface ProcessPanelRootActionProps {
+ onContextMenu: (event: React.MouseEvent<HTMLElement>) => void;
+}
+
+export type ProcessPanelRootProps = ProcessPanelRootDataProps & ProcessPanelRootActionProps;
+
+export const ProcessPanelRoot = (props: ProcessPanelRootProps) =>
+ props.process
+ ? <Grid container spacing={16}>
+ <Grid item xs={7}>
+ <ProcessInformationCard
+ process={props.process}
+ onContextMenu={props.onContextMenu} />
+ </Grid>
+ <Grid item xs={5}>
+ <SubprocessesCard
+ subprocesses={4}
+ filters={[
+ {
+ key: 'queued',
+ value: 1,
+ label: 'Queued',
+ checked: true
+ }, {
+ key: 'active',
+ value: 2,
+ label: 'Active',
+ checked: true
+ },
+ {
+ key: 'completed',
+ value: 2,
+ label: 'Completed',
+ checked: true
+ },
+ {
+ key: 'failed',
+ value: 2,
+ label: 'Failed',
+ checked: true
+ }
+ ]}
+ onToggle={() => { return; }}
+ />
+ </Grid>
+ </Grid>
+ : <Grid container
+ alignItems='center'
+ justify='center'>
+ <DefaultView
+ icon={ProcessIcon}
+ messages={['Process not found']} />
+ </Grid>;
// SPDX-License-Identifier: AGPL-3.0
import * as React from 'react';
-import { Grid } from '@material-ui/core';
-import { ProcessInformationCard } from '~/views-components/process-information-card/process-information-card';
-import { SubprocessesCard } from '~/views/process-panel/subprocesses-card';
-import { SubprocessFilterDataProps } from '~/components/subprocess-filter/subprocess-filter';
+import { RootState } from '~/store/store';
+import { connect } from 'react-redux';
+import { getProcess } from '~/store/processes/process';
+import { Dispatch } from 'redux';
+import { openProcessContextMenu } from '~/store/context-menu/context-menu-actions';
+import { matchProcessRoute } from '~/routes/routes';
+import { ProcessPanelRootDataProps, ProcessPanelRootActionProps, ProcessPanelRoot } from './process-panel-root';
-export class ProcessPanel extends React.Component {
- state = {
- filters: [
- {
- key: 'queued',
- value: 1,
- label: 'Queued',
- checked: true
- }, {
- key: 'active',
- value: 2,
- label: 'Active',
- checked: true
- },
- {
- key: 'completed',
- value: 2,
- label: 'Completed',
- checked: true
- },
- {
- key: 'failed',
- value: 2,
- label: 'Failed',
- checked: true
- }
- ]
+const mapStateToProps = ({ router, resources }: RootState): ProcessPanelRootDataProps => {
+ const pathname = router.location ? router.location.pathname : '';
+ const match = matchProcessRoute(pathname);
+ const uuid = match ? match.params.id : '';
+ return {
+ process: getProcess(uuid)(resources)
};
+};
- onToggle = (filter: SubprocessFilterDataProps) => {
- this.setState((prev: { filters: any[] }) => {
- return {
- filters: prev.filters.map((f: SubprocessFilterDataProps) => {
- if(f.key === filter.key) {
- return {
- ...filter,
- checked: !filter.checked
- };
- }
- return f;
- })
- };
- });
+const mapDispatchToProps = (dispatch: Dispatch): ProcessPanelRootActionProps => ({
+ onContextMenu: (event: React.MouseEvent<HTMLElement>) => {
+ dispatch<any>(openProcessContextMenu(event));
}
+});
- render() {
- return <Grid container spacing={16}>
- <Grid item xs={7}>
- <ProcessInformationCard />
- </Grid>
- <Grid item xs={5}>
- <SubprocessesCard
- subprocesses={4}
- filters={this.state.filters}
- onToggle={this.onToggle}
- />
- </Grid>
- </Grid>;
- }
-}
+export const ProcessPanel = connect(mapStateToProps, mapDispatchToProps)(ProcessPanelRoot);
<Route path={Routes.PROJECTS} component={ProjectPanel} />
<Route path={Routes.COLLECTIONS} component={CollectionPanel} />
<Route path={Routes.FAVORITES} component={FavoritePanel} />
- <Route path={Routes.PROCESS} component={ProcessPanel} />
+ <Route path={Routes.PROCESSES} component={ProcessPanel} />
</Switch>
</div>
{user && <DetailsPanel />}