Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Vault Management UI (round 2) #4631

Merged
merged 36 commits into from
Feb 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
3a482ef
Add VaultMeta edit dialog
jacogr Feb 22, 2017
955f1f8
Updated (WIP)
jacogr Feb 22, 2017
1f9a98b
Meta & password edit completed
jacogr Feb 22, 2017
d20f23f
Added SelectionList component for selections
jacogr Feb 22, 2017
c7e3491
Use SelectionList in DappPermisions
jacogr Feb 22, 2017
1e27a10
AddDapps uses SelectionList
jacogr Feb 22, 2017
a5abb28
Fix AccountCard to consistent height
jacogr Feb 22, 2017
c057003
Merge branch 'master' into jg-vaults-2
jacogr Feb 22, 2017
f4b1c03
Merge branch 'master' into jg-selectionlist
jacogr Feb 22, 2017
69105a9
Convert Signer defaults to SelectionList
jacogr Feb 22, 2017
7b6f50d
Subtle selection border
jacogr Feb 23, 2017
1a87840
Display account vault information
jacogr Feb 23, 2017
e730c4a
Merge branch 'jg-selectionlist' into jg-vaults-2
jacogr Feb 23, 2017
c49aef2
Merge branch 'master' into jg-vaults-2
jacogr Feb 23, 2017
caf4403
Allow invalid addresses to display icons (e.g. vaults)
jacogr Feb 23, 2017
34a00b3
Display vault on edit meta
jacogr Feb 23, 2017
02e13e7
Convert VaultAccounts to SelectionList
jacogr Feb 23, 2017
bdb61ad
Merge branch 'jg-selectionlist' into jg-vaults-2
jacogr Feb 23, 2017
9ef1e2c
Allow editing of Vault in meta
jacogr Feb 23, 2017
b25ae9f
Merge branch 'master' into jg-selectionlist
jacogr Feb 23, 2017
3812efd
Add tests for SectionList component
jacogr Feb 23, 2017
c8789cc
Add tests for VaultSelector component
jacogr Feb 23, 2017
ed88435
Merge branch 'master' into jg-vaults-2
jacogr Feb 24, 2017
442b20c
Auto-focus description field (aligns with #4657)
jacogr Feb 24, 2017
853d644
Merge branch 'master' into jg-selectionlist
jacogr Feb 24, 2017
93c4eef
Apply scroll fixes from lates commit in #4621
jacogr Feb 24, 2017
a08dde9
Merge branch 'jg-selectionlist' into jg-vaults-2
jacogr Feb 24, 2017
fe098aa
Remove unneeded logs
jacogr Feb 24, 2017
9e81b22
Remove extra div, fixing ParityBar overflow
jacogr Feb 24, 2017
cae456b
Merge branch 'jg-selectionlist' into jg-vaults-2
jacogr Feb 24, 2017
2cad995
Merge branch 'master' into jg-vaults-2
jacogr Feb 24, 2017
e4369f3
Merge branch 'master' into jg-vaults-2
jacogr Feb 24, 2017
a55de14
Merge branch 'master' into jg-vaults-2
jacogr Feb 24, 2017
d8dca9c
Disable save if password don't match
jacogr Feb 24, 2017
b98f115
s/disabled/readOnly/
jacogr Feb 24, 2017
c22a1a4
string -> bool
jacogr Feb 24, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 75 additions & 1 deletion js/src/modals/EditMeta/editMeta.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

import { newError } from '~/redux/actions';
import { Button, Form, Input, InputChip, Portal } from '~/ui';
import { Button, Form, Input, InputAddress, InputChip, Portal } from '~/ui';
import { CancelIcon, SaveIcon } from '~/ui/Icons';
import VaultStore from '~/views/Vaults/store';

import VaultSelector from '../VaultSelector';
import Store from './store';

@observer
Expand All @@ -39,6 +41,11 @@ class EditMeta extends Component {
}

store = new Store(this.context.api, this.props.account);
vaultStore = VaultStore.get(this.context.api);

componentWillMount () {
this.vaultStore.loadVaults();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't it be loaded only once (the Vault Store) when the app starts ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason it is done here is to ensure we have the current info. It is loaded already at this point, basically a refresh if/when it was changed outside of the window. (It should be ok, but rather safe than sorry)

}

render () {
const { description, name, nameError, tags } = this.store;
Expand All @@ -55,6 +62,7 @@ class EditMeta extends Component {
/>
}
>
{ this.renderVaultSelector() }
<Form>
<Input
autoFocus
Expand Down Expand Up @@ -102,6 +110,7 @@ class EditMeta extends Component {
onTokensChange={ this.store.setTags }
tokens={ tags.slice() }
/>
{ this.renderVault() }
</Form>
</Portal>
);
Expand Down Expand Up @@ -154,22 +163,87 @@ class EditMeta extends Component {
);
}

renderVault () {
const { isAccount, vaultName } = this.store;

if (!isAccount) {
return null;
}

return (
<InputAddress
allowCopy={ false }
allowInvalid
readOnly
hint={
<FormattedMessage
id='editMeta.vault.hint'
defaultMessage='the vault this account is attached to'
/>
}
label={
<FormattedMessage
id='editMeta.vault.label'
defaultMessage='associated vault'
/>
}
onClick={ this.toggleVaultSelector }
value={ vaultName }
/>
);
}

renderVaultSelector () {
const { isAccount, isVaultSelectorOpen, vaultName } = this.store;

if (!isAccount || !isVaultSelectorOpen) {
return null;
}

return (
<VaultSelector
onClose={ this.toggleVaultSelector }
onSelect={ this.setVaultName }
selected={ vaultName }
vaultStore={ this.vaultStore }
/>
);
}

onClose = () => {
this.props.onClose();
}

onSave = () => {
const { address, isAccount, meta, vaultName } = this.store;

if (this.store.hasError) {
return;
}

return this.store
.save()
.then(() => {
if (isAccount && (meta.vault !== vaultName)) {
return this.vaultStore.moveAccount(vaultName, address);
}

return true;
})
.then(this.onClose)
.catch((error) => {
this.props.newError(error);
});
}

setVaultName = (vaultName) => {
this.store.setVaultName(vaultName);
this.toggleVaultSelector();
}

toggleVaultSelector = () => {
this.store.toggleVaultSelector();
}
}

