frontend/app/projectsearch/ProjectLockerLoginComponent.jsx (90 lines of code) (raw):

import React from "react"; import PropTypes from "prop-types"; import { authenticatedFetch } from "../auth"; class ProjectLockerLoginComponent extends React.Component { static propTypes = { projectLockerBaseUrl: PropTypes.string.isRequired, loginSuccess: PropTypes.func.isRequired, loginFailure: PropTypes.func, }; constructor(props) { super(props); this.state = { enteredUid: "", enteredPw: "", lastError: null, loading: false, }; this.performLogin = this.performLogin.bind(this); } noop() {} async performLogin() { const loginData = { username: this.state.enteredUid, password: this.state.enteredPw, }; try { const result = await authenticatedFetch( this.props.projectLockerBaseUrl + "/api/login", { method: "POST", body: JSON.stringify(loginData), headers: { "Content-Type": "application/json" }, credentials: "include", } ); const body = await result.text(); if (result.ok) { const content = JSON.parse(body); this.setState({ loading: false, lastError: null }, () => this.props.loginSuccess(content.uid) ); } else if (result.status === 403) { this.setState( { loading: false, lastError: "Permission denied, please check your username and password", }, () => this.props.loginFailure ? this.props.loginFailure() : this.noop() ); } else { this.setState({ loading: false, lastError: body }); } } catch (err) { if (!err.toString().includes("Not logged in")) this.setState({ lastError: err.toString() }); } } render() { return ( <div className="sub-login-box centered"> <label htmlFor="id-pl-username">User name</label> <input type="text" onChange={(evt) => this.setState({ enteredUid: evt.target.value })} value={this.state.enteredUid} id="id-pl-username" disabled={this.state.loading} /> <label htmlFor="id-pl-passwd">Password</label> <input type="password" onChange={(evt) => this.setState({ enteredPw: evt.target.value })} value={this.state.enteredPw} id="id-pl-passwd" disabled={this.state.loading} /> <button onClick={this.performLogin}>Log in</button> <p className="error" style={{ display: this.state.lastError ? "block" : "hidden" }} > {this.state.lastError} </p> </div> ); } } export default ProjectLockerLoginComponent;