summaryrefslogtreecommitdiffstats
path: root/devtools/client/aboutdebugging/src/components/connect
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/aboutdebugging/src/components/connect')
-rw-r--r--devtools/client/aboutdebugging/src/components/connect/ConnectPage.css50
-rw-r--r--devtools/client/aboutdebugging/src/components/connect/ConnectPage.js315
-rw-r--r--devtools/client/aboutdebugging/src/components/connect/ConnectSection.css50
-rw-r--r--devtools/client/aboutdebugging/src/components/connect/ConnectSection.js69
-rw-r--r--devtools/client/aboutdebugging/src/components/connect/ConnectSteps.css13
-rw-r--r--devtools/client/aboutdebugging/src/components/connect/ConnectSteps.js51
-rw-r--r--devtools/client/aboutdebugging/src/components/connect/NetworkLocationsForm.css23
-rw-r--r--devtools/client/aboutdebugging/src/components/connect/NetworkLocationsForm.js148
-rw-r--r--devtools/client/aboutdebugging/src/components/connect/NetworkLocationsList.css20
-rw-r--r--devtools/client/aboutdebugging/src/components/connect/NetworkLocationsList.js67
-rw-r--r--devtools/client/aboutdebugging/src/components/connect/moz.build11
11 files changed, 817 insertions, 0 deletions
diff --git a/devtools/client/aboutdebugging/src/components/connect/ConnectPage.css b/devtools/client/aboutdebugging/src/components/connect/ConnectPage.css
new file mode 100644
index 0000000000..a693bf4113
--- /dev/null
+++ b/devtools/client/aboutdebugging/src/components/connect/ConnectPage.css
@@ -0,0 +1,50 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+.connect-page__breather {
+ margin-block-start: calc(var(--base-unit) * 6);
+}
+
+/*
+ * +--------+----------------------+
+ * | USB | |<button> |
+ * +--------+ | |
+ * | status | | |
+ * +--------+----------------------+
+ */
+.connect-page__usb-section__heading {
+ display: grid;
+ align-items: center;
+ grid-template-areas: "title . toggle"
+ "status . toggle";
+ grid-template-columns: auto 1fr auto;
+ grid-column-gap: calc(var(--base-unit) * 2);
+ grid-row-gap: var(--base-unit);
+}
+
+.connect-page__usb-section__heading__toggle {
+ grid-area: toggle;
+}
+
+.connect-page__usb-section__heading__title {
+ grid-area: title;
+ line-height: 1;
+}
+.connect-page__usb-section__heading__status {
+ grid-area: status;
+ line-height: 1;
+ font-size: var(--caption-20-font-size);
+ font-weight: var(--caption-20-font-weight);
+ color: var(--secondary-text-color);
+}
+
+.connect-page__troubleshoot {
+ font-size: var(--body-10-font-size);
+ font-weight: var(--body-10-font-weight);
+ margin-block-start: calc(var(--base-unit) * 2);
+}
+
+.connect-page__troubleshoot--network {
+ padding-inline: calc(var(--base-unit) * 6);
+}
diff --git a/devtools/client/aboutdebugging/src/components/connect/ConnectPage.js b/devtools/client/aboutdebugging/src/components/connect/ConnectPage.js
new file mode 100644
index 0000000000..97b1b01df7
--- /dev/null
+++ b/devtools/client/aboutdebugging/src/components/connect/ConnectPage.js
@@ -0,0 +1,315 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const {
+ createFactory,
+ PureComponent,
+} = require("resource://devtools/client/shared/vendor/react.js");
+const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
+const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js");
+
+const FluentReact = require("resource://devtools/client/shared/vendor/fluent-react.js");
+const Localized = createFactory(FluentReact.Localized);
+
+const {
+ USB_STATES,
+} = require("resource://devtools/client/aboutdebugging/src/constants.js");
+
+const Actions = require("resource://devtools/client/aboutdebugging/src/actions/index.js");
+
+loader.lazyRequireGetter(
+ this,
+ "ADB_ADDON_STATES",
+ "resource://devtools/client/shared/remote-debugging/adb/adb-addon.js",
+ true
+);
+
+const Link = createFactory(
+ require("resource://devtools/client/shared/vendor/react-router-dom.js").Link
+);
+const ConnectSection = createFactory(
+ require("resource://devtools/client/aboutdebugging/src/components/connect/ConnectSection.js")
+);
+const ConnectSteps = createFactory(
+ require("resource://devtools/client/aboutdebugging/src/components/connect/ConnectSteps.js")
+);
+const NetworkLocationsForm = createFactory(
+ require("resource://devtools/client/aboutdebugging/src/components/connect/NetworkLocationsForm.js")
+);
+const NetworkLocationsList = createFactory(
+ require("resource://devtools/client/aboutdebugging/src/components/connect/NetworkLocationsList.js")
+);
+
+const {
+ PAGE_TYPES,
+ RUNTIMES,
+} = require("resource://devtools/client/aboutdebugging/src/constants.js");
+const Types = require("resource://devtools/client/aboutdebugging/src/types/index.js");
+
+const USB_ICON_SRC =
+ "chrome://devtools/skin/images/aboutdebugging-usb-icon.svg";
+const GLOBE_ICON_SRC =
+ "chrome://devtools/skin/images/aboutdebugging-globe-icon.svg";
+
+const TROUBLESHOOT_USB_URL =
+ "https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-to-a-remote-device";
+const TROUBLESHOOT_NETWORK_URL =
+ "https://firefox-source-docs.mozilla.org/devtools-user/about_colon_debugging/index.html#connecting-over-the-network";
+
+class ConnectPage extends PureComponent {
+ static get propTypes() {
+ return {
+ adbAddonStatus: Types.adbAddonStatus,
+ dispatch: PropTypes.func.isRequired,
+ networkLocations: PropTypes.arrayOf(Types.location).isRequired,
+ };
+ }
+
+ // TODO: avoid the use of this method
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1774507
+ UNSAFE_componentWillMount() {
+ this.props.dispatch(Actions.selectPage(PAGE_TYPES.CONNECT));
+ }
+
+ onToggleUSBClick() {
+ const { adbAddonStatus } = this.props;
+ const isAddonInstalled = adbAddonStatus === ADB_ADDON_STATES.INSTALLED;
+ if (isAddonInstalled) {
+ this.props.dispatch(Actions.uninstallAdbAddon());
+ } else {
+ this.props.dispatch(Actions.installAdbAddon());
+ }
+ }
+
+ getUsbStatus() {
+ switch (this.props.adbAddonStatus) {
+ case ADB_ADDON_STATES.INSTALLED:
+ return USB_STATES.ENABLED_USB;
+ case ADB_ADDON_STATES.UNINSTALLED:
+ return USB_STATES.DISABLED_USB;
+ default:
+ return USB_STATES.UPDATING_USB;
+ }
+ }
+
+ renderUsbStatus() {
+ const statusTextId = {
+ [USB_STATES.ENABLED_USB]: "about-debugging-setup-usb-status-enabled",
+ [USB_STATES.DISABLED_USB]: "about-debugging-setup-usb-status-disabled",
+ [USB_STATES.UPDATING_USB]: "about-debugging-setup-usb-status-updating",
+ }[this.getUsbStatus()];
+
+ return Localized(
+ {
+ id: statusTextId,
+ },
+ dom.span(
+ {
+ className: "connect-page__usb-section__heading__status",
+ },
+ statusTextId
+ )
+ );
+ }
+
+ renderUsbToggleButton() {
+ const usbStatus = this.getUsbStatus();
+
+ const localizedStates = {
+ [USB_STATES.ENABLED_USB]: "about-debugging-setup-usb-disable-button",
+ [USB_STATES.DISABLED_USB]: "about-debugging-setup-usb-enable-button",
+ [USB_STATES.UPDATING_USB]: "about-debugging-setup-usb-updating-button",
+ };
+ const localizedState = localizedStates[usbStatus];
+
+ // Disable the button while the USB status is updating.
+ const disabled = usbStatus === USB_STATES.UPDATING_USB;
+
+ return Localized(
+ {
+ id: localizedState,
+ },
+ dom.button(
+ {
+ className:
+ "default-button connect-page__usb-section__heading__toggle " +
+ "qa-connect-usb-toggle-button",
+ disabled,
+ onClick: () => this.onToggleUSBClick(),
+ },
+ localizedState
+ )
+ );
+ }
+
+ renderUsb() {
+ const { adbAddonStatus } = this.props;
+ const isAddonInstalled = adbAddonStatus === ADB_ADDON_STATES.INSTALLED;
+ return ConnectSection(
+ {
+ icon: USB_ICON_SRC,
+ title: dom.div(
+ {
+ className: "connect-page__usb-section__heading",
+ },
+ Localized(
+ { id: "about-debugging-setup-usb-title" },
+ dom.span(
+ {
+ className: "connect-page__usb-section__heading__title",
+ },
+ "USB"
+ )
+ ),
+ this.renderUsbStatus(),
+ this.renderUsbToggleButton()
+ ),
+ },
+ isAddonInstalled
+ ? ConnectSteps({
+ steps: [
+ {
+ localizationId:
+ "about-debugging-setup-usb-step-enable-dev-menu2",
+ },
+ {
+ localizationId: "about-debugging-setup-usb-step-enable-debug2",
+ },
+ {
+ localizationId:
+ "about-debugging-setup-usb-step-enable-debug-firefox2",
+ },
+ {
+ localizationId: "about-debugging-setup-usb-step-plug-device",
+ },
+ ],
+ })
+ : Localized(
+ {
+ id: "about-debugging-setup-usb-disabled",
+ },
+ dom.aside(
+ {
+ className: "qa-connect-usb-disabled-message",
+ },
+ "Enabling this will download and add the required Android USB debugging " +
+ "components to Firefox."
+ )
+ ),
+ this.renderTroubleshootText(RUNTIMES.USB)
+ );
+ }
+
+ renderNetwork() {
+ const { dispatch, networkLocations } = this.props;
+
+ return Localized(
+ {
+ id: "about-debugging-setup-network",
+ attrs: { title: true },
+ },
+ ConnectSection({
+ icon: GLOBE_ICON_SRC,
+ title: "Network Location",
+ extraContent: dom.div(
+ {},
+ NetworkLocationsList({ dispatch, networkLocations }),
+ NetworkLocationsForm({ dispatch, networkLocations }),
+ this.renderTroubleshootText(RUNTIMES.NETWORK)
+ ),
+ })
+ );
+ }
+
+ renderTroubleshootText(connectionType) {
+ const localizationId =
+ connectionType === RUNTIMES.USB
+ ? "about-debugging-setup-usb-troubleshoot"
+ : "about-debugging-setup-network-troubleshoot";
+
+ const className =
+ "connect-page__troubleshoot connect-page__troubleshoot--" +
+ `${connectionType === RUNTIMES.USB ? "usb" : "network"}`;
+
+ const url =
+ connectionType === RUNTIMES.USB
+ ? TROUBLESHOOT_USB_URL
+ : TROUBLESHOOT_NETWORK_URL;
+
+ return dom.aside(
+ {
+ className,
+ },
+ Localized(
+ {
+ id: localizationId,
+ a: dom.a({
+ href: url,
+ target: "_blank",
+ }),
+ },
+ dom.p({}, localizationId)
+ )
+ );
+ }
+
+ render() {
+ return dom.article(
+ {
+ className: "page connect-page qa-connect-page",
+ },
+ Localized(
+ {
+ id: "about-debugging-setup-title",
+ },
+ dom.h1(
+ {
+ className: "alt-heading alt-heading--larger",
+ },
+ "Setup"
+ )
+ ),
+ Localized(
+ {
+ id: "about-debugging-setup-intro",
+ },
+ dom.p(
+ {},
+ "Configure the connection method you wish to remotely debug your device with."
+ )
+ ),
+ Localized(
+ {
+ id: "about-debugging-setup-this-firefox2",
+ a: Link({
+ to: `/runtime/${RUNTIMES.THIS_FIREFOX}`,
+ }),
+ },
+ dom.p({}, "about-debugging-setup-this-firefox")
+ ),
+ dom.section(
+ {
+ className: "connect-page__breather",
+ },
+ Localized(
+ {
+ id: "about-debugging-setup-connect-heading",
+ },
+ dom.h2(
+ {
+ className: "alt-heading",
+ },
+ "Connect a device"
+ )
+ ),
+ this.renderUsb(),
+ this.renderNetwork()
+ )
+ );
+ }
+}
+
+module.exports = FluentReact.withLocalization(ConnectPage);
diff --git a/devtools/client/aboutdebugging/src/components/connect/ConnectSection.css b/devtools/client/aboutdebugging/src/components/connect/ConnectSection.css
new file mode 100644
index 0000000000..4349b147b0
--- /dev/null
+++ b/devtools/client/aboutdebugging/src/components/connect/ConnectSection.css
@@ -0,0 +1,50 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+.connect-section {
+ --icon-size: calc(var(--base-unit) * 9);
+ --header-col-gap: calc(var(--base-unit) * 2);
+ margin-block-end: calc(var(--base-unit) * 4);
+}
+
+/*
+ * +--------+----------------+
+ * | <icon> | <heading> 1fr |
+ * +--------+----------------+
+ */
+.connect-section__header {
+ display: grid;
+ grid-template-areas: "icon heading";
+ grid-template-columns: auto 1fr;
+ grid-template-rows: var(--icon-size);
+ grid-column-gap: var(--header-col-gap);
+ align-items: center;
+
+ padding-block-end: calc(var(--base-unit) * 4);
+ padding-inline: calc(var(--base-unit) * 5);
+}
+
+.connect-section__header__title {
+ grid-area: heading;
+}
+
+.connect-section__header__icon {
+ grid-area: icon;
+ width: var(--icon-size);
+ height: var(--icon-size);
+
+ -moz-context-properties: fill;
+ fill: currentColor;
+}
+
+.connect-section__content {
+ line-height: 1.5;
+ padding-inline-start: calc(var(--base-unit) * 5
+ + var(--header-col-gap) + var(--icon-size));
+ padding-inline-end: calc(var(--base-unit) * 5);
+}
+
+.connect-section__extra {
+ border-block-start: 1px solid var(--card-separator-color);
+}
diff --git a/devtools/client/aboutdebugging/src/components/connect/ConnectSection.js b/devtools/client/aboutdebugging/src/components/connect/ConnectSection.js
new file mode 100644
index 0000000000..55f8eb4e78
--- /dev/null
+++ b/devtools/client/aboutdebugging/src/components/connect/ConnectSection.js
@@ -0,0 +1,69 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const {
+ PureComponent,
+} = require("resource://devtools/client/shared/vendor/react.js");
+const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
+const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js");
+
+class ConnectSection extends PureComponent {
+ static get propTypes() {
+ return {
+ children: PropTypes.node,
+ className: PropTypes.string,
+ extraContent: PropTypes.node,
+ icon: PropTypes.string.isRequired,
+ title: PropTypes.node.isRequired,
+ };
+ }
+
+ renderExtraContent() {
+ const { extraContent } = this.props;
+ return dom.section(
+ {
+ className: "connect-section__extra",
+ },
+ extraContent
+ );
+ }
+
+ render() {
+ const { extraContent } = this.props;
+
+ return dom.section(
+ {
+ className: `card connect-section ${this.props.className || ""}`,
+ },
+ dom.header(
+ {
+ className: "connect-section__header",
+ },
+ dom.img({
+ className: "connect-section__header__icon",
+ src: this.props.icon,
+ }),
+ dom.h1(
+ {
+ className: "card__heading connect-section__header__title",
+ },
+ this.props.title
+ )
+ ),
+ this.props.children
+ ? dom.div(
+ {
+ className: "connect-section__content",
+ },
+ this.props.children
+ )
+ : null,
+ extraContent ? this.renderExtraContent() : null
+ );
+ }
+}
+
+module.exports = ConnectSection;
diff --git a/devtools/client/aboutdebugging/src/components/connect/ConnectSteps.css b/devtools/client/aboutdebugging/src/components/connect/ConnectSteps.css
new file mode 100644
index 0000000000..bddd513aa7
--- /dev/null
+++ b/devtools/client/aboutdebugging/src/components/connect/ConnectSteps.css
@@ -0,0 +1,13 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+.connect-page__step-list {
+ list-style-type: decimal;
+ list-style-position: outside;
+ margin-inline-start: calc(var(--base-unit) * 4);
+}
+
+.connect-page__step {
+ padding-inline-start: var(--base-unit);
+}
diff --git a/devtools/client/aboutdebugging/src/components/connect/ConnectSteps.js b/devtools/client/aboutdebugging/src/components/connect/ConnectSteps.js
new file mode 100644
index 0000000000..0e8d304108
--- /dev/null
+++ b/devtools/client/aboutdebugging/src/components/connect/ConnectSteps.js
@@ -0,0 +1,51 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const {
+ PureComponent,
+ createFactory,
+} = require("resource://devtools/client/shared/vendor/react.js");
+const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
+const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js");
+
+const FluentReact = require("resource://devtools/client/shared/vendor/fluent-react.js");
+const Localized = createFactory(FluentReact.Localized);
+
+class ConnectSteps extends PureComponent {
+ static get propTypes() {
+ return {
+ steps: PropTypes.arrayOf(
+ PropTypes.shape({
+ localizationId: PropTypes.string.isRequired,
+ }).isRequired
+ ),
+ };
+ }
+
+ render() {
+ return dom.ul(
+ {
+ className: "connect-page__step-list",
+ },
+ ...this.props.steps.map(step =>
+ Localized(
+ {
+ id: step.localizationId,
+ },
+ dom.li(
+ {
+ className: "connect-page__step",
+ key: step.localizationId,
+ },
+ step.localizationId
+ )
+ )
+ )
+ );
+ }
+}
+
+module.exports = ConnectSteps;
diff --git a/devtools/client/aboutdebugging/src/components/connect/NetworkLocationsForm.css b/devtools/client/aboutdebugging/src/components/connect/NetworkLocationsForm.css
new file mode 100644
index 0000000000..5694bcf216
--- /dev/null
+++ b/devtools/client/aboutdebugging/src/components/connect/NetworkLocationsForm.css
@@ -0,0 +1,23 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Layout of a network location form
+ *
+ * +-------------+--------------------+------------+
+ * | "Host:port" | Input | Add button |
+ * +-------------+--------------------+------------+
+ */
+.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;
+}
diff --git a/devtools/client/aboutdebugging/src/components/connect/NetworkLocationsForm.js b/devtools/client/aboutdebugging/src/components/connect/NetworkLocationsForm.js
new file mode 100644
index 0000000000..347167921b
--- /dev/null
+++ b/devtools/client/aboutdebugging/src/components/connect/NetworkLocationsForm.js
@@ -0,0 +1,148 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const {
+ createFactory,
+ PureComponent,
+} = require("resource://devtools/client/shared/vendor/react.js");
+const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
+const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js");
+
+const FluentReact = require("resource://devtools/client/shared/vendor/fluent-react.js");
+const Localized = createFactory(FluentReact.Localized);
+
+const Message = createFactory(
+ require("resource://devtools/client/aboutdebugging/src/components/shared/Message.js")
+);
+
+const Actions = require("resource://devtools/client/aboutdebugging/src/actions/index.js");
+const {
+ MESSAGE_LEVEL,
+} = require("resource://devtools/client/aboutdebugging/src/constants.js");
+const Types = require("resource://devtools/client/aboutdebugging/src/types/index.js");
+
+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 " +
+ "qa-connect-page__network-form__error-message",
+ level: MESSAGE_LEVEL.ERROR,
+ isCloseable: true,
+ },
+ Localized(
+ {
+ id: errorMessageId,
+ "$host-value": errorHostValue,
+ },
+ dom.p(
+ {
+ className: "technical-text",
+ },
+ errorMessageId
+ )
+ )
+ );
+ }
+
+ render() {
+ return dom.form(
+ {
+ className: "connect-page__network-form",
+ 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",
+ },
+ "Host"
+ )
+ ),
+ dom.input({
+ id: "about-debugging-network-locations-host-input",
+ className: "default-input qa-network-form-input",
+ placeholder: "localhost:6080",
+ type: "text",
+ value: this.state.value,
+ onChange: e => {
+ const value = e.target.value;
+ this.setState({ value });
+ },
+ }),
+ Localized(
+ {
+ id: "about-debugging-network-locations-add-button",
+ },
+ dom.button(
+ {
+ className: "primary-button qa-network-form-submit-button",
+ },
+ "Add"
+ )
+ )
+ );
+ }
+}
+
+module.exports = NetworkLocationsForm;
diff --git a/devtools/client/aboutdebugging/src/components/connect/NetworkLocationsList.css b/devtools/client/aboutdebugging/src/components/connect/NetworkLocationsList.css
new file mode 100644
index 0000000000..e5676b784a
--- /dev/null
+++ b/devtools/client/aboutdebugging/src/components/connect/NetworkLocationsList.css
@@ -0,0 +1,20 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Layout of a network location item
+ *
+ * +-------------------------------------+---------------+
+ * | Location (eg localhost:8080) | Remove button |
+ * +-------------------------------------+---------------+
+ */
+.network-location {
+ display: grid;
+ grid-template-columns: auto max-content;
+ align-items: center;
+
+ padding-block: calc(var(--base-unit) * 2);
+ padding-inline: calc(var(--base-unit) * 6);
+ border-bottom: 1px solid var(--card-separator-color);
+}
diff --git a/devtools/client/aboutdebugging/src/components/connect/NetworkLocationsList.js b/devtools/client/aboutdebugging/src/components/connect/NetworkLocationsList.js
new file mode 100644
index 0000000000..e680fe525f
--- /dev/null
+++ b/devtools/client/aboutdebugging/src/components/connect/NetworkLocationsList.js
@@ -0,0 +1,67 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const {
+ createFactory,
+ PureComponent,
+} = require("resource://devtools/client/shared/vendor/react.js");
+const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
+const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js");
+
+const FluentReact = require("resource://devtools/client/shared/vendor/fluent-react.js");
+const Localized = createFactory(FluentReact.Localized);
+
+const Actions = require("resource://devtools/client/aboutdebugging/src/actions/index.js");
+const Types = require("resource://devtools/client/aboutdebugging/src/types/index.js");
+
+class NetworkLocationsList extends PureComponent {
+ static get propTypes() {
+ return {
+ dispatch: PropTypes.func.isRequired,
+ networkLocations: PropTypes.arrayOf(Types.location).isRequired,
+ };
+ }
+
+ renderList() {
+ return dom.ul(
+ {},
+ this.props.networkLocations.map(location =>
+ dom.li(
+ {
+ className: "network-location qa-network-location",
+ key: location,
+ },
+ dom.span(
+ {
+ className: "ellipsis-text qa-network-location-value",
+ },
+ location
+ ),
+ Localized(
+ {
+ id: "about-debugging-network-locations-remove-button",
+ },
+ dom.button(
+ {
+ className: "default-button qa-network-location-remove-button",
+ onClick: () => {
+ this.props.dispatch(Actions.removeNetworkLocation(location));
+ },
+ },
+ "Remove"
+ )
+ )
+ )
+ )
+ );
+ }
+
+ render() {
+ return this.props.networkLocations.length ? this.renderList() : null;
+ }
+}
+
+module.exports = NetworkLocationsList;
diff --git a/devtools/client/aboutdebugging/src/components/connect/moz.build b/devtools/client/aboutdebugging/src/components/connect/moz.build
new file mode 100644
index 0000000000..9228e80125
--- /dev/null
+++ b/devtools/client/aboutdebugging/src/components/connect/moz.build
@@ -0,0 +1,11 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DevToolsModules(
+ "ConnectPage.js",
+ "ConnectSection.js",
+ "ConnectSteps.js",
+ "NetworkLocationsForm.js",
+ "NetworkLocationsList.js",
+)