// Copyright 2015-2017 Parity Technologies (UK) Ltd. // This file is part of Parity. // Parity is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Parity is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Parity. If not, see <http://www.gnu.org/licenses/>. import { observer } from 'mobx-react'; import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { newError } from '@parity/shared/redux/actions'; import { Button, Form, Input, InputChip, Portal, VaultSelect } from '@parity/ui'; import { CancelIcon, SaveIcon } from '@parity/ui/Icons'; import VaultStore from '@parity/dapp-vaults/store'; import Store from './store'; @observer class EditMeta extends Component { static contextTypes = { api: PropTypes.object.isRequired } static propTypes = { account: PropTypes.object.isRequired, newError: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired } store = new Store(this.context.api, this.props.account); vaultStore = VaultStore.get(this.context.api); componentWillMount () { this.vaultStore.loadVaults(); } render () { const { description, isBusy, name, nameError, tags } = this.store; return ( <Portal buttons={ this.renderActions() } busy={ isBusy } onClose={ this.onClose } open title={ <FormattedMessage id='editMeta.title' defaultMessage='edit metadata' /> } > <Form> <Input autoFocus error={ nameError } label={ <FormattedMessage id='editMeta.name.label' defaultMessage='name' /> } onSubmit={ this.store.setName } value={ name } /> <Input hint={ <FormattedMessage id='editMeta.description.hint' defaultMessage='description for this address' /> } label={ <FormattedMessage id='editMeta.description.label' defaultMessage='address description' /> } value={ description } onSubmit={ this.store.setDescription } /> { this.renderAccountFields() } <InputChip addOnBlur hint={ <FormattedMessage id='editMeta.tags.hint' defaultMessage='press <Enter> to add a tag' /> } label={ <FormattedMessage id='editMeta.tags.label' defaultMessage='(optional) tags' /> } onTokensChange={ this.store.setTags } tokens={ tags.slice() } /> { this.renderVaultSelector() } </Form> </Portal> ); } renderActions () { const { hasError } = this.store; return [ <Button label='Cancel' icon={ <CancelIcon /> } key='cancel' onClick={ this.onClose } />, <Button disabled={ hasError } label='Save' icon={ <SaveIcon /> } key='save' onClick={ this.onSave } /> ]; } renderAccountFields () { const { isAccount, passwordHint } = this.store; if (!isAccount) { return null; } return ( <Input hint={ <FormattedMessage id='editMeta.passwordHint.hint' defaultMessage='a hint to allow password recovery' /> } label={ <FormattedMessage id='editMeta.passwordHint.label' defaultMessage='(optional) password hint' /> } value={ passwordHint } onSubmit={ this.store.setPasswordHint } /> ); } renderVaultSelector () { const { isAccount, vaultName } = this.store; if (!isAccount) { return null; } return ( <VaultSelect onSelect={ this.setVaultName } value={ vaultName } vaultStore={ this.vaultStore } /> ); } onClose = () => { this.props.onClose(); } onSave = () => { if (this.store.hasError) { return; } return this.store .save(this.vaultStore) .then(this.onClose) .catch((error) => { this.props.newError(error); }); } setVaultName = (vaultName) => { this.store.setVaultName(vaultName); } } function mapDispatchToProps (dispatch) { return bindActionCreators({ newError }, dispatch); } export default connect( null, mapDispatchToProps )(EditMeta);