RunProcessInputsForm [WIP]
authorMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Fri, 28 Sep 2018 15:38:56 +0000 (17:38 +0200)
committerMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Fri, 28 Sep 2018 15:38:56 +0000 (17:38 +0200)
Feature #13863

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

src/models/workflow.ts
src/validators/is-float.tsx [new file with mode: 0644]
src/validators/is-integer.tsx [new file with mode: 0644]
src/validators/is-number.tsx [new file with mode: 0644]
src/views/run-process-panel/inputs/float-input.tsx [new file with mode: 0644]
src/views/run-process-panel/inputs/int-input.tsx [new file with mode: 0644]
src/views/run-process-panel/inputs/string-input.tsx [new file with mode: 0644]
src/views/run-process-panel/run-process-inputs-form.tsx [new file with mode: 0644]
src/views/workflow-panel/workflow-description-card.tsx

index 95cc926fbd09dfa19eff94abb897d2f8bcb6b053..1cb3d46e8cb09a925adf1cd1b87de5f61f49b2ea 100644 (file)
@@ -118,7 +118,20 @@ export const getWorkflowInputs = (workflowDefinition: WorkflowResoruceDefinition
         ? mainWorkflow.inputs
         : undefined;
 };
+export const getInputLabel = (input: CommandInputParameter) => {
+    return `${input.label || input.id}${isRequiredInput(input) ? '*' : ''}`;
+};
 
