17782: Fixes almost all tests (4 left) mostly by fixing namespace-type imports.
[arvados-workbench2.git] / src / views / run-process-panel / inputs / file-array-input.tsx
index 39884a6d7ea9726af9b25be6de49f46e307f1027..f105a6bed1b8660e8e345a7a0e681edda634f255 100644 (file)
@@ -2,33 +2,34 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import * as React from 'react';
+import React from 'react';
 import {
     isRequiredInput,
     FileArrayCommandInputParameter,
     File,
     CWLType
-} from '~/models/workflow';
+} from 'models/workflow';
 import { Field } from 'redux-form';
-import { ERROR_MESSAGE } from '~/validators/require';
-import { Input, Dialog, DialogTitle, DialogContent, DialogActions, Button, Divider, Grid, WithStyles, Typography } from '@material-ui/core';
+import { ERROR_MESSAGE } from 'validators/require';
+import { Input, Dialog, DialogTitle, DialogContent, DialogActions, Button, Divider, WithStyles, Typography } from '@material-ui/core';
 import { GenericInputProps, GenericInput } from './generic-input';
-import { ProjectsTreePicker } from '~/views-components/projects-tree-picker/projects-tree-picker';
+import { ProjectsTreePicker } from 'views-components/projects-tree-picker/projects-tree-picker';
 import { connect, DispatchProp } from 'react-redux';
-import { initProjectsTreePicker, getSelectedNodes, treePickerActions, getProjectsTreePickerIds } from '~/store/tree-picker/tree-picker-actions';
-import { ProjectsTreePickerItem } from '~/views-components/projects-tree-picker/generic-projects-tree-picker';
-import { CollectionFile, CollectionFileType } from '~/models/collection-file';
+import { initProjectsTreePicker, getSelectedNodes, treePickerActions, getProjectsTreePickerIds } from 'store/tree-picker/tree-picker-actions';
+import { ProjectsTreePickerItem } from 'views-components/projects-tree-picker/generic-projects-tree-picker';
+import { CollectionFile, CollectionFileType } from 'models/collection-file';
 import { createSelector, createStructuredSelector } from 'reselect';
-import { ChipsInput } from '~/components/chips-input/chips-input';
+import { ChipsInput } from 'components/chips-input/chips-input';
 import { identity, values, noop } from 'lodash';
 import { InputProps } from '@material-ui/core/Input';
-import { TreePicker } from '~/store/tree-picker/tree-picker';
-import { RootState } from '~/store/store';
-import { Chips } from '~/components/chips/chips';
+import { TreePicker } from 'store/tree-picker/tree-picker';
+import { RootState } from 'store/store';
+import { Chips } from 'components/chips/chips';
 import withStyles, { StyleRulesCallback } from '@material-ui/core/styles/withStyles';
 
 export interface FileArrayInputProps {
     input: FileArrayCommandInputParameter;
+    options?: { showOnlyOwned: boolean, showOnlyWritable: boolean };
 }
 export const FileArrayInput = ({ input }: FileArrayInputProps) =>
     <Field
@@ -39,10 +40,10 @@ export const FileArrayInput = ({ input }: FileArrayInputProps) =>
         format={formatFiles}
         validate={validationSelector(input)} />;
 
