UNPKG

passbolt-styleguide

Version:

Passbolt styleguide contains common styling assets used by the different sites, plugin, etc.

289 lines (264 loc) 8.35 kB
/** * Passbolt ~ Open source password manager for teams * Copyright (c) 2020 Passbolt SA (https://www.passbolt.com) * * Licensed under GNU Affero General Public License version 3 of the or any later version. * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @copyright Copyright (c) 2020 Passbolt SA (https://www.passbolt.com) * @license https://opensource.org/licenses/AGPL-3.0 AGPL License * @link https://www.passbolt.com Passbolt(tm) * @since 3.0.0 */ import React, { Component } from "react"; import PropTypes from "prop-types"; import { withAppContext } from "../../../../shared/context/AppContext/AppContext"; import { withApiTriageContext } from "../../../contexts/ApiTriageContext"; import FormSubmitButton from "../../Common/Inputs/FormSubmitButton/FormSubmitButton"; import { Trans, withTranslation } from "react-i18next"; class EnterNameForm extends Component { /** * Constructor * @param {Object} props */ constructor(props) { super(props); this.state = this.defaultState; this.createInputRefs(); this.bindEventHandlers(); } /** * ComponentDidMount * Invoked immediately after component is inserted into the tree * @return {void} */ componentDidMount() { this.setState({ loading: false }, () => { this.firstnameRef.current.focus(); }); } /** * Get default state * @returns {*} */ get defaultState() { return { loading: true, processing: false, firstname: "", firstnameError: null, lastname: "", lastnameError: null, hasAlreadyBeenValidated: false, // True if the form has already been submitted once }; } /** * Bind event handlers * @returns {void} */ bindEventHandlers() { this.handleInputChange = this.handleInputChange.bind(this); this.handleFormSubmit = this.handleFormSubmit.bind(this); this.handleFirstnameInputOnKeyUp = this.handleFirstnameInputOnKeyUp.bind(this); this.handleLastnameInputOnKeyUp = this.handleLastnameInputOnKeyUp.bind(this); } /** * Create references * @returns {void} */ createInputRefs() { this.firstnameRef = React.createRef(); this.lastnameRef = React.createRef(); } /** * Handle form input changes. * @params {ReactEvent} The react event * @returns {void} */ handleInputChange(event) { const target = event.target; const value = target.value; const name = target.name; this.setState({ [name]: value }); } /** * Handle firstname input keyUp event. */ handleFirstnameInputOnKeyUp() { if (this.state.hasAlreadyBeenValidated) { const state = this.validateFirstnameInput(); this.setState(state); } } /** * Handle firstname input keyUp event. */ handleLastnameInputOnKeyUp() { if (this.state.hasAlreadyBeenValidated) { const state = this.validateLastnameInput(); this.setState(state); } } /** * Handle form submit event. * @params {ReactEvent} The react event * @returns {void} */ async handleFormSubmit(event) { // Avoid the form to be submitted. event.preventDefault(); // Prevent submission chile processing if (this.state.processing) { return; } this.setState({ hasAlreadyBeenValidated: true, processing: true }); const errors = this.validate(); if (this.hasValidationError(errors)) { this.setState({ processing: false }); this.focusFirstFieldError(errors); return; } await this.props.apiTriageContext.onRegistrationRequested(this.state.firstname, this.state.lastname); } /** * Validate the form. * @returns {object} */ validate() { const firstnameError = this.validateFirstnameInput(); const lastnameError = this.validateLastnameInput(); this.setState({ firstnameError, lastnameError }); return { firstnameError, lastnameError }; } /** * Validate the firstname input. * @returns {string | null} */ validateFirstnameInput() { let firstnameError = null; const firstname = this.state.firstname.trim(); if (!firstname.length) { firstnameError = this.translate("A first name is required."); } return firstnameError; } /** * Validate the firstname input. * @returns {string | null} */ validateLastnameInput() { let lastnameError = null; const lastname = this.state.lastname.trim(); if (!lastname.length) { lastnameError = this.translate("A last name is required."); } return lastnameError; } /** * Focus the first field of the form which is in error state. * @param {object} errors * @returns {void} */ focusFirstFieldError(errors) { if (errors.firstnameError) { this.firstnameRef.current.focus(); } else if (errors.lastnameError) { this.lastnameRef.current.focus(); } } /** * Return true if the form has some validation error * @param {object} errors * @returns {boolean} */ hasValidationError(errors) { return errors.firstnameError !== null || errors.lastnameError !== null; } /** * Should input be disabled? True if state is loading or processing * @returns {boolean} */ hasAllInputDisabled() { return this.state.processing || this.state.loading; } /** * Get the translate function * @returns {function(...[*]=)} */ get translate() { return this.props.t; } render() { return ( <div className="enter-name"> <h1> <Trans>New here? Enter your name to get started.</Trans> </h1> <form acceptCharset="utf-8" onSubmit={this.handleFormSubmit} noValidate> <div className={`input text required ${this.state.firstnameError ? "error" : ""} ${this.hasAllInputDisabled() ? "disabled" : ""}`} > <label htmlFor="firstname"> <Trans>First name</Trans> </label> <input id="firstname-input" type="text" name="firstname" ref={this.firstnameRef} value={this.state.firstname} onKeyUp={this.handleFirstnameInputOnKeyUp} onChange={this.handleInputChange} disabled={this.hasAllInputDisabled()} placeholder={this.translate("First name")} required="required" /> {this.state.firstnameError && <div className="error-message">{this.state.firstnameError}</div>} </div> <div className={`input text required ${this.state.lastnameError ? "error" : ""} ${this.hasAllInputDisabled() ? "disabled" : ""}`} > <label htmlFor="lastname"> <Trans>Last name</Trans> </label> <input id="lastname-input" type="text" name="lastname" ref={this.lastnameRef} value={this.state.lastname} onKeyUp={this.handleLastnameInputOnKeyUp} onChange={this.handleInputChange} disabled={this.hasAllInputDisabled()} placeholder={this.translate("Last name")} required="required" /> {this.state.lastnameError && <div className="error-message">{this.state.lastnameError}</div>} </div> <div className="form-actions"> <FormSubmitButton disabled={this.hasAllInputDisabled()} big={true} fullWidth={true} processing={this.state.processing} value={this.translate("Sign up")} /> <a href={`${this.props.context.trustedDomain}/auth/login?locale=${this.props.context.locale}`} rel="noopener noreferrer" > <Trans>I already have an account</Trans> </a> </div> </form> </div> ); } } EnterNameForm.propTypes = { apiTriageContext: PropTypes.object, // The api triage context context: PropTypes.any, // The application context provider t: PropTypes.func, // The translation function }; export default withAppContext(withApiTriageContext(withTranslation("common")(EnterNameForm)));