+export const isRequiredInput = ({ type }: CommandInputParameter) => {
+    if (type instanceof Array) {
+        for (const t of type) {
+            if (t === CWLType.NULL) {
+                return false;
+            }
+        }
+    }
+    return true;
+};
 export const stringifyInputType = ({ type }: CommandInputParameter) => {
     if (typeof type === 'string') {
         return type;
diff --git a/src/validators/is-float.tsx b/src/validators/is-float.tsx
new file mode 100644 (file)
index 0000000..9bde5f9
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { isInteger, isNumber } from 'lodash';
+
+const ERROR_MESSAGE = 'This field must be a float';
+
+export const isFloat = (value: any) => {
+    return isNumber(value) ? undefined : ERROR_MESSAGE;
+};
diff --git a/src/validators/is-integer.tsx b/src/validators/is-integer.tsx
new file mode 100644 (file)
index 0000000..fbfe8fb
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { isInteger as isInt } from 'lodash';
+
+const ERROR_MESSAGE = 'This field must be an integer';
+
+export const isInteger = (value: any) => {
+    return isInt(value) ? undefined : ERROR_MESSAGE;
+};
diff --git a/src/validators/is-number.tsx b/src/validators/is-number.tsx
new file mode 100644 (file)
index 0000000..9b548b9
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { isNumber as isNum } from 'lodash';
+const ERROR_MESSAGE = 'This field must be a number';
+
+export const isNumber = (value: any) => {
+    return isNum(value) ? undefined : ERROR_MESSAGE;
+};
diff --git a/src/views/run-process-panel/inputs/float-input.tsx b/src/views/run-process-panel/inputs/float-input.tsx
new file mode 100644 (file)
index 0000000..0f5a116
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { getInputLabel, FloatCommandInputParameter } from '~/models/workflow';
+import { Field } from 'redux-form';
+import { TextField } from '~/components/text-field/text-field';
+import { isNumber } from '~/validators/is-number';
+import { toNumber } from 'lodash';
+export interface FloatInputProps {
+    input: FloatCommandInputParameter;
+}
+export const FloatInput = ({ input }: FloatInputProps) =>
+    <Field
+        name={input.id}
+        label={getInputLabel(input)}
+        component={TextField}
+        parse={value => toNumber(value)}
+        format={value => isNaN(value) ? '' : JSON.stringify(value)}
+        validate={[isNumber]} />;
+
diff --git a/src/views/run-process-panel/inputs/int-input.tsx b/src/views/run-process-panel/inputs/int-input.tsx
new file mode 100644 (file)
index 0000000..5b6f95d
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { IntCommandInputParameter, getInputLabel } from '~/models/workflow';
+import { Field } from 'redux-form';
+import { TextField } from '~/components/text-field/text-field';
+import { isInteger } from '~/validators/is-integer';
+
+export interface IntInputProps {
+    input: IntCommandInputParameter;
+}
+export const IntInput = ({ input }: IntInputProps) =>
+    <Field
+        name={input.id}
+        label={getInputLabel(input)}
+        component={TextField}
+        parse={value => parseInt(value, 10)}
+        format={value => isNaN(value) ? '' : JSON.stringify(value)}
+        validate={[isInteger]} />;
+
diff --git a/src/views/run-process-panel/inputs/string-input.tsx b/src/views/run-process-panel/inputs/string-input.tsx
new file mode 100644 (file)
index 0000000..8c72a46
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { getInputLabel, isRequiredInput, StringCommandInputParameter } from '~/models/workflow';
+import { Field } from 'redux-form';
+import { TextField } from '~/components/text-field/text-field';
+import { require } from '~/validators/require';
+
+export interface StringInputProps {
+    input: StringCommandInputParameter;
+}
+export const StringInput = ({ input }: StringInputProps) =>
+    <Field
+        name={input.id}
+        label={getInputLabel(input)}
+        component={TextField}
+        validate={[
+            isRequiredInput(input)
+                ? require
+                : () => undefined,
+        ]} />;
+
diff --git a/src/views/run-process-panel/run-process-inputs-form.tsx b/src/views/run-process-panel/run-process-inputs-form.tsx
new file mode 100644 (file)
index 0000000..193e5ab
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { reduxForm, InjectedFormProps } from 'redux-form';
+import { WorkflowResource, CommandInputParameter, CWLType, IntCommandInputParameter } 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 } from '../../models/workflow';
+import { FloatInput } from '~/views/run-process-panel/inputs/float-input';
+
+const RUN_PROCESS_INPUTS_FORM = 'runProcessInputsForm';
+
+export interface RunProcessInputFormProps {
+    inputs: CommandInputParameter[];
+}
+
+export const RunProcessInputsForm = reduxForm<any, RunProcessInputFormProps>({
+    form: RUN_PROCESS_INPUTS_FORM
+})((props: InjectedFormProps & RunProcessInputFormProps) =>
+    <form>
+        {props.inputs.map(input => {
+            switch (true) {
+                case input.type === CWLType.INT:
+                case input.type === CWLType.LONG:
+                    return <IntInput key={input.id} input={input as IntCommandInputParameter} />;
+                case input.type === CWLType.FLOAT:
+                case input.type === CWLType.DOUBLE:
+                    return <FloatInput key={input.id} input={input as FloatCommandInputParameter} />;
+                case input.type === CWLType.STRING:
+                    return <StringInput key={input.id} input={input as StringCommandInputParameter} />;
+                default:
+                    return null;
+            }
+        })}
+    </form>);
\ No newline at end of file
index f6b2fcba38967a16b9a0800f597c1ced7e602670..c297276e7bc6283e541473d5b2f81ab118d45465 100644 (file)
@@ -9,6 +9,7 @@ import { WorkflowIcon } from '~/components/icon/icon';
 import { DataTableDefaultView } from '~/components/data-table-default-view/data-table-default-view';
 import { WorkflowResource, parseWorkflowDefinition, getWorkflowInputs } from '~/models/workflow';
 import { WorkflowInput } from '~/components/workflow-inputs-form/workflow-input';
+import { RunProcessInputsForm } from '../run-process-panel/run-process-inputs-form';
 
 export type CssRules = 'root' | 'tab';
 
@@ -54,7 +55,7 @@ export const WorkflowDetailsCard = withStyles(styles)(
                 </CardContent>}
                 {value === 1 && <CardContent>
                     {workflow && this.inputs
-                        ? this.inputs.map(input => <WorkflowInput key={input.id} input={input}/>)
+                        ? <RunProcessInputsForm inputs={this.inputs} />
                         : <DataTableDefaultView
                             icon={WorkflowIcon}
                             messages={['Please select a workflow to see its description.']} />}