Add integer array input
authorMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Sun, 21 Oct 2018 20:45:18 +0000 (22:45 +0200)
committerMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Sun, 21 Oct 2018 20:45:18 +0000 (22:45 +0200)
Feature #13862

Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski@contractors.roche.com>

src/components/int-input/int-input.tsx [new file with mode: 0644]
src/views/run-process-panel/inputs/int-array-input.tsx [new file with mode: 0644]
src/views/run-process-panel/inputs/int-input.tsx
src/views/run-process-panel/run-process-inputs-form.tsx

diff --git a/src/components/int-input/int-input.tsx b/src/components/int-input/int-input.tsx
new file mode 100644 (file)
index 0000000..0527efa
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { Input } from '@material-ui/core';
+import { InputProps } from '@material-ui/core/Input';
+
+export class IntInput extends React.Component<InputProps> {
+    handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
+        const { onChange = () => { return; } } = this.props;
+        const parsedValue = parseInt(event.target.value, 10);
+        event.target.value = parsedValue.toString();
+        onChange(event);
+    }
+
+    render() {
+        const parsedValue = parseInt(typeof this.props.value === 'string' ? this.props.value : '', 10);
+        const value = isNaN(parsedValue) ? '' : parsedValue.toString();
+        const props = {
+            ...this.props,
+            value,
+            onChange: this.handleChange,
+        };
+        return <Input {...props} />;
+    }
+}
diff --git a/src/views/run-process-panel/inputs/int-array-input.tsx b/src/views/run-process-panel/inputs/int-array-input.tsx
new file mode 100644 (file)
index 0000000..a878444
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { isRequiredInput, IntArrayCommandInputParameter } from '~/models/workflow';
+import { Field } from 'redux-form';
+import { ERROR_MESSAGE } from '~/validators/require';
+import { GenericInputProps, GenericInput } from '~/views/run-process-panel/inputs/generic-input';
+import { ChipsInput } from '~/components/chips-input/chips-input';
+import { identity } from 'lodash';
+import { createSelector } from 'reselect';
+import { IntInput } from '~/components/int-input/int-input';
+
+export interface IntArrayInputProps {
+    input: IntArrayCommandInputParameter;
+}
+export const IntArrayInput = ({ input }: IntArrayInputProps) =>
+    <Field
+        name={input.id}
+        commandInput={input}
+        component={IntArrayInputComponent}
+        validate={validationSelector(input)} />;
+
+
+const validationSelector = createSelector(
+    isRequiredInput,
+    isRequired => isRequired
+        ? [required]
+        : undefined
+);
+
+const required = (value: string[]) =>
+    value.length > 0
+        ? undefined
+        : ERROR_MESSAGE;
+
+const IntArrayInputComponent = (props: GenericInputProps) =>
+    <GenericInput
+        component={InputComponent}
+        {...props} />;
+
+class InputComponent extends React.PureComponent<GenericInputProps>{
+    render() {
+        return <ChipsInput
+            deletable
+            orderable
+            value={this.props.input.value}
+            onChange={this.handleChange}
+            createNewValue={identity}
+            inputComponent={IntInput}
+            inputProps={{
+                error: this.props.meta.error,
+            }} />;
+    }
+
+    handleChange = (values: {}[]) => {
+        const { input, meta } = this.props;
+        if (!meta.touched) {
+            input.onBlur(values);
+        }
+        input.onChange(values);
+    }
+}
index 193de26ccb2d3e224d4ba120eea524a03ded87b3..410d2dfebf7272d7b21035e3a786843a2672eede 100644 (file)
@@ -7,7 +7,7 @@ import { IntCommandInputParameter, getInputLabel, isRequiredInput } from '~/mode
 import { Field } from 'redux-form';
 import { isInteger } from '~/validators/is-integer';
 import { GenericInputProps, GenericInput } from '~/views/run-process-panel/inputs/generic-input';
