[ARVADOS-WORKBENCH2] updated: 1.1.4-228-gd8c787e
Git user
git at public.curoverse.com
Tue Jul 10 05:09:30 EDT 2018
Summary of changes:
src/store/details-panel/details-panel-action.ts | 35 ++++++
src/store/details-panel/details-panel-reducer.ts | 26 +++++
src/store/navigation/navigation-action.ts | 10 +-
src/store/store.ts | 5 +-
.../details-panel/details-panel.tsx | 119 ++++++++++++++-------
src/views/workbench/workbench.tsx | 27 ++---
6 files changed, 158 insertions(+), 64 deletions(-)
create mode 100644 src/store/details-panel/details-panel-action.ts
create mode 100644 src/store/details-panel/details-panel-reducer.ts
via d8c787ee061c3953628362f5eb6c37123f5ca0f5 (commit)
via 7622261116e685cad4af9cf6a4d1dd9c58cd1605 (commit)
from 0b1b9f181db6c43a8bbc9b2b2d6ab48a51003b2d (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit d8c787ee061c3953628362f5eb6c37123f5ca0f5
Merge: 7622261 0b1b9f1
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date: Tue Jul 10 11:09:08 2018 +0200
merge changes
Feature #13765
Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
diff --cc src/views-components/details-panel/details-panel.tsx
index 13498f3,6bf04c4..b29e190
--- a/src/views-components/details-panel/details-panel.tsx
+++ b/src/views-components/details-panel/details-panel.tsx
@@@ -13,15 -13,8 +13,15 @@@ import Tab from '@material-ui/core/Tab'
import Typography from '@material-ui/core/Typography';
import Grid from '@material-ui/core/Grid';
import * as classnames from "classnames";
+import { connect, Dispatch } from 'react-redux';
import EmptyState from '../../components/empty-state/empty-state';
- import IconBase from '../../components/icon/icon';
+import { RootState } from '../../store/store';
+import actions from "../../store/details-panel/details-panel-action";
+import { Resource } from '../../common/api/common-resource-service';
+import { ResourceKind } from '../../models/kinds';
+import { ProjectResource } from '../../models/project';
+import { CollectionResource } from '../../models/collection';
+ import IconBase, { IconTypes } from '../../components/icon/icon';
export interface DetailsPanelDataProps {
onCloseDrawer: () => void;
@@@ -53,18 -46,24 +53,18 @@@ class DetailsPanel extends React.Compon
return (
<Typography component="div" className={classnames([classes.container, { [classes.opened]: isOpened }])}>
<Drawer variant="permanent" anchor="right" classes={{ paper: classes.drawerPaper }}>
- <Typography component="div" className={classes.headerContainer}>
- <Grid container alignItems='center' justify='space-around'>
- {renderHeader}
- {/* TODO: renderHeader */}
- <IconBase icon={IconTypes.PROCESS} />
- <Typography variant="title">
- Tutorial pipeline
- </Typography>
- {/* End */}
+ <Typography component="div" className={classes.headerContainer}>
+ <Grid container alignItems='center' justify='space-around'>
+ {header}
<IconButton color="inherit" onClick={onCloseDrawer}>
- <IconBase icon='close' />
+ <IconBase icon={IconTypes.CLOSE} />
- </IconButton>
- </Grid>
- </Typography>
- <Tabs value={tabsValue} onChange={this.handleChange}>
- <Tab disableRipple label="Details" />
- <Tab disableRipple label="Activity" />
- </Tabs>
+ </IconButton>
+ </Grid>
+ </Typography>
+ <Tabs value={tabsValue} onChange={this.handleChange}>
+ <Tab disableRipple label="Details" />
+ <Tab disableRipple label="Activity" />
+ </Tabs>
{tabsValue === 0 && this.renderTabContainer(
<Grid container direction="column">
{renderDetails}
@@@ -83,9 -82,9 +83,9 @@@
{tabsValue === 1 && this.renderTabContainer(
<Grid container direction="column">
{renderActivity}
- <EmptyState icon='announcement' message='Select a file or folder to view its details.' />
+ <EmptyState icon={IconTypes.ANNOUNCEMENT} message='Select a file or folder to view its details.' />
</Grid>
- )}
+ )}
</Drawer>
</Typography>
);
@@@ -118,50 -117,10 +118,50 @@@ const styles: StyleRulesCallback<CssRul
fontSize: "24px",
color: theme.customs.colors.green700
}
- },
- tabContainer: {
- padding: theme.spacing.unit * 3
- }
+ },
+ tabContainer: {
+ padding: theme.spacing.unit * 3
+ }
});
-export default withStyles(styles)(DetailsPanel);
+const renderCollectionHeader = (collection: CollectionResource) =>
+ <>
- <IconBase icon="collection" />
++ <IconBase icon={IconTypes.COLLECTION} />
+ <Typography variant="title">
+ {collection.name}
+ </Typography>
+ </>;
+
+const renderProjectHeader = (project: ProjectResource) =>
+ <>
- <IconBase icon="project" />
++ <IconBase icon={IconTypes.FOLDER} />
+ <Typography variant="title">
+ {project.name}
+ </Typography>
+ </>;
+
+const renderHeader = (resource: Resource) => {
+ switch(resource.kind) {
+ case ResourceKind.Project:
+ return renderProjectHeader(resource as ProjectResource);
+ case ResourceKind.Collection:
+ return renderCollectionHeader(resource as CollectionResource);
+ default:
+ return null;
+ }
+};
+
+const mapStateToProps = ({detailsPanel}: RootState) => ({
+ isOpened: detailsPanel.isOpened,
+ header: detailsPanel.item ? renderHeader(detailsPanel.item) : null
+});
+
+const mapDispatchToProps = (dispatch: Dispatch) => ({
+ onCloseDrawer: () => {
+ dispatch(actions.TOGGLE_DETAILS_PANEL());
+ }
+});
+
+const DetailsPanelContainer = connect(mapStateToProps, mapDispatchToProps)(DetailsPanel);
+
+export default withStyles(styles)(DetailsPanelContainer);
commit 7622261116e685cad4af9cf6a4d1dd9c58cd1605
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date: Tue Jul 10 11:06:49 2018 +0200
Create store and connect detail panel
Feature #13765
Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
diff --git a/src/store/details-panel/details-panel-action.ts b/src/store/details-panel/details-panel-action.ts
new file mode 100644
index 0000000..e2d2479
--- /dev/null
+++ b/src/store/details-panel/details-panel-action.ts
@@ -0,0 +1,35 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { unionize, ofType, UnionOf } from "unionize";
+import { Resource } from "../../common/api/common-resource-service";
+import { ResourceKind } from "../../models/kinds";
+import { Dispatch } from "redux";
+import { groupsService } from "../../services/services";
+
+const actions = unionize({
+ TOGGLE_DETAILS_PANEL: ofType<{}>(),
+ LOAD_DETAILS: ofType<{ uuid: string, kind: ResourceKind }>(),
+ LOAD_DETAILS_SUCCESS: ofType<{ item: Resource }>(),
+}, { tag: 'type', value: 'payload' });
+
+export default actions;
+
+export type DetailsPanelAction = UnionOf<typeof actions>;
+
+export const loadDetails = (uuid: string, kind: ResourceKind) =>
+ (dispatch: Dispatch) => {
+ dispatch(actions.LOAD_DETAILS({ uuid, kind }));
+ if (kind === ResourceKind.Project) {
+ groupsService
+ .get(uuid)
+ .then(project => {
+ dispatch(actions.LOAD_DETAILS_SUCCESS({ item: project }));
+ });
+ }
+
+ };
+
+
+
diff --git a/src/store/details-panel/details-panel-reducer.ts b/src/store/details-panel/details-panel-reducer.ts
new file mode 100644
index 0000000..73fc604
--- /dev/null
+++ b/src/store/details-panel/details-panel-reducer.ts
@@ -0,0 +1,26 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { Resource } from "../../common/api/common-resource-service";
+import actions, { DetailsPanelAction } from "./details-panel-action";
+
+export interface DetailsPanelState {
+ item: Resource | null;
+ isOpened: boolean;
+}
+
+const initialState = {
+ item: null,
+ isOpened: false
+};
+
+const reducer = (state: DetailsPanelState = initialState, action: DetailsPanelAction) =>
+ actions.match(action, {
+ default: () => state,
+ LOAD_DETAILS: () => state,
+ LOAD_DETAILS_SUCCESS: ({ item }) => ({ ...state, item }),
+ TOGGLE_DETAILS_PANEL: () => ({ ...state, isOpened: !state.isOpened })
+ });
+
+export default reducer;
diff --git a/src/store/navigation/navigation-action.ts b/src/store/navigation/navigation-action.ts
index 5fb6b72..034cdac 100644
--- a/src/store/navigation/navigation-action.ts
+++ b/src/store/navigation/navigation-action.ts
@@ -7,17 +7,19 @@ import projectActions, { getProjectList } from "../project/project-action";
import { push } from "react-router-redux";
import { TreeItemStatus } from "../../components/tree/tree";
import { findTreeItem } from "../project/project-reducer";
-import { Resource, ResourceKind } from "../../models/resource";
+import { Resource, ResourceKind as R } 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 { RootState } from "../store";
import { sidePanelData } from "../side-panel/side-panel-reducer";
+import { loadDetails } from "../details-panel/details-panel-action";
+import { ResourceKind } from "../../models/kinds";
export const getResourceUrl = (resource: Resource): string => {
switch (resource.kind) {
- case ResourceKind.PROJECT: return `/projects/${resource.uuid}`;
- case ResourceKind.COLLECTION: return `/collections/${resource.uuid}`;
+ case R.PROJECT: return `/projects/${resource.uuid}`;
+ case R.COLLECTION: return `/collections/${resource.uuid}`;
default: return "";
}
};
@@ -34,6 +36,8 @@ export const setProjectItem = (itemId: string, itemMode: ItemMode) =>
const treeItem = findTreeItem(projects.items, itemId);
if (treeItem) {
+ // TODO: Get correct resource kind
+ dispatch<any>(loadDetails(treeItem.data.uuid, ResourceKind.Project));
dispatch(sidePanelActions.RESET_SIDE_PANEL_ACTIVITY());
const projectsItem = sidePanelData[0];
diff --git a/src/store/store.ts b/src/store/store.ts
index 00c2ad7..f74b877 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -13,6 +13,7 @@ import authReducer, { AuthState } from "./auth/auth-reducer";
import dataExplorerReducer, { DataExplorerState } from './data-explorer/data-explorer-reducer';
import collectionsReducer, { CollectionState } from "./collection/collection-reducer";
import { projectPanelMiddleware } from '../store/project-panel/project-panel-middleware';
+import detailsPanelReducer, { DetailsPanelState } from './details-panel/details-panel-reducer';
const composeEnhancers =
(process.env.NODE_ENV === 'development' &&
@@ -26,6 +27,7 @@ export interface RootState {
router: RouterState;
dataExplorer: DataExplorerState;
sidePanel: SidePanelState;
+ detailsPanel: DetailsPanelState;
}
const rootReducer = combineReducers({
@@ -34,7 +36,8 @@ const rootReducer = combineReducers({
collections: collectionsReducer,
router: routerReducer,
dataExplorer: dataExplorerReducer,
- sidePanel: sidePanelReducer
+ sidePanel: sidePanelReducer,
+ detailsPanel: detailsPanelReducer
});
diff --git a/src/views-components/details-panel/details-panel.tsx b/src/views-components/details-panel/details-panel.tsx
index f47dfa0..13498f3 100644
--- a/src/views-components/details-panel/details-panel.tsx
+++ b/src/views-components/details-panel/details-panel.tsx
@@ -13,13 +13,20 @@ import Tab from '@material-ui/core/Tab';
import Typography from '@material-ui/core/Typography';
import Grid from '@material-ui/core/Grid';
import * as classnames from "classnames";
+import { connect, Dispatch } from 'react-redux';
import EmptyState from '../../components/empty-state/empty-state';
import IconBase from '../../components/icon/icon';
+import { RootState } from '../../store/store';
+import actions from "../../store/details-panel/details-panel-action";
+import { Resource } from '../../common/api/common-resource-service';
+import { ResourceKind } from '../../models/kinds';
+import { ProjectResource } from '../../models/project';
+import { CollectionResource } from '../../models/collection';
export interface DetailsPanelDataProps {
onCloseDrawer: () => void;
isOpened: boolean;
- renderHeader?: React.ComponentType<{}>;
+ header: React.ReactElement<any>;
renderDetails?: React.ComponentType<{}>;
renderActivity?: React.ComponentType<{}>;
}
@@ -27,47 +34,41 @@ export interface DetailsPanelDataProps {
type DetailsPanelProps = DetailsPanelDataProps & WithStyles<CssRules>;
class DetailsPanel extends React.Component<DetailsPanelProps, {}> {
- state = {
+ state = {
tabsValue: 0
- };
+ };
- handleChange = (event: any, value: boolean) => {
- this.setState({ tabsValue: value });
- }
-
- renderTabContainer = (children: React.ReactElement<any>) =>
+ handleChange = (event: any, value: boolean) => {
+ this.setState({ tabsValue: value });
+ }
+
+ renderTabContainer = (children: React.ReactElement<any>) =>
<Typography className={this.props.classes.tabContainer} component="div">
{children}
</Typography>
-
- render() {
- const { classes, onCloseDrawer, isOpened, renderHeader, renderDetails, renderActivity } = this.props;
+
+ render() {
+ const { classes, onCloseDrawer, isOpened, header, renderDetails, renderActivity } = this.props;
const { tabsValue } = this.state;
return (
<Typography component="div" className={classnames([classes.container, { [classes.opened]: isOpened }])}>
<Drawer variant="permanent" anchor="right" classes={{ paper: classes.drawerPaper }}>
- <Typography component="div" className={classes.headerContainer}>
- <Grid container alignItems='center' justify='space-around'>
- {renderHeader}
- {/* TODO: renderHeader */}
- <IconBase icon='process' />
- <Typography variant="title">
- Tutorial pipeline
- </Typography>
- {/* End */}
+ <Typography component="div" className={classes.headerContainer}>
+ <Grid container alignItems='center' justify='space-around'>
+ {header}
<IconButton color="inherit" onClick={onCloseDrawer}>
<IconBase icon='close' />
- </IconButton>
- </Grid>
- </Typography>
- <Tabs value={tabsValue} onChange={this.handleChange}>
- <Tab disableRipple label="Details" />
- <Tab disableRipple label="Activity" />
- </Tabs>
+ </IconButton>
+ </Grid>
+ </Typography>
+ <Tabs value={tabsValue} onChange={this.handleChange}>
+ <Tab disableRipple label="Details" />
+ <Tab disableRipple label="Activity" />
+ </Tabs>
{tabsValue === 0 && this.renderTabContainer(
<Grid container direction="column">
{renderDetails}
- <EmptyState icon='announcement'
+ <EmptyState icon='announcement'
message='Select a file or folder to view its details.' />
<Attribute label='Type' value='Process' />
<Attribute label='Size' value='---' />
@@ -77,14 +78,14 @@ class DetailsPanel extends React.Component<DetailsPanelProps, {}> {
</Attribute>
<Attribute label='Outputs' link='http://www.google.pl' value='New output as link' />
<Attribute label='Owner' value='me' />
- </Grid>
- )}
+ </Grid>
+ )}
{tabsValue === 1 && this.renderTabContainer(
<Grid container direction="column">
{renderActivity}
<EmptyState icon='announcement' message='Select a file or folder to view its details.' />
</Grid>
- )}
+ )}
</Drawer>
</Typography>
);
@@ -96,9 +97,9 @@ type CssRules = 'drawerPaper' | 'container' | 'opened' | 'headerContainer' | 'ta
const drawerWidth = 320;
const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
- container: {
+ container: {
width: 0,
- position: 'relative',
+ position: 'relative',
height: 'auto',
transition: 'width 0.5s ease',
'&$opened': {
@@ -109,18 +110,58 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
drawerPaper: {
position: 'relative',
width: drawerWidth
- },
- headerContainer: {
+ },
+ headerContainer: {
color: theme.palette.grey["600"],
margin: `${theme.spacing.unit}px 0`,
'& .fa-cogs': {
fontSize: "24px",
color: theme.customs.colors.green700
}
- },
- tabContainer: {
- padding: theme.spacing.unit * 3
- }
+ },
+ tabContainer: {
+ padding: theme.spacing.unit * 3
+ }
});
-export default withStyles(styles)(DetailsPanel);
\ No newline at end of file
+const renderCollectionHeader = (collection: CollectionResource) =>
+ <>
+ <IconBase icon="collection" />
+ <Typography variant="title">
+ {collection.name}
+ </Typography>
+ </>;
+
+const renderProjectHeader = (project: ProjectResource) =>
+ <>
+ <IconBase icon="project" />
+ <Typography variant="title">
+ {project.name}
+ </Typography>
+ </>;
+
+const renderHeader = (resource: Resource) => {
+ switch(resource.kind) {
+ case ResourceKind.Project:
+ return renderProjectHeader(resource as ProjectResource);
+ case ResourceKind.Collection:
+ return renderCollectionHeader(resource as CollectionResource);
+ default:
+ return null;
+ }
+};
+
+const mapStateToProps = ({detailsPanel}: RootState) => ({
+ isOpened: detailsPanel.isOpened,
+ header: detailsPanel.item ? renderHeader(detailsPanel.item) : null
+});
+
+const mapDispatchToProps = (dispatch: Dispatch) => ({
+ onCloseDrawer: () => {
+ dispatch(actions.TOGGLE_DETAILS_PANEL());
+ }
+});
+
+const DetailsPanelContainer = connect(mapStateToProps, mapDispatchToProps)(DetailsPanel);
+
+export default withStyles(styles)(DetailsPanelContainer);
\ No newline at end of file
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index 8315d5b..e848784 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -6,9 +6,8 @@ import * as React from 'react';
import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
import Drawer from '@material-ui/core/Drawer';
import { connect, DispatchProp } from "react-redux";
-import { Route, Switch, RouteComponentProps, withRouter } from "react-router";
+import { Route, Switch, RouteComponentProps } 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, {
@@ -20,16 +19,15 @@ import { push } from 'react-router-redux';
import ProjectTree from '../../views-components/project-tree/project-tree';
import { TreeItem } from "../../components/tree/tree";
import { Project } from "../../models/project";
-import { getTreePath, findTreeItem } from '../../store/project/project-reducer';
+import { getTreePath } from '../../store/project/project-reducer';
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";
-import { sidePanelData } from '../../store/side-panel/side-panel-reducer';
import DetailsPanel from '../../views-components/details-panel/details-panel';
import { ArvadosTheme } from '../../common/custom-theme';
+import detailsPanelActions from "../../store/details-panel/details-panel-action";
const drawerWidth = 240;
const appBarHeight = 100;
@@ -100,10 +98,6 @@ interface WorkbenchState {
helpMenu: NavMenuItem[],
anonymousMenu: NavMenuItem[]
};
- isDetailsPanelOpened: boolean;
- detailsPanelHeader: React.ComponentType<{}> | undefined;
- detailsPanelDetails: React.ComponentType<{}> | undefined;
- detailsPanelActivity: React.ComponentType<{}> | undefined;
}
@@ -135,11 +129,7 @@ class Workbench extends React.Component<WorkbenchProps, WorkbenchState> {
action: () => this.props.dispatch(authActions.LOGIN())
}
]
- },
- isDetailsPanelOpened: false,
- detailsPanelHeader: undefined,
- detailsPanelDetails: undefined,
- detailsPanelActivity: undefined,
+ }
};
mainAppBarActions: MainAppBarActionProps = {
@@ -152,7 +142,7 @@ class Workbench extends React.Component<WorkbenchProps, WorkbenchState> {
},
onMenuItemClick: (menuItem: NavMenuItem) => menuItem.action(),
onDetailsPanelToggle: () => {
- this.setState(prev => ({ isDetailsPanelOpened: !prev.isDetailsPanelOpened }));
+ this.props.dispatch(detailsPanelActions.TOGGLE_DETAILS_PANEL());
}
};
@@ -209,12 +199,7 @@ class Workbench extends React.Component<WorkbenchProps, WorkbenchState> {
<Route path="/projects/:id" render={this.renderProjectPanel} />
</Switch>
</div>
- <DetailsPanel
- renderHeader={this.state.detailsPanelHeader}
- renderDetails={this.state.detailsPanelDetails}
- renderActivity={this.state.detailsPanelActivity}
- isOpened={this.state.isDetailsPanelOpened}
- onCloseDrawer={this.mainAppBarActions.onDetailsPanelToggle} />
+ <DetailsPanel/>
</main>
</div>
);
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list