Update styles to match mui form
authorMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Sat, 13 Oct 2018 21:59:59 +0000 (23:59 +0200)
committerMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Sat, 13 Oct 2018 21:59:59 +0000 (23:59 +0200)
Feature #13862

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

src/components/chips-input/chips-input.tsx
src/components/chips/chips.tsx
src/views/run-process-panel/inputs/string-array-input.tsx

index 96e7b70a104286e4c5a059ba85eb4cc941af6ce3..12932c54f5775c3d55fe1653171b32fbf7dfb325 100644 (file)
@@ -4,31 +4,34 @@
 
 import * as React from 'react';
 import { Chips } from '~/components/chips/chips';
-import { Input, withStyles, WithStyles } from '@material-ui/core';
+import { Input as MuiInput, withStyles, WithStyles } from '@material-ui/core';
 import { StyleRulesCallback } from '@material-ui/core/styles';
+import { InputProps } from '@material-ui/core/Input';
 
 interface ChipsInputProps<Value> {
-    values: Value[];
+    value: Value[];
     getLabel?: (value: Value) => string;
     onChange: (value: Value[]) => void;
     createNewValue: (value: string) => Value;
+    inputComponent?: React.ComponentType<InputProps>;
+    inputProps?: InputProps;
 }
 
 type CssRules = 'chips' | 'input' | 'inputContainer';
 
