diff --git a/package.json b/package.json index a9ca38b81..9f41467c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "apla-front", - "version": "1.1.0", + "version": "2.0.0", "author": { "name": "apla-front" }, diff --git a/public/locales/en-US.json b/public/locales/en-US.json index 9aa27af3c..63024d30a 100644 --- a/public/locales/en-US.json +++ b/public/locales/en-US.json @@ -28,6 +28,7 @@ "auth.wallet.remove": "Remove", "auth.wallet.share": "Share", "auth.wallet.share.long": "Share account data", + "auth.wallet.unregistered": "Unregistered account", "auth.authentication": "Authentication", "auth.create.success": "Account has been successfully created", "auth.error.E_INVALID_KEY": "Provided key is corrupted or contains invalid data", @@ -147,8 +148,10 @@ "general.password.repeat": "Repeat password", "general.password.old": "Old password", "general.password.new": "New password", + "general.print": "Print", "general.title": "Apla", "general.title.format": "{title} | Apla", + "general.save": "Save", "general.security.warning": "Please use desktop version or mobile application for better security", "history.newer": "Newer", "history.older": "Older", @@ -199,7 +202,9 @@ "process.confirm": "Confirm", "process.continue": "Continue", "undo": "Undo", + "tx.data.missing": "Data is missing", "tx.param.value": "Value", + "tx.report": "Transaction report", "tx.error.error": "Error", "tx.error.error.desc": "{error}", "tx.error.exception": "Runtime exception", diff --git a/public/locales/ru-RU.json b/public/locales/ru-RU.json index f3a9192ea..5b97dce9f 100644 --- a/public/locales/ru-RU.json +++ b/public/locales/ru-RU.json @@ -28,6 +28,7 @@ "auth.wallet.remove": "Удалить", "auth.wallet.share": "Копировать", "auth.wallet.share.long": "Копировать данные аккаунта", + "auth.wallet.unregistered": "Незарегистрированный аккаунт", "auth.authentication": "Аутентификация", "auth.create.success": "Аккаунт успешно создан", "auth.error.E_INVALID_KEY": "Указанный ключ содержит некорректные данные или повреждён", @@ -147,8 +148,10 @@ "general.password.repeat": "Повторите пароль", "general.password.old": "Старый пароль", "general.password.new": "Новый пароль", + "general.print": "Печать", "general.title": "Apla", "general.title.format": "{title} | Apla", + "general.save": "Сохранить", "general.security.warning": "Для большей безопасности используйте desktop или мобильное приложение", "history.newer": "Новее", "history.older": "Старше", @@ -199,7 +202,9 @@ "process.confirm": "Подтвердить", "process.continue": "Далее", "undo": "Отмена", + "tx.data.missing": "Данные отсутствуют", "tx.param.value": "Значение", + "tx.report": "Отчёт транзакции", "tx.error.error": "Ошибка", "tx.error.error.desc": "{error}", "tx.error.exception": "Программное исключение", diff --git a/src/app/components/Auth/Login/PasswordPrompt.tsx b/src/app/components/Auth/Login/PasswordPrompt.tsx index 177d1d551..5b9efabc2 100644 --- a/src/app/components/Auth/Login/PasswordPrompt.tsx +++ b/src/app/components/Auth/Login/PasswordPrompt.tsx @@ -35,7 +35,7 @@ const PasswordPrompt: React.SFC = prop
diff --git a/src/app/components/Auth/Login/WalletList/WalletButton.tsx b/src/app/components/Auth/Login/WalletList/WalletButton.tsx index d3c46a4dc..6066dca6a 100644 --- a/src/app/components/Auth/Login/WalletList/WalletButton.tsx +++ b/src/app/components/Auth/Login/WalletList/WalletButton.tsx @@ -7,7 +7,7 @@ import React from 'react'; import styled from 'styled-components'; import { FormattedMessage } from 'react-intl'; import { Button, Clearfix } from 'react-bootstrap'; -import { IAccount, IKeyInfo, IRoleInfo } from 'apla/api'; +import { IAccount, IRoleInfo, IEcosystemInfo } from 'apla/api'; import { INotificationsMessage } from 'apla/socket'; import Avatar from 'containers/Avatar'; @@ -19,11 +19,11 @@ export interface IWalletButtonProps { notifications: INotificationsMessage[]; onCopy: () => void; onRemove: () => void; - onSelect: (params: { access: IKeyInfo, role: IRoleInfo }) => void; + onSelect: (params: { access: IEcosystemInfo, role: IRoleInfo }) => void; onRegister?: () => void; } -const getNotificationsCount = (notifications: INotificationsMessage[], role: number, ecosystem: string) => { +const getNotificationsCount = (notifications: INotificationsMessage[], role: string, ecosystem: string) => { const value = notifications.find(l => l.role === role && l.ecosystem === ecosystem); return value ? value.count : 0; }; @@ -35,7 +35,14 @@ const WalletButton: React.SFC = (props) => (

- {props.wallet.address} + {props.wallet.address ? + ( + {props.wallet.address} + ) : + ( + + ) + }

{0 === props.wallet.access.length && props.onRegister && (
@@ -63,7 +70,7 @@ const WalletButton: React.SFC = (props) => (
@@ -74,11 +81,11 @@ const WalletButton: React.SFC = (props) => ( : - props.onSelect({ access, role: null })}> + props.onSelect({ access, role: null })}> {access.roles.map(role => ( - props.onSelect({ access, role })}> + props.onSelect({ access, role })}> {role.name} ))} diff --git a/src/app/components/Main/Backup.tsx b/src/app/components/Main/Backup.tsx index 7adc06bfd..3400386d2 100644 --- a/src/app/components/Main/Backup.tsx +++ b/src/app/components/Main/Backup.tsx @@ -8,7 +8,7 @@ import { Button, Panel } from 'react-bootstrap'; import { FormattedMessage } from 'react-intl'; import keyring from 'lib/keyring'; import { sendAttachment } from 'lib/fs'; -import { IAccountContext } from 'apla/auth'; +import { IAccount } from 'apla/api'; import CopyToClipboard from 'react-copy-to-clipboard'; import QRCode from 'qrcode.react'; @@ -16,7 +16,7 @@ import Wrapper from 'components/Wrapper'; import Validation from 'components/Validation'; export interface IBackupProps { - wallet: IAccountContext; + account: IAccount; privateKey: string; onError?: () => any; onCopy?: () => any; @@ -37,7 +37,7 @@ class Backup extends React.Component { } onSubmit = (values: { [key: string]: string }) => { - const privateKey = keyring.decryptAES(this.props.wallet.wallet.encKey, values.password); + const privateKey = keyring.decryptAES(this.props.account.encKey, values.password); if (keyring.validatePrivateKey(privateKey)) { const publicKey = keyring.generatePublicKey(privateKey); @@ -125,7 +125,7 @@ class Backup extends React.Component { - {this.props.wallet.wallet.address} + {this.props.account && this.props.account.address} @@ -163,7 +163,7 @@ class Backup extends React.Component { } > - {this.props.wallet && ( + {this.props.account && ( {this.state.privateKey ? this.renderSecond() : this.renderFirst()} diff --git a/src/app/components/Main/UserMenu.tsx b/src/app/components/Main/UserMenu.tsx index 7f55745ec..6c1c29dfc 100644 --- a/src/app/components/Main/UserMenu.tsx +++ b/src/app/components/Main/UserMenu.tsx @@ -7,12 +7,12 @@ import React from 'react'; import styled from 'styled-components'; import { FormattedMessage } from 'react-intl'; import { IAccountContext } from 'apla/auth'; +import { IEcosystemInfo } from 'apla/api'; import { CloseDropdownButton } from 'components/DropdownButton'; import PageLink from 'containers/Routing/PageLink'; import SystemButton from './SystemButton'; import Avatar from 'containers/Avatar'; -import { IKeyInfo } from 'apla/api'; const StyledUserMenu = styled.div` -webkit-app-region: no-drag; @@ -64,7 +64,7 @@ const StyledUserMenu = styled.div` export interface IUserMenuProps { isDefaultWallet: boolean; wallet: IAccountContext; - walletEcosystems: IKeyInfo[]; + walletEcosystems: IEcosystemInfo[]; onSwitchEcosystem: (ecosystem: string, defaultRole?: boolean) => void; onLogout: () => void; onChangePassword: () => void; @@ -156,7 +156,7 @@ class UserMenu extends React.Component { diff --git a/src/app/components/Modal/Auth/CopyWalletModal.tsx b/src/app/components/Modal/Auth/CopyWalletModal.tsx index 49b8bdbe1..92a92b88b 100644 --- a/src/app/components/Modal/Auth/CopyWalletModal.tsx +++ b/src/app/components/Modal/Auth/CopyWalletModal.tsx @@ -22,7 +22,7 @@ class CopyWalletModal extends Modal { } getCopyPayload = () => { - return `${this.props.params.wallet.address}\n${this.props.params.wallet.publicKey}`; + return this.props.params.wallet.publicKey; } render() { @@ -34,12 +34,6 @@ class CopyWalletModal extends Modal { - - - -
- - {this.props.params.wallet.address}
diff --git a/src/app/components/Modal/RolePickerModal.tsx b/src/app/components/Modal/RolePickerModal.tsx index 4a808b896..ef93f2dbb 100644 --- a/src/app/components/Modal/RolePickerModal.tsx +++ b/src/app/components/Modal/RolePickerModal.tsx @@ -12,7 +12,7 @@ import Modal, { ModalContainer, IModalProps } from './'; import Avatar from 'containers/Avatar'; export interface IRolePickerModalParams { - walletID: string; + account: string; ecosystem: string; ecosystemName: string; roles: IRoleInfo[]; @@ -33,7 +33,7 @@ class RolePickerModal extends ModalContainer {
diff --git a/src/app/components/PrintZone/index.tsx b/src/app/components/PrintZone/index.tsx new file mode 100644 index 000000000..eebc7d2f6 --- /dev/null +++ b/src/app/components/PrintZone/index.tsx @@ -0,0 +1,87 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) EGAAS S.A. All rights reserved. + * See LICENSE in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import React from 'react'; +import Button from 'components/Button'; +import { sendAttachment } from 'lib/fs'; +import { FormattedMessage } from 'react-intl'; + +export interface IPrintZoneProps { + stylesheet: string; +} + +class PrintZone extends React.Component { + private _container: HTMLDivElement; + private _output: HTMLIFrameElement; + + componentDidUpdate() { + this.onRepaint(); + } + + componentDidMount() { + this.onRepaint(); + } + + onRepaint = () => { + setTimeout(() => { + if (!this._output || !this._output.contentDocument.body) { + return; + } + + this._output.style.height = '0px'; + this._output.contentDocument.body.innerHTML = this._container.innerHTML; + const style = this._output.contentDocument.createElement('style'); + style.innerText = this.props.stylesheet; + this._output.contentDocument.body.appendChild(style); + this._output.style.height = this._output.contentDocument.body.scrollHeight + 'px'; + }); + } + + onSave = () => { + sendAttachment('Tx.html', this._output.contentDocument.body.innerHTML, 'text/html'); + } + + onPrint = () => { + this._output.contentWindow.focus(); + this._output.contentWindow.print(); + } + + render() { + return ( +
+
this._container = l} style={{ position: 'absolute', top: -50000, left: -50000 }}> + {this.props.children} +
+