Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DDW-811] Re-enable the old wallet creation process #1515

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Changelog

### Features

- Implemented the new "Wallet Creation" process ([PR 1499](https://github.com/input-output-hk/daedalus/pull/1499), [PR 1515](https://github.com/input-output-hk/daedalus/pull/1515))
- Implemented css rules automatic sort ([PR 1483](https://github.com/input-output-hk/daedalus/pull/1483))
- Improved scrollbar look and feel on wallets list ([PR 1475](https://github.com/input-output-hk/daedalus/pull/1475))
- Implemented new delegation countdown design ([PR 1481](https://github.com/input-output-hk/daedalus/pull/1481))
Expand Down
289 changes: 289 additions & 0 deletions source/renderer/app/components/wallet/WalletCreateDialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
// @flow
// TODO: Remove once the new wallet creation process is ready
import React, { Component } from 'react';
import { observer } from 'mobx-react';
import classnames from 'classnames';
import { Checkbox } from 'react-polymorph/lib/components/Checkbox';
import { Input } from 'react-polymorph/lib/components/Input';
import { SwitchSkin } from 'react-polymorph/lib/skins/simple/SwitchSkin';
import { InputSkin } from 'react-polymorph/lib/skins/simple/InputSkin';
import { IDENTIFIERS } from 'react-polymorph/lib/themes/API';
import { defineMessages, intlShape } from 'react-intl';
import ReactToolboxMobxForm, {
handleFormErrors,
} from '../../utils/ReactToolboxMobxForm';
import DialogCloseButton from '../widgets/DialogCloseButton';
import Dialog from '../widgets/Dialog';
import {
isValidWalletName,
isValidSpendingPassword,
isValidRepeatPassword,
} from '../../utils/validations';
import globalMessages from '../../i18n/global-messages';
import styles from './WalletCreateDialog.scss';
import { FORM_VALIDATION_DEBOUNCE_WAIT } from '../../config/timingConfig';
import { submitOnEnter } from '../../utils/form';

const messages = defineMessages({
dialogTitle: {
id: 'wallet.create.dialog.title',
defaultMessage: '!!!Create a new wallet',
description: 'Title "Create a new wallet" in the wallet create form.',
},
walletName: {
id: 'wallet.create.dialog.name.label',
defaultMessage: '!!!Wallet Name',
description:
'Label for the "Wallet Name" text input in the wallet create form.',
},
walletNameHint: {
id: 'wallet.create.dialog.walletNameHint',
defaultMessage: '!!!e.g: Shopping Wallet',
description:
'Hint for the "Wallet Name" text input in the wallet create form.',
},
createPersonalWallet: {
id: 'wallet.create.dialog.create.personal.wallet.button.label',
defaultMessage: '!!!Create personal wallet',
description:
'Label for the "Create personal wallet" button on create wallet dialog.',
},
passwordSwitchPlaceholder: {
id: 'wallet.create.dialog.passwordSwitchPlaceholder',
defaultMessage:
'!!!Keep your private keys safely encrypted by setting the spending password',
description:
'Text for the "Activate to create password" switch in the create wallet dialog.',
},
passwordSwitchLabel: {
id: 'wallet.create.dialog.passwordSwitchLabel',
defaultMessage: '!!!Spending password',
description:
'Label for the "Activate to create password" switch in the create wallet dialog.',
},
spendingPasswordLabel: {
id: 'wallet.create.dialog.spendingPasswordLabel',
defaultMessage: '!!!Enter password',
description:
'Label for the "Wallet password" input in the create wallet dialog.',
},
repeatPasswordLabel: {
id: 'wallet.create.dialog.repeatPasswordLabel',
defaultMessage: '!!!Repeat password',
description:
'Label for the "Repeat password" input in the create wallet dialog.',
},
passwordFieldPlaceholder: {
id: 'wallet.create.dialog.passwordFieldPlaceholder',
defaultMessage: '!!!Password',
description:
'Placeholder for the "Password" inputs in the create wallet dialog.',
},
});

type Props = {
onSubmit: Function,
onCancel: Function,
};

type State = {
isSubmitting: boolean,
createPassword: boolean,
};

@observer
export default class WalletCreateDialog extends Component<Props, State> {
static contextTypes = {
intl: intlShape.isRequired,
};

state = {
isSubmitting: false,
createPassword: true,
};

componentDidMount() {
setTimeout(() => {
this.walletNameInput.focus();
});
}

walletNameInput: Input;

form = new ReactToolboxMobxForm(
{
fields: {
walletName: {
label: this.context.intl.formatMessage(messages.walletName),
placeholder: this.context.intl.formatMessage(messages.walletNameHint),
value: '',
validators: [
({ field }) => [
isValidWalletName(field.value),
this.context.intl.formatMessage(globalMessages.invalidWalletName),
],
],
},
spendingPassword: {
type: 'password',
label: this.context.intl.formatMessage(
messages.spendingPasswordLabel
),
placeholder: this.context.intl.formatMessage(
messages.passwordFieldPlaceholder
),
value: '',
validators: [
({ field, form }) => {
if (!this.state.createPassword) return [true];
const repeatPasswordField = form.$('repeatPassword');
if (repeatPasswordField.value.length > 0) {
repeatPasswordField.validate({ showErrors: true });
}
return [
isValidSpendingPassword(field.value),
this.context.intl.formatMessage(
globalMessages.invalidSpendingPassword
),
];
},
],
},
repeatPassword: {
type: 'password',
label: this.context.intl.formatMessage(messages.repeatPasswordLabel),
placeholder: this.context.intl.formatMessage(
messages.passwordFieldPlaceholder
),
value: '',
validators: [
({ field, form }) => {
if (!this.state.createPassword) return [true];
const spendingPassword = form.$('spendingPassword').value;
if (spendingPassword.length === 0) return [true];
return [
isValidRepeatPassword(spendingPassword, field.value),
this.context.intl.formatMessage(
globalMessages.invalidRepeatPassword
),
];
},
],
},
},
},
{
options: {
validateOnChange: true,
validationDebounceWait: FORM_VALIDATION_DEBOUNCE_WAIT,
},
}
);

submit = () => {
this.form.submit({
onSuccess: form => {
this.setState({ isSubmitting: true });
const { createPassword } = this.state;
const { walletName, spendingPassword } = form.values();
const walletData = {
name: walletName,
spendingPassword: createPassword ? spendingPassword : null,
};
this.props.onSubmit(walletData);
},
onError: () => {
handleFormErrors('.SimpleFormField_error', { focusElement: true });
this.setState({ isSubmitting: false });
},
});
};

handleSubmitOnEnter = submitOnEnter.bind(this, this.submit);

handlePasswordSwitchToggle = (value: boolean) => {
this.setState({ createPassword: value });
};

render() {
const { form } = this;
const { intl } = this.context;
const { onCancel } = this.props;
const { createPassword, isSubmitting } = this.state;
const dialogClasses = classnames([styles.component, 'WalletCreateDialog']);
const spendingPasswordFieldsClasses = classnames([
styles.spendingPasswordFields,
createPassword ? styles.show : null,
]);

const actions = [
{
className: isSubmitting ? styles.isSubmitting : null,
label: this.context.intl.formatMessage(messages.createPersonalWallet),
primary: true,
onClick: this.submit,
},
];

const walletNameField = form.$('walletName');
const spendingPasswordField = form.$('spendingPassword');
const repeatedPasswordField = form.$('repeatPassword');

return (
<Dialog
className={dialogClasses}
title={intl.formatMessage(messages.dialogTitle)}
actions={actions}
closeOnOverlayClick
onClose={!isSubmitting ? onCancel : () => {}}
closeButton={<DialogCloseButton />}
>
<Input
className="walletName"
onKeyPress={this.handleSubmitOnEnter}
ref={input => {
this.walletNameInput = input;
}}
{...walletNameField.bind()}
error={walletNameField.error}
skin={InputSkin}
/>

<div className={styles.spendingPassword}>
<div className={styles.spendingPasswordSwitch}>
<div className={styles.passwordLabel}>
{intl.formatMessage(messages.passwordSwitchLabel)}
</div>
<Checkbox
themeId={IDENTIFIERS.SWITCH}
onChange={this.handlePasswordSwitchToggle}
label={intl.formatMessage(messages.passwordSwitchPlaceholder)}
checked={createPassword}
skin={SwitchSkin}
/>
</div>

<div className={spendingPasswordFieldsClasses}>
<Input
className="spendingPassword"
onKeyPress={this.handleSubmitOnEnter}
{...spendingPasswordField.bind()}
error={spendingPasswordField.error}
skin={InputSkin}
/>
<Input
className="repeatedPassword"
onKeyPress={this.handleSubmitOnEnter}
{...repeatedPasswordField.bind()}
error={repeatedPasswordField.error}
skin={InputSkin}
/>
<p className={styles.passwordInstructions}>
{intl.formatMessage(globalMessages.passwordInstructions)}
</p>
</div>
</div>
</Dialog>
);
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// TODO: Remove once the new wallet creation process is ready
@import '../../themes/mixins/loading-spinner';
@import '../../themes/mixins/place-form-field-error-below-input';

Expand Down
23 changes: 20 additions & 3 deletions source/renderer/app/containers/wallet/WalletAddPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import WalletCreateDialogContainer from './dialogs/WalletCreateDialogContainer';
import Layout from '../MainLayout';
import type { InjectedProps } from '../../types/injectedPropsType';

// TODO: Remove once the new wallet creation process is ready
import WalletCreateDialogContainerOld from './dialogs/WalletCreateDialogContainerOld';
import WalletCreateDialog from '../../components/wallet/WalletCreateDialog';

type Props = InjectedProps;

@inject('actions', 'stores')
Expand All @@ -26,14 +30,27 @@ export default class WalletAddPage extends Component<Props> {
render() {
const { actions, stores } = this.props;
const { wallets, uiDialogs, app } = stores;
const { isRestoreActive } = wallets;
const {
isRestoreActive,
createWalletStep,
useNewWalletCreationProcess,
} = wallets;
const {
environment: { isMainnet, isTestnet },
} = app;

const walletCreationAction = useNewWalletCreationProcess
? () => actions.wallets.createWalletBegin.trigger()
: // TODO: Remove once the new wallet creation process is ready
() => actions.dialogs.open.trigger({ dialog: WalletCreateDialog });

let content = null;

if (wallets.createWalletStep !== null) {
// TODO: Remove once the new wallet creation process is ready
if (uiDialogs.isOpen(WalletCreateDialog)) {
content = <WalletCreateDialogContainerOld onClose={this.onClose} />;
// ----
} else if (createWalletStep !== null) {
content = <WalletCreateDialogContainer onClose={this.onClose} />;
} else if (uiDialogs.isOpen(WalletBackupDialog)) {
content = <WalletBackupDialogContainer onClose={this.onClose} />;
Expand All @@ -46,7 +63,7 @@ export default class WalletAddPage extends Component<Props> {
<WalletAdd
isMainnet={isMainnet}
isTestnet={isTestnet}
onCreate={() => actions.wallets.createWalletBegin.trigger()}
onCreate={walletCreationAction}
onRestore={() =>
actions.dialogs.open.trigger({ dialog: WalletRestoreDialog })
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// @flow
// TODO: Remove once the new wallet creation process is ready
import React, { Component } from 'react';
import { observer, inject } from 'mobx-react';
import WalletCreateDialog from '../../../components/wallet/WalletCreateDialog';
import type { InjectedDialogContainerProps } from '../../../types/injectedPropsType';

type Props = InjectedDialogContainerProps;

@inject('stores', 'actions')
@observer
export default class WalletCreateDialogContainer extends Component<Props> {
static defaultProps = {
actions: null,
stores: null,
children: null,
onClose: () => {},
};

onSubmit = (values: { name: string, spendingPassword: ?string }) => {
this.props.actions.wallets.createWallet.trigger(values);
};

render() {
return (
<WalletCreateDialog
onSubmit={this.onSubmit}
onCancel={this.props.onClose}
/>
);
}
}
Loading