diff options
Diffstat (limited to 'devtools/client/responsive/components/DeviceForm.js')
-rw-r--r-- | devtools/client/responsive/components/DeviceForm.js | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/devtools/client/responsive/components/DeviceForm.js b/devtools/client/responsive/components/DeviceForm.js new file mode 100644 index 0000000000..656f846d33 --- /dev/null +++ b/devtools/client/responsive/components/DeviceForm.js @@ -0,0 +1,231 @@ +/* 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/. */ + +/* eslint-env browser */ + +"use strict"; + +const { + createFactory, + createRef, + 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 ViewportDimension = createFactory( + require("resource://devtools/client/responsive/components/ViewportDimension.js") +); + +const { + getStr, +} = require("resource://devtools/client/responsive/utils/l10n.js"); +const Types = require("resource://devtools/client/responsive/types.js"); + +class DeviceForm extends PureComponent { + static get propTypes() { + return { + formType: PropTypes.string.isRequired, + device: PropTypes.shape(Types.device).isRequired, + devices: PropTypes.shape(Types.devices).isRequired, + onSave: PropTypes.func.isRequired, + viewportTemplate: PropTypes.shape(Types.viewport).isRequired, + onDeviceFormHide: PropTypes.func.isRequired, + }; + } + + constructor(props) { + super(props); + + const { height, width } = this.props.viewportTemplate; + + this.state = { + height, + width, + }; + + this.nameInputRef = createRef(); + this.pixelRatioInputRef = createRef(); + this.touchInputRef = createRef(); + this.userAgentInputRef = createRef(); + + this.onChangeSize = this.onChangeSize.bind(this); + this.onDeviceFormHide = this.onDeviceFormHide.bind(this); + this.onDeviceFormSave = this.onDeviceFormSave.bind(this); + this.onInputFocus = this.onInputFocus.bind(this); + this.validateNameField = this.validateNameField.bind(this); + } + + onChangeSize(_, width, height) { + this.setState({ + width, + height, + }); + } + + onDeviceFormSave(e) { + e.preventDefault(); + + if (!this.pixelRatioInputRef.current.checkValidity()) { + return; + } + + if ( + !this.validateNameField( + this.nameInputRef.current.value, + this.props.device + ) + ) { + this.nameInputRef.current.setCustomValidity( + getStr("responsive.deviceNameAlreadyInUse") + ); + return; + } + + this.props.onSave({ + name: this.nameInputRef.current.value.trim(), + width: this.state.width, + height: this.state.height, + pixelRatio: parseFloat(this.pixelRatioInputRef.current.value), + userAgent: this.userAgentInputRef.current.value, + touch: this.touchInputRef.current.checked, + }); + + this.onDeviceFormHide(); + } + + onDeviceFormHide() { + // Ensure that we have onDeviceFormHide before calling it. + if (this.props.onDeviceFormHide) { + this.props.onDeviceFormHide(); + } + } + + onInputFocus(e) { + // If the formType is "add", select all text in input field when focused. + if (this.props.formType === "add") { + e.target.select(); + } + } + + /** + * Validates the name field's value. + * + * @param {String} value + * The input field value for the device name. + * @return {Boolean} true if device name is valid, false otherwise. + */ + validateNameField(value) { + const nameFieldValue = value.trim(); + let isValidDeviceName = false; + + // If the formType is "add", then we just need to check if a custom device with that + // same name exists. + if (this.props.formType === "add") { + isValidDeviceName = !this.props.devices.custom.find( + device => device.name == nameFieldValue + ); + } else { + // Otherwise, the formType is "edit". We'd have to find another device that + // already has the same name, but not itself, so: + // Find the index of the device being edited. Use this index value to distinguish + // between the device being edited from other devices in the list. + const deviceIndex = this.props.devices.custom.findIndex(({ name }) => { + return name === this.props.device.name; + }); + + isValidDeviceName = !this.props.devices.custom.find((d, index) => { + return d.name === nameFieldValue && index !== deviceIndex; + }); + } + + return isValidDeviceName; + } + + render() { + const { device, formType } = this.props; + const { width, height } = this.state; + + return dom.form( + { id: "device-form" }, + dom.label( + { id: "device-form-name" }, + dom.span( + { className: "device-form-label" }, + getStr("responsive.deviceAdderName") + ), + dom.input({ + defaultValue: device.name, + ref: this.nameInputRef, + onFocus: this.onInputFocus, + }) + ), + dom.label( + { id: "device-form-size" }, + dom.span( + { className: "device-form-label" }, + getStr("responsive.deviceAdderSize") + ), + ViewportDimension({ + viewport: { width, height }, + doResizeViewport: this.onChangeSize, + onRemoveDeviceAssociation: () => {}, + }) + ), + dom.label( + { id: "device-form-pixel-ratio" }, + dom.span( + { className: "device-form-label" }, + getStr("responsive.deviceAdderPixelRatio2") + ), + dom.input({ + type: "number", + step: "any", + defaultValue: device.pixelRatio, + ref: this.pixelRatioInputRef, + onFocus: this.onInputFocus, + }) + ), + dom.label( + { id: "device-form-user-agent" }, + dom.span( + { className: "device-form-label" }, + getStr("responsive.deviceAdderUserAgent2") + ), + dom.input({ + defaultValue: device.userAgent, + ref: this.userAgentInputRef, + onFocus: this.onInputFocus, + }) + ), + dom.label( + { id: "device-form-touch" }, + dom.input({ + defaultChecked: device.touch, + type: "checkbox", + ref: this.touchInputRef, + }), + dom.span( + { className: "device-form-label" }, + getStr("responsive.deviceAdderTouch2") + ) + ), + dom.div( + { className: "device-form-buttons" }, + dom.button( + { id: "device-form-save", onClick: this.onDeviceFormSave }, + formType === "add" + ? getStr("responsive.deviceAdderSave") + : getStr("responsive.deviceFormUpdate") + ), + dom.button( + { id: "device-form-cancel", onClick: this.onDeviceFormHide }, + getStr("responsive.deviceAdderCancel") + ) + ) + ); + } +} + +module.exports = DeviceForm; |