18128: Adds panel maximizing capabilities.
authorLucas Di Pentima <lucas.dipentima@curii.com>
Thu, 14 Oct 2021 21:04:09 +0000 (18:04 -0300)
committerLucas Di Pentima <lucas.dipentima@curii.com>
Thu, 2 Dec 2021 23:01:56 +0000 (20:01 -0300)
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima@curii.com>

src/components/data-explorer/data-explorer.tsx
src/components/icon/icon.tsx
src/components/multi-panel-view/multi-panel-view.tsx
src/views/process-panel/process-information-card.tsx
src/views/subprocess-panel/subprocess-panel-root.tsx

index 940dbd0a505ecc9592ce5f5a760c38778d1b5daf..7fce77dee8b4b5a018bab27fb6abbb8eb7a745fc 100644 (file)
@@ -11,8 +11,9 @@ import { SearchInput } from 'components/search-input/search-input';
 import { ArvadosTheme } from "common/custom-theme";
 import { createTree } from 'models/tree';
 import { DataTableFilters } from 'components/data-table-filters/data-table-filters-tree';
 import { ArvadosTheme } from "common/custom-theme";
 import { createTree } from 'models/tree';
 import { DataTableFilters } from 'components/data-table-filters/data-table-filters-tree';
-import { CloseIcon, MoreOptionsIcon } from 'components/icon/icon';
+import { CloseIcon, MaximizeIcon, MoreOptionsIcon } from 'components/icon/icon';
 import { PaperProps } from '@material-ui/core/Paper';
 import { PaperProps } from '@material-ui/core/Paper';
+import { MPVPanelProps } from 'components/multi-panel-view/multi-panel-view';
 
 type CssRules = 'searchBox' | "toolbar" | "toolbarUnderTitle" | "footer" | "root" | 'moreOptionsButton' | 'title';
 
 
 type CssRules = 'searchBox' | "toolbar" | "toolbarUnderTitle" | "footer" | "root" | 'moreOptionsButton' | 'title';
 
