--- /dev/null
+// 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} />;
+ }
+}
--- /dev/null
+// 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);
+ }
+}
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;
<Field
name={input.id}
commandInput={input}
- component={IntInputComponent}
+ component={InputComponent}
parse={value => parseInt(value, 10)}
format={value => isNaN(value) ? '' : JSON.stringify(value)}
validate={[
: () => 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} />;
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';
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';
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} />;