-import { Input as MaterialInput } from '@material-ui/core';
+import { IntInput as IntInputComponent } from '~/components/int-input/int-input';
 
 export interface IntInputProps {
     input: IntCommandInputParameter;
@@ -16,7 +16,7 @@ export const IntInput = ({ input }: IntInputProps) =>
     <Field
         name={input.id}
         commandInput={input}
-        component={IntInputComponent}
+        component={InputComponent}
         parse={value => parseInt(value, 10)}
         format={value => isNaN(value) ? '' : JSON.stringify(value)}
         validate={[
@@ -25,12 +25,12 @@ export const IntInput = ({ input }: IntInputProps) =>
                 : () => undefined,
         ]} />;
 
-const IntInputComponent = (props: GenericInputProps) =>
+const InputComponent = (props: GenericInputProps) =>
     <GenericInput
         component={Input}
         {...props} />;
 
 
 const Input = (props: GenericInputProps) =>
-    <MaterialInput fullWidth type='number' {...props.input} error={props.meta.touched && !!props.meta.error} />;
+    <IntInputComponent fullWidth type='number' {...props.input} error={props.meta.touched && !!props.meta.error} />;
 
index c985dff11eddc2534cc5acc57dd8e77fd366899f..37349a6e369e40ecc74534c886a3534917abefcf 100644 (file)
@@ -4,7 +4,7 @@
 
 import * as React from 'react';
 import { reduxForm, InjectedFormProps } from 'redux-form';
-import { CommandInputParameter, CWLType, IntCommandInputParameter, BooleanCommandInputParameter, FileCommandInputParameter, DirectoryCommandInputParameter, DirectoryArrayCommandInputParameter, FloatArrayCommandInputParameter } from '~/models/workflow';
+import { CommandInputParameter, CWLType, IntCommandInputParameter, BooleanCommandInputParameter, FileCommandInputParameter, DirectoryCommandInputParameter, DirectoryArrayCommandInputParameter, FloatArrayCommandInputParameter, IntArrayCommandInputParameter } from '~/models/workflow';
 import { IntInput } from '~/views/run-process-panel/inputs/int-input';
 import { StringInput } from '~/views/run-process-panel/inputs/string-input';
 import { StringCommandInputParameter, FloatCommandInputParameter, isPrimitiveOfType, File, Directory, WorkflowInputsData, EnumCommandInputParameter, isArrayOfType, StringArrayCommandInputParameter, FileArrayCommandInputParameter } from '../../models/workflow';
@@ -21,6 +21,7 @@ import { createStructuredSelector, createSelector } from 'reselect';
 import { FileArrayInput } from './inputs/file-array-input';
 import { DirectoryArrayInput } from './inputs/directory-array-input';
 import { FloatArrayInput } from './inputs/float-array-input';
+import { IntArrayInput } from './inputs/int-array-input';
 
 export const RUN_PROCESS_INPUTS_FORM = 'runProcessInputsForm';
 
@@ -100,13 +101,18 @@ const getInputComponent = (input: CommandInputParameter) => {
 
         case isArrayOfType(input, CWLType.STRING):
             return <StringArrayInput input={input as StringArrayCommandInputParameter} />;
-        
+
+        case isArrayOfType(input, CWLType.INT):
+        case isArrayOfType(input, CWLType.LONG):
+            return <IntArrayInput input={input as IntArrayCommandInputParameter} />;
+
         case isArrayOfType(input, CWLType.FLOAT):
+        case isArrayOfType(input, CWLType.DOUBLE):
             return <FloatArrayInput input={input as FloatArrayCommandInputParameter} />;
 
         case isArrayOfType(input, CWLType.FILE):
             return <FileArrayInput input={input as FileArrayCommandInputParameter} />;
-        
+
         case isArrayOfType(input, CWLType.DIRECTORY):
             return <DirectoryArrayInput input={input as DirectoryArrayCommandInputParameter} />;