expect(dataTable.find(TableBody).find(TableCell).key()).toBe("column-1-key");
});
- it("shows information that items array is empty", () => {
- const columns: DataColumns<string> = [
- {
- name: "Column 1",
- render: () => <span />,
- selected: true
- }
- ];
- const dataTable = mount(<DataTable
- columns={columns}
- items={[]}
- onFiltersChange={jest.fn()}
- onRowClick={jest.fn()}
- onRowContextMenu={jest.fn()}
- onSortToggle={jest.fn()} />);
- expect(dataTable.find(Typography).text()).toBe("No items");
- });
-
it("renders items", () => {
- const columns: Array<DataColumn<string>> = [
+ const columns: DataColumns<string> = [
{
name: "Column 1",
render: (item) => <Typography>{item}</Typography>,
--- /dev/null
-import { TreeItem, TreeItemStatus } from "../../components/tree/tree";
+ // Copyright (C) The Arvados Authors. All rights reserved.
+ //
+ // SPDX-License-Identifier: AGPL-3.0
+
+ import { Dispatch } from "redux";
+ import projectActions, { getProjectList } from "../project/project-action";
+ import { push } from "react-router-redux";
-import { Project } from "../../models/project";
++import { TreeItemStatus } from "../../components/tree/tree";
+ import { getCollectionList } from "../collection/collection-action";
+ import { findTreeItem } from "../project/project-reducer";
-export const setProjectItem = (projects: Array<TreeItem<Project>>, itemId: string, itemKind: ResourceKind, itemMode: ItemMode) => (dispatch: Dispatch) => {
+ import { Resource, ResourceKind } from "../../models/resource";
+ import sidePanelActions from "../side-panel/side-panel-action";
++import dataExplorerActions from "../data-explorer/data-explorer-action";
++import { PROJECT_PANEL_ID } from "../../views/project-panel/project-panel";
++import { projectPanelItems } from "../../views/project-panel/project-panel-selectors";
++import { RootState } from "../store";
+
+ export const getResourceUrl = (resource: Resource): string => {
+ switch (resource.kind) {
+ case ResourceKind.LEVEL_UP: return `/projects/${resource.ownerUuid}`;
+ case ResourceKind.PROJECT: return `/projects/${resource.uuid}`;
+ case ResourceKind.COLLECTION: return `/collections/${resource.uuid}`;
+ default:
+ return "#";
+ }
+ };
+
+ export enum ItemMode {
+ BOTH,
+ OPEN,
+ ACTIVE
+ }
+
- const openProjectItem = (resource: Resource) => {
- if (itemMode === ItemMode.OPEN || itemMode === ItemMode.BOTH) {
- dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN(resource.uuid));
++export const setProjectItem = (itemId: string, itemKind = ResourceKind.PROJECT, itemMode = ItemMode.OPEN) =>
++ (dispatch: Dispatch, getState: () => RootState) => {
++ const { projects } = getState();
+
- if (itemMode === ItemMode.ACTIVE || itemMode === ItemMode.BOTH) {
- dispatch(sidePanelActions.RESET_SIDE_PANEL_ACTIVITY(resource.uuid));
- }
++ let treeItem = findTreeItem(projects.items, itemId);
++ if (treeItem && itemKind === ResourceKind.LEVEL_UP) {
++ treeItem = findTreeItem(projects.items, treeItem.data.ownerUuid);
+ }
+
- dispatch(push(getResourceUrl({...resource, kind: itemKind})));
++ if (treeItem) {
++ dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(treeItem.data.uuid));
+
- let treeItem = findTreeItem(projects, itemId);
- if (treeItem && itemKind === ResourceKind.LEVEL_UP) {
- treeItem = findTreeItem(projects, treeItem.data.ownerUuid);
- }
++ if (treeItem.status === TreeItemStatus.Loaded) {
++ dispatch<any>(openProjectItem(treeItem.data, itemKind, itemMode));
++ } else {
++ dispatch<any>(getProjectList(itemId))
++ .then(() => dispatch<any>(openProjectItem(treeItem!.data, itemKind, itemMode)));
++ }
++ if (itemMode === ItemMode.ACTIVE || itemMode === ItemMode.BOTH) {
++ dispatch<any>(getCollectionList(itemId));
++ }
++ }
+ };
+
- if (treeItem) {
- dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(treeItem.data.uuid));
++const openProjectItem = (resource: Resource, itemKind: ResourceKind, itemMode: ItemMode) =>
++ (dispatch: Dispatch, getState: () => RootState) => {
+
- if (treeItem.status === TreeItemStatus.Loaded) {
- openProjectItem(treeItem.data);
- } else {
- dispatch<any>(getProjectList(itemId))
- .then(() => openProjectItem(treeItem!.data));
++ const { collections, projects } = getState();
+
- dispatch<any>(getCollectionList(itemId));
++ if (itemMode === ItemMode.OPEN || itemMode === ItemMode.BOTH) {
++ dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN(resource.uuid));
+ }
++
+ if (itemMode === ItemMode.ACTIVE || itemMode === ItemMode.BOTH) {
- }
-};
++ dispatch(sidePanelActions.RESET_SIDE_PANEL_ACTIVITY(resource.uuid));
+ }
++
++ dispatch(push(getResourceUrl({ ...resource, kind: itemKind })));
++ dispatch(dataExplorerActions.SET_ITEMS({
++ id: PROJECT_PANEL_ID,
++ items: projectPanelItems(
++ projects.items,
++ resource.uuid,
++ collections
++ )
++ }));
++ };
import projectsReducer, { ProjectState } from "./project/project-reducer";
import sidePanelReducer, { SidePanelState } from './side-panel/side-panel-reducer';
import authReducer, { AuthState } from "./auth/auth-reducer";
- import collectionsReducer from "./collection/collection-reducer";
+import dataExplorerReducer, { DataExplorerState } from './data-explorer/data-explorer-reducer';
+ import collectionsReducer, { CollectionState } from "./collection/collection-reducer";
const composeEnhancers =
(process.env.NODE_ENV === 'development' &&
export interface RootState {
auth: AuthState;
projects: ProjectState;
+ collections: CollectionState;
router: RouterState;
+ dataExplorer: DataExplorerState;
sidePanel: SidePanelState;
}
--- /dev/null
-export interface ProjectExplorerItem {
+ // Copyright (C) The Arvados Authors. All rights reserved.
+ //
+ // SPDX-License-Identifier: AGPL-3.0
+
++import { TreeItem } from "../../components/tree/tree";
++import { Project } from "../../models/project";
+ import { getResourceKind, Resource, ResourceKind } from "../../models/resource";
+
++export interface ProjectPanelItem {
+ uuid: string;
+ name: string;
+ kind: ResourceKind;
+ url: string;
+ owner: string;
+ lastModified: string;
+ fileSize?: number;
+ status?: string;
+ }
+
+ function resourceToDataItem(r: Resource, kind?: ResourceKind) {
+ return {
+ uuid: r.uuid,
+ name: r.name,
+ kind: kind ? kind : getResourceKind(r.kind),
+ owner: r.ownerUuid,
+ lastModified: r.modifiedAt
+ };
+ }
+
--- /dev/null
-import { ProjectExplorerItem } from "../../views-components/project-explorer/project-explorer-item";
+ // Copyright (C) The Arvados Authors. All rights reserved.
+ //
+ // SPDX-License-Identifier: AGPL-3.0
+
+ import { TreeItem } from "../../components/tree/tree";
+ import { Project } from "../../models/project";
+ import { findTreeItem } from "../../store/project/project-reducer";
+ import { ResourceKind } from "../../models/resource";
+ import { Collection } from "../../models/collection";
+ import { getResourceUrl } from "../../store/navigation/navigation-action";
-export const projectExplorerItems = (projects: Array<TreeItem<Project>>, treeItemId: string, collections: Array<Collection>): ProjectExplorerItem[] => {
- const dataItems: ProjectExplorerItem[] = [];
++import { ProjectPanelItem } from "./project-panel-item";
+
- } as ProjectExplorerItem;
++export const projectPanelItems = (projects: Array<TreeItem<Project>>, treeItemId: string, collections: Array<Collection>): ProjectPanelItem[] => {
++ const dataItems: ProjectPanelItem[] = [];
+
+ const treeItem = findTreeItem(projects, treeItemId);
+ if (treeItem) {
+ dataItems.push({
+ name: "..",
+ url: getResourceUrl(treeItem.data),
+ kind: ResourceKind.LEVEL_UP,
+ owner: "",
+ uuid: treeItem.data.uuid,
+ lastModified: ""
+ });
+
+ if (treeItem.items) {
+ treeItem.items.forEach(p => {
+ const item = {
+ name: p.data.name,
+ kind: ResourceKind.PROJECT,
+ url: getResourceUrl(treeItem.data),
+ owner: p.data.ownerUuid,
+ uuid: p.data.uuid,
+ lastModified: p.data.modifiedAt
- } as ProjectExplorerItem;
++ } as ProjectPanelItem;
+
+ dataItems.push(item);
+ });
+ }
+ }
+
+ collections.forEach(c => {
+ const item = {
+ name: c.name,
+ kind: ResourceKind.COLLECTION,
+ url: getResourceUrl(c),
+ owner: c.ownerUuid,
+ uuid: c.uuid,
+ lastModified: c.modifiedAt
++ } as ProjectPanelItem;
+
+ dataItems.push(item);
+ });
+
+ return dataItems;
+ };
+
// SPDX-License-Identifier: AGPL-3.0
import * as React from 'react';
- import { ProjectExplorerItem } from './project-explorer-item';
-import { RouteComponentProps } from 'react-router';
-import { ProjectState } from '../../store/project/project-reducer';
-import { RootState } from '../../store/store';
-import { connect, DispatchProp } from 'react-redux';
-import { CollectionState } from "../../store/collection/collection-reducer";
-import { ItemMode, setProjectItem } from "../../store/navigation/navigation-action";
-import ProjectExplorer from "../../views-components/project-explorer/project-explorer";
-import { projectExplorerItems } from "./project-panel-selectors";
-import { ProjectExplorerItem } from "../../views-components/project-explorer/project-explorer-item";
-import { Button, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
-import { DataColumn, SortDirection } from '../../components/data-table/data-column';
++import { ProjectPanelItem } from './project-panel-item';
+import { Grid, Typography, Button, Toolbar, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
+import { formatDate, formatFileSize } from '../../common/formatters';
- import DataExplorer from '../data-explorer/data-explorer';
- import { DataColumn } from '../../components/data-table/data-column';
++import DataExplorer from "../../views-components/data-explorer/data-explorer";
++import { DataColumn, toggleSortDirection } from '../../components/data-table/data-column';
import { DataTableFilterItem } from '../../components/data-table-filters/data-table-filters';
+import { ContextMenuAction } from '../../components/context-menu/context-menu';
+import { DispatchProp, connect } from 'react-redux';
+import actions from "../../store/data-explorer/data-explorer-action";
++import { setProjectItem } from "../../store/navigation/navigation-action";
+import { DataColumns } from '../../components/data-table/data-table';
++import { ResourceKind } from "../../models/resource";
- export const PROJECT_EXPLORER_ID = "projectExplorer";
- class ProjectExplorer extends React.Component<DispatchProp & WithStyles<CssRules>> {
-interface ProjectPanelDataProps {
- projects: ProjectState;
- collections: CollectionState;
-}
++export const PROJECT_PANEL_ID = "projectPanel";
++class ProjectPanel extends React.Component<DispatchProp & WithStyles<CssRules>> {
+ render() {
+ return <div>
+ <div className={this.props.classes.toolbar}>
+ <Button color="primary" variant="raised" className={this.props.classes.button}>
+ Create a collection
+ </Button>
+ <Button color="primary" variant="raised" className={this.props.classes.button}>
+ Run a process
+ </Button>
+ <Button color="primary" variant="raised" className={this.props.classes.button}>
+ Create a project
+ </Button>
+ </div>
+ <DataExplorer
- id={PROJECT_EXPLORER_ID}
++ id={PROJECT_PANEL_ID}
+ contextActions={contextMenuActions}
+ onColumnToggle={this.toggleColumn}
+ onFiltersChange={this.changeFilters}
- onRowClick={console.log}
++ onRowClick={this.openProject}
+ onSortToggle={this.toggleSort}
+ onSearch={this.search}
+ onContextAction={this.executeAction}
+ onChangePage={this.changePage}
+ onChangeRowsPerPage={this.changeRowsPerPage} />;
+ </div>;
+ }
-type ProjectPanelProps = ProjectPanelDataProps & RouteComponentProps<{ name: string }> & DispatchProp;
+ componentDidMount() {
- this.props.dispatch(actions.SET_COLUMNS({ id: PROJECT_EXPLORER_ID, columns }));
++ this.props.dispatch(actions.SET_COLUMNS({ id: PROJECT_PANEL_ID, columns }));
+ }
- toggleColumn = (toggledColumn: DataColumn<ProjectExplorerItem>) => {
- this.props.dispatch(actions.TOGGLE_COLUMN({ id: PROJECT_EXPLORER_ID, columnName: toggledColumn.name }));
-interface ProjectPanelState {
- sort: {
- columnName: string;
- direction: SortDirection;
- };
- filters: string[];
-}
++ toggleColumn = (toggledColumn: DataColumn<ProjectPanelItem>) => {
++ this.props.dispatch(actions.TOGGLE_COLUMN({ id: PROJECT_PANEL_ID, columnName: toggledColumn.name }));
+ }
- toggleSort = (toggledColumn: DataColumn<ProjectExplorerItem>) => {
- this.props.dispatch(actions.TOGGLE_SORT({ id: PROJECT_EXPLORER_ID, columnName: toggledColumn.name }));
-class ProjectPanel extends React.Component<ProjectPanelProps & WithStyles<CssRules>, ProjectPanelState> {
- state: ProjectPanelState = {
- sort: {
- columnName: "Name",
- direction: "desc"
- },
- filters: ['collection', 'project']
- };
++ toggleSort = (column: DataColumn<ProjectPanelItem>) => {
++ this.props.dispatch(actions.TOGGLE_SORT({ id: PROJECT_PANEL_ID, columnName: column.name }));
+ }
- changeFilters = (filters: DataTableFilterItem[], updatedColumn: DataColumn<ProjectExplorerItem>) => {
- this.props.dispatch(actions.SET_FILTERS({ id: PROJECT_EXPLORER_ID, columnName: updatedColumn.name, filters }));
- render() {
- const items = projectExplorerItems(
- this.props.projects.items,
- this.props.projects.currentItemId,
- this.props.collections
- );
- const [goBackItem, ...otherItems] = items;
- const filteredItems = otherItems.filter(i => this.state.filters.some(f => f === i.kind));
- const sortedItems = sortItems(this.state.sort, filteredItems);
- return (
- <div>
- <div className={this.props.classes.toolbar}>
- <Button color="primary" variant="raised" className={this.props.classes.button}>
- Create a collection
- </Button>
- <Button color="primary" variant="raised" className={this.props.classes.button}>
- Run a process
- </Button>
- <Button color="primary" variant="raised" className={this.props.classes.button}>
- Create a project
- </Button>
- </div>
- <ProjectExplorer
- items={goBackItem ? [goBackItem, ...sortedItems] : sortedItems}
- onRowClick={this.goToItem}
- onToggleSort={this.toggleSort}
- onChangeFilters={this.changeFilters}
- />
- </div>
- );
++ changeFilters = (filters: DataTableFilterItem[], column: DataColumn<ProjectPanelItem>) => {
++ this.props.dispatch(actions.SET_FILTERS({ id: PROJECT_PANEL_ID, columnName: column.name, filters }));
}
- executeAction = (action: ContextMenuAction, item: ProjectExplorerItem) => {
- goToItem = (item: ProjectExplorerItem) => {
- this.props.dispatch<any>(setProjectItem(this.props.projects.items, item.uuid, item.kind, ItemMode.BOTH));
++ executeAction = (action: ContextMenuAction, item: ProjectPanelItem) => {
+ alert(`Executing ${action.name} on ${item.name}`);
}
- toggleSort = (column: DataColumn<ProjectExplorerItem>) => {
- this.setState({
- sort: {
- columnName: column.name,
- direction: column.sortDirection || "none"
- }
- });
+ search = (searchValue: string) => {
- this.props.dispatch(actions.SET_SEARCH_VALUE({ id: PROJECT_EXPLORER_ID, searchValue }));
++ this.props.dispatch(actions.SET_SEARCH_VALUE({ id: PROJECT_PANEL_ID, searchValue }));
}
- changeFilters = (filters: DataTableFilterItem[]) => {
- this.setState({ filters: filters.filter(f => f.selected).map(f => f.name.toLowerCase()) });
+ changePage = (page: number) => {
- this.props.dispatch(actions.SET_PAGE({ id: PROJECT_EXPLORER_ID, page }));
++ this.props.dispatch(actions.SET_PAGE({ id: PROJECT_PANEL_ID, page }));
}
-}
-const sortItems = (sort: { columnName: string, direction: SortDirection }, items: ProjectExplorerItem[]) => {
- const sortedItems = items.slice(0);
- const direction = sort.direction === "asc" ? -1 : 1;
- sortedItems.sort((a, b) => {
- if (sort.columnName === "Last modified") {
- return ((new Date(a.lastModified)).getTime() - (new Date(b.lastModified)).getTime()) * direction;
- } else {
- return a.name.localeCompare(b.name) * direction;
- }
- });
- return sortedItems;
-};
+ changeRowsPerPage = (rowsPerPage: number) => {
- this.props.dispatch(actions.SET_ROWS_PER_PAGE({ id: PROJECT_EXPLORER_ID, rowsPerPage }));
++ this.props.dispatch(actions.SET_ROWS_PER_PAGE({ id: PROJECT_PANEL_ID, rowsPerPage }));
++ }
++
++ openProject = (item: ProjectPanelItem) => {
++ this.props.dispatch<any>(setProjectItem(item.uuid));
+ }
+}
type CssRules = "toolbar" | "button";
}
});
- const renderName = (item: ProjectExplorerItem) =>
-export default withStyles(styles)(
- connect(
- (state: RootState) => ({
- projects: state.projects,
- collections: state.collections
- })
- )(ProjectPanel));
++const renderName = (item: ProjectPanelItem) =>
+ <Grid
+ container
+ alignItems="center"
+ wrap="nowrap"
+ spacing={16}>
+ <Grid item>
+ {renderIcon(item)}
+ </Grid>
+ <Grid item>
+ <Typography color="primary">
+ {item.name}
+ </Typography>
+ </Grid>
+ </Grid>;
+
- const renderIcon = (item: ProjectExplorerItem) => {
- switch (item.type) {
- case "arvados#group":
++
++const renderIcon = (item: ProjectPanelItem) => {
++ switch (item.kind) {
++ case ResourceKind.LEVEL_UP:
++ return <i className="icon-level-up" style={{ fontSize: "1rem" }} />;
++ case ResourceKind.PROJECT:
+ return <i className="fas fa-folder fa-lg" />;
- case "arvados#groupList":
++ case ResourceKind.COLLECTION:
+ return <i className="fas fa-th fa-lg" />;
+ default:
+ return <i />;
+ }
+};
+
+const renderDate = (date: string) =>
+ <Typography noWrap>
+ {formatDate(date)}
+ </Typography>;
+
+const renderFileSize = (fileSize?: number) =>
+ <Typography noWrap>
+ {formatFileSize(fileSize)}
+ </Typography>;
+
+const renderOwner = (owner: string) =>
+ <Typography noWrap color="primary">
+ {owner}
+ </Typography>;
+
+const renderType = (type: string) =>
+ <Typography noWrap>
+ {type}
+ </Typography>;
+
- const renderStatus = (item: ProjectExplorerItem) =>
++const renderStatus = (item: ProjectPanelItem) =>
+ <Typography noWrap align="center">
+ {item.status || "-"}
+ </Typography>;
+
- const columns: DataColumns<ProjectExplorerItem> = [{
++const columns: DataColumns<ProjectPanelItem> = [{
+ name: "Name",
+ selected: true,
- sortDirection: "asc",
- render: renderName
++ sortDirection: "desc",
++ render: renderName,
++ width: "450px"
+}, {
+ name: "Status",
+ selected: true,
- filters: [{
- name: "In progress",
- selected: true
- }, {
- name: "Complete",
- selected: true
- }],
- render: renderStatus
++ render: renderStatus,
++ width: "75px"
+}, {
+ name: "Type",
+ selected: true,
+ filters: [{
+ name: "Collection",
+ selected: true
+ }, {
- name: "Group",
++ name: "Project",
+ selected: true
+ }],
- render: item => renderType(item.type)
++ render: item => renderType(item.kind),
++ width: "125px"
+}, {
+ name: "Owner",
+ selected: true,
- render: item => renderOwner(item.owner)
++ render: item => renderOwner(item.owner),
++ width: "200px"
+}, {
+ name: "File size",
+ selected: true,
- sortDirection: "none",
- render: item => renderFileSize(item.fileSize)
++ render: item => renderFileSize(item.fileSize),
++ width: "50px"
+}, {
+ name: "Last modified",
+ selected: true,
- render: item => renderDate(item.lastModified)
++ sortDirection: "none",
++ render: item => renderDate(item.lastModified),
++ width: "150px"
+}];
+
+const contextMenuActions = [[{
+ icon: "fas fa-users fa-fw",
+ name: "Share"
+}, {
+ icon: "fas fa-sign-out-alt fa-fw",
+ name: "Move to"
+}, {
+ icon: "fas fa-star fa-fw",
+ name: "Add to favourite"
+}, {
+ icon: "fas fa-edit fa-fw",
+ name: "Rename"
+}, {
+ icon: "fas fa-copy fa-fw",
+ name: "Make a copy"
+}, {
+ icon: "fas fa-download fa-fw",
+ name: "Download"
+}], [{
+ icon: "fas fa-trash-alt fa-fw",
+ name: "Remove"
+}
+]];
+
- export default withStyles(styles)(connect()(ProjectExplorer));
++export default withStyles(styles)(connect()(ProjectPanel));
import { connect, DispatchProp } from "react-redux";
import { Route, Switch } from "react-router";
import authActions from "../../store/auth/auth-action";
+import dataExplorerActions from "../../store/data-explorer/data-explorer-action";
import { User } from "../../models/user";
import { RootState } from "../../store/store";
- import MainAppBar, { MainAppBarActionProps, MainAppBarMenuItem } from '../../views-components/main-app-bar/main-app-bar';
+ import MainAppBar, {
+ MainAppBarActionProps,
+ MainAppBarMenuItem
+ } from '../../views-components/main-app-bar/main-app-bar';
import { Breadcrumb } from '../../components/breadcrumbs/breadcrumbs';
import { push } from 'react-router-redux';
- import projectActions, { getProjectList } from "../../store/project/project-action";
import ProjectTree from '../../views-components/project-tree/project-tree';
- import { TreeItem, TreeItemStatus } from "../../components/tree/tree";
+ import { TreeItem } from "../../components/tree/tree";
import { Project } from "../../models/project";
-import { getTreePath } from '../../store/project/project-reducer';
-import ProjectPanel from '../project-panel/project-panel';
+import { getTreePath, findTreeItem } from '../../store/project/project-reducer';
- import ProjectExplorer, { PROJECT_EXPLORER_ID } from '../../views-components/project-explorer/project-explorer';
- import { ProjectExplorerItem, mapProjectTreeItem } from '../../views-components/project-explorer/project-explorer-item';
import sidePanelActions from '../../store/side-panel/side-panel-action';
import SidePanel, { SidePanelItem } from '../../components/side-panel/side-panel';
+ import { ResourceKind } from "../../models/resource";
+ import { ItemMode, setProjectItem } from "../../store/navigation/navigation-action";
+ import projectActions from "../../store/project/project-action";
++import ProjectPanel from "../project-panel/project-panel";
const drawerWidth = 240;
const appBarHeight = 102;
}
};
-
mainAppBarActions: MainAppBarActionProps = {
- onBreadcrumbClick: ({ itemId, status }: NavBreadcrumb) => {
- this.toggleProjectTreeItemOpen(itemId, status);
+ onBreadcrumbClick: ({ itemId }: NavBreadcrumb) => {
- this.props.dispatch<any>(
- setProjectItem(this.props.projects, itemId, ResourceKind.PROJECT, ItemMode.BOTH)
- );
++ this.props.dispatch<any>(setProjectItem(itemId, ResourceKind.PROJECT, ItemMode.BOTH));
},
onSearch: searchText => {
this.setState({ searchText });
<SidePanel
toggleOpen={this.toggleSidePanelOpen}
toggleActive={this.toggleSidePanelActive}
- sidePanelItems={sidePanelItems}>
+ sidePanelItems={this.props.sidePanelItems}>
<ProjectTree
- projects={projects}
- toggleOpen={this.toggleProjectTreeItemOpen}
- toggleActive={this.toggleProjectTreeItemActive} />
+ projects={this.props.projects}
+ toggleOpen={itemId =>
+ this.props.dispatch<any>(
- setProjectItem(this.props.projects, itemId, ResourceKind.PROJECT, ItemMode.OPEN)
++ setProjectItem(itemId, ResourceKind.PROJECT, ItemMode.OPEN)
+ )}
+ toggleActive={itemId =>
+ this.props.dispatch<any>(
- setProjectItem(this.props.projects, itemId, ResourceKind.PROJECT, ItemMode.ACTIVE)
++ setProjectItem(itemId, ResourceKind.PROJECT, ItemMode.ACTIVE)
+ )}
+ />
</SidePanel>
</Drawer>}
<main className={classes.contentWrapper}>