[ARVADOS-WORKBENCH2] updated: 1.1.4-248-gba19588

Git user git at public.curoverse.com
Tue Jul 10 06:40:50 EDT 2018


Summary of changes:
 .../dialog-create/dialog-project-create.tsx        |  69 -----------
 src/utils/dialog-validator.tsx                     |  72 +++++++++++
 .../create-project-dialog.tsx                      |   2 +-
 .../dialog-create/dialog-project-create.tsx        | 132 +++++++++++++++++++++
 src/views/project-panel/project-panel.tsx          |   2 +-
 5 files changed, 206 insertions(+), 71 deletions(-)
 delete mode 100644 src/components/dialog-create/dialog-project-create.tsx
 create mode 100644 src/utils/dialog-validator.tsx
 create mode 100644 src/views-components/dialog-create/dialog-project-create.tsx

       via  ba1958858cbb152de49946cf7c1c8ce923eb628a (commit)
       via  3429b49bb9ff70db11f3239c7fbbc03ac7c2e460 (commit)
      from  5114536622bd9abf5bd729629b9249ccd11fd3ce (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit ba1958858cbb152de49946cf7c1c8ce923eb628a
Merge: 3429b49 5114536
Author: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>
Date:   Tue Jul 10 12:40:40 2018 +0200

    merge conficts
    
    Feature #13694
    
    Arvados-DCO-1.1-Signed-off-by: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>

diff --cc src/views-components/create-project-dialog/create-project-dialog.tsx
index 0000000,d97eebc..c7a7852
mode 000000,100644..100644
--- a/src/views-components/create-project-dialog/create-project-dialog.tsx
+++ b/src/views-components/create-project-dialog/create-project-dialog.tsx
@@@ -1,0 -1,21 +1,21 @@@
+ // Copyright (C) The Arvados Authors. All rights reserved.
+ //
+ // SPDX-License-Identifier: AGPL-3.0
+ 
+ import { connect } from "react-redux";
+ import { Dispatch } from "../../../node_modules/redux";
+ import { RootState } from "../../store/store";
 -import DialogProjectCreate from "../../components/dialog-create/dialog-project-create";
++import DialogProjectCreate from "../dialog-create/dialog-project-create";
+ import actions from "../../store/project/project-action";
+ 
+ const mapStateToProps = (state: RootState) => ({
+     open: state.projects.creator.opened
+ });
+ 
+ const mapDispatchToProps = (dispatch: Dispatch) => ({
+     handleClose: () => {
+         dispatch(actions.CLOSE_PROJECT_CREATOR());
+     }
+ });
+ 
+ export default connect(mapStateToProps, mapDispatchToProps)(DialogProjectCreate);
diff --cc src/views-components/dialog-create/dialog-project-create.tsx
index 4cdf746,0000000..475f837
mode 100644,000000..100644
--- a/src/views-components/dialog-create/dialog-project-create.tsx
+++ b/src/views-components/dialog-create/dialog-project-create.tsx
@@@ -1,135 -1,0 +1,132 @@@
 +// Copyright (C) The Arvados Authors. All rights reserved.
 +//
 +// SPDX-License-Identifier: AGPL-3.0
 +
 +import * as React from 'react';
 +import TextField from '@material-ui/core/TextField';
 +import Dialog from '@material-ui/core/Dialog';
 +import DialogActions from '@material-ui/core/DialogActions';
 +import DialogContent from '@material-ui/core/DialogContent';
 +import DialogTitle from '@material-ui/core/DialogTitle';
 +import { Button, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
 +
 +import Validator from '../../utils/dialog-validator';
 +
 +interface ProjectCreateProps {
 +  open: boolean;
 +  handleClose: () => void;
 +}
 +
 +interface DialogState {
 +  name: string;
 +  description: string;
 +  isNameValid: boolean;
 +  isDescriptionValid: boolean;
 +}
 +
 +class DialogProjectCreate extends React.Component<ProjectCreateProps & WithStyles<CssRules>> {
 +  state: DialogState = {
 +    name: '',
 +    description: '',
-     isNameValid: true,
++    isNameValid: false,
 +    isDescriptionValid: true
 +  };
 +
 +  render() {
 +    const { name, description } = this.state;
 +    const { classes, open, handleClose } = this.props;
 +
 +    return (
 +      <Dialog
 +        open={open}
 +        onClose={handleClose}>
 +        <div className={classes.dialog}>
 +          <DialogTitle id="form-dialog-title" className={classes.dialogTitle}>Create a project</DialogTitle>
 +          <DialogContent className={classes.dialogContent}>
 +            <Validator
 +              value={name}
 +              onChange={e => this.isNameValid(e)}
 +              isRequired={true}
 +              render={hasError =>
 +                <TextField
 +                  margin="dense"
 +                  className={classes.textField}
 +                  id="name"
 +                  onChange={e => this.handleProjectName(e)}
 +                  label="Project name"
 +                  error={hasError}
 +                  fullWidth />} />
 +            <Validator
 +              value={description}
 +              onChange={e => this.isDescriptionValid(e)}
 +              isRequired={false}
 +              render={hasError =>
 +                <TextField
 +                  margin="dense"
 +                  className={classes.textField}
 +                  id="description"
 +                  onChange={e => this.handleDescriptionValue(e)}
 +                  label="Description - optional"
 +                  error={hasError}
 +                  fullWidth />} />
 +          </DialogContent>
-           <DialogActions className={classes.dialogActions}>
++          <DialogActions>
 +            <Button onClick={handleClose} className={classes.button} color="primary">CANCEL</Button>
 +            <Button onClick={handleClose} className={classes.lastButton} color="primary" disabled={!this.state.isNameValid || (!this.state.isDescriptionValid && description.length > 0)} variant="raised">CREATE A PROJECT</Button>
 +          </DialogActions>
 +        </div>
 +      </Dialog>
 +    );
 +  }
 +
 +  handleProjectName(e: any) {
 +    this.setState({
 +      name: e.target.value,
 +    });
 +  }
 +
 +  handleDescriptionValue(e: any) {
 +    this.setState({
 +      description: e.target.value,
 +    });
 +  }
 +
 +  isNameValid(value: boolean | string) {
 +    this.setState({
 +      isNameValid: value,
 +    });
 +  }
 +
 +  isDescriptionValid(value: boolean | string) {
 +    this.setState({
 +      isDescriptionValid: value,
 +    });
 +  }
 +}
 +
- type CssRules = "button" | "lastButton" | "dialogContent" | "textField" | "dialog" | "dialogTitle" | "dialogActions";
++type CssRules = "button" | "lastButton" | "dialogContent" | "textField" | "dialog" | "dialogTitle";
 +
 +const styles: StyleRulesCallback<CssRules> = theme => ({
 +  button: {
 +    marginLeft: theme.spacing.unit
 +  },
 +  lastButton: {
 +    marginLeft: theme.spacing.unit,
 +    marginRight: "20px",
 +  },
 +  dialogContent: {
 +    marginTop: "20px",
 +  },
 +  dialogTitle: {
 +    paddingBottom: "0"
 +  },
-   dialogActions: {
-     marginBottom: "5px"
-   },
 +  textField: {
 +    marginTop: "32px",
 +  },
 +  dialog: {
 +    minWidth: "600px",
 +    minHeight: "320px"
 +  }
 +});
 +
 +export default withStyles(styles)(DialogProjectCreate);

commit 3429b49bb9ff70db11f3239c7fbbc03ac7c2e460
Author: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>
Date:   Tue Jul 10 12:30:43 2018 +0200

    validation-for-dialog
    
    Feature #13694
    
    Arvados-DCO-1.1-Signed-off-by: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>

diff --git a/src/components/dialog-create/dialog-project-create.tsx b/src/components/dialog-create/dialog-project-create.tsx
deleted file mode 100644
index dd8c7d1..0000000
--- a/src/components/dialog-create/dialog-project-create.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import * as React from 'react';
-import TextField from '@material-ui/core/TextField';
-import Dialog from '@material-ui/core/Dialog';
-import DialogActions from '@material-ui/core/DialogActions';
-import DialogContent from '@material-ui/core/DialogContent';
-import DialogTitle from '@material-ui/core/DialogTitle';
-import { Button, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
-
-interface ProjectCreateProps {
-  open: boolean;
-  handleClose: () => void;
-}
-
-const DialogProjectCreate: React.SFC<ProjectCreateProps & WithStyles<CssRules>> = ({ classes, open, handleClose }) => {
-  return (
-    <Dialog
-      open={open}
-      onClose={handleClose}>
-      <div className={classes.dialog}>
-        <DialogTitle id="form-dialog-title">Create a project</DialogTitle>
-        <DialogContent className={classes.dialogContent}>
-          <TextField
-            margin="dense"
-            className={classes.textField}
-            id="name"
-            label="Project name"
-            fullWidth />
-          <TextField
-            margin="dense"
-            id="description"
-            label="Description - optional"
-            fullWidth />
-        </DialogContent>
-        <DialogActions>
-          <Button onClick={handleClose} className={classes.button} color="primary">CANCEL</Button>
-          <Button onClick={handleClose} className={classes.lastButton} color="primary" variant="raised">CREATE A PROJECT</Button>
-        </DialogActions>
-      </div>
-    </Dialog>
-  );
-};
-
-type CssRules = "button" | "lastButton" | "dialogContent" | "textField" | "dialog";
-
-const styles: StyleRulesCallback<CssRules> = theme => ({
-  button: {
-    marginLeft: theme.spacing.unit
-  },
-  lastButton: {
-    marginLeft: theme.spacing.unit,
-    marginRight: "20px",
-  },
-  dialogContent: {
-    marginTop: "20px",
-  },
-  textField: {
-    marginBottom: "32px",
-  },
-  dialog: {
-    minWidth: "550px",
-    minHeight: "320px"
-  }
-});
-
-export default withStyles(styles)(DialogProjectCreate);
\ No newline at end of file
diff --git a/src/utils/dialog-validator.tsx b/src/utils/dialog-validator.tsx
new file mode 100644
index 0000000..1d1a921
--- /dev/null
+++ b/src/utils/dialog-validator.tsx
@@ -0,0 +1,72 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+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;
+};
+
+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());
+    }
+  }
+
+  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>
+    );
+  }
+}
+
+type CssRules = "formInputError";
+
+const styles: StyleRulesCallback<CssRules> = theme => ({
+  formInputError: {
+    color: "#ff0000",
+    marginLeft: "5px",
+    fontSize: "11px",
+  }
+});
+
+export default withStyles(styles)(Validator);
\ No newline at end of file
diff --git a/src/views-components/dialog-create/dialog-project-create.tsx b/src/views-components/dialog-create/dialog-project-create.tsx
new file mode 100644
index 0000000..4cdf746
--- /dev/null
+++ b/src/views-components/dialog-create/dialog-project-create.tsx
@@ -0,0 +1,135 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import TextField from '@material-ui/core/TextField';
+import Dialog from '@material-ui/core/Dialog';
+import DialogActions from '@material-ui/core/DialogActions';
+import DialogContent from '@material-ui/core/DialogContent';
+import DialogTitle from '@material-ui/core/DialogTitle';
+import { Button, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
+
+import Validator from '../../utils/dialog-validator';
+
+interface ProjectCreateProps {
+  open: boolean;
+  handleClose: () => void;
+}
+
+interface DialogState {
+  name: string;
+  description: string;
+  isNameValid: boolean;
+  isDescriptionValid: boolean;
+}
+
+class DialogProjectCreate extends React.Component<ProjectCreateProps & WithStyles<CssRules>> {
+  state: DialogState = {
+    name: '',
+    description: '',
+    isNameValid: true,
+    isDescriptionValid: true
+  };
+
+  render() {
+    const { name, description } = this.state;
+    const { classes, open, handleClose } = this.props;
+
+    return (
+      <Dialog
+        open={open}
+        onClose={handleClose}>
+        <div className={classes.dialog}>
+          <DialogTitle id="form-dialog-title" className={classes.dialogTitle}>Create a project</DialogTitle>
+          <DialogContent className={classes.dialogContent}>
+            <Validator
+              value={name}
+              onChange={e => this.isNameValid(e)}
+              isRequired={true}
+              render={hasError =>
+                <TextField
+                  margin="dense"
+                  className={classes.textField}
+                  id="name"
+                  onChange={e => this.handleProjectName(e)}
+                  label="Project name"
+                  error={hasError}
+                  fullWidth />} />
+            <Validator
+              value={description}
+              onChange={e => this.isDescriptionValid(e)}
+              isRequired={false}
+              render={hasError =>
+                <TextField
+                  margin="dense"
+                  className={classes.textField}
+                  id="description"
+                  onChange={e => this.handleDescriptionValue(e)}
+                  label="Description - optional"
+                  error={hasError}
+                  fullWidth />} />
+          </DialogContent>
+          <DialogActions className={classes.dialogActions}>
+            <Button onClick={handleClose} className={classes.button} color="primary">CANCEL</Button>
+            <Button onClick={handleClose} className={classes.lastButton} color="primary" disabled={!this.state.isNameValid || (!this.state.isDescriptionValid && description.length > 0)} variant="raised">CREATE A PROJECT</Button>
+          </DialogActions>
+        </div>
+      </Dialog>
+    );
+  }
+
+  handleProjectName(e: any) {
+    this.setState({
+      name: e.target.value,
+    });
+  }
+
+  handleDescriptionValue(e: any) {
+    this.setState({
+      description: e.target.value,
+    });
+  }
+
+  isNameValid(value: boolean | string) {
+    this.setState({
+      isNameValid: value,
+    });
+  }
+
+  isDescriptionValid(value: boolean | string) {
+    this.setState({
+      isDescriptionValid: value,
+    });
+  }
+}
+
+type CssRules = "button" | "lastButton" | "dialogContent" | "textField" | "dialog" | "dialogTitle" | "dialogActions";
+
+const styles: StyleRulesCallback<CssRules> = theme => ({
+  button: {
+    marginLeft: theme.spacing.unit
+  },
+  lastButton: {
+    marginLeft: theme.spacing.unit,
+    marginRight: "20px",
+  },
+  dialogContent: {
+    marginTop: "20px",
+  },
+  dialogTitle: {
+    paddingBottom: "0"
+  },
+  dialogActions: {
+    marginBottom: "5px"
+  },
+  textField: {
+    marginTop: "32px",
+  },
+  dialog: {
+    minWidth: "600px",
+    minHeight: "320px"
+  }
+});
+
+export default withStyles(styles)(DialogProjectCreate);
\ No newline at end of file
diff --git a/src/views/project-panel/project-panel.tsx b/src/views/project-panel/project-panel.tsx
index f1b8235..b7c8b95 100644
--- a/src/views/project-panel/project-panel.tsx
+++ b/src/views/project-panel/project-panel.tsx
@@ -4,7 +4,7 @@
 
 import * as React from 'react';
 import { ProjectPanelItem } from './project-panel-item';
-import { Grid, Typography, Button, Toolbar, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
+import { Grid, Typography, Button, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
 import { formatDate, formatFileSize } from '../../common/formatters';
 import DataExplorer from "../../views-components/data-explorer/data-explorer";
 import { DispatchProp, connect } from 'react-redux';
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index 9c1336c..3ca9acc 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -29,7 +29,7 @@ import DetailsPanel from '../../views-components/details-panel/details-panel';
 import { ArvadosTheme } from '../../common/custom-theme';
 import ContextMenu, { ContextMenuAction } from '../../components/context-menu/context-menu';
 import { mockAnchorFromMouseEvent } from '../../components/popover/helpers';
-import DialogProjectCreate from '../../components/dialog-create/dialog-project-create';
+import DialogProjectCreate from '../../views-components/dialog-create/dialog-project-create';
 
 const drawerWidth = 240;
 const appBarHeight = 100;

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list