merge conflicts
[arvados-workbench2.git] / src / utils / dialog-validator.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import * as React from 'react';
6 import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
7
8 type CssRules = "formInputError";
9
10 const styles: StyleRulesCallback<CssRules> = theme => ({
11     formInputError: {
12         color: "#ff0000",
13         marginLeft: "5px",
14         fontSize: "11px",
15     }
16 });
17
18 type ValidatorProps = {
19     value: string,
20     onChange: (isValid: boolean | string) => void;
21     render: (hasError: boolean) => React.ReactElement<any>;
22     isRequired: boolean;
23 };
24
25 interface ValidatorState {
26     isPatternValid: boolean;
27     isLengthValid: boolean;
28 }
29
30 const nameRegEx = /^[a-zA-Z0-9-_ ]+$/;
31 const maxInputLength = 60;
32
33 export const Validator = withStyles(styles)(
34     class extends React.Component<ValidatorProps & WithStyles<CssRules>> {
35         state: ValidatorState = {
36             isPatternValid: true,
37             isLengthValid: true
38         };
39
40         componentWillReceiveProps(nextProps: ValidatorProps) {
41             const { value } = nextProps;
42
43             if (this.props.value !== value) {
44                 this.setState({
45                     isPatternValid: value.match(nameRegEx),
46                     isLengthValid: value.length < maxInputLength
47                 }, () => this.onChange());
48             }
49         }
50
51         onChange() {
52             const { value, onChange, isRequired } = this.props;
53             const { isPatternValid, isLengthValid } = this.state;
54             const isValid = value && isPatternValid && isLengthValid && (isRequired || (!isRequired && value.length > 0));
55
56             onChange(isValid);
57         }
58
59         render() {
60             const { classes, isRequired, value } = this.props;
61             const { isPatternValid, isLengthValid } = this.state;
62
63             return (
64                 <span>
65             {this.props.render(!(isPatternValid && isLengthValid) && (isRequired || (!isRequired && value.length > 0)))}
66                     {!isPatternValid && (isRequired || (!isRequired && value.length > 0)) ?
67                         <span className={classes.formInputError}>This field allow only alphanumeric characters, dashes, spaces and underscores.<br/></span> : null}
68                     {!isLengthValid ?
69                         <span className={classes.formInputError}>This field should have max 60 characters.</span> : null}
70           </span>
71             );
72         }
73     }
74 );