function mapDispatchToProps (dispatch) {
Expand Down
4 changes: 3 additions & 1 deletion js/src/modals/EditMeta/editMeta.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ function createApi () {
return {
parity: {
setAccountName: sinon.stub().resolves(),
setAccountMeta: sinon.stub().resolves()
setAccountMeta: sinon.stub().resolves(),
listVaults: sinon.stub().resolves([]),
listOpenedVaults: sinon.stub().resolves([])
}
};
}
Expand Down
17 changes: 16 additions & 1 deletion js/src/modals/EditMeta/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,30 @@ import { validateName } from '~/util/validation';
export default class Store {
@observable address = null;
@observable isAccount = false;
@observable isVaultSelectorOpen = false;
@observable description = null;
@observable meta = null;
@observable name = null;
@observable nameError = null;
@observable passwordHint = null;
@observable tags = null;
@observable vaultName = null;

constructor (api, account) {
const { address, name, meta, uuid } = account;

this._api = api;

transaction(() => {
this.isAccount = !!uuid;
this.address = address;
this.meta = meta || {};
this.name = name || '';
this.isAccount = !!uuid;

this.description = this.meta.description || '';
this.passwordHint = this.meta.passwordHint || '';
this.tags = this.meta.tags && this.meta.tags.peek() || [];
this.vaultName = this.meta.vault;
});
}

Expand Down Expand Up @@ -74,6 +77,14 @@ export default class Store {
this.tags = tags.slice();
}

@action setVaultName = (vaultName) => {
this.vaultName = vaultName;
}

@action setVaultSelectorOpen = (isOpen) => {
this.isVaultSelectorOpen = isOpen;
}

save () {
const meta = {
description: this.description,
Expand All @@ -94,4 +105,8 @@ export default class Store {
throw error;
});
}

toggleVaultSelector () {
this.setVaultSelectorOpen(!this.isVaultSelectorOpen);
}
}
61 changes: 42 additions & 19 deletions js/src/modals/EditMeta/store.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,31 +142,54 @@ describe('modals/EditMeta/Store', () => {
expect(store.tags.peek()).to.deep.equal(['taga', 'tagb']);
});
});
});

