toolbar accurately selects for appropriate buttons Arvados-DCO-1.1-Signed-off-by...
[arvados-workbench2.git] / src / components / multiselectToolbar / MultiselectToolbar.tsx
index d857d7ffa07dae596ffc999bbd6209ec958c5e07..bd01b36161479c2b54ee814564d87920338dce2f 100644 (file)
@@ -7,66 +7,146 @@ import { connect } from 'react-redux';
 import { StyleRulesCallback, withStyles, WithStyles, Toolbar, Button } from '@material-ui/core';
 import { ArvadosTheme } from 'common/custom-theme';
 import { RootState } from 'store/store';
+import { Dispatch } from 'redux';
 import { CopyToClipboardSnackbar } from 'components/copy-to-clipboard-snackbar/copy-to-clipboard-snackbar';
+import { TCheckedList } from 'components/data-table/data-table';
+import { openRemoveProcessDialog, openRemoveManyProcessesDialog } from 'store/processes/processes-actions';
+import { processResourceActionSet } from '../../views-components/context-menu/action-sets/process-resource-action-set';
+import { ContextMenuResource } from 'store/context-menu/context-menu-actions';
+import { toggleTrashed } from 'store/trash/trash-actions';
+import { ResourceKind, extractUuidKind } from 'models/resource';
 
-type CssRules = 'root' | 'button';
+type CssRules = 'root' | 'expanded' | 'button';
 
 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     root: {
         display: 'flex',
         flexDirection: 'row',
+        width: 0,
+        padding: 0,
+        margin: '1rem auto auto 0.5rem',
+        overflow: 'hidden',
+    },
+    expanded: {
+        transition: 'width 150ms',
     },
     button: {
-        color: theme.palette.text.primary,
-        margin: '0.5rem',
+        backgroundColor: '#017ead',
+        color: 'white',
+        fontSize: '0.75rem',
+        width: 'auto',
+        margin: 'auto',
+        padding: '1px',
     },
 });
 
 type MultiselectToolbarAction = {
     name: string;
-    fn: () => ReactElement;
-};
-
-export type MultiselectToolbarActions = {
-    actions: Array<MultiselectToolbarAction>;
+    action: string;
+    relevantKinds: Array<ResourceKind>;
 };
 
 export const defaultActions: Array<MultiselectToolbarAction> = [
+    {
+        name: 'copy',
+        action: 'copySelected',
+        relevantKinds: [ResourceKind.COLLECTION],
+    },
+    {
+        name: 'move',
+        action: 'moveSelected',
+        relevantKinds: [ResourceKind.COLLECTION, ResourceKind.PROCESS],
+    },
+    {
+        name: 'remove',
+        action: 'removeSelected',
+        relevantKinds: [ResourceKind.COLLECTION, ResourceKind.PROCESS, ResourceKind.PROJECT],
+    },
     {
         name: 'foo',
-        fn: () => MSToolbarCopyButton({ button: { border: '1px solid blue' } }),
+        action: 'barSelected',
+        relevantKinds: [ResourceKind.COLLECTION, ResourceKind.PROJECT],
     },
 ];
 
-const MSToolbarCopyButton = (classes) => {
-    return (
-        <Button className={classes.button}>
-            <CopyToClipboardSnackbar value='foo' children={<div>Copy</div>} />
-        </Button>
-    );
+export type MultiselectToolbarProps = {
+    actions: Array<MultiselectToolbarAction>;
+    isVisible: boolean;
+    checkedList: TCheckedList;
+    copySelected: () => void;
+    moveSelected: () => void;
+    barSelected: () => void;
+    removeSelected: (selectedList: TCheckedList) => void;
 };
 
-type MultiselectToolbarProps = MultiselectToolbarActions & WithStyles<CssRules>;
+export const MultiselectToolbar = connect(
+    mapStateToProps,
+    mapDispatchToProps
+)(
+    withStyles(styles)((props: MultiselectToolbarProps & WithStyles<CssRules>) => {
+        // console.log(props);
+        const { classes, actions, isVisible, checkedList } = props;
+
+        const currentResourceKinds = selectedToArray(checkedList).map((element) => extractUuidKind(element));
+
+        const buttons = actions.filter(
+            (action) => currentResourceKinds.length && currentResourceKinds.every((kind) => action.relevantKinds.includes(kind as ResourceKind))
+        );
 
-export const MultiselectToolbar = connect(mapStateToProps)(
-    withStyles(styles)((props: MultiselectToolbarProps) => {
-        const { classes, actions } = props;
         return (
-            <Toolbar className={classes.root}>
-                {actions.map((action, i) => (
-                    <Button key={i} className={classes.button} onClick={action.fn}>
-                        {action.name}
-                    </Button>
-                ))}
-                <MSToolbarCopyButton />
-                {/* <CopyToClipboardSnackbar value='foo' children={<div>test</div>} /> */}
+            <Toolbar className={isVisible && buttons.length ? `${classes.root} ${classes.expanded}` : classes.root} style={{ width: `${buttons.length * 5.5}rem` }}>
+                {buttons.length ? (
+                    buttons.map((btn) => (
+                        <Button key={btn.name} className={`${classes.button} ${classes.expanded}`} onClick={() => props[btn.action](checkedList)}>
+                            {btn.name}
+                        </Button>
+                    ))
+                ) : (
+                    <></>
+                )}
             </Toolbar>
         );
     })
 );
 
+function selectedToString(checkedList: TCheckedList) {
+    let stringifiedSelectedList: string = '';
+    for (const [key, value] of Object.entries(checkedList)) {
+        if (value === true) {
+            stringifiedSelectedList += key + ',';
+        }
+    }
+    return stringifiedSelectedList.slice(0, -1);
+}
+
+function selectedToArray<T>(checkedList: TCheckedList): Array<string> {
+    const arrayifiedSelectedList: Array<string> = [];
+    for (const [key, value] of Object.entries(checkedList)) {
+        if (value === true) {
+            arrayifiedSelectedList.push(key);
+        }
+    }
+    return arrayifiedSelectedList;
+}
+
 function mapStateToProps(state: RootState) {
+    const { isVisible, checkedList } = state.multiselect;
     return {
-        // state: state,
+        isVisible: isVisible,
+        checkedList: checkedList as TCheckedList,
     };
 }
+
+function mapDispatchToProps(dispatch: Dispatch) {
+    return {
+        copySelected: () => {},
+        moveSelected: () => {},
+        barSelected: () => {},
+        removeSelected: (checkedList: TCheckedList) => removeMulti(dispatch, checkedList),
+    };
+}
+
+function removeMulti(dispatch: Dispatch, checkedList: TCheckedList): void {
+    const list: Array<string> = selectedToArray(checkedList);
+    dispatch<any>(list.length === 1 ? openRemoveProcessDialog(list[0]) : openRemoveManyProcessesDialog(list));
+}