@@ -21,7 +22,8 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
         paddingBottom: theme.spacing.unit * 2
     },
     toolbar: {
         paddingBottom: theme.spacing.unit * 2
     },
     toolbar: {
-        paddingTop: theme.spacing.unit * 2
+        paddingTop: theme.spacing.unit,
+        paddingRight: theme.spacing.unit * 2,
     },
     toolbarUnderTitle: {
         paddingTop: 0
     },
     toolbarUnderTitle: {
         paddingTop: 0
@@ -62,7 +64,6 @@ interface DataExplorerDataProps<T> {
     title?: React.ReactNode;
     paperKey?: string;
     currentItemUuid: string;
     title?: React.ReactNode;
     paperKey?: string;
     currentItemUuid: string;
-    panelName?: string
 }
 
 interface DataExplorerActionProps<T> {
 }
 
 interface DataExplorerActionProps<T> {
@@ -78,10 +79,10 @@ interface DataExplorerActionProps<T> {
     onChangeRowsPerPage: (rowsPerPage: number) => void;
     onLoadMore: (page: number) => void;
     extractKey?: (item: T) => React.Key;
     onChangeRowsPerPage: (rowsPerPage: number) => void;
     onLoadMore: (page: number) => void;
     extractKey?: (item: T) => React.Key;
-    doHidePanel?: () => void;
 }
 
 }
 
-type DataExplorerProps<T> = DataExplorerDataProps<T> & DataExplorerActionProps<T> & WithStyles<CssRules>;
+type DataExplorerProps<T> = DataExplorerDataProps<T> &
+    DataExplorerActionProps<T> & WithStyles<CssRules> & MPVPanelProps;
 
 export const DataExplorer = withStyles(styles)(
     class DataExplorerGeneric<T> extends React.Component<DataExplorerProps<T>> {
 
 export const DataExplorer = withStyles(styles)(
     class DataExplorerGeneric<T> extends React.Component<DataExplorerProps<T>> {
@@ -96,7 +97,8 @@ export const DataExplorer = withStyles(styles)(
                 rowsPerPage, rowsPerPageOptions, onColumnToggle, searchLabel, searchValue, onSearch,
                 items, itemsAvailable, onRowClick, onRowDoubleClick, classes,
                 dataTableDefaultView, hideColumnSelector, actions, paperProps, hideSearchInput,
                 rowsPerPage, rowsPerPageOptions, onColumnToggle, searchLabel, searchValue, onSearch,
                 items, itemsAvailable, onRowClick, onRowDoubleClick, classes,
                 dataTableDefaultView, hideColumnSelector, actions, paperProps, hideSearchInput,
-                paperKey, fetchMode, currentItemUuid, title, doHidePanel, panelName
+                paperKey, fetchMode, currentItemUuid, title,
+                doHidePanel, doMaximizePanel, panelName, panelMaximized
             } = this.props;
             return <Paper className={classes.root} {...paperProps} key={paperKey}>
                 {title && <div className={classes.title}>{title}</div>}
             } = this.props;
             return <Paper className={classes.root} {...paperProps} key={paperKey}>
                 {title && <div className={classes.title}>{title}</div>}
@@ -113,9 +115,13 @@ export const DataExplorer = withStyles(styles)(
                             columns={columns}
                             onColumnToggle={onColumnToggle} />}
                     </Grid>
                             columns={columns}
                             onColumnToggle={onColumnToggle} />}
                     </Grid>
+                    { doMaximizePanel && !!!panelMaximized &&
+                        <Tooltip title={`Maximize ${panelName || 'panel'}`} disableFocusListener>
+                            <IconButton onClick={doMaximizePanel}><MaximizeIcon /></IconButton>
+                        </Tooltip> }
                     { doHidePanel &&
                         <Tooltip title={`Close ${panelName || 'panel'}`} disableFocusListener>
                     { doHidePanel &&
                         <Tooltip title={`Close ${panelName || 'panel'}`} disableFocusListener>
-                            <Button onClick={doHidePanel}><CloseIcon /></Button>
+                            <IconButton onClick={doHidePanel}><CloseIcon /></IconButton>
                         </Tooltip> }
                 </Toolbar>}
                 <DataTable
                         </Tooltip> }
                 </Toolbar>}
                 <DataTable
index 94374c624a8df985698cf6537e9ef09a38dd4c22..523eefbd10c7b75bb0e6904f59a1abf62555f563 100644 (file)
@@ -67,6 +67,7 @@ import LinkOutlined from '@material-ui/icons/LinkOutlined';
 // Import FontAwesome icons
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faPencilAlt, faSlash } from '@fortawesome/free-solid-svg-icons';
 // Import FontAwesome icons
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faPencilAlt, faSlash } from '@fortawesome/free-solid-svg-icons';
+import { CropFreeSharp } from '@material-ui/icons';
 library.add(
     faPencilAlt,
     faSlash,
 library.add(
     faPencilAlt,
     faSlash,
@@ -119,6 +120,7 @@ export const InputIcon: IconType = (props) => <InsertDriveFile {...props} />;
 export const KeyIcon: IconType = (props) => <VpnKey {...props} />;
 export const LogIcon: IconType = (props) => <SettingsEthernet {...props} />;
 export const MailIcon: IconType = (props) => <Mail {...props} />;
 export const KeyIcon: IconType = (props) => <VpnKey {...props} />;
 export const LogIcon: IconType = (props) => <SettingsEthernet {...props} />;
 export const MailIcon: IconType = (props) => <Mail {...props} />;
+export const MaximizeIcon: IconType = (props) => <CropFreeSharp {...props} />;
 export const MoreOptionsIcon: IconType = (props) => <MoreVert {...props} />;
 export const MoveToIcon: IconType = (props) => <Input {...props} />;
 export const NewProjectIcon: IconType = (props) => <CreateNewFolder {...props} />;
 export const MoreOptionsIcon: IconType = (props) => <MoreVert {...props} />;
 export const MoveToIcon: IconType = (props) => <Input {...props} />;
 export const NewProjectIcon: IconType = (props) => <CreateNewFolder {...props} />;
index fd192d1362fb4b17d98e2522ae9e243cf8b99737..05c1de05ba59232d0b7392a83a4ac6b07597afeb 100644 (file)
@@ -28,28 +28,32 @@ const styles: StyleRulesCallback<CssRules> = theme => ({
 interface MPVHideablePanelDataProps {
     name: string;
     visible: boolean;
 interface MPVHideablePanelDataProps {
     name: string;
     visible: boolean;
+    maximized: boolean;
     children: ReactNode;
 }
 
 interface MPVHideablePanelActionProps {
     doHidePanel: () => void;
     children: ReactNode;
 }
 
 interface MPVHideablePanelActionProps {
     doHidePanel: () => void;
+    doMaximizePanel: () => void;
 }
 
 type MPVHideablePanelProps = MPVHideablePanelDataProps & MPVHideablePanelActionProps;
 
 }
 
 type MPVHideablePanelProps = MPVHideablePanelDataProps & MPVHideablePanelActionProps;
 
-const MPVHideablePanel = ({doHidePanel, name, visible, ...props}: MPVHideablePanelProps) =>
+const MPVHideablePanel = ({doHidePanel, doMaximizePanel, name, visible, maximized, ...props}: MPVHideablePanelProps) =>
     visible
     ? <>
     visible
     ? <>
-        {React.cloneElement((props.children as ReactElement), { doHidePanel, panelName: name })}
+        {React.cloneElement((props.children as ReactElement), { doHidePanel, doMaximizePanel,panelName: name, panelMaximized: maximized })}
     </>
     : null;
 
 interface MPVPanelDataProps {
     panelName?: string;
     </>
     : null;
 
 interface MPVPanelDataProps {
     panelName?: string;
+    panelMaximized?: boolean;
 }
 
 interface MPVPanelActionProps {
     doHidePanel?: () => void;
 }
 
 interface MPVPanelActionProps {
     doHidePanel?: () => void;
+    doMaximizePanel?: () => void;
 }
 
 // Props received by panel implementors
 }
 
 // Props received by panel implementors
@@ -58,9 +62,9 @@ export type MPVPanelProps = MPVPanelDataProps & MPVPanelActionProps;
 type MPVPanelContentProps = {children: ReactElement} & MPVPanelProps & GridProps;
 
 // Grid item compatible component for layout and MPV props passing
 type MPVPanelContentProps = {children: ReactElement} & MPVPanelProps & GridProps;
 
 // Grid item compatible component for layout and MPV props passing
-export const MPVPanelContent = ({doHidePanel, panelName, ...props}: MPVPanelContentProps) =>
+export const MPVPanelContent = ({doHidePanel, doMaximizePanel, panelName, panelMaximized, ...props}: MPVPanelContentProps) =>
     <Grid item {...props}>
     <Grid item {...props}>
-        {React.cloneElement(props.children, { doHidePanel, panelName })}
+        {React.cloneElement(props.children, { doHidePanel, doMaximizePanel, panelName, panelMaximized })}
     </Grid>;
 
 export interface MPVPanelState {
     </Grid>;
 
 export interface MPVPanelState {
@@ -97,6 +101,14 @@ const MPVContainerComponent = ({children, panelStates, classes, ...props}: MPVCo
                     ...panelVisibility.slice(idx+1)
                 ])
             };
                     ...panelVisibility.slice(idx+1)
                 ])
             };
+            const maximizeFn = (idx: number) => () => {
+                // Maximize X == hide all but X
+                setPanelVisibility([
+                    ...panelVisibility.slice(0, idx).map(() => false),
+                    true,
+                    ...panelVisibility.slice(idx+1).map(() => false),
+                ])
+            };
             const toggleIcon = panelVisibility[idx]
                 ? <VisibleIcon className={classNames(classes.buttonIcon)} />
                 : <InvisibleIcon className={classNames(classes.buttonIcon)}/>
             const toggleIcon = panelVisibility[idx]
                 ? <VisibleIcon className={classNames(classes.buttonIcon)} />
                 : <InvisibleIcon className={classNames(classes.buttonIcon)}/>
@@ -109,6 +121,8 @@ const MPVContainerComponent = ({children, panelStates, classes, ...props}: MPVCo
             const toggleTooltip = panelVisibility[idx]
                 ? `Hide ${panelName} panel`
                 : `Show ${panelName} panel`;
             const toggleTooltip = panelVisibility[idx]
                 ? `Hide ${panelName} panel`
                 : `Show ${panelName} panel`;
+            const panelIsMaximized = panelVisibility[idx] &&
+                panelVisibility.filter(e => e).length === 1;
 
             toggles = [
                 ...toggles,
 
             toggles = [
                 ...toggles,
@@ -123,7 +137,9 @@ const MPVContainerComponent = ({children, panelStates, classes, ...props}: MPVCo
             ];
 
             const aPanel =
             ];
 
             const aPanel =
-                <MPVHideablePanel visible={panelVisibility[idx]} name={panelName} doHidePanel={toggleFn(idx)}>
+                <MPVHideablePanel visible={panelVisibility[idx]} name={panelName}
+                    maximized={panelIsMaximized}
+                    doHidePanel={toggleFn(idx)} doMaximizePanel={maximizeFn(idx)}>
                     {children[idx]}
                 </MPVHideablePanel>;
             panels = [...panels, aPanel];
                     {children[idx]}
                 </MPVHideablePanel>;
             panels = [...panels, aPanel];
index 8be7d1cc9550e853cd4c72c0805f62810e6374cf..4c93801707864341a4698b93bb4449827ecd32cf 100644 (file)
@@ -5,7 +5,7 @@
 import React from 'react';
 import {
     StyleRulesCallback, WithStyles, withStyles, Card,
 import React from 'react';
 import {
     StyleRulesCallback, WithStyles, withStyles, Card,
-    CardHeader, IconButton, CardContent, Grid, Chip, Typography, Tooltip, Button
+    CardHeader, IconButton, CardContent, Grid, Chip, Typography, Tooltip
 } from '@material-ui/core';
 import { ArvadosTheme } from 'common/custom-theme';
 import { CloseIcon, MoreOptionsIcon, ProcessIcon } from 'components/icon/icon';
 } from '@material-ui/core';
 import { ArvadosTheme } from 'common/custom-theme';
 import { CloseIcon, MoreOptionsIcon, ProcessIcon } from 'components/icon/icon';
@@ -114,7 +114,7 @@ export const ProcessInformationCard = withStyles(styles, { withTheme: true })(
                         </Tooltip>
                         { doHidePanel &&
                         <Tooltip title={`Close ${panelName || 'panel'}`} disableFocusListener>
                         </Tooltip>
                         { doHidePanel &&
                         <Tooltip title={`Close ${panelName || 'panel'}`} disableFocusListener>
-                            <Button onClick={doHidePanel}><CloseIcon /></Button>
+                            <IconButton onClick={doHidePanel}><CloseIcon /></IconButton>
                         </Tooltip> }
                     </div>
                 }
                         </Tooltip> }
                     </div>
                 }
index 493546717c67d6de3408a85babff420392112696..41a8f66b80457a6fdbe693a8f0884e6a7d7edb07 100644 (file)
@@ -94,5 +94,7 @@ export const SubprocessPanelRoot = (props: SubprocessPanelProps & MPVPanelProps)
                 messages={DEFAULT_VIEW_MESSAGES} />
         }
         doHidePanel={props.doHidePanel}
                 messages={DEFAULT_VIEW_MESSAGES} />
         }
         doHidePanel={props.doHidePanel}
+        doMaximizePanel={props.doMaximizePanel}
+        panelMaximized={props.panelMaximized}
         panelName={props.panelName} />;
 };
\ No newline at end of file
         panelName={props.panelName} />;
 };
\ No newline at end of file