describe('save', () => {
beforeEach(() => {
createStore(ACCOUNT);
describe('setVaultName', () => {
it('sets the name', () => {
store.setVaultName('testing');
expect(store.vaultName).to.equal('testing');
});
});

it('calls parity.setAccountName with the set value', () => {
store.setName('test name');
store.save();
describe('setVaultSelectorOpen', () => {
it('sets the state', () => {
store.setVaultSelectorOpen('testing');
expect(store.isVaultSelectorOpen).to.equal('testing');
});
});
});

expect(api.parity.setAccountName).to.be.calledWith(ACCOUNT.address, 'test name');
describe('operations', () => {
describe('save', () => {
beforeEach(() => {
createStore(ACCOUNT);
});

it('calls parity.setAccountName with the set value', () => {
store.setName('test name');
store.save();

expect(api.parity.setAccountName).to.be.calledWith(ACCOUNT.address, 'test name');
});

it('calls parity.setAccountMeta with the adjusted values', () => {
store.setDescription('some new description');
store.setPasswordHint('some new passwordhint');
store.setTags(['taga']);
store.save();

expect(api.parity.setAccountMeta).to.have.been.calledWith(ACCOUNT.address, Object.assign({}, ACCOUNT.meta, {
description: 'some new description',
passwordHint: 'some new passwordhint',
tags: ['taga']
}));
});
});
});

it('calls parity.setAccountMeta with the adjusted values', () => {
store.setDescription('some new description');
store.setPasswordHint('some new passwordhint');
store.setTags(['taga']);
store.save();

expect(api.parity.setAccountMeta).to.have.been.calledWith(ACCOUNT.address, Object.assign({}, ACCOUNT.meta, {
description: 'some new description',
passwordHint: 'some new passwordhint',
tags: ['taga']
}));
describe('toggleVaultSelector', () => {
it('inverts the selector state', () => {
store.toggleVaultSelector();
expect(store.isVaultSelectorOpen).to.be.true;
});
});
});
36 changes: 21 additions & 15 deletions js/src/modals/VaultCreate/vaultCreate.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,30 @@
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
*/

.body {
/* TODO: These styles are shared with CreateAccount - DRY up */
.passwords {
display: flex;
flex-wrap: wrap;
/* TODO: These styles are shared with CreateAccount - DRY up */
.passwords {
display: flex;
flex-wrap: wrap;

.password {
box-sizing: border-box;
flex: 0 1 50%;
width: 50%;
.password {
box-sizing: border-box;
flex: 0 1 50%;
width: 50%;

&:nth-child(odd) {
padding-right: 0.25rem;
}
&:nth-child(odd) {
padding-right: 0.25rem;
}

&:nth-child(even) {
padding-left: 0.25rem;
}
&:nth-child(even) {
padding-left: 0.25rem;
}
}
}

.disabled {
opacity: 0.25;
}

.group+.group {
margin-top: 1em;
}
2 changes: 1 addition & 1 deletion js/src/modals/VaultCreate/vaultCreate.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class VaultCreate extends Component {
/>
}
>
<div className={ styles.body }>
<div>
<Input
error={ vaultNameError }
hint={
Expand Down
17 changes: 17 additions & 0 deletions js/src/modals/VaultMeta/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// 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/>.

export default from './vaultMeta';
Loading