redux-form-validation
[arvados-workbench2.git] / src / utils / dialog-validator.tsx
index 1d1a9214bdcb9e3647504ca2e945969628cd5c7b..42a22e1c75baf40486175a19042be3e1363d6922 100644 (file)
@@ -6,67 +6,45 @@ import * as React from 'react';
 import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
 
 type ValidatorProps = {
-  value: string,
-  onChange: (isValid: boolean | string) => void;
-  render: (hasError: boolean) => React.ReactElement<any>;
-  isRequired: boolean;
+    value: string,
+    render: (hasError: boolean) => React.ReactElement<any>;
+    isUniqName?: boolean;
+    validators: Array<(value: string) => string>;
 };
 
-interface ValidatorState {
-  isPatternValid: boolean;
-  isLengthValid: boolean;
-}
-
-const nameRegEx = /^[a-zA-Z0-9-_ ]+$/;
-const maxInputLength = 60;
-
 class Validator extends React.Component<ValidatorProps & WithStyles<CssRules>> {
-  state: ValidatorState = {
-    isPatternValid: true,
-    isLengthValid: true
-  };
-
-  componentWillReceiveProps(nextProps: ValidatorProps) {
-    const { value } = nextProps;
-
-    if (this.props.value !== value) {
-      this.setState({
-        isPatternValid: value.match(nameRegEx),
-        isLengthValid: value.length < maxInputLength
-      }, () => this.onChange());
+    render() {
+        const { classes, value, isUniqName } = this.props;
+
+        return (
+            <span>
+                {this.props.render(!this.isValid(value))}
+                {isUniqName ? <span className={classes.formInputError}>Project with this name already exists</span> : null}
+                {this.props.validators.map(validate => {
+                    const errorMsg = validate(value);
+                    return errorMsg ? <span className={classes.formInputError}>{errorMsg}</span> : null;
+                })}
+            </span>
+        );
     }
-  }
-
-  onChange() {
-    const { value, onChange, isRequired } = this.props;
-    const { isPatternValid, isLengthValid } = this.state;
-    const isValid = value && isPatternValid && isLengthValid && (isRequired || (!isRequired && value.length > 0));
 
-    onChange(isValid);
-  }
-
-  render() {
-    const { classes, isRequired, value } = this.props;
-    const { isPatternValid, isLengthValid } = this.state;
-
-    return (
-      <span>
-        {this.props.render(!(isPatternValid && isLengthValid) && (isRequired || (!isRequired && value.length > 0)))}
-        {!isPatternValid && (isRequired || (!isRequired && value.length > 0)) ? <span className={classes.formInputError}>This field allow only alphanumeric characters, dashes, spaces and underscores.<br /></span> : null}
-        {!isLengthValid ? <span className={classes.formInputError}>This field should have max 60 characters.</span> : null}
-      </span>
-    );
-  }
+    isValid(value: string) {
+        return this.props.validators.every(validate => validate(value).length === 0);
+    }
 }
 
+export const required = (value: string) => value.length > 0 ? "" : "This value is required";
+export const maxLength = (max: number) => (value: string) => value.length <= max ? "" : `This field should have max ${max} characters.`;
+export const isUniq = (getError: () => string) => (value: string) => getError() ? "Project with this name already exists" : "";
+
 type CssRules = "formInputError";
 
 const styles: StyleRulesCallback<CssRules> = theme => ({
-  formInputError: {
-    color: "#ff0000",
-    marginLeft: "5px",
-    fontSize: "11px",
-  }
+    formInputError: {
+        color: "#ff0000",
+        marginLeft: "5px",
+        fontSize: "11px",
+    }
 });
 
 export default withStyles(styles)(Validator);
\ No newline at end of file