Forget confirmation & account name editing (#4)

* Forget confirmation & account name editing

* Update ActionBar padding
This commit is contained in:
Jaco Greeff
2019-05-20 15:56:11 +02:00
committed by GitHub
parent 7f35ea1e8e
commit 93b135d685
14 changed files with 158 additions and 42 deletions
+2 -1
View File
@@ -6,7 +6,8 @@
"license": "Apache-2",
"dependencies": {
"@polkadot/ui-identicon": "^0.39.0-beta.5",
"@types/react-router-dom": "^4.3.2",
"@types/react-router": "^5.0.0",
"@types/react-router-dom": "^4.3.3",
"react-router": "^5.0.0",
"react-router-dom": "^5.0.0"
}
@@ -2,31 +2,58 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import React from 'react';
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import { ActionBar, Address } from '../../components';
import { forgetAccount } from '../../messaging';
import { editAccount } from '../../messaging';
import { Name } from '../../partials';
type Props = {
className?: string,
address: string,
name?: string,
name?: string | null,
onAction: () => void
};
export default function Account ({ address, name, onAction }: Props) {
const _onForget = (): void => {
forgetAccount(address)
.then(onAction)
.catch(console.error);
export default function Account ({ address, className, name, onAction }: Props) {
const [isEditing, setEditing] = useState(false);
const [editedname, setName] = useState(name);
const _toggleEdit = (): void => {
setEditing(!isEditing);
};
const _saveChanges = (): void => {
if (editedname && editedname !== name) {
editAccount(address, editedname)
.then(onAction)
.catch(console.error);
}
_toggleEdit();
};
return (
<Address
address={address}
name={name}
className={className}
name={
isEditing
? (
<Name
defaultValue={name}
isFocussed
label={null}
onBlur={_saveChanges}
onChange={setName}
/>
)
: name
}
>
<ActionBar>
<a onClick={_onForget}>Forget</a>
<a onClick={_toggleEdit}>Edit</a>
<Link to={`/account/forget/${address}`}>Forget</Link>
</ActionBar>
</Address>
);
@@ -0,0 +1,47 @@
// Copyright 2019 @polkadot/extension-ui authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { KeyringJson } from '@polkadot/ui-keyring/types';
import React from 'react';
import { RouteComponentProps, withRouter } from 'react-router';
import { Address, Button, Header, Tip } from '../components';
import { forgetAccount } from '../messaging';
import { Back } from '../partials';
type Props = RouteComponentProps<{ address: string }> & {
accounts: Array<KeyringJson>,
onAction: () => void
};
function Forget (props: Props) {
const { accounts, match: { params: { address } }, onAction } = props;
const account = accounts.find((account) => address === account.address);
const _onClick = (): void => {
forgetAccount(address)
.then(onAction)
.catch(console.error);
};
return (
<div>
<Header label='forget account' />
<Back />
<Tip header='danger' type='error'>You are about to remove the account. This means that you will not be able to access it via this extension anymore. If you wish to recover it, you would need to use the seed.</Tip>
<Address
address={address}
name={account && account.meta.name}
/>
<Button
isFull
label='I want to forget this account'
onClick={_onClick}
/>
</div>
);
}
export default withRouter(Forget);
@@ -34,7 +34,7 @@ export default function Request ({ accounts, isFirst, onAction, request: { addre
return (
<Address
address={address}
name={account ? account.meta.name : '<invalid account>'}
name={account && account.meta.name}
>
<Details
method={method}
@@ -12,6 +12,7 @@ import { Loading } from '../components';
import { getAccounts, getRequests } from '../messaging';
import Accounts from './Accounts';
import Create from './Create';
import Forget from './Forget';
import Import from './Import';
import Signing from './Signing';
@@ -43,6 +44,9 @@ export default function Popup (props: Props) {
<Route path='/account/create' component={() =>
<Create onAction={onAction} />
} />
<Route path='/account/forget/:address' component={() =>
<Forget accounts={accounts} onAction={onAction} />
} />
<Route path='/account/import' component={() =>
<Import onAction={onAction} />
} />
@@ -5,8 +5,6 @@
import React from 'react';
import styled from 'styled-components';
import defaults from './defaults';
type Props = {
children: React.ReactNode;
className?: string;
@@ -21,7 +19,7 @@ function ActionBar ({ children, className }: Props) {
}
export default styled(ActionBar)`
padding: ${defaults.boxPadding};
padding: 0.25rem;
text-align: right;
a {
@@ -14,7 +14,7 @@ type Props = {
children?: React.ReactNode;
className?: string,
isHidden?: boolean,
name?: string | null,
name?: React.ReactNode | null,
theme?: 'polkadot' | 'substrate'
};
+21 -9
View File
@@ -10,32 +10,44 @@ import defaults from './defaults';
type Props = {
className?: string,
defaultValue?: string | null,
isError?: boolean,
isFocussed?: boolean,
isReadOnly?: boolean,
label: string,
label?: string | null,
onBlur?: () => void,
onChange?: (value: string) => void,
type?: 'text' | 'password',
value?: string
};
function Input ({ className, label, isFocussed, isReadOnly, onChange, type = 'text', value }: Props) {
function Input ({ className, defaultValue, label, isFocussed, isReadOnly, onBlur, onChange, type = 'text', value }: Props) {
const _onChange = ({ target: { value } }: React.ChangeEvent<HTMLInputElement>): void => {
onChange && onChange(value.trim());
};
const element = (
<input
autoFocus={isFocussed}
defaultValue={defaultValue || undefined}
readOnly={isReadOnly}
onBlur={onBlur}
onChange={_onChange}
type={type}
value={value}
/>
);
if (!label) {
return <div className={className}>{element}</div>;
}
return (
<Label
className={className}
label={label}
>
<input
autoFocus={isFocussed}
readOnly={isReadOnly}
onChange={_onChange}
type={type}
value={value}
/>
{element}
</Label>
);
}
+4
View File
@@ -22,6 +22,10 @@ function sendMessage (message: MessageTypes, request: any = {}): Promise<any> {
});
}
export async function editAccount (address: string, name: string): Promise<boolean> {
return sendMessage('accounts.edit', { address, name });
}
export async function forgetAccount (address: string): Promise<boolean> {
return sendMessage('accounts.forget', { address });
}
+1 -1
View File
@@ -16,7 +16,7 @@ type Props = {
function Back ({ className, to = '/' }: Props) {
return (
<div className={className}>
<Link to='/'>{unicode.BACK} Back</Link>
<Link to={to}>{unicode.BACK} Back</Link>
</div>
);
}
+17 -12
View File
@@ -7,14 +7,18 @@ import React, { useEffect, useState } from 'react';
import { Input } from '../components';
type Props = {
defaultValue?: string | null,
isFocussed?: boolean,
onChange: (name: string | null) => void
label?: string | null,
onBlur?: () => void,
onChange: (name: string | null) => void,
value?: string
};
const MIN_LENGTH = 3;
export default function Name ({ isFocussed, onChange }: Props) {
const [name, setName] = useState('');
export default function Name ({ defaultValue, isFocussed, label = 'a descriptive name for this account', onBlur, onChange, value }: Props) {
const [name, setName] = useState(defaultValue || '');
useEffect(() => {
onChange(
@@ -25,14 +29,15 @@ export default function Name ({ isFocussed, onChange }: Props) {
}, [name]);
return (
<>
<Input
isError={name.length < MIN_LENGTH}
isFocussed={isFocussed}
label='a descriptive name for this account'
onChange={setName}
type='text'
/>
</>
<Input
defaultValue={defaultValue}
isError={name.length < MIN_LENGTH}
isFocussed={isFocussed}
label={label}
onBlur={onBlur}
onChange={setName}
type='text'
value={value}
/>
);
}