Merge branch 'master' into 13797-refactoring
authorJanicki Artur <artur.janicki@contractors.roche.com>
Thu, 19 Jul 2018 10:10:40 +0000 (12:10 +0200)
committerJanicki Artur <artur.janicki@contractors.roche.com>
Thu, 19 Jul 2018 10:10:40 +0000 (12:10 +0200)
refs #13797

Arvados-DCO-1.1-Signed-off-by: Janicki Artur <artur.janicki@contractors.roche.com>

src/common/custom-theme.ts
src/components/list-item-text-icon/list-item-text-icon.tsx [new file with mode: 0644]
src/components/side-panel/side-panel.tsx
src/components/tree/tree.tsx
src/views-components/main-app-bar/main-app-bar.tsx
src/views-components/project-tree/project-tree.tsx
src/views/workbench/workbench.tsx

index e81473aea1c2c3b19c8c21732072f557051f3d7d..f412024a3613e20854ba3cf8954b250b31fe2b1e 100644 (file)
@@ -8,6 +8,8 @@ import purple from '@material-ui/core/colors/purple';
 import blue from '@material-ui/core/colors/blue';
 import grey from '@material-ui/core/colors/grey';
 import green from '@material-ui/core/colors/green';
+import yellow from '@material-ui/core/colors/yellow';
+import red from '@material-ui/core/colors/red';
 
 interface ArvadosThemeOptions extends ThemeOptions {
     customs: any;
@@ -17,8 +19,16 @@ export interface ArvadosTheme extends Theme {
     customs: any;
 }
 
+// const red = 
+const yellow700 = yellow["700"];
 const purple800 = purple["800"];
+const grey200 = grey["200"];
+const grey300 = grey["300"];
+const grey500 = grey["500"];
 const grey600 = grey["600"];
+const grey700 = grey["700"];
+const grey900 = grey["900"];
+
 const themeOptions: ArvadosThemeOptions = {
     customs: {
         colors: {
@@ -26,6 +36,11 @@ const themeOptions: ArvadosThemeOptions = {
         }
     },
     overrides: {
+        MuiTypography: {
+            body1: {
+                fontSize: '0.8125rem'
+            }
+        },
         MuiAppBar: {
             colorPrimary: {
                 backgroundColor: purple800
@@ -44,6 +59,21 @@ const themeOptions: ArvadosThemeOptions = {
                 fontWeight: 700,
                 color: purple800
             }
+        },
+        MuiList: {
+            root: {
+                color: grey900
+            }
+        },
+        MuiListItemText: {
+            root: {
+                padding: 0
+            }
+        },
+        MuiListItemIcon: {
+            root: {
+                fontSize: '1.25rem'
+            }
         }
     },
     mixins: {
diff --git a/src/components/list-item-text-icon/list-item-text-icon.tsx b/src/components/list-item-text-icon/list-item-text-icon.tsx
new file mode 100644 (file)
index 0000000..f140d86
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
+import { ArvadosTheme } from '../../common/custom-theme';
+import { ListItemIcon, ListItemText, Typography } from '@material-ui/core';
+import { IconType } from '../icon/icon';
+import * as classnames from "classnames";
+
+export interface ListItemTextIconDataProps {
+    icon: IconType;
+    name: string;
+    isActive?: boolean;
+    hasMargin?: boolean;
+}
+
+type ListItemTextIconProps = ListItemTextIconDataProps & WithStyles<CssRules>;
+
+class ListItemTextIcon extends React.Component<ListItemTextIconProps, {}> {
+    render() {
+        const { classes, isActive, hasMargin, name, icon: Icon } = this.props;
+        return (
+            <Typography component='span' className={classes.root}>
+                <ListItemIcon className={classnames({
+                        [classes.hasMargin]: hasMargin,
+                        [classes.active]: isActive
+                    })}>
+                    <Icon />
+                </ListItemIcon>
+                <ListItemText primary={
+                    <Typography variant='body1' className={classnames(classes.listItemText, {
+                            [classes.active]: isActive
+                        })}>
+                        {name}
+                    </Typography>
+                } />
+            </Typography>
+        );
+    }
+}
+        
+type CssRules = 'root' | 'listItemText' | 'hasMargin' | 'active';
+        
+const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
+    root: {
+        display: 'flex',
+        alignItems: 'center'
+    },
+    listItemText: {
+        fontWeight: 700
+    },
+    active: {
+        color: theme.palette.primary.main,
+    },
+    hasMargin: {
+        marginLeft: '18px',
+    },
+});
+
+export default withStyles(styles)(ListItemTextIcon);
\ No newline at end of file
index eedc499f55143bc640e5d799aef30d83ef792989..165bd5651c562591f4cac543ea4910973b63035c 100644 (file)
@@ -9,6 +9,7 @@ import { ArvadosTheme } from '../../common/custom-theme';
 import { List, ListItem, ListItemText, ListItemIcon, Collapse, Typography } from "@material-ui/core";
 import { SidePanelRightArrowIcon, IconType } from '../icon/icon';
 import * as classnames from "classnames";
+import ListItemTextIcon from '../list-item-text-icon/list-item-text-icon';
 
 export interface SidePanelItem {
     id: string;
@@ -30,24 +31,22 @@ interface SidePanelProps {
 class SidePanel extends React.Component<SidePanelProps & WithStyles<CssRules>> {
     render(): ReactElement<any> {
         const { classes, toggleOpen, toggleActive, sidePanelItems, children } = this.props;
-        const { listItemText, leftSidePanelContainer, row, list, icon, projectIconMargin, active, iconArrowContainer } = classes;
+        const { root, row, list, toggableIconContainer } = classes;
         return (
-            <div className={leftSidePanelContainer}>
+            <div className={root}>
                 <List>
                     {sidePanelItems.map(it => (
                         <span key={it.name}>
                             <ListItem button className={list} onClick={() => toggleActive(it.id)} onContextMenu={this.handleRowContextMenu(it)}>
                                 <span className={row}>
                                     {it.openAble ? (
-                                        <i onClick={() => toggleOpen(it.id)} className={iconArrowContainer}>
-                                            <SidePanelRightArrowIcon className={this.getIconClassNames(it.open, it.active)} />
+                                        <i onClick={() => toggleOpen(it.id)} className={toggableIconContainer}>
+                                            <ListItemIcon className={this.getToggableIconClassNames(it.open, it.active)}>
+                                                < SidePanelRightArrowIcon />
+                                            </ListItemIcon>
                                         </i>
                                     ) : null}
-                                    <ListItemIcon className={it.active ? active : ''}>
-                                        {<it.icon className={`${icon} ${it.margin ? projectIconMargin : ''}`} />}
-                                    </ListItemIcon>
-                                    <ListItemText className={listItemText} 
-                                        primary={renderListItemText(it.name, active, it.active)} />
+                                    <ListItemTextIcon icon={it.icon} name={it.name} isActive={it.active} hasMargin={it.margin} />
                                 </span>
                             </ListItem>
                             {it.openAble ? (
@@ -62,12 +61,12 @@ class SidePanel extends React.Component<SidePanelProps & WithStyles<CssRules>> {
         );
     }
 
-    getIconClassNames = (itemOpen ?: boolean, itemActive ?: boolean) => {
+    getToggableIconClassNames = (isOpen?: boolean, isActive ?: boolean) => {
         const { classes } = this.props;
-        return classnames(classes.iconArrow, {
-            [classes.iconOpen]: itemOpen,
-            [classes.iconClose]: !itemOpen,
-            [classes.active]: itemActive
+        return classnames(classes.toggableIcon, {
+            [classes.iconOpen]: isOpen,
+            [classes.iconClose]: !isOpen,
+            [classes.active]: isActive
         });
     }
 
@@ -77,55 +76,42 @@ class SidePanel extends React.Component<SidePanelProps & WithStyles<CssRules>> {
 
 }
 
-const renderListItemText = (itemName: string, active: string, itemActive?: boolean) =>
-    <Typography className={itemActive ? active : ''}>{itemName}</Typography>;
-
-type CssRules = 'active' | 'listItemText' | 'row' | 'leftSidePanelContainer' | 'list' | 'icon' | 
-    'projectIconMargin' | 'iconClose' | 'iconOpen' | 'iconArrowContainer' | 'iconArrow';
+type CssRules = 'active' | 'row' | 'root' | 'list' | 'iconClose' | 'iconOpen' | 'toggableIconContainer' | 'toggableIcon';
 
 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
-    active: {
-        color: theme.palette.primary.main,
+    root: {
+        overflowY: 'auto',
+        minWidth: '240px',
+        whiteSpace: 'nowrap',
+        marginTop: '52px',
+        display: 'flex',
+        flexGrow: 1,
     },
-    listItemText: {
-        padding: '0px',
+    list: {
+        padding: '5px 0px 5px 14px',
+        minWidth: '240px',
     },
     row: {
         display: 'flex',
         alignItems: 'center',
     },
-    iconArrowContainer: {
+    toggableIconContainer: {
         color: theme.palette.grey["700"],
         height: '14px',
         position: 'absolute'
     },
-    iconArrow: {
+    toggableIcon: {
         fontSize: '14px'
     },
+    active: {
+        color: theme.palette.primary.main,
+    },
     iconClose: {
         transition: 'all 0.1s ease',
     },
     iconOpen: {
         transition: 'all 0.1s ease',
         transform: 'rotate(90deg)',
-    },
-    leftSidePanelContainer: {
-        overflowY: 'auto',
-        minWidth: '240px',
-        whiteSpace: 'nowrap',
-        marginTop: '52px',
-        display: 'flex',
-        flexGrow: 1,
-    },
-    list: {
-        padding: '5px 0px 5px 14px',
-        minWidth: '240px',
-    },
-    icon: {
-        fontSize: '20px'
-    },
-    projectIconMargin: {
-        marginLeft: '17px',
     }
 });
 
index 8de9bda5970ffe7d495f94f24b51229aacf9c1df..16f3ab2ce31d57d4f9311701ace1840ad80520ee 100644 (file)
@@ -5,10 +5,11 @@
 import * as React from 'react';
 import List from "@material-ui/core/List/List";
 import ListItem from "@material-ui/core/ListItem/ListItem";
-import { StyleRulesCallback, Theme, withStyles, WithStyles } from '@material-ui/core/styles';
+import { StyleRulesCallback, withStyles, WithStyles } from '@material-ui/core/styles';
 import { ReactElement } from "react";
 import Collapse from "@material-ui/core/Collapse/Collapse";
 import CircularProgress from '@material-ui/core/CircularProgress';
+import { ArvadosTheme } from '../../common/custom-theme';
 
 export enum TreeItemStatus {
     Initial,
@@ -61,6 +62,7 @@ class Tree<T> extends React.Component<TreeProps<T> & WithStyles<CssRules>, {}> {
                 </div>)}
         </List>;
     }
+
     renderArrow(status: TreeItemStatus, arrowClass: string, open: boolean, id: string) {
         const { arrowTransition, arrowVisibility, arrowRotate } = this.props.classes;
         return <i onClick={() => this.props.toggleItemOpen(id, status)}
@@ -77,16 +79,17 @@ class Tree<T> extends React.Component<TreeProps<T> & WithStyles<CssRules>, {}> {
 
 type CssRules = 'list' | 'activeArrow' | 'inactiveArrow' | 'arrowRotate' | 'arrowTransition' | 'loader' | 'arrowVisibility';
 
-const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
+const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     list: {
         paddingBottom: '3px',
         paddingTop: '3px',
     },
     activeArrow: {
-        color: '#4285F6',
+        color: theme.palette.primary.main,
         position: 'absolute',
     },
     inactiveArrow: {
+        color: theme.palette.grey["700"],
         position: 'absolute',
     },
     arrowTransition: {
index 30eee0d2d5530b48319f5abb811571619c103ae3..c44448aadc029f115ce394ba9523d357c096b6a5 100644 (file)
@@ -73,9 +73,10 @@ export const MainAppBar: React.SFC<MainAppBarProps> = (props) => {
                     onClick={props.onBreadcrumbClick}
                     onContextMenu={props.onContextMenu} />
             }
-            <IconButton color="inherit" onClick={props.onDetailsPanelToggle}>
-                { <DetailsIcon /> }
-            </IconButton>
+            { props.user && <IconButton color="inherit" onClick={props.onDetailsPanelToggle}>
+                    <DetailsIcon />
+                </IconButton>
+            }
         </Toolbar>
     </AppBar>;
 };
@@ -86,7 +87,7 @@ const renderMenuForUser = ({ user, menuItems, onMenuItemClick }: MainAppBarProps
         <>
             <IconButton color="inherit">
                 <Badge badgeContent={3} color="primary">
-                    {<NotificationIcon />}
+                    <NotificationIcon />
                 </Badge>
             </IconButton>
             <DropdownMenu icon={<UserPanelIcon />} id="account-menu">
index 17592a7f36d9374e8c6bef603e132d9690567944..3a84471c32c80508addc34fa7038cde77ce641c7 100644 (file)
@@ -5,12 +5,11 @@
 import * as React from 'react';
 import { ReactElement } from 'react';
 import { StyleRulesCallback, Theme, WithStyles, withStyles } from '@material-ui/core/styles';
-import ListItemText from "@material-ui/core/ListItemText/ListItemText";
-import ListItemIcon from '@material-ui/core/ListItemIcon';
-import Typography from '@material-ui/core/Typography';
-
 import Tree, { TreeItem, TreeItemStatus } from '../../components/tree/tree';
 import { ProjectResource } from '../../models/project';
+import { ProjectIcon } from '../../components/icon/icon';
+import { ArvadosTheme } from '../../common/custom-theme';
+import ListItemTextIcon from '../../components/list-item-text-icon/list-item-text-icon';
 
 export interface ProjectTreeProps {
     projects: Array<TreeItem<ProjectResource>>;
@@ -22,46 +21,26 @@ export interface ProjectTreeProps {
 class ProjectTree<T> extends React.Component<ProjectTreeProps & WithStyles<CssRules>> {
     render(): ReactElement<any> {
         const { classes, projects, toggleOpen, toggleActive, onContextMenu } = this.props;
-        const { active, listItemText, row, treeContainer } = classes;
         return (
-            <div className={treeContainer}>
+            <div className={classes.root}>
                 <Tree items={projects}
                     onContextMenu={onContextMenu}
                     toggleItemOpen={toggleOpen}
                     toggleItemActive={toggleActive}
-                    render={(project: TreeItem<ProjectResource>) =>
-                        <span className={row}>
-                            <ListItemIcon className={project.active ? active : ''}>
-                                <i className="fas fa-folder" />
-                            </ListItemIcon>
-                            <ListItemText className={listItemText} primary={
-                                <Typography className={project.active ? active : ''}>{project.data.name}</Typography>
-                            } />
-                        </span>
-                    } />
+                    render={
+                        (project: TreeItem<ProjectResource>) =>
+                            <ListItemTextIcon icon={ProjectIcon} name={project.data.name} isActive={project.active} hasMargin={true} />
+                    }/>
             </div>
         );
     }
 }
 
-type CssRules = 'active' | 'listItemText' | 'row' | 'treeContainer';
+type CssRules = 'root';
 
-const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
-    active: {
-        color: '#4285F6',
-    },
-    listItemText: {
-        padding: '0px',
-    },
-    row: {
-        display: 'flex',
-        alignItems: 'center',
-        marginLeft: '20px',
-    },
-    treeContainer: {
-        minWidth: '240px',
-        whiteSpace: 'nowrap',
-        marginLeft: '13px',
+const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
+    root: {
+        marginLeft: `${theme.spacing.unit * 1.5}px`,
     }
 });
 
index c7bfc8b4c40966c36827c468d9664f83d6c85a1a..eaf3a2ee803e490a0076c470d107d87747d2d97d 100644 (file)
@@ -147,7 +147,7 @@ class Workbench extends React.Component<WorkbenchProps, WorkbenchState> {
                             <Route path="/projects/:id" render={this.renderProjectPanel} />
                         </Switch>
                     </div>
-                    <DetailsPanel />
+                    { user && <DetailsPanel /> }
                 </main>
                 <ContextMenu />
                 <CreateProjectDialog />