From: Michal Klobukowski Date: Mon, 25 Jun 2018 13:22:34 +0000 (+0200) Subject: Connect project explorer to the store X-Git-Tag: 1.2.0~63^2~13 X-Git-Url: https://git.arvados.org/arvados-workbench2.git/commitdiff_plain/ade15546a44f9930095b1047318967e9a74dbc68 Connect project explorer to the store Feature #13678 Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski --- diff --git a/src/index.tsx b/src/index.tsx index cf1610f8..58048784 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -18,16 +18,7 @@ import { getProjectList } from "./store/project/project-action"; const history = createBrowserHistory(); -const store = configureStore({ - projects: [ - ], - router: { - location: null - }, - auth: { - user: undefined - } -}, history); +const store = configureStore(history); store.dispatch(authActions.INIT()); const rootUuid = authService.getRootUuid(); diff --git a/src/store/data-explorer/data-explorer-reducer.ts b/src/store/data-explorer/data-explorer-reducer.ts index 1f782778..af1eb469 100644 --- a/src/store/data-explorer/data-explorer-reducer.ts +++ b/src/store/data-explorer/data-explorer-reducer.ts @@ -11,13 +11,15 @@ interface DataExplorer { items: any[]; page: number; rowsPerPage: number; + searchValue: string; } export const initialDataExplorer: DataExplorer = { columns: [], items: [], page: 0, - rowsPerPage: 0 + rowsPerPage: 0, + searchValue: "" }; export type DataExplorerState = Record; @@ -36,7 +38,7 @@ const dataExplorerReducer = (state: DataExplorerState = {}, action: DataExplorer export default dataExplorerReducer; -const get = (state: DataExplorerState, id: string) => state[id] || initialDataExplorer; +export const get = (state: DataExplorerState, id: string) => state[id] || initialDataExplorer; const update = (state: DataExplorerState, id: string, updateFn: (dataExplorer: DataExplorer) => DataExplorer) => ({ ...state, [id]: updateFn(get(state, id)) }); diff --git a/src/store/store.ts b/src/store/store.ts index 6b9c31ff..9d2a9535 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -9,6 +9,7 @@ import { History } from "history"; import projectsReducer, { ProjectState } from "./project/project-reducer"; import authReducer, { AuthState } from "./auth/auth-reducer"; import collectionsReducer from "./collection/collection-reducer"; +import dataExplorerReducer, { DataExplorerState } from './data-explorer/data-explorer-reducer'; const composeEnhancers = (process.env.NODE_ENV === 'development' && @@ -19,21 +20,23 @@ export interface RootState { auth: AuthState; projects: ProjectState; router: RouterState; + dataExplorer: DataExplorerState; } const rootReducer = combineReducers({ auth: authReducer, projects: projectsReducer, collections: collectionsReducer, - router: routerReducer + router: routerReducer, + dataExplorer: dataExplorerReducer }); -export default function configureStore(initialState: RootState, history: History) { +export default function configureStore(history: History) { const middlewares: Middleware[] = [ routerMiddleware(history), thunkMiddleware ]; const enhancer = composeEnhancers(applyMiddleware(...middlewares)); - return createStore(rootReducer, initialState!, enhancer); + return createStore(rootReducer, enhancer); } diff --git a/src/views-components/data-explorer/data-explorer.tsx b/src/views-components/data-explorer/data-explorer.tsx new file mode 100644 index 00000000..f00664fa --- /dev/null +++ b/src/views-components/data-explorer/data-explorer.tsx @@ -0,0 +1,10 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import { connect } from "react-redux"; +import { RootState } from "../../store/store"; +import DataExplorer from "../../components/data-explorer/data-explorer"; +import { get } from "../../store/data-explorer/data-explorer-reducer"; + +export default connect((state: RootState, props: { id: string }) => get(state.dataExplorer, props.id))(DataExplorer); diff --git a/src/views-components/project-explorer/project-explorer.tsx b/src/views-components/project-explorer/project-explorer.tsx index 4931c09a..7fff08a3 100644 --- a/src/views-components/project-explorer/project-explorer.tsx +++ b/src/views-components/project-explorer/project-explorer.tsx @@ -6,79 +6,15 @@ import * as React from 'react'; import { ProjectExplorerItem } from './project-explorer-item'; import { Grid, Typography } from '@material-ui/core'; import { formatDate, formatFileSize } from '../../common/formatters'; -import DataExplorer from '../../components/data-explorer/data-explorer'; +import DataExplorer from '../data-explorer/data-explorer'; import { DataColumn, toggleSortDirection, resetSortDirection } 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"; -export interface ProjectExplorerContextActions { - onAddToFavourite: (item: ProjectExplorerItem) => void; - onCopy: (item: ProjectExplorerItem) => void; - onDownload: (item: ProjectExplorerItem) => void; - onMoveTo: (item: ProjectExplorerItem) => void; - onRemove: (item: ProjectExplorerItem) => void; - onRename: (item: ProjectExplorerItem) => void; - onShare: (item: ProjectExplorerItem) => void; -} - -interface ProjectExplorerProps { - items: ProjectExplorerItem[]; -} - -interface ProjectExplorerState { - columns: Array>; - searchValue: string; - page: number; - rowsPerPage: number; -} - -class ProjectExplorer extends React.Component { - state: ProjectExplorerState = { - searchValue: "", - page: 0, - rowsPerPage: 10, - columns: [{ - name: "Name", - selected: true, - sortDirection: "asc", - render: renderName - }, { - name: "Status", - selected: true, - filters: [{ - name: "In progress", - selected: true - }, { - name: "Complete", - selected: true - }], - render: renderStatus - }, { - name: "Type", - selected: true, - filters: [{ - name: "Collection", - selected: true - }, { - name: "Group", - selected: true - }], - render: item => renderType(item.type) - }, { - name: "Owner", - selected: true, - render: item => renderOwner(item.owner) - }, { - name: "File size", - selected: true, - sortDirection: "none", - render: item => renderFileSize(item.fileSize) - }, { - name: "Last modified", - selected: true, - render: item => renderDate(item.lastModified) - }] - }; +export const PROJECT_EXPLORER_ID = "projectExplorer"; +class ProjectExplorer extends React.Component { contextMenuActions = [[{ icon: "fas fa-users fa-fw", @@ -106,12 +42,8 @@ class ProjectExplorer extends React.Component; } + componentDidMount() { + this.props.dispatch(actions.SET_COLUMNS({ id: PROJECT_EXPLORER_ID, columns })); + } + toggleColumn = (toggledColumn: DataColumn) => { - this.setState({ - columns: this.state.columns.map(column => - column.name === toggledColumn.name - ? { ...column, selected: !column.selected } - : column - ) - }); + this.props.dispatch(actions.TOGGLE_COLUMN({ id: PROJECT_EXPLORER_ID, columnName: toggledColumn.name })); } toggleSort = (toggledColumn: DataColumn) => { - this.setState({ - columns: this.state.columns.map(column => - column.name === toggledColumn.name - ? toggleSortDirection(column) - : resetSortDirection(column) - ) - }); + this.props.dispatch(actions.TOGGLE_SORT({ id: PROJECT_EXPLORER_ID, columnName: toggledColumn.name })); } changeFilters = (filters: DataTableFilterItem[], updatedColumn: DataColumn) => { - this.setState({ - columns: this.state.columns.map(column => - column.name === updatedColumn.name - ? { ...column, filters } - : column - ) - }); + this.props.dispatch(actions.SET_FILTERS({ id: PROJECT_EXPLORER_ID, columnName: updatedColumn.name, filters })); } executeAction = (action: ContextMenuAction, item: ProjectExplorerItem) => { @@ -157,15 +75,15 @@ class ProjectExplorer extends React.Component { - this.setState({ searchValue }); + this.props.dispatch(actions.SET_SEARCH_VALUE({ id: PROJECT_EXPLORER_ID, searchValue })); } changePage = (page: number) => { - this.setState({ page }); + this.props.dispatch(actions.SET_PAGE({ id: PROJECT_EXPLORER_ID, page })); } changeRowsPerPage = (rowsPerPage: number) => { - this.setState({ rowsPerPage }); + this.props.dispatch(actions.SET_ROWS_PER_PAGE({ id: PROJECT_EXPLORER_ID, rowsPerPage })); } } @@ -221,4 +139,46 @@ const renderStatus = (item: ProjectExplorerItem) => {item.status || "-"} ; -export default ProjectExplorer; +const columns: Array> = [{ + name: "Name", + selected: true, + sortDirection: "asc", + render: renderName +}, { + name: "Status", + selected: true, + filters: [{ + name: "In progress", + selected: true + }, { + name: "Complete", + selected: true + }], + render: renderStatus +}, { + name: "Type", + selected: true, + filters: [{ + name: "Collection", + selected: true + }, { + name: "Group", + selected: true + }], + render: item => renderType(item.type) +}, { + name: "Owner", + selected: true, + render: item => renderOwner(item.owner) +}, { + name: "File size", + selected: true, + sortDirection: "none", + render: item => renderFileSize(item.fileSize) +}, { + name: "Last modified", + selected: true, + render: item => renderDate(item.lastModified) +}]; + +export default connect()(ProjectExplorer); diff --git a/src/views/project-panel/project-panel.tsx b/src/views/project-panel/project-panel.tsx index f9e6c8b8..afc6ce0f 100644 --- a/src/views/project-panel/project-panel.tsx +++ b/src/views/project-panel/project-panel.tsx @@ -6,9 +6,8 @@ import * as React from 'react'; import { RouteComponentProps } from 'react-router-dom'; import { DispatchProp, connect } from 'react-redux'; import { ProjectState, findTreeItem } from '../../store/project/project-reducer'; -import ProjectExplorer from '../../views-components/project-explorer/project-explorer'; import { RootState } from '../../store/store'; -import { mapProjectTreeItem } from './project-panel-selectors'; +import ProjectExplorer from '../../views-components/project-explorer/project-explorer'; interface ProjectPanelDataProps { projects: ProjectState; @@ -19,10 +18,8 @@ type ProjectPanelProps = ProjectPanelDataProps & RouteComponentProps<{ name: str class ProjectPanel extends React.Component { render() { - const project = findTreeItem(this.props.projects, this.props.match.params.name); - const projectItems = project && project.items || []; return ( - + ); } } diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx index bac0b473..6a8698fd 100644 --- a/src/views/workbench/workbench.tsx +++ b/src/views/workbench/workbench.tsx @@ -9,6 +9,7 @@ import Drawer from '@material-ui/core/Drawer'; 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'; @@ -18,8 +19,10 @@ import projectActions, { getProjectList } from "../../store/project/project-acti import ProjectTree from '../../views-components/project-tree/project-tree'; import { TreeItem, TreeItemStatus } from "../../components/tree/tree"; import { Project } from "../../models/project"; -import { getTreePath } from '../../store/project/project-reducer'; +import { getTreePath, findTreeItem } from '../../store/project/project-reducer'; import ProjectPanel from '../project-panel/project-panel'; +import { PROJECT_EXPLORER_ID } from '../../views-components/project-explorer/project-explorer'; +import { ProjectExplorerItem } from '../../views-components/project-explorer/project-explorer-item'; const drawerWidth = 240; const appBarHeight = 102; @@ -154,6 +157,18 @@ class Workbench extends React.Component { }); this.props.dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM(itemId)); this.props.dispatch(push(`/project/${itemId}`)); + + const project = findTreeItem(this.props.projects, itemId); + const items: ProjectExplorerItem[] = project && project.items + ? project.items.map(({ data }) => ({ + uuid: data.uuid, + name: data.name, + type: data.kind, + owner: data.ownerUuid, + lastModified: data.modifiedAt + })) + : []; + this.props.dispatch(dataExplorerActions.SET_ITEMS({ id: PROJECT_EXPLORER_ID, items })); } render() {