Allow editing account name in account details modal

feature/default_network_editable
Alexander Tseung 7 years ago committed by Chi Kei Chan
parent fa95303e1e
commit 22d9e3a7e6
  1. 26
      ui/app/actions.js
  2. 115
      ui/app/components/editable-label.js
  3. 21
      ui/app/components/modals/account-details-modal.js
  4. 10
      ui/app/components/qr-code.js
  5. 34
      ui/app/css/itcss/components/editable-label.scss
  6. 2
      ui/app/css/itcss/components/index.scss
  7. 5
      ui/app/css/itcss/components/modal.scss

@ -1034,7 +1034,7 @@ function setProviderType (type) {
dispatch(actions.updateProviderType(type))
dispatch(actions.setSelectedToken())
})
}
}
@ -1213,14 +1213,22 @@ function saveAccountLabel (account, label) {
return (dispatch) => {
dispatch(actions.showLoadingIndication())
log.debug(`background.saveAccountLabel`)
background.saveAccountLabel(account, label, (err) => {
dispatch(actions.hideLoadingIndication())
if (err) {
return dispatch(actions.displayWarning(err.message))
}
dispatch({
type: actions.SAVE_ACCOUNT_LABEL,
value: { account, label },
return new Promise((resolve, reject) => {
background.saveAccountLabel(account, label, (err) => {
dispatch(actions.hideLoadingIndication())
if (err) {
dispatch(actions.displayWarning(err.message))
reject(err)
}
dispatch({
type: actions.SAVE_ACCOUNT_LABEL,
value: { account, label },
})
resolve(account)
})
})
}

@ -1,57 +1,88 @@
const Component = require('react').Component
const { Component } = require('react')
const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const inherits = require('util').inherits
const findDOMNode = require('react-dom').findDOMNode
const classnames = require('classnames')
module.exports = EditableLabel
class EditableLabel extends Component {
constructor (props) {
super(props)
inherits(EditableLabel, Component)
function EditableLabel () {
Component.call(this)
}
this.state = {
isEditing: false,
value: props.defaultValue || '',
}
}
handleSubmit () {
const { value } = this.state
if (value === '') {
return
}
Promise.resolve(this.props.onSubmit(value))
.then(() => this.setState({ isEditing: false }))
}
saveIfEnter (event) {
if (event.key === 'Enter') {
this.handleSubmit()
}
}
EditableLabel.prototype.render = function () {
const props = this.props
const state = this.state
renderEditing () {
const { value } = this.state
if (state && state.isEditingLabel) {
return h('div.editable-label', [
h('input.sizing-input', {
defaultValue: props.textValue,
maxLength: '20',
return ([
h('input.large-input.editable-label__input', {
type: 'text',
required: true,
value: this.state.value,
onKeyPress: (event) => {
this.saveIfEnter(event)
if (event.key === 'Enter') {
this.handleSubmit()
}
},
onChange: event => this.setState({ value: event.target.value }),
className: classnames({ 'editable-label__input--error': value === '' }),
}),
h('button.editable-button', {
onClick: () => this.saveText(),
}, 'Save'),
h('div.editable-label__icon-wrapper', [
h('i.fa.fa-check.editable-label__icon', {
onClick: () => this.handleSubmit(),
}),
]),
])
} else {
return h('div.name-label', {
onClick: (event) => {
const nameAttribute = event.target.getAttribute('name')
// checks for class to handle smaller CTA above the account name
const classAttribute = event.target.getAttribute('class')
if (nameAttribute === 'edit' || classAttribute === 'edit-text') {
this.setState({ isEditingLabel: true })
}
},
}, this.props.children)
}
}
EditableLabel.prototype.saveIfEnter = function (event) {
if (event.key === 'Enter') {
this.saveText()
renderReadonly () {
return ([
h('div.editable-label__value', this.state.value),
h('div.editable-label__icon-wrapper', [
h('i.fa.fa-pencil.editable-label__icon', {
onClick: () => this.setState({ isEditing: true }),
}),
]),
])
}
render () {
const { isEditing } = this.state
const { className } = this.props
return (
h('div.editable-label', { className: classnames(className) },
isEditing
? this.renderEditing()
: this.renderReadonly()
)
)
}
}
EditableLabel.prototype.saveText = function () {
// eslint-disable-next-line react/no-find-dom-node
var container = findDOMNode(this)
var text = container.querySelector('.editable-label input').value
var truncatedText = text.substring(0, 20)
this.props.saveText(truncatedText)
this.setState({ isEditingLabel: false, textLabel: truncatedText })
EditableLabel.propTypes = {
onSubmit: PropTypes.func.isRequired,
defaultValue: PropTypes.string,
className: PropTypes.string,
}
module.exports = EditableLabel

@ -7,6 +7,7 @@ const AccountModalContainer = require('./account-modal-container')
const { getSelectedIdentity, getSelectedAddress } = require('../../selectors')
const genAccountLink = require('../../../lib/account-link.js')
const QrView = require('../qr-code')
const EditableLabel = require('../editable-label')
function mapStateToProps (state) {
return {
@ -23,6 +24,7 @@ function mapDispatchToProps (dispatch) {
dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' }))
},
hideModal: () => dispatch(actions.hideModal()),
saveAccountLabel: (address, label) => dispatch(actions.saveAccountLabel(address, label)),
}
}
@ -41,14 +43,19 @@ AccountDetailsModal.prototype.render = function () {
selectedIdentity,
network,
showExportPrivateKeyModal,
hideModal,
saveAccountLabel,
} = this.props
const { name, address } = selectedIdentity
return h(AccountModalContainer, {}, [
h(EditableLabel, {
className: 'account-modal__name',
defaultValue: name,
onSubmit: label => saveAccountLabel(address, label),
}),
h(QrView, {
Qr: {
message: name,
data: address,
},
}),
@ -57,14 +64,12 @@ AccountDetailsModal.prototype.render = function () {
h('button.btn-clear', {
onClick: () => global.platform.openWindow({ url: genAccountLink(address, network) }),
}, [ 'View account on Etherscan' ]),
}, 'View account on Etherscan'),
// Holding on redesign for Export Private Key functionality
h('button.btn-clear', {
onClick: () => {
showExportPrivateKeyModal()
},
}, [ 'Export private key' ]),
onClick: () => showExportPrivateKeyModal(),
}, 'Export private key'),
])
}

@ -29,11 +29,11 @@ QrCodeView.prototype.render = function () {
const qrImage = qrCode(4, 'M')
qrImage.addData(address)
qrImage.make()
return h('.div.flex-column.flex-center', {
style: {
},
}, [
Array.isArray(Qr.message) ? h('.message-container', this.renderMultiMessage()) : h('.qr-header', Qr.message),
return h('.div.flex-column.flex-center', [
Array.isArray(Qr.message)
? h('.message-container', this.renderMultiMessage())
: Qr.message && h('.qr-header', Qr.message),
this.props.warning ? this.props.warning && h('span.error.flex-center', {
style: {

@ -0,0 +1,34 @@
.editable-label {
display: flex;
align-items: center;
justify-content: center;
position: relative;
&__value {
max-width: 250px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
&__input {
width: 250px;
font-size: 14px;
text-align: center;
&--error {
border: 1px solid $monzo;
}
}
&__icon-wrapper {
position: absolute;
margin-left: 10px;
left: 100%;
}
&__icon {
cursor: pointer;
color: $dusty-gray;
}
}

@ -47,3 +47,5 @@
@import './request-signature.scss';
@import './account-dropdown-mini.scss';
@import './editable-label.scss';

@ -294,6 +294,11 @@
font-size: 18px;
}
.account-modal__name {
margin-top: 9px;
font-size: 20px;
}
.private-key-password {
display: flex;
flex-direction: column;

Loading…
Cancel
Save