Merge branch '21128-toolbar-context-menu'
[arvados-workbench2.git] / src / views-components / virtual-machines-dialog / group-array-input.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React from 'react';
6 import { StringArrayCommandInputParameter } from 'models/workflow';
7 import { Field, GenericField } from 'redux-form';
8 import { GenericInputProps } from 'views/run-process-panel/inputs/generic-input';
9 import { ChipsInput } from 'components/chips-input/chips-input';
10 import { identity } from 'lodash';
11 import { withStyles, WithStyles, FormGroup, Input, InputLabel, FormControl, FormHelperText } from '@material-ui/core';
12 import classnames from "classnames";
13 import { ArvadosTheme } from 'common/custom-theme';
14
15 export interface GroupArrayDataProps {
16   hasPartialGroupInput?: boolean;
17   setPartialGroupInput?: (value: boolean) => void;
18 }
19
20 interface GroupArrayFieldProps {
21   commandInput: StringArrayCommandInputParameter;
22 }
23
24 const GroupArrayField = Field as new () => GenericField<GroupArrayDataProps & GroupArrayFieldProps>;
25
26 export interface GroupArrayInputProps {
27   name: string;
28   input: StringArrayCommandInputParameter;
29   required: boolean;
30 }
31
32 type CssRules = 'chips' | 'partialInputHelper' | 'partialInputHelperVisible';
33
34 const styles = (theme: ArvadosTheme) => ({
35     chips: {
36         marginTop: "16px",
37     },
38     partialInputHelper: {
39         textAlign: 'right' as 'right',
40         visibility: 'hidden' as 'hidden',
41         color: theme.palette.error.dark,
42     },
43     partialInputHelperVisible: {
44         visibility: 'visible' as 'visible',
45     }
46 });
47
48 export const GroupArrayInput = ({name, input, setPartialGroupInput, hasPartialGroupInput}: GroupArrayInputProps & GroupArrayDataProps) => {
49   return <GroupArrayField
50       name={name}
51       commandInput={input}
52       component={GroupArrayInputComponent as any}
53       setPartialGroupInput={setPartialGroupInput}
54       hasPartialGroupInput={hasPartialGroupInput}
55       />;
56 }
57
58 const GroupArrayInputComponent = (props: GenericInputProps & GroupArrayDataProps) => {
59   return <FormGroup>
60         <FormControl fullWidth error={props.meta.error}>
61           <InputLabel shrink={props.meta.active || props.input.value.length > 0}>{props.commandInput.id}</InputLabel>
62           <StyledInputComponent {...props} />
63         </FormControl>
64     </FormGroup>;
65     };
66
67 const StyledInputComponent = withStyles(styles)(
68   class InputComponent extends React.PureComponent<GenericInputProps & WithStyles<CssRules> & GroupArrayDataProps>{
69       render() {
70           const { classes } = this.props;
71           const { commandInput, input, meta, hasPartialGroupInput } = this.props;
72           return <>
73             <ChipsInput
74                 deletable={!commandInput.disabled}
75                 orderable={!commandInput.disabled}
76                 disabled={commandInput.disabled}
77                 values={input.value}
78                 onChange={this.handleChange}
79                 handleFocus={input.onFocus}
80                 createNewValue={identity}
81                 inputComponent={Input}
82                 chipsClassName={classes.chips}
83                 pattern={/[_a-z][-0-9_a-z]*/ig}
84                 onPartialInput={this.props.setPartialGroupInput}
85                 inputProps={{
86                     error: meta.error || hasPartialGroupInput,
87                 }} />
88                 <FormHelperText className={classnames([classes.partialInputHelper, ...(hasPartialGroupInput ? [classes.partialInputHelperVisible] : [])])}>
89                   Press enter to complete group name
90                 </FormHelperText>
91           </>;
92       }
93
94       handleChange = (values: {}[]) => {
95         const { input, meta } = this.props;
96           if (!meta.touched) {
97               input.onBlur(values);
98           }
99           input.onChange(values);
100       }
101
102   }
103 );