-const styles: StyleRulesCallback = () => ({
+const styles: StyleRulesCallback = ({ spacing }) => ({
     chips: {
-        minHeight: '40px',
+        minHeight: spacing.unit * 5,
         zIndex: 1,
         position: 'relative',
     },
     input: {
-        position: 'relative',
-        top: '-5px',
         zIndex: 1,
+        marginBottom: 8,
+        position: 'relative',
     },
     inputContainer: {
-        top: '-24px',
+        marginTop: -34
     },
 });
 
@@ -58,13 +61,13 @@ export const ChipsInput = withStyles(styles)(
             if (this.state.text) {
                 const newValue = this.props.createNewValue(this.state.text);
                 this.setState({ text: '' });
-                this.props.onChange([...this.props.values, newValue]);
+                this.props.onChange([...this.props.value, newValue]);
             }
         }
 
         deleteLastValue = () => {
-            if (this.state.text.length === 0 && this.props.values.length > 0) {
-                this.props.onChange(this.props.values.slice(0, -1));
+            if (this.state.text.length === 0 && this.props.value.length > 0) {
+                this.props.onChange(this.props.value.slice(0, -1));
             }
         }
 
@@ -77,7 +80,7 @@ export const ChipsInput = withStyles(styles)(
 
         getInputStyles = (): React.CSSProperties => ({
             width: this.filler.current
-                ? this.filler.current.offsetWidth + 8
+                ? this.filler.current.offsetWidth
                 : '100%',
             right: this.filler.current
                 ? `calc(${this.filler.current.offsetWidth}px - 100%)`
@@ -91,27 +94,40 @@ export const ChipsInput = withStyles(styles)(
 
         render() {
             return <>
-                <div className={this.props.classes.chips}>
-                    <Chips
-                        {...this.props}
-                        filler={<div ref={this.filler} />}
-                    />
-                </div>
-                <Input
-                    value={this.state.text}
-                    onChange={this.setText}
-                    onKeyDown={this.handleKeyPress}
-                    inputProps={{
-                        className: this.props.classes.input,
-                        style: this.getInputStyles(),
-                    }}
-                    fullWidth
-                    className={this.props.classes.inputContainer} />
+                {this.renderChips()}
+                {this.renderInput()}
             </>;
         }
 
+        renderChips() {
+            const { classes, value, ...props } = this.props;
+            return <div className={classes.chips}>
+                <Chips
+                    {...props}
+                    values={value}
+                    filler={<div ref={this.filler} />}
+                />
+            </div>;
+        }
+
+        renderInput() {
+            const { inputProps: InputProps, inputComponent: Input = MuiInput, classes } = this.props;
+            return <Input
+                {...InputProps}
+                value={this.state.text}
+                onChange={this.setText}
+                onKeyDown={this.handleKeyPress}
+                inputProps={{
+                    ...(InputProps && InputProps.inputProps),
+                    className: classes.input,
+                    style: this.getInputStyles(),
+                }}
+                fullWidth
+                className={classes.inputContainer} />;
+        }
+
         componentDidUpdate(prevProps: ChipsInputProps<Value>) {
-            if (prevProps.values !== this.props.values) {
+            if (prevProps.value !== this.props.value) {
                 this.updateCursorPosition();
             }
         }
index c63b584a100ff2de0088057ced2c99d271a38925..8f597de6035c58f05f1b303a45d3227965d3cf86 100644 (file)
 // SPDX-License-Identifier: AGPL-3.0
 
 import * as React from 'react';
-import { Chip, Grid } from '@material-ui/core';
+import { Chip, Grid, StyleRulesCallback, withStyles } from '@material-ui/core';
 import { DragSource, DragSourceSpec, DragSourceCollector, ConnectDragSource, DropTarget, DropTargetSpec, DropTargetCollector, ConnectDropTarget } from 'react-dnd';
 import { compose } from 'lodash/fp';
+import { WithStyles } from '@material-ui/core/styles';
 interface ChipsProps<Value> {
     values: Value[];
     getLabel?: (value: Value) => string;
     filler?: React.ReactNode;
     onChange: (value: Value[]) => void;
 }
-export class Chips<Value> extends React.Component<ChipsProps<Value>> {
-    render() {
-        const { values, filler } = this.props;
-        return <Grid container spacing={8}>
-            {values.map(this.renderChip)}
-            {filler && <Grid item xs>{filler}</Grid>}
-        </Grid>;
-    }
 
-    renderChip = (value: Value, index: number) =>
-        <Grid item key={index}>
-            <this.chip {...{ value }} />
-        </Grid>
+type CssRules = 'root';
 
-    type = 'chip';
+const styles: StyleRulesCallback<CssRules> = ({ spacing }) => ({
+    root: {
+        margin: `0px -${spacing.unit / 2}px`,
+    },
+});
+export const Chips = withStyles(styles)(
+    class Chips<Value> extends React.Component<ChipsProps<Value> & WithStyles<CssRules>> {
+        render() {
+            const { values, filler } = this.props;
+            return <Grid container spacing={8} className={this.props.classes.root}>
+                {values.map(this.renderChip)}
+                {filler && <Grid item xs>{filler}</Grid>}
+            </Grid>;
+        }
+
+        renderChip = (value: Value, index: number) =>
+            <Grid item key={index}>
+                <this.chip {...{ value }} />
+            </Grid>
+
+        type = 'chip';
 
-    dragSpec: DragSourceSpec<DraggableChipProps<Value>, { value: Value }> = {
-        beginDrag: ({ value }) => ({ value }),
-        endDrag: ({ value: dragValue }, monitor) => {
-            const result = monitor.getDropResult();
-            if (result) {
-                const { value: dropValue } = monitor.getDropResult();
-                const dragIndex = this.props.values.indexOf(dragValue);
-                const dropIndex = this.props.values.indexOf(dropValue);
-                const newValues = this.props.values.slice(0);
-                if (dragIndex < dropIndex) {
-                    newValues.splice(dragIndex, 1);
-                    newValues.splice(dropIndex - 1 || 0, 0, dragValue);
-                } else if (dragIndex > dropIndex) {
-                    newValues.splice(dragIndex, 1);
-                    newValues.splice(dropIndex, 0, dragValue);
+        dragSpec: DragSourceSpec<DraggableChipProps<Value>, { value: Value }> = {
+            beginDrag: ({ value }) => ({ value }),
+            endDrag: ({ value: dragValue }, monitor) => {
+                const result = monitor.getDropResult();
+                if (result) {
+                    const { value: dropValue } = monitor.getDropResult();
+                    const dragIndex = this.props.values.indexOf(dragValue);
+                    const dropIndex = this.props.values.indexOf(dropValue);
+                    const newValues = this.props.values.slice(0);
+                    if (dragIndex < dropIndex) {
+                        newValues.splice(dragIndex, 1);
+                        newValues.splice(dropIndex - 1 || 0, 0, dragValue);
+                    } else if (dragIndex > dropIndex) {
+                        newValues.splice(dragIndex, 1);
+                        newValues.splice(dropIndex, 0, dragValue);
+                    }
+                    this.props.onChange(newValues);
                 }
-                this.props.onChange(newValues);
             }
-        }
-    };
+        };
 
-    dragCollector: DragSourceCollector<{}> = connect => ({
-        connectDragSource: connect.dragSource(),
-    })
+        dragCollector: DragSourceCollector<{}> = connect => ({
+            connectDragSource: connect.dragSource(),
+        })
 
-    dropSpec: DropTargetSpec<DraggableChipProps<Value>> = {
-        drop: ({ value }) => ({ value }),
-    };
+        dropSpec: DropTargetSpec<DraggableChipProps<Value>> = {
+            drop: ({ value }) => ({ value }),
+        };
 
-    dropCollector: DropTargetCollector<{}> = (connect, monitor) => ({
-        connectDropTarget: connect.dropTarget(),
-        isOver: monitor.isOver(),
-    })
-    chip = compose(
-        DragSource(this.type, this.dragSpec, this.dragCollector),
-        DropTarget(this.type, this.dropSpec, this.dropCollector),
-    )(
-        ({ connectDragSource, connectDropTarget, isOver, value }: DraggableChipProps<Value> & CollectedProps) =>
-            compose(
-                connectDragSource,
-                connectDropTarget,
-            )(
-                <span>
-                    <Chip
-                        color={isOver ? 'primary' : 'default'}
-                        onDelete={this.deleteValue(value)}
-                        label={this.props.getLabel ?
-                            this.props.getLabel(value)
-                            : typeof value === 'object'
-                                ? JSON.stringify(value)
-                                : value} />
-                </span>
-            )
-    );
+        dropCollector: DropTargetCollector<{}> = (connect, monitor) => ({
+            connectDropTarget: connect.dropTarget(),
+            isOver: monitor.isOver(),
+        })
+        chip = compose(
+            DragSource(this.type, this.dragSpec, this.dragCollector),
+            DropTarget(this.type, this.dropSpec, this.dropCollector),
+        )(
+            ({ connectDragSource, connectDropTarget, isOver, value }: DraggableChipProps<Value> & CollectedProps) =>
+                compose(
+                    connectDragSource,
+                    connectDropTarget,
+                )(
+                    <span>
+                        <Chip
+                            color={isOver ? 'primary' : 'default'}
+                            onDelete={this.deleteValue(value)}
+                            label={this.props.getLabel ?
+                                this.props.getLabel(value)
+                                : typeof value === 'object'
+                                    ? JSON.stringify(value)
+                                    : value} />
+                    </span>
+                )
+        );
 
-    deleteValue = (value: Value) => () => {
-        const { values } = this.props;
-        const index = values.indexOf(value);
-        const newValues = values.slice(0);
-        newValues.splice(index, 1);
-        this.props.onChange(newValues);
-    }
-}
+        deleteValue = (value: Value) => () => {
+            const { values } = this.props;
+            const index = values.indexOf(value);
+            const newValues = values.slice(0);
+            newValues.splice(index, 1);
+            this.props.onChange(newValues);
+        }
+    });
 
 interface CollectedProps {
     connectDragSource: ConnectDragSource;
index 3b29d1a8cf9fa48c822b3b1019b5e9f56cc5e877..dafd9466d7e0b420c8c271cecb89292dc4cde11c 100644 (file)
@@ -10,6 +10,7 @@ import { GenericInputProps, GenericInput } from '~/views/run-process-panel/input
 import { ChipsInput } from '~/components/chips-input/chips-input';
 import { identity } from 'lodash';
 import { createSelector } from 'reselect';
+import { Input } from '@material-ui/core';
 
 export interface StringArrayInputProps {
     input: StringArrayCommandInputParameter;
@@ -36,15 +37,19 @@ const required = (value: string[]) =>
 
 const StringArrayInputComponent = (props: GenericInputProps) =>
     <GenericInput
-        component={Input}
+        component={InputComponent}
         {...props} />;
 
-class Input extends React.PureComponent<GenericInputProps>{
+class InputComponent extends React.PureComponent<GenericInputProps>{
     render() {
         return <ChipsInput
-            values={this.props.input.value}
+            value={this.props.input.value}
             onChange={this.handleChange}
-            createNewValue={identity} />;
+            createNewValue={identity}
+            inputComponent={Input}
+            inputProps={{
+                error: this.props.meta.error,
+            }} />;
     }
 
     handleChange = (values: {}[]) => {