this.props.onMenuOpen(event, item);
}
- handleToggle = (id: string, status: TreeItemStatus) => {
+ handleToggle = (event: React.MouseEvent<{}>, { id, status }: TreeItem<{}>) => {
this.props.onCollapseToggle(id, status);
}
}
export interface TreeProps<T> {
+ disableRipple?: boolean;
items?: Array<TreeItem<T>>;
- render: (item: TreeItem<T>, level?: number) => ReactElement<{}>;
- toggleItemOpen: (id: string, status: TreeItemStatus) => void;
- toggleItemActive: (id: string, status: TreeItemStatus) => void;
level?: number;
onContextMenu: (event: React.MouseEvent<HTMLElement>, item: TreeItem<T>) => void;
+ render: (item: TreeItem<T>, level?: number) => ReactElement<{}>;
showSelection?: boolean;
+ toggleItemActive: (event: React.MouseEvent<HTMLElement>, item: TreeItem<T>) => void;
+ toggleItemOpen: (event: React.MouseEvent<HTMLElement>, item: TreeItem<T>) => void;
toggleItemSelection?: (event: React.MouseEvent<HTMLElement>, item: TreeItem<T>) => void;
- disableRipple?: boolean;
}
export const Tree = withStyles(styles)(
<div key={`item/${level}/${idx}`}>
<ListItem button className={listItem} style={{ paddingLeft: (level + 1) * 20 }}
disableRipple={disableRipple}
- onClick={() => toggleItemActive(it.id, it.status)}
+ onClick={event => toggleItemActive(event, it)}
onContextMenu={this.handleRowContextMenu(it)}>
{it.status === TreeItemStatus.PENDING ?
<CircularProgress size={10} className={loader} /> : null}
- <i onClick={this.handleToggleItemOpen(it.id, it.status)}
+ <i onClick={this.handleToggleItemOpen(it)}
className={toggableIconContainer}>
<ListItemIcon className={this.getToggableIconClassNames(it.open, it.active)}>
{this.getProperArrowAnimation(it.status, it.items!)}
: undefined;
}
- handleToggleItemOpen = (id: string, status: TreeItemStatus) => (event: React.MouseEvent<HTMLElement>) => {
+ handleToggleItemOpen = (item: TreeItem<T>) => (event: React.MouseEvent<HTMLElement>) => {
event.stopPropagation();
- this.props.toggleItemOpen(id, status);
+ this.props.toggleItemOpen(event, item);
}
}
);
import { setUuidPrefix } from '~/store/workflow-panel/workflow-panel-actions';
import { trashedCollectionActionSet } from '~/views-components/context-menu/action-sets/trashed-collection-action-set';
import { ContainerRequestState } from '~/models/container-request';
-import { MountKind } from './models/mount-types';
+import { MountKind } from '~/models/mount-types';
+import { receiveTreePickerData } from '~/store/tree-picker/tree-picker-actions';
+import { loadProject, loadCollection } from './store/tree-picker/tree-picker-actions';
+import { ResourceKind } from '~/models/resource';
const getBuildNumber = () => "BN-" + (process.env.REACT_APP_BUILD_NUMBER || "dev");
const getGitCommit = () => "GIT-" + (process.env.REACT_APP_GIT_COMMIT || "latest").substr(0, 7);
await store.dispatch(loadWorkbench());
addRouteChangeHandlers(history, store);
// createEnumCollectorWorkflow(services);
+ store.dispatch(receiveTreePickerData({
+ id: '',
+ pickerId: 'testPicker',
+ data: [{name: 'Projects', uuid: 'c97qk-tpzed-1k14sp44jonn0n3'}],
+ extractNodeData: value => ({id: value.uuid, value}),
+ }));
+ await store.dispatch(loadProject(
+ 'c97qk-tpzed-1k14sp44jonn0n3',
+ 'testPicker',
+ [ResourceKind.COLLECTION],
+ ));
+ await store.dispatch(loadCollection(
+ 'c97qk-4zz18-9sn8ygaf62chkkd',
+ 'testPicker',
+ ));
}
};
};
-const createPrimitivesCollectorWorkflow = ({workflowService}:ServiceRepository) => {
+const createPrimitivesCollectorWorkflow = ({ workflowService }: ServiceRepository) => {
workflowService.create({
- name: 'Primitive values collector',
- description: 'Workflow for collecting primitive values',
- definition: "cwlVersion: v1.0\n$graph:\n- class: CommandLineTool\n requirements:\n - listing:\n - entryname: input_collector.log\n entry: |\n \"flag\":\n $(inputs.example_flag)\n \"string\":\n $(inputs.example_string)\n \"int\":\n $(inputs.example_int)\n \"long\":\n $(inputs.example_long)\n \"float\":\n $(inputs.example_float)\n \"double\":\n $(inputs.example_double)\n class: InitialWorkDirRequirement\n inputs:\n - type: double\n id: '#input_collector.cwl/example_double'\n - type: boolean\n id: '#input_collector.cwl/example_flag'\n - type: float\n id: '#input_collector.cwl/example_float'\n - type: int\n id: '#input_collector.cwl/example_int'\n - type: long\n id: '#input_collector.cwl/example_long'\n - type: string\n id: '#input_collector.cwl/example_string'\n outputs:\n - type: File\n outputBinding:\n glob: '*'\n id: '#input_collector.cwl/output'\n baseCommand: [echo]\n id: '#input_collector.cwl'\n- class: Workflow\n doc: Workflw for collecting primitive values\n inputs:\n - type: double\n label: Double value\n doc: This should allow for entering a decimal number (64-bit).\n id: '#main/example_double'\n default: 0.3333333333333333\n - type: boolean\n label: Boolean Flag\n doc: This should render as in checkbox.\n id: '#main/example_flag'\n default: true\n - type: float\n label: Float value\n doc: This should allow for entering a decimal number (32-bit).\n id: '#main/example_float'\n default: 0.15625\n - type: int\n label: Integer Number\n doc: This should allow for entering a number (32-bit signed).\n id: '#main/example_int'\n default: 2147483647\n - type: long\n label: Long Number\n doc: This should allow for entering a number (64-bit signed).\n id: '#main/example_long'\n default: 9223372036854775807\n - type: string\n label: Freetext\n doc: This should allow for entering an arbitrary char sequence.\n id: '#main/example_string'\n default: This is a string\n outputs:\n - type: File\n outputSource: '#main/input_collector/output'\n id: '#main/log_file'\n steps:\n - run: '#input_collector.cwl'\n in:\n - source: '#main/example_double'\n id: '#main/input_collector/example_double'\n - source: '#main/example_flag'\n id: '#main/input_collector/example_flag'\n - source: '#main/example_float'\n id: '#main/input_collector/example_float'\n - source: '#main/example_int'\n id: '#main/input_collector/example_int'\n - source: '#main/example_long'\n id: '#main/input_collector/example_long'\n - source: '#main/example_string'\n id: '#main/input_collector/example_string'\n out: ['#main/input_collector/output']\n id: '#main/input_collector'\n id: '#main'\n",
- });
+ name: 'Primitive values collector',
+ description: 'Workflow for collecting primitive values',
+ definition: "cwlVersion: v1.0\n$graph:\n- class: CommandLineTool\n requirements:\n - listing:\n - entryname: input_collector.log\n entry: |\n \"flag\":\n $(inputs.example_flag)\n \"string\":\n $(inputs.example_string)\n \"int\":\n $(inputs.example_int)\n \"long\":\n $(inputs.example_long)\n \"float\":\n $(inputs.example_float)\n \"double\":\n $(inputs.example_double)\n class: InitialWorkDirRequirement\n inputs:\n - type: double\n id: '#input_collector.cwl/example_double'\n - type: boolean\n id: '#input_collector.cwl/example_flag'\n - type: float\n id: '#input_collector.cwl/example_float'\n - type: int\n id: '#input_collector.cwl/example_int'\n - type: long\n id: '#input_collector.cwl/example_long'\n - type: string\n id: '#input_collector.cwl/example_string'\n outputs:\n - type: File\n outputBinding:\n glob: '*'\n id: '#input_collector.cwl/output'\n baseCommand: [echo]\n id: '#input_collector.cwl'\n- class: Workflow\n doc: Workflw for collecting primitive values\n inputs:\n - type: double\n label: Double value\n doc: This should allow for entering a decimal number (64-bit).\n id: '#main/example_double'\n default: 0.3333333333333333\n - type: boolean\n label: Boolean Flag\n doc: This should render as in checkbox.\n id: '#main/example_flag'\n default: true\n - type: float\n label: Float value\n doc: This should allow for entering a decimal number (32-bit).\n id: '#main/example_float'\n default: 0.15625\n - type: int\n label: Integer Number\n doc: This should allow for entering a number (32-bit signed).\n id: '#main/example_int'\n default: 2147483647\n - type: long\n label: Long Number\n doc: This should allow for entering a number (64-bit signed).\n id: '#main/example_long'\n default: 9223372036854775807\n - type: string\n label: Freetext\n doc: This should allow for entering an arbitrary char sequence.\n id: '#main/example_string'\n default: This is a string\n outputs:\n - type: File\n outputSource: '#main/input_collector/output'\n id: '#main/log_file'\n steps:\n - run: '#input_collector.cwl'\n in:\n - source: '#main/example_double'\n id: '#main/input_collector/example_double'\n - source: '#main/example_flag'\n id: '#main/input_collector/example_flag'\n - source: '#main/example_float'\n id: '#main/input_collector/example_float'\n - source: '#main/example_int'\n id: '#main/input_collector/example_int'\n - source: '#main/example_long'\n id: '#main/input_collector/example_long'\n - source: '#main/example_string'\n id: '#main/input_collector/example_string'\n out: ['#main/input_collector/output']\n id: '#main/input_collector'\n id: '#main'\n",
+ });
};
-const createEnumCollectorWorkflow = ({workflowService}:ServiceRepository) => {
+const createEnumCollectorWorkflow = ({ workflowService }: ServiceRepository) => {
workflowService.create({
- name: 'Enum values collector',
- description: 'Workflow for collecting enum values',
- definition: "cwlVersion: v1.0\n$graph:\n- class: CommandLineTool\n requirements:\n - listing:\n - entryname: input_collector.log\n entry: |\n \"enum_type\":\n $(inputs.enum_type)\n\n class: InitialWorkDirRequirement\n inputs:\n - type:\n type: enum\n symbols: ['#input_collector.cwl/enum_type/OTU table', '#input_collector.cwl/enum_type/Pathway\n table', '#input_collector.cwl/enum_type/Function table', '#input_collector.cwl/enum_type/Ortholog\n table']\n id: '#input_collector.cwl/enum_type'\n outputs:\n - type: File\n outputBinding:\n glob: '*'\n id: '#input_collector.cwl/output'\n baseCommand: [echo]\n id: '#input_collector.cwl'\n- class: Workflow\n doc: This is the description of the workflow\n inputs:\n - type:\n type: enum\n symbols: ['#main/enum_type/OTU table', '#main/enum_type/Pathway table', '#main/enum_type/Function\n table', '#main/enum_type/Ortholog table']\n name: '#enum_typef4179c7f-45f9-482d-a5db-1abb86698384'\n label: Enumeration Type\n doc: This should render as a drop-down menu.\n id: '#main/enum_type'\n default: OTU table\n outputs:\n - type: File\n outputSource: '#main/input_collector/output'\n id: '#main/log_file'\n steps:\n - run: '#input_collector.cwl'\n in:\n - source: '#main/enum_type'\n id: '#main/input_collector/enum_type'\n out: ['#main/input_collector/output']\n id: '#main/input_collector'\n id: '#main'\n",
- });
+ name: 'Enum values collector',
+ description: 'Workflow for collecting enum values',
+ definition: "cwlVersion: v1.0\n$graph:\n- class: CommandLineTool\n requirements:\n - listing:\n - entryname: input_collector.log\n entry: |\n \"enum_type\":\n $(inputs.enum_type)\n\n class: InitialWorkDirRequirement\n inputs:\n - type:\n type: enum\n symbols: ['#input_collector.cwl/enum_type/OTU table', '#input_collector.cwl/enum_type/Pathway\n table', '#input_collector.cwl/enum_type/Function table', '#input_collector.cwl/enum_type/Ortholog\n table']\n id: '#input_collector.cwl/enum_type'\n outputs:\n - type: File\n outputBinding:\n glob: '*'\n id: '#input_collector.cwl/output'\n baseCommand: [echo]\n id: '#input_collector.cwl'\n- class: Workflow\n doc: This is the description of the workflow\n inputs:\n - type:\n type: enum\n symbols: ['#main/enum_type/OTU table', '#main/enum_type/Pathway table', '#main/enum_type/Function\n table', '#main/enum_type/Ortholog table']\n name: '#enum_typef4179c7f-45f9-482d-a5db-1abb86698384'\n label: Enumeration Type\n doc: This should render as a drop-down menu.\n id: '#main/enum_type'\n default: OTU table\n outputs:\n - type: File\n outputSource: '#main/input_collector/output'\n id: '#main/log_file'\n steps:\n - run: '#input_collector.cwl'\n in:\n - source: '#main/enum_type'\n id: '#main/input_collector/enum_type'\n out: ['#main/input_collector/output']\n id: '#main/input_collector'\n id: '#main'\n",
+ });
};
const createSampleProcess = ({ containerRequestService }: ServiceRepository) => {
"class": "CommandLineTool",
"requirements": [
{
- "listing": [
- {
- "entryname": "input_collector.log",
- "entry": "$(inputs.single_file.basename)\n"
- }
- ],
- "class": "InitialWorkDirRequirement"
+ "listing": [
+ {
+ "entryname": "input_collector.log",
+ "entry": "$(inputs.single_file.basename)\n"
+ }
+ ],
+ "class": "InitialWorkDirRequirement"
}
- ],
+ ],
"inputs": [
{
"type": "File",
"class": "File",
"location": "keep:233454526794c0a2d56a305baeff3d30+145/1.txt",
"basename": "fileA"
- }
+ }
},
}
},
// SPDX-License-Identifier: AGPL-3.0
import { unionize, ofType, UnionOf } from "~/common/unionize";
-import { TreeNode } from '~/models/tree';
-
+import { TreeNode, initTreeNode, getNodeDescendants, getNodeDescendantsIds, getNodeValue, TreeNodeStatus } from '~/models/tree';
+import { Dispatch } from 'redux';
+import { RootState } from '~/store/store';
+import { ServiceRepository } from '~/services/services';
+import { FilterBuilder } from '~/services/api/filter-builder';
+import { pipe } from 'lodash/fp';
+import { ResourceKind } from '~/models/resource';
+import { GroupContentsResource } from '../../services/groups-service/groups-service';
+import { CollectionDirectory, CollectionFile } from '../../models/collection-file';
export const treePickerActions = unionize({
LOAD_TREE_PICKER_NODE: ofType<{ id: string, pickerId: string }>(),
});
export type TreePickerAction = UnionOf<typeof treePickerActions>;
+
+interface ReceiveTreePickerDataParams<T> {
+ data: T[];
+ extractNodeData: (value: T) => { id: string, value: T, status?: TreeNodeStatus };
+ id: string;
+ pickerId: string;
+}
+export const receiveTreePickerData = <T>(params: ReceiveTreePickerDataParams<T>) =>
+ (dispatch: Dispatch) => {
+ const { data, extractNodeData, id, pickerId, } = params;
+ dispatch(treePickerActions.LOAD_TREE_PICKER_NODE_SUCCESS({
+ id,
+ nodes: data.map(item => initTreeNode(extractNodeData(item))),
+ pickerId,
+ }));
+ dispatch(treePickerActions.TOGGLE_TREE_PICKER_NODE_COLLAPSE({ id, pickerId }));
+ };
+
+export const loadProject = (id: string, pickerId: string, include?: ResourceKind[]) =>
+ async (dispatch: Dispatch, _: () => RootState, services: ServiceRepository) => {
+ dispatch(treePickerActions.LOAD_TREE_PICKER_NODE({ id, pickerId }));
+
+ const filters = pipe(
+ (fb: FilterBuilder) => fb.addEqual('ownerUuid', id),
+ fb => include ? fb.addIsA('uuid', include) : fb,
+ fb => fb.getFilters(),
+ )(new FilterBuilder());
+
+ const { items } = await services.groupsService.contents(id, { filters });
+
+ dispatch<any>(receiveTreePickerData<GroupContentsResource>({
+ id,
+ pickerId,
+ data: items,
+ extractNodeData: item => ({ id: item.uuid, value: item }),
+ }));
+ };
+
+export const loadCollection = (id: string, pickerId: string) =>
+ async (dispatch: Dispatch, _: () => RootState, services: ServiceRepository) => {
+ dispatch(treePickerActions.LOAD_TREE_PICKER_NODE({ id, pickerId }));
+
+ const files = await services.collectionService.files(id);
+ const data = getNodeDescendants('')(files).map(node => node.value);
+
+ dispatch<any>(receiveTreePickerData<CollectionDirectory | CollectionFile>({
+ id,
+ pickerId,
+ data,
+ extractNodeData: value => {
+ return {
+ id: value.id,
+ value,
+ status: TreeNodeStatus.LOADED,
+ };
+ },
+ }));
+ };
import { WrappedFieldProps } from 'redux-form';
import { initTreeNode } from '~/models/tree';
-type ProjectTreePickerProps = Pick<TreePickerProps, 'onContextMenu' | 'toggleItemActive' | 'toggleItemOpen' | 'toggleItemSelection'>;
+type ProjectTreePickerProps = Pick<TreePickerProps<ProjectResource>, 'onContextMenu' | 'toggleItemActive' | 'toggleItemOpen' | 'toggleItemSelection'>;
const mapDispatchToProps = (dispatch: Dispatch, props: { onChange: (projectUuid: string) => void }): ProjectTreePickerProps => ({
onContextMenu: () => { return; },
- toggleItemActive: (id, status, pickerId) => {
+ toggleItemActive: (_, { id }, pickerId) => {
getNotSelectedTreePickerKind(pickerId)
.forEach(pickerId => dispatch(treePickerActions.ACTIVATE_TREE_PICKER_NODE({ id: '', pickerId })));
dispatch(treePickerActions.ACTIVATE_TREE_PICKER_NODE({ id, pickerId }));
props.onChange(id);
},
- toggleItemOpen: (id, status, pickerId) => {
+ toggleItemOpen: (_, { id, status }, pickerId) => {
dispatch<any>(toggleItemOpen(id, status, pickerId));
},
- toggleItemSelection: (id, pickerId) => {
+ toggleItemSelection: (_, { id }, pickerId) => {
dispatch<any>(treePickerActions.TOGGLE_TREE_PICKER_NODE_SELECTION({ id, pickerId }));
},
});
}
});
-export interface ProjectTreeProps {
+export interface ProjectTreeProps<T> {
projects: Array<TreeItem<ProjectResource>>;
- toggleOpen: (id: string, status: TreeItemStatus) => void;
- toggleActive: (id: string, status: TreeItemStatus) => void;
+ toggleOpen: (event: React.MouseEvent<HTMLElement>, item: TreeItem<T>) => void;
+ toggleActive: (event: React.MouseEvent<HTMLElement>, item: TreeItem<T>) => void;
onContextMenu: (event: React.MouseEvent<HTMLElement>, item: TreeItem<ProjectResource>) => void;
}
export const ProjectTree = withStyles(styles)(
- class ProjectTreeGeneric<T> extends React.Component<ProjectTreeProps & WithStyles<CssRules>> {
+ class ProjectTreeGeneric<T> extends React.Component<ProjectTreeProps<T> & WithStyles<CssRules>> {
render(): ReactElement<any> {
const { classes, projects, toggleOpen, toggleActive, onContextMenu } = this.props;
return (
icon={ProjectIcon}
name={project.data.name}
isActive={project.active}
- hasMargin={true}/>
- }/>
+ hasMargin={true} />
+ } />
</div>
);
}
sidePanelProgress?: boolean;
}
-type SidePanelTreeActionProps = Pick<TreePickerProps, 'onContextMenu' | 'toggleItemActive' | 'toggleItemOpen' | 'toggleItemSelection'>;
+type SidePanelTreeActionProps = Pick<TreePickerProps<ProjectResource | string>, 'onContextMenu' | 'toggleItemActive' | 'toggleItemOpen' | 'toggleItemSelection'>;
const mapDispatchToProps = (dispatch: Dispatch, props: SidePanelTreeProps): SidePanelTreeActionProps => ({
- onContextMenu: (event, id) => {
+ onContextMenu: (event, { id }) => {
dispatch<any>(openSidePanelContextMenu(event, id));
},
- toggleItemActive: (nodeId) => {
- dispatch<any>(activateSidePanelTreeItem(nodeId));
- props.onItemActivation(nodeId);
+ toggleItemActive: (_, { id }) => {
+ dispatch<any>(activateSidePanelTreeItem(id));
+ props.onItemActivation(id);
},
- toggleItemOpen: (nodeId) => {
- dispatch<any>(toggleSidePanelTreeItemCollapse(nodeId));
+ toggleItemOpen: (_, { id }) => {
+ dispatch<any>(toggleSidePanelTreeItemCollapse(id));
},
toggleItemSelection: noop,
});
import { connect } from "react-redux";
import { Tree, TreeProps, TreeItem, TreeItemStatus } from "~/components/tree/tree";
import { RootState } from "~/store/store";
-import { getNodeValue, getNodeChildrenIds, Tree as Ttree, createTree, getNode, TreeNodeStatus } from '~/models/tree';
+import { getNodeChildrenIds, Tree as Ttree, createTree, getNode, TreeNodeStatus } from '~/models/tree';
import { Dispatch } from "redux";
import { initTreeNode } from '../../models/tree';
-export interface TreePickerProps {
+type Callback<T> = (event: React.MouseEvent<HTMLElement>, item: TreeItem<T>, pickerId: string) => void;
+export interface TreePickerProps<T> {
pickerId: string;
- onContextMenu: (event: React.MouseEvent<HTMLElement>, nodeId: string, pickerId: string) => void;
- toggleItemOpen: (nodeId: string, status: TreeItemStatus, pickerId: string) => void;
- toggleItemActive: (nodeId: string, status: TreeItemStatus, pickerId: string) => void;
- toggleItemSelection: (nodeId: string, pickerId: string) => void;
+ onContextMenu: Callback<T>;
+ toggleItemOpen: Callback<T>;
+ toggleItemActive: Callback<T>;
+ toggleItemSelection: Callback<T>;
}
const memoizedMapStateToProps = () => {
let prevTree: Ttree<any>;
let mappedProps: Pick<TreeProps<any>, 'items'>;
- return (state: RootState, props: TreePickerProps): Pick<TreeProps<any>, 'items'> => {
+ return <T>(state: RootState, props: TreePickerProps<T>): Pick<TreeProps<T>, 'items'> => {
const tree = state.treePicker[props.pickerId] || createTree();
if (tree !== prevTree) {
prevTree = tree;
};
};
-const mapDispatchToProps = (dispatch: Dispatch, props: TreePickerProps): Pick<TreeProps<any>, 'onContextMenu' | 'toggleItemOpen' | 'toggleItemActive' | 'toggleItemSelection'> => ({
- onContextMenu: (event, item) => props.onContextMenu(event, item.id, props.pickerId),
- toggleItemActive: (id, status) => props.toggleItemActive(id, status, props.pickerId),
- toggleItemOpen: (id, status) => props.toggleItemOpen(id, status, props.pickerId),
- toggleItemSelection: (_, item) => props.toggleItemSelection(item.id, props.pickerId),
+const mapDispatchToProps = (_: Dispatch, props: TreePickerProps<any>): Pick<TreeProps<any>, 'onContextMenu' | 'toggleItemOpen' | 'toggleItemActive' | 'toggleItemSelection'> => ({
+ onContextMenu: (event, item) => props.onContextMenu(event, item, props.pickerId),
+ toggleItemActive: (event, item) => props.toggleItemActive(event, item, props.pickerId),
+ toggleItemOpen: (event, item) => props.toggleItemOpen(event, item, props.pickerId),
+ toggleItemSelection: (event, item) => props.toggleItemSelection(event, item, props.pickerId),
});
export const TreePicker = connect(memoizedMapStateToProps(), mapDispatchToProps)(Tree);
import { RunProcessPanel } from '~/views/run-process-panel/run-process-panel';
import SplitterLayout from 'react-splitter-layout';
import { WorkflowPanel } from '~/views/workflow-panel/workflow-panel';
+import { TreePicker } from '../../views-components/tree-picker/tree-picker';
+import { noop } from 'lodash';
+import { TreeItem } from '~/components/tree/tree';
+import { GroupContentsResource } from '~/services/groups-service/groups-service';
type CssRules = 'root' | 'container' | 'splitter' | 'asidePanel' | 'contentWrapper' | 'content';
type WorkbenchPanelProps = WithStyles<CssRules>;
-export const WorkbenchPanel =
- withStyles(styles)(({ classes }: WorkbenchPanelProps) =>
+export const WorkbenchPanel =
+ withStyles(styles)(({ classes }: WorkbenchPanelProps) =>
<Grid container item xs className={classes.root}>
<Grid container item xs className={classes.container}>
<SplitterLayout customClassName={classes.splitter} percentage={true}
<MainContentBar />
</Grid>
<Grid item xs className={classes.content}>
+ <TreePicker
+ render={({ data }: TreeItem<GroupContentsResource>) =>
+ <p>{JSON.stringify(data.name)}</p>}
+ pickerId='testPicker'
+ onContextMenu={noop}
+ toggleItemOpen={noop}
+ toggleItemActive={item => console.log(item)}
+ toggleItemSelection={noop} />
<Switch>
<Route path={Routes.PROJECTS} component={ProjectPanel} />
<Route path={Routes.COLLECTIONS} component={CollectionPanel} />