-const parseFiles = (files: CollectionFile[]) =>
-    files.length > 0
-        ? files.map(parse)
-        : undefined;
+const parseFiles = (files: CollectionFile[] | string) =>
+    typeof files === 'string'
+        ? undefined
+        : files.map(parse);
 
 const parse = (file: CollectionFile): File => ({
     class: CWLType.FILE,
@@ -51,7 +52,8 @@ const parse = (file: CollectionFile): File => ({
     path: file.path,
 });
 
-const formatFiles = (files: File[] = []) => files.map(format);
+const formatFiles = (files: File[] = []) =>
+    files ? files.map(format) : [];
 
 const format = (file: File): CollectionFile => ({
     id: file.location
@@ -91,7 +93,9 @@ const mapStateToProps = createStructuredSelector({
 });
 
 const FileArrayInputComponent = connect(mapStateToProps)(
-    class FileArrayInputComponent extends React.Component<FileArrayInputComponentProps & GenericInputProps & DispatchProp, FileArrayInputComponentState> {
+    class FileArrayInputComponent extends React.Component<FileArrayInputComponentProps & GenericInputProps & DispatchProp & {
+        options?: { showOnlyOwned: boolean, showOnlyWritable: boolean };
+    }, FileArrayInputComponentState> {
         state: FileArrayInputComponentState = {
             open: false,
             files: [],
@@ -116,7 +120,6 @@ const FileArrayInputComponent = connect(mapStateToProps)(
             this.setState({ open: true });
         }
 
-
         closeDialog = () => {
             this.setState({ open: false });
         }
@@ -138,14 +141,12 @@ const FileArrayInputComponent = connect(mapStateToProps)(
             this.setState({ files });
 
             const ids = values(getProjectsTreePickerIds(this.props.commandInput.id));
-            deletedFiles.forEach(({ id }) => {
-                ids.forEach(pickerId => {
-                    this.props.dispatch(
-                        treePickerActions.DESELECT_TREE_PICKER_NODE({
-                            pickerId, id,
-                        })
-                    );
-                });
+            ids.forEach(pickerId => {
+                this.props.dispatch(
+                    treePickerActions.DESELECT_TREE_PICKER_NODE({
+                        pickerId, id: deletedFiles.map(({ id }) => id),
+                    })
+                );
             });
 
         }
@@ -159,19 +160,16 @@ const FileArrayInputComponent = connect(mapStateToProps)(
                         : [...addedFiles, file]
                     , []);
 
-            this.setState({ files });
-
             const ids = values(getProjectsTreePickerIds(this.props.commandInput.id));
-            addedFiles.forEach(({ id }) => {
-                ids.forEach(pickerId => {
-                    this.props.dispatch(
-                        treePickerActions.SELECT_TREE_PICKER_NODE({
-                            pickerId, id,
-                        })
-                    );
-                });
+            ids.forEach(pickerId => {
+                this.props.dispatch(
+                    treePickerActions.SELECT_TREE_PICKER_NODE({
+                        pickerId, id: addedFiles.map(({ id }) => id),
+                    })
+                );
             });
 
+            this.setFiles(files);
         }
 
         refreshFiles = () => {
@@ -197,7 +195,8 @@ const FileArrayInputComponent = connect(mapStateToProps)(
 
         chipsInput = () =>
             <ChipsInput
-                value={this.props.input.value}
+                values={this.props.input.value}
+                disabled={this.props.commandInput.disabled}
                 onChange={noop}
                 createNewValue={identity}
                 getLabel={(file: CollectionFile) => file.name}
@@ -208,8 +207,9 @@ const FileArrayInputComponent = connect(mapStateToProps)(
                 {...props}
                 error={this.props.meta.touched && !!this.props.meta.error}
                 readOnly
-                onClick={this.openDialog}
-                onKeyPress={this.openDialog}
+                disabled={this.props.commandInput.disabled}
+                onClick={!this.props.commandInput.disabled ? this.openDialog : undefined}
+                onKeyPress={!this.props.commandInput.disabled ? this.openDialog : undefined}
                 onBlur={this.props.input.onBlur} />
 
         dialog = () =>
@@ -225,6 +225,7 @@ const FileArrayInputComponent = connect(mapStateToProps)(
                 <DialogActions>
                     <Button onClick={this.closeDialog}>Cancel</Button>
                     <Button
+                        data-cy='ok-button'
                         variant='contained'
                         color='primary'
                         onClick={this.submit}>Ok</Button>
@@ -261,12 +262,15 @@ const FileArrayInputComponent = connect(mapStateToProps)(
                             includeCollections
                             includeFiles
                             showSelection
+                            options={this.props.options}
                             toggleItemSelection={this.refreshFiles} />
                     </div>
                     <Divider />
                     <div className={classes.chips}>
-                        <Typography variant='subheading'>Selected files ({this.state.files.length}):</Typography>
+                        <Typography variant='subtitle1'>Selected files ({this.state.files.length}):</Typography>
                         <Chips
+                            orderable
+                            deletable
                             values={this.state.files}
                             onChange={this.setFiles}
                             getLabel={(file: CollectionFile) => file.name} />
@@ -277,6 +281,3 @@ const FileArrayInputComponent = connect(mapStateToProps)(
     });
 
 type DialogContentCssRules = 'root' | 'tree' | 'divider' | 'chips';
-
-
-