diff options
Diffstat (limited to 'mascara/src/app/first-time/import-account-screen.js')
-rw-r--r-- | mascara/src/app/first-time/import-account-screen.js | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/mascara/src/app/first-time/import-account-screen.js b/mascara/src/app/first-time/import-account-screen.js new file mode 100644 index 000000000..ab0aca0f0 --- /dev/null +++ b/mascara/src/app/first-time/import-account-screen.js @@ -0,0 +1,204 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import {connect} from 'react-redux' +import classnames from 'classnames' +import LoadingScreen from './loading-screen' +import {importNewAccount, hideWarning} from '../../../../ui/app/actions' + +const Input = ({ label, placeholder, onChange, errorMessage, type = 'text' }) => ( + <div className="import-account__input-wrapper"> + <div className="import-account__input-label">{label}</div> + <input + type={type} + placeholder={placeholder} + className={classnames('first-time-flow__input import-account__input', { + 'first-time-flow__input--error': errorMessage, + })} + onChange={onChange} + /> + <div className="import-account__input-error-message">{errorMessage}</div> + </div> +) + +Input.prototype.propTypes = { + label: PropTypes.string.isRequired, + placeholder: PropTypes.string.isRequired, + type: PropTypes.string.isRequired, + errorMessage: PropTypes.string.isRequired, + onChange: PropTypes.func.isRequired, +} + +class ImportAccountScreen extends Component { + static OPTIONS = { + PRIVATE_KEY: 'private_key', + JSON_FILE: 'json_file', + }; + + static propTypes = { + warning: PropTypes.string, + back: PropTypes.func.isRequired, + next: PropTypes.func.isRequired, + importNewAccount: PropTypes.func.isRequired, + hideWarning: PropTypes.func.isRequired, + isLoading: PropTypes.bool.isRequired, + }; + + state = { + selectedOption: ImportAccountScreen.OPTIONS.PRIVATE_KEY, + privateKey: '', + jsonFile: {}, + } + + isValid () { + const { OPTIONS } = ImportAccountScreen + const { privateKey, jsonFile, password } = this.state + + switch (this.state.selectedOption) { + case OPTIONS.JSON_FILE: + return Boolean(jsonFile && password) + case OPTIONS.PRIVATE_KEY: + default: + return Boolean(privateKey) + } + } + + onClick = () => { + const { OPTIONS } = ImportAccountScreen + const { importNewAccount, next } = this.props + const { privateKey, jsonFile, password } = this.state + + switch (this.state.selectedOption) { + case OPTIONS.JSON_FILE: + return importNewAccount('JSON File', [ jsonFile, password ]) + .then(next) + case OPTIONS.PRIVATE_KEY: + default: + return importNewAccount('Private Key', [ privateKey ]) + .then(next) + } + } + + renderPrivateKey () { + return Input({ + label: 'Add Private Key String', + placeholder: 'Enter private key', + onChange: e => this.setState({ privateKey: e.target.value }), + errorMessage: this.props.warning && 'Something went wrong. Please make sure your private key is correct.', + }) + } + + renderJsonFile () { + const { jsonFile: { name } } = this.state + const { warning } = this.props + + return ( + <div className=""> + <div className="import-account__input-wrapper"> + <div className="import-account__input-label">Upload File</div> + <div className="import-account__file-picker-wrapper"> + <input + type="file" + id="file" + className="import-account__file-input" + onChange={e => this.setState({ jsonFile: e.target.files[0] })} + /> + <label + htmlFor="file" + className={classnames('import-account__file-input-label', { + 'import-account__file-input-label--error': warning, + })} + > + Choose File + </label> + <div className="import-account__file-name">{name}</div> + </div> + <div className="import-account__input-error-message"> + {warning && 'Something went wrong. Please make sure your JSON file is properly formatted.'} + </div> + </div> + {Input({ + label: 'Enter Password', + placeholder: 'Enter Password', + type: 'password', + onChange: e => this.setState({ password: e.target.value }), + errorMessage: warning && 'Please make sure your password is correct.', + })} + </div> + ) + } + + renderContent () { + const { OPTIONS } = ImportAccountScreen + + switch (this.state.selectedOption) { + case OPTIONS.JSON_FILE: + return this.renderJsonFile() + case OPTIONS.PRIVATE_KEY: + default: + return this.renderPrivateKey() + } + } + + render () { + const { OPTIONS } = ImportAccountScreen + const { selectedOption } = this.state + + return this.props.isLoading + ? <LoadingScreen loadingMessage="Creating your new account" /> + : ( + <div className="import-account"> + <a + className="import-account__back-button" + onClick={e => { + e.preventDefault() + this.props.back() + }} + href="#" + > + {`< Back`} + </a> + <div className="import-account__title"> + Import an Account + </div> + <div className="import-account__selector-label"> + How would you like to import your account? + </div> + <select + className="import-account__dropdown" + value={selectedOption} + onChange={e => { + this.setState({ selectedOption: e.target.value }) + this.props.hideWarning() + }} + > + <option value={OPTIONS.PRIVATE_KEY}>Private Key</option> + <option value={OPTIONS.JSON_FILE}>JSON File</option> + </select> + {this.renderContent()} + <button + className="first-time-flow__button" + disabled={!this.isValid()} + onClick={this.onClick} + > + Import + </button> + <a + href="https://github.com/MetaMask/faq/blob/master/README.md#q-i-cant-use-the-import-feature-for-uploading-a-json-file-the-window-keeps-closing-when-i-try-to-select-a-file" + className="first-time-flow__link import-account__faq-link" + rel="noopener noreferrer" + target="_blank" + > + File import not working? + </a> + </div> + ) + } +} + +export default connect( + ({ appState: { isLoading, warning } }) => ({ isLoading, warning }), + dispatch => ({ + importNewAccount: (strategy, args) => dispatch(importNewAccount(strategy, args)), + hideWarning: () => dispatch(hideWarning()), + }) +)(ImportAccountScreen) |