Bug 1488503: Validation for network location. r=jdescottes,flod
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Thu, 21 Mar 2019 11:17:04 +0000
changeset 465397 4354c226d3388236c307849644c135f9532f3d4a
parent 465396 d03df68738c80cce9182ea0113244633a42bca4e
child 465398 5841b4e9959374c8d594e50bf1141d36edb5ced8
push id35738
push userccoroiu@mozilla.com
push dateThu, 21 Mar 2019 21:59:09 +0000
treeherdermozilla-central@7eb8e627961c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes, flod
bugs1488503
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1488503: Validation for network location. r=jdescottes,flod Differential Revision: https://phabricator.services.mozilla.com/D23993
devtools/client/aboutdebugging-new/src/components/connect/ConnectPage.js
devtools/client/aboutdebugging-new/src/components/connect/NetworkLocationsForm.css
devtools/client/aboutdebugging-new/src/components/connect/NetworkLocationsForm.js
devtools/client/locales/en-US/aboutdebugging.ftl
--- a/devtools/client/aboutdebugging-new/src/components/connect/ConnectPage.js
+++ b/devtools/client/aboutdebugging-new/src/components/connect/ConnectPage.js
@@ -185,17 +185,17 @@ class ConnectPage extends PureComponent 
       },
       ConnectSection({
         className: "connect-page__breather",
         icon: GLOBE_ICON_SRC,
         title: "Network Location",
         extraContent: dom.div(
           {},
           NetworkLocationsList({ dispatch, networkLocations }),
-          NetworkLocationsForm({ dispatch }),
+          NetworkLocationsForm({ dispatch, networkLocations }),
         ),
       })
     );
   }
 
   render() {
     return dom.article(
       {
--- a/devtools/client/aboutdebugging-new/src/components/connect/NetworkLocationsForm.css
+++ b/devtools/client/aboutdebugging-new/src/components/connect/NetworkLocationsForm.css
@@ -12,8 +12,12 @@
 .connect-page__network-form {
   display: grid;
   grid-column-gap: calc(var(--base-unit) * 2);
   grid-template-columns: auto 1fr auto;
   align-items: center;
   padding-block-start: calc(var(--base-unit) * 4);
   padding-inline: calc(var(--base-unit) * 6);
 }
+
+.connect-page__network-form__error-message {
+  grid-column: 1 / -1;
+}
--- a/devtools/client/aboutdebugging-new/src/components/connect/NetworkLocationsForm.js
+++ b/devtools/client/aboutdebugging-new/src/components/connect/NetworkLocationsForm.js
@@ -6,45 +6,98 @@
 
 const { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
 const dom = require("devtools/client/shared/vendor/react-dom-factories");
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 
 const FluentReact = require("devtools/client/shared/vendor/fluent-react");
 const Localized = createFactory(FluentReact.Localized);
 
+const Message = createFactory(require("../shared/Message"));
+
 const Actions = require("../../actions/index");
+const { MESSAGE_LEVEL } = require("../../constants");
+const Types = require("../../types/index");
 
 class NetworkLocationsForm extends PureComponent {
   static get propTypes() {
     return {
       dispatch: PropTypes.func.isRequired,
+      networkLocations: PropTypes.arrayOf(Types.location).isRequired,
     };
   }
 
   constructor(props) {
     super(props);
     this.state = {
+      errorHostValue: null,
+      errorMessageId: null,
       value: "",
     };
   }
 
+  onSubmit(e) {
+    const { networkLocations } = this.props;
+    const { value } = this.state;
+
+    e.preventDefault();
+
+    if (!value) {
+      return;
+    }
+
+    if (!value.match(/[^:]+:\d+/)) {
+      this.setState({
+        errorHostValue: value,
+        errorMessageId: "about-debugging-network-location-form-invalid",
+      });
+      return;
+    }
+
+    if (networkLocations.includes(value)) {
+      this.setState({
+        errorHostValue: value,
+        errorMessageId: "about-debugging-network-location-form-duplicate",
+      });
+      return;
+    }
+
+    this.props.dispatch(Actions.addNetworkLocation(value));
+    this.setState({ errorHostValue: null, errorMessageId: null, value: "" });
+  }
+
+  renderError() {
+    const { errorHostValue, errorMessageId } = this.state;
+
+    if (!errorMessageId) {
+      return null;
+    }
+
+    return Message(
+      {
+        className: "connect-page__network-form__error-message",
+        level: MESSAGE_LEVEL.ERROR,
+      },
+      Localized(
+        {
+          id: errorMessageId,
+          "$host-value": errorHostValue,
+        },
+        dom.p({}, errorMessageId)
+      ),
+    );
+  }
+
   render() {
     return dom.form(
       {
         className: "connect-page__network-form",
-        onSubmit: (e) => {
-          const { value } = this.state;
-          if (value) {
-            this.props.dispatch(Actions.addNetworkLocation(value));
-            this.setState({ value: "" });
-          }
-          e.preventDefault();
-        },
+        onSubmit: (e) => this.onSubmit(e),
       },
+      this.renderError(),
       Localized(
         {
           id: "about-debugging-network-locations-host-input-label",
         },
         dom.label(
           {
             htmlFor: "about-debugging-network-locations-host-input",
           },
@@ -67,14 +120,14 @@ class NetworkLocationsForm extends PureC
           id: "about-debugging-network-locations-add-button",
         },
         dom.button(
           {
             className: "primary-button js-network-form-submit-button",
           },
           "Add"
         )
-      )
+      ),
     );
   }
 }
 
 module.exports = NetworkLocationsForm;
--- a/devtools/client/locales/en-US/aboutdebugging.ftl
+++ b/devtools/client/locales/en-US/aboutdebugging.ftl
@@ -134,16 +134,26 @@ about-debugging-network-locations-empty-
 # the Connect page. A host is a hostname and a port separated by a colon, as suggested by
 # the input's placeholder "localhost:6080".
 about-debugging-network-locations-host-input-label = Host
 
 # Text of a button displayed next to existing network locations in the Connect page.
 # Clicking on it removes the network location from the list.
 about-debugging-network-locations-remove-button = Remove
 
+# Text used as error message if the format of the input value was invalid in the network locations form of the Setup page.
+# Variables:
+#   $host-value (string) - The input value submitted by the user in the network locations form
+about-debugging-network-location-form-invalid = Invalid host “{ $host-value }”. The expected format is “hostname:portnumber”.
+
+# Text used as error message if the input value was already registered in the network locations form of the Setup page.
+# Variables:
+#   $host-value (string) - The input value submitted by the user in the network locations form
+about-debugging-network-location-form-duplicate = The host “{ $host-value }” is already registered
+
 # Runtime Page strings
 
 # Below are the titles for the various categories of debug targets that can be found
 # on "runtime" pages of about:debugging.
 # Title of the temporary extensions category (only available for "This Firefox" runtime).
 about-debugging-runtime-temporary-extensions =
   .name = Temporary Extensions
 # Title of the extensions category.