Extract i18n from shared UI components (#4834)
* Actionbar i18n * ui Errors i18n * Features i18n * GapPriceSelector i18n * WIP * WIP #2 * Update methodDecoding * ModalBox -> functional * Signer pages i18n (missed previously) * Update ModalBox tests * Update variable
This commit is contained in:
parent
d98b7aab61
commit
4e5fd92e67
@ -15,11 +15,12 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import FileSaver from 'file-saver';
|
||||
import FileDownloadIcon from 'material-ui/svg-icons/file/file-download';
|
||||
|
||||
import Button from '../../Button';
|
||||
import { FileDownloadIcon } from '../../Icons';
|
||||
|
||||
class ActionbarExport extends Component {
|
||||
static propTypes = {
|
||||
@ -38,7 +39,12 @@ class ActionbarExport extends Component {
|
||||
<Button
|
||||
className={ className }
|
||||
icon={ <FileDownloadIcon /> }
|
||||
label='export'
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='ui.actionbar.export.button.export'
|
||||
defaultMessage='export'
|
||||
/>
|
||||
}
|
||||
onClick={ this.handleExport }
|
||||
/>
|
||||
);
|
||||
@ -46,9 +52,7 @@ class ActionbarExport extends Component {
|
||||
|
||||
handleExport = () => {
|
||||
const { filename, content } = this.props;
|
||||
|
||||
const text = JSON.stringify(content, null, 4);
|
||||
|
||||
const blob = new Blob([ text ], { type: 'application/json' });
|
||||
|
||||
FileSaver.saveAs(blob, `${filename}.json`);
|
||||
|
@ -15,10 +15,11 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import ActionSearch from 'material-ui/svg-icons/action/search';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import Button from '../../Button';
|
||||
import InputChip from '../../Form/InputChip';
|
||||
import { SearchIcon } from '../../Icons';
|
||||
|
||||
import styles from './search.css';
|
||||
|
||||
@ -74,7 +75,12 @@ export default class ActionbarSearch extends Component {
|
||||
<InputChip
|
||||
addOnBlur
|
||||
className={ styles.input }
|
||||
hint='Enter search input...'
|
||||
hint={
|
||||
<FormattedMessage
|
||||
id='ui.actionbar.search.hint'
|
||||
defaultMessage='Enter search input...'
|
||||
/>
|
||||
}
|
||||
ref='inputChip'
|
||||
tokens={ tokens }
|
||||
|
||||
@ -86,7 +92,7 @@ export default class ActionbarSearch extends Component {
|
||||
|
||||
<Button
|
||||
className={ styles.searchButton }
|
||||
icon={ <ActionSearch /> }
|
||||
icon={ <SearchIcon /> }
|
||||
label=''
|
||||
onClick={ this.handleSearchClick }
|
||||
/>
|
||||
|
@ -15,6 +15,7 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { Snackbar } from 'material-ui';
|
||||
@ -24,6 +25,19 @@ import { closeErrors } from './actions';
|
||||
import styles from './errors.css';
|
||||
|
||||
const ERROR_REGEX = /-(\d+): (.+)$/;
|
||||
const DURATION_OPEN = 60000;
|
||||
const STYLE_BODY = {
|
||||
height: 'auto',
|
||||
whiteSpace: 'pre-line'
|
||||
};
|
||||
const STYLE_CONTENT = {
|
||||
alignItems: 'center',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
lineHeight: '1.5em',
|
||||
padding: '0.75em 0'
|
||||
};
|
||||
|
||||
class Errors extends Component {
|
||||
static propTypes = {
|
||||
@ -46,23 +60,18 @@ class Errors extends Component {
|
||||
<Snackbar
|
||||
className={ styles.container }
|
||||
open
|
||||
action='close'
|
||||
autoHideDuration={ 60000 }
|
||||
action={
|
||||
<FormattedMessage
|
||||
id='ui.errors.close'
|
||||
defaultMessage='close'
|
||||
/>
|
||||
}
|
||||
autoHideDuration={ DURATION_OPEN }
|
||||
message={ text }
|
||||
onActionTouchTap={ onCloseErrors }
|
||||
onRequestClose={ this.onRequestClose }
|
||||
bodyStyle={ {
|
||||
whiteSpace: 'pre-line',
|
||||
height: 'auto'
|
||||
} }
|
||||
contentStyle={ {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
lineHeight: '1.5em',
|
||||
padding: '0.75em 0',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between'
|
||||
} }
|
||||
bodyStyle={ STYLE_BODY }
|
||||
contentStyle={ STYLE_CONTENT }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -14,6 +14,9 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
const MODES = {
|
||||
DEVELOPMENT: 1000, // only in dev mode, disabled by default, can be toggled
|
||||
TESTING: 1011, // feature is available in dev mode
|
||||
@ -28,13 +31,33 @@ const FEATURES = {
|
||||
const DEFAULTS = {
|
||||
[FEATURES.LANGUAGE]: {
|
||||
mode: MODES.TESTING,
|
||||
name: 'Language Selection',
|
||||
description: 'Allows changing the default interface language'
|
||||
name: (
|
||||
<FormattedMessage
|
||||
id='ui.features.defaults.i18n.name'
|
||||
defaultMssage='Language Selection'
|
||||
/>
|
||||
),
|
||||
description: (
|
||||
<FormattedMessage
|
||||
id='ui.features.defaults.i18n.desc'
|
||||
defaultMssage='Allows changing the default interface language'
|
||||
/>
|
||||
)
|
||||
},
|
||||
[FEATURES.LOGLEVELS]: {
|
||||
mode: MODES.TESTING,
|
||||
name: 'Logging Level Selection',
|
||||
description: 'Allows changing of the log levels for various components'
|
||||
name: (
|
||||
<FormattedMessage
|
||||
id='ui.features.defaults.logging.name'
|
||||
defaultMssage='Logging Level Selection'
|
||||
/>
|
||||
),
|
||||
description: (
|
||||
<FormattedMessage
|
||||
id='ui.features.defaults.logging.desc'
|
||||
defaultMssage='Allows changing of the log levels for various components'
|
||||
/>
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
export default class CustomTooltip extends Component {
|
||||
static propTypes = {
|
||||
@ -41,11 +42,15 @@ export default class CustomTooltip extends Component {
|
||||
return (
|
||||
<div>
|
||||
<p className='label'>
|
||||
{ count.toNumber() } transactions
|
||||
with gas price set from
|
||||
<span> { minprice.toFormat(0) } </span>
|
||||
to
|
||||
<span> { maxprice.toFormat(0) } </span>
|
||||
<FormattedMessage
|
||||
id='ui.gasPriceSelector.customTooltip.transactions'
|
||||
defaultMessage='{number} {number, plural, one {transaction} other {transactions}} with gas price set from {minPrice} to {maxPrice}'
|
||||
values={ {
|
||||
number: count.toNumber(),
|
||||
minPrice: <span>{ minprice.toFormat(0) }</span>,
|
||||
maxPrice: <span>{ maxprice.toFormat(0) }</span>
|
||||
} }
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
@ -34,6 +34,7 @@ export DoneIcon from 'material-ui/svg-icons/action/done-all';
|
||||
export DialIcon from 'material-ui/svg-icons/communication/dialpad';
|
||||
export EditIcon from 'material-ui/svg-icons/content/create';
|
||||
export ErrorIcon from 'material-ui/svg-icons/alert/error';
|
||||
export FileDownloadIcon from 'material-ui/svg-icons/file/file-download';
|
||||
export FileUploadIcon from 'material-ui/svg-icons/file/file-upload';
|
||||
export FileIcon from 'material-ui/svg-icons/editor/insert-drive-file';
|
||||
export FingerprintIcon from 'material-ui/svg-icons/action/fingerprint';
|
||||
@ -55,6 +56,7 @@ export RefreshIcon from 'material-ui/svg-icons/action/autorenew';
|
||||
export ReorderIcon from 'material-ui/svg-icons/action/reorder';
|
||||
export ReplayIcon from 'material-ui/svg-icons/av/replay';
|
||||
export SaveIcon from 'material-ui/svg-icons/content/save';
|
||||
export SearchIcon from 'material-ui/svg-icons/action/search';
|
||||
export SendIcon from 'material-ui/svg-icons/content/send';
|
||||
export SettingsIcon from 'material-ui/svg-icons/action/settings';
|
||||
export SnoozeIcon from 'material-ui/svg-icons/av/snooze';
|
||||
|
@ -17,6 +17,7 @@
|
||||
import { CircularProgress } from 'material-ui';
|
||||
import moment from 'moment';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { TypedInput, InputAddress } from '../Form';
|
||||
@ -112,28 +113,50 @@ class MethodDecoding extends Component {
|
||||
return null;
|
||||
}
|
||||
|
||||
const gasValue = gas.mul(gasPrice);
|
||||
const gasProvided = (
|
||||
<span className={ styles.highlight }>
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.gasValues'
|
||||
defaultMessage='{gas} gas ({gasPrice}M/{tag})'
|
||||
values={ {
|
||||
gas: gas.toFormat(0),
|
||||
gasPrice: gasPrice.div(1000000).toFormat(0),
|
||||
tag: <small>ETH</small>
|
||||
} }
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
const gasProvidedEth = (
|
||||
<span className={ styles.highlight }>
|
||||
{ this.renderEtherValue(gas.mul(gasPrice)) }
|
||||
</span>
|
||||
);
|
||||
const gasUsed = transaction.gasUsed
|
||||
? (
|
||||
<span className={ styles.highlight }>
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.gasUsed'
|
||||
defaultMessage=' ({gas} gas used)'
|
||||
values={ {
|
||||
gas: transaction.gasUsed.toFormat(0)
|
||||
} }
|
||||
/>
|
||||
</span>
|
||||
)
|
||||
: '';
|
||||
|
||||
return (
|
||||
<div className={ styles.gasDetails }>
|
||||
<span>{ historic ? 'Provided' : 'Provides' } </span>
|
||||
<span className={ styles.highlight }>
|
||||
{ gas.toFormat(0) } gas ({ gasPrice.div(1000000).toFormat(0) }M/<small>ETH</small>)
|
||||
</span>
|
||||
{
|
||||
transaction.gasUsed
|
||||
? (
|
||||
<span>
|
||||
<span>used</span>
|
||||
<span className={ styles.highlight }>
|
||||
{ transaction.gasUsed.toFormat(0) } gas
|
||||
</span>
|
||||
</span>
|
||||
)
|
||||
: null
|
||||
}
|
||||
<span> for a total transaction value of </span>
|
||||
<span className={ styles.highlight }>{ this.renderEtherValue(gasValue) }</span>
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.txValues'
|
||||
defaultMessage='{historic, select, true {Provided} false {Provides}} {gasProvided}{gasUsed} for a total transaction value of {gasProvidedEth}'
|
||||
values={ {
|
||||
historic,
|
||||
gasProvided,
|
||||
gasProvidedEth,
|
||||
gasUsed
|
||||
} }
|
||||
/>
|
||||
{ this.renderMinBlock() }
|
||||
</div>
|
||||
);
|
||||
@ -148,14 +171,40 @@ class MethodDecoding extends Component {
|
||||
}
|
||||
|
||||
if (condition.block && condition.block.gt(0)) {
|
||||
const blockNumber = (
|
||||
<span className={ styles.highlight }>
|
||||
#{ condition.block.toFormat(0) }
|
||||
</span>
|
||||
);
|
||||
|
||||
return (
|
||||
<span>, { historic ? 'Submitted' : 'Submission' } at block <span className={ styles.highlight }>#{ condition.block.toFormat(0) }</span></span>
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.condition.block'
|
||||
defaultMessage=', {historic, select, true {Submitted} false {Submission}} at block {blockNumber}'
|
||||
values={ {
|
||||
historic,
|
||||
blockNumber
|
||||
} }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (condition.time) {
|
||||
const timestamp = (
|
||||
<span className={ styles.highlight }>
|
||||
{ moment(condition.time).format('LLLL') }
|
||||
</span>
|
||||
);
|
||||
|
||||
return (
|
||||
<span>, { historic ? 'Submitted' : 'Submission' } at <span className={ styles.highlight }>{ moment(condition.time).format('LLLL') }</span></span>
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.condition.time'
|
||||
defaultMessage=', {historic, select, true {Submitted} false {Submission}} at {timestamp}'
|
||||
values={ {
|
||||
historic,
|
||||
timestamp
|
||||
} }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -190,9 +239,12 @@ class MethodDecoding extends Component {
|
||||
getAscii () {
|
||||
const { api } = this.context;
|
||||
const { transaction } = this.props;
|
||||
const ascii = api.util.hexToAscii(transaction.input || transaction.data);
|
||||
const value = api.util.hexToAscii(transaction.input || transaction.data);
|
||||
|
||||
return { value: ascii, valid: ASCII_INPUT.test(ascii) };
|
||||
return {
|
||||
value,
|
||||
valid: ASCII_INPUT.test(value)
|
||||
};
|
||||
}
|
||||
|
||||
renderInputValue () {
|
||||
@ -218,16 +270,29 @@ class MethodDecoding extends Component {
|
||||
? text
|
||||
: text.slice(0, 50) + '...';
|
||||
|
||||
return (
|
||||
<div className={ styles.details }>
|
||||
<span>with the </span>
|
||||
const inputDesc = (
|
||||
<span
|
||||
onClick={ this.toggleInputType }
|
||||
className={ [ styles.clickable, styles.noSelect ].join(' ') }
|
||||
>
|
||||
{ type === 'ascii' ? 'input' : 'data' }
|
||||
{
|
||||
type === 'ascii'
|
||||
? (
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.input.input'
|
||||
defaultMessage='input'
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.input.data'
|
||||
defaultMessage='data'
|
||||
/>
|
||||
)
|
||||
}
|
||||
</span>
|
||||
<span> </span>
|
||||
);
|
||||
const inputValue = (
|
||||
<span
|
||||
onClick={ this.toggleInputExpand }
|
||||
className={ expandable ? styles.clickable : '' }
|
||||
@ -236,6 +301,18 @@ class MethodDecoding extends Component {
|
||||
{ textToShow }
|
||||
</code>
|
||||
</span>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={ styles.details }>
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.input.withInput'
|
||||
defaultMessage='with the {inputDesc} {inputValue}'
|
||||
values={ {
|
||||
inputDesc,
|
||||
inputValue
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -251,15 +328,19 @@ class MethodDecoding extends Component {
|
||||
default:
|
||||
return (
|
||||
<div className={ styles.details }>
|
||||
<div>
|
||||
<span>{ historic ? 'Transferred' : 'Will transfer' } </span>
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.token.transfer'
|
||||
defaultMessage='{historic, select, true {Transferred} false {Will transfer}} {value} to {address}'
|
||||
values={ {
|
||||
historic,
|
||||
value: (
|
||||
<span className={ styles.highlight }>
|
||||
{ this.renderTokenValue(value.value) }
|
||||
</span>
|
||||
<span> to </span>
|
||||
</div>
|
||||
|
||||
{ this.renderAddressName(address) }
|
||||
),
|
||||
address: this.renderAddressName(address)
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -272,7 +353,10 @@ class MethodDecoding extends Component {
|
||||
if (!historic) {
|
||||
return (
|
||||
<div className={ styles.details }>
|
||||
Will deploy a contract.
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.deploy.willDeploy'
|
||||
defaultMessage='Will deploy a contract'
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -280,15 +364,24 @@ class MethodDecoding extends Component {
|
||||
return (
|
||||
<div className={ styles.details }>
|
||||
<div>
|
||||
<span>Deployed a contract at address </span>
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.deploy.address'
|
||||
defaultMessage='Deployed a contract at address '
|
||||
/>
|
||||
</div>
|
||||
|
||||
{ this.renderAddressName(transaction.creates, false) }
|
||||
|
||||
<div>
|
||||
{ methodInputs && methodInputs.length ? 'with the following parameters:' : ''}
|
||||
{
|
||||
methodInputs && methodInputs.length
|
||||
? (
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.deploy.params'
|
||||
defaultMessage='with the following parameters:'
|
||||
/>
|
||||
)
|
||||
: ''
|
||||
}
|
||||
</div>
|
||||
|
||||
<div className={ styles.inputs }>
|
||||
{ this.renderInputs() }
|
||||
</div>
|
||||
@ -300,17 +393,32 @@ class MethodDecoding extends Component {
|
||||
const { historic, transaction } = this.props;
|
||||
const { isContract } = this.state;
|
||||
|
||||
return (
|
||||
<div className={ styles.details }>
|
||||
<div>
|
||||
<span>{ historic ? 'Received' : 'Will receive' } </span>
|
||||
const valueEth = (
|
||||
<span className={ styles.highlight }>
|
||||
{ this.renderEtherValue(transaction.value) }
|
||||
</span>
|
||||
<span> from { isContract ? 'the contract' : '' } </span>
|
||||
</div>
|
||||
);
|
||||
const aContract = isContract
|
||||
? (
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.receive.contract'
|
||||
defaultMessage='the contract '
|
||||
/>
|
||||
)
|
||||
: '';
|
||||
|
||||
{ this.renderAddressName(transaction.from) }
|
||||
return (
|
||||
<div className={ styles.details }>
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.receive.info'
|
||||
defaultMessage='{historic, select, true {Received} false {Will receive}} {valueEth} from {aContract}{address}'
|
||||
values={ {
|
||||
historic,
|
||||
valueEth,
|
||||
aContract,
|
||||
address: this.renderAddressName(transaction.from)
|
||||
} }
|
||||
/>
|
||||
{ this.renderInputValue() }
|
||||
</div>
|
||||
);
|
||||
@ -320,17 +428,32 @@ class MethodDecoding extends Component {
|
||||
const { historic, transaction } = this.props;
|
||||
const { isContract } = this.state;
|
||||
|
||||
return (
|
||||
<div className={ styles.details }>
|
||||
<div>
|
||||
<span>{ historic ? 'Transferred' : 'Will transfer' } </span>
|
||||
const valueEth = (
|
||||
<span className={ styles.highlight }>
|
||||
{ this.renderEtherValue(transaction.value) }
|
||||
</span>
|
||||
<span> to { isContract ? 'the contract' : '' } </span>
|
||||
</div>
|
||||
);
|
||||
const aContract = isContract
|
||||
? (
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.transfer.contract'
|
||||
defaultMessage='the contract '
|
||||
/>
|
||||
)
|
||||
: '';
|
||||
|
||||
{ this.renderAddressName(transaction.to) }
|
||||
return (
|
||||
<div className={ styles.details }>
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.transfer.info'
|
||||
defaultMessage='{historic, select, true {Transferred} false {Will transfer}} {valueEth} to {aContract}{address}'
|
||||
values={ {
|
||||
historic,
|
||||
valueEth,
|
||||
aContract,
|
||||
address: this.renderAddressName(transaction.to)
|
||||
} }
|
||||
/>
|
||||
{ this.renderInputValue() }
|
||||
</div>
|
||||
);
|
||||
@ -340,26 +463,31 @@ class MethodDecoding extends Component {
|
||||
const { historic, transaction } = this.props;
|
||||
const { methodName, methodInputs } = this.state;
|
||||
|
||||
return (
|
||||
<div className={ styles.details }>
|
||||
<div className={ styles.description }>
|
||||
<div>
|
||||
<span>{ historic ? 'Executed' : 'Will execute' } the </span>
|
||||
<span className={ styles.name }>{ methodName }</span>
|
||||
<span> function on the contract </span>
|
||||
</div>
|
||||
|
||||
{ this.renderAddressName(transaction.to) }
|
||||
|
||||
<div>
|
||||
<span>transferring </span>
|
||||
const method = (
|
||||
<span className={ styles.name }>
|
||||
{ methodName }
|
||||
</span>
|
||||
);
|
||||
const ethValue = (
|
||||
<span className={ styles.highlight }>
|
||||
{ this.renderEtherValue(transaction.value) }
|
||||
</span>
|
||||
<span>
|
||||
{ methodInputs.length ? ', passing the following parameters:' : '.' }
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={ styles.details }>
|
||||
<div className={ styles.description }>
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.signature.info'
|
||||
defaultMessage='{historic, select, true {Executed} false {Will execute}} the {method} function on the contract {address} trsansferring {ethValue}{inputLength, plural, zero {,} other {passing the following {inputLength, plural, one {parameter} other {parameters}}}}'
|
||||
values={ {
|
||||
historic,
|
||||
method,
|
||||
ethValue,
|
||||
address: this.renderAddressName(transaction.to),
|
||||
inputLength: methodInputs.length
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
<div className={ styles.inputs }>
|
||||
{ this.renderInputs() }
|
||||
@ -371,23 +499,29 @@ class MethodDecoding extends Component {
|
||||
renderUnknownMethod () {
|
||||
const { historic, transaction } = this.props;
|
||||
|
||||
return (
|
||||
<div className={ styles.details }>
|
||||
<div>
|
||||
<span>{ historic ? 'Executed' : 'Will execute' } </span>
|
||||
<span className={ styles.name }>an unknown/unregistered</span>
|
||||
<span> method on the contract </span>
|
||||
</div>
|
||||
|
||||
{ this.renderAddressName(transaction.to) }
|
||||
|
||||
<div>
|
||||
<span>transferring </span>
|
||||
const method = (
|
||||
<span className={ styles.name }>
|
||||
an unknown/unregistered
|
||||
</span>
|
||||
);
|
||||
const ethValue = (
|
||||
<span className={ styles.highlight }>
|
||||
{ this.renderEtherValue(transaction.value) }
|
||||
</span>
|
||||
<span>.</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={ styles.details }>
|
||||
<FormattedMessage
|
||||
id='ui.methodDecoding.unknown.info'
|
||||
defaultMessage='{historic, select, true {Executed} false {Will execute}} the {method} on the contract {address} transferring {ethValue}.'
|
||||
values={ {
|
||||
historic,
|
||||
method,
|
||||
ethValue,
|
||||
address: this.renderAddressName(transaction.to)
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
35
js/src/ui/ModalBox/body.js
Normal file
35
js/src/ui/ModalBox/body.js
Normal file
@ -0,0 +1,35 @@
|
||||
// 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/>.
|
||||
|
||||
import React, { PropTypes } from 'react';
|
||||
|
||||
import styles from './modalBox.css';
|
||||
|
||||
export default function Body ({ children }) {
|
||||
if (!children) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ styles.body }>
|
||||
{ children }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Body.propTypes = {
|
||||
children: PropTypes.node
|
||||
};
|
@ -14,60 +14,30 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import React, { PropTypes } from 'react';
|
||||
|
||||
import { nodeOrStringProptype } from '~/util/proptypes';
|
||||
|
||||
import Body from './body';
|
||||
import Summary from './summary';
|
||||
import styles from './modalBox.css';
|
||||
|
||||
export default class ModalBox extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
icon: PropTypes.node.isRequired,
|
||||
summary: nodeOrStringProptype()
|
||||
}
|
||||
|
||||
render () {
|
||||
const { icon } = this.props;
|
||||
|
||||
export default function ModalBox ({ children, icon, summary }) {
|
||||
return (
|
||||
<div className={ styles.body }>
|
||||
<div className={ styles.icon }>
|
||||
{ icon }
|
||||
</div>
|
||||
<div className={ styles.content }>
|
||||
{ this.renderSummary() }
|
||||
{ this.renderBody() }
|
||||
<Summary summary={ summary } />
|
||||
<Body children={ children } />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderBody () {
|
||||
const { children } = this.props;
|
||||
|
||||
if (!children) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ styles.body }>
|
||||
{ children }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderSummary () {
|
||||
const { summary } = this.props;
|
||||
|
||||
if (!summary) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ styles.summary }>
|
||||
{ summary }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ModalBox.propTypes = {
|
||||
children: PropTypes.node,
|
||||
icon: PropTypes.node.isRequired,
|
||||
summary: nodeOrStringProptype()
|
||||
};
|
||||
|
@ -21,12 +21,16 @@ import ModalBox from './';
|
||||
|
||||
let component;
|
||||
|
||||
const CHILDREN = <div id='testChild'>testChild</div>;
|
||||
const ICON = <div id='testIcon'>testIcon</div>;
|
||||
const SUMMARY = <div id='testSummary'>testSummary</div>;
|
||||
|
||||
function render () {
|
||||
component = shallow(
|
||||
<ModalBox
|
||||
children={ <div id='testChild'>testChild</div> }
|
||||
icon={ <div id='testIcon'>testIcon</div> }
|
||||
summary={ <div id='testSummary'>testSummary</div> }
|
||||
children={ CHILDREN }
|
||||
icon={ ICON }
|
||||
summary={ SUMMARY }
|
||||
/>
|
||||
);
|
||||
|
||||
@ -42,15 +46,17 @@ describe('ui/ModalBox', () => {
|
||||
expect(component).to.be.ok;
|
||||
});
|
||||
|
||||
it('adds the children as supplied', () => {
|
||||
expect(component.find('#testChild').text()).to.equal('testChild');
|
||||
});
|
||||
|
||||
it('adds the icon as supplied', () => {
|
||||
expect(component.find('#testIcon').text()).to.equal('testIcon');
|
||||
});
|
||||
|
||||
it('adds the summary as supplied', () => {
|
||||
expect(component.find('#testSummary').text()).to.equal('testSummary');
|
||||
describe('components', () => {
|
||||
it('adds the Body as supplied', () => {
|
||||
expect(component.find('Body').props().children).to.deep.equal(CHILDREN);
|
||||
});
|
||||
|
||||
it('adds the Summary as supplied', () => {
|
||||
expect(component.find('Summary').props().summary).to.deep.equal(SUMMARY);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
37
js/src/ui/ModalBox/summary.js
Normal file
37
js/src/ui/ModalBox/summary.js
Normal file
@ -0,0 +1,37 @@
|
||||
// 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/>.
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { nodeOrStringProptype } from '~/util/proptypes';
|
||||
|
||||
import styles from './modalBox.css';
|
||||
|
||||
export default function Summary ({ summary }) {
|
||||
if (!summary) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ styles.summary }>
|
||||
{ summary }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Summary.propTypes = {
|
||||
summary: nodeOrStringProptype()
|
||||
};
|
@ -16,6 +16,7 @@
|
||||
|
||||
import BigNumber from 'bignumber.js';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
|
||||
@ -65,7 +66,10 @@ class Embedded extends Component {
|
||||
if (!pending.length) {
|
||||
return (
|
||||
<div className={ styles.none }>
|
||||
There are currently no pending requests awaiting your confirmation
|
||||
<FormattedMessage
|
||||
id='signer.embedded.noPending'
|
||||
defaultMessage='There are currently no pending requests awaiting your confirmation'
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -15,10 +15,11 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import BigNumber from 'bignumber.js';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { observer } from 'mobx-react';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
|
||||
import Store from '../../store';
|
||||
import * as RequestsActions from '~/redux/providers/signerActions';
|
||||
@ -74,7 +75,14 @@ class RequestsPage extends Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<Container title='Local Transactions'>
|
||||
<Container
|
||||
title={
|
||||
<FormattedMessage
|
||||
id='signer.requestsPage.queueTitle'
|
||||
defaultMessage='Local Transactions'
|
||||
/>
|
||||
}
|
||||
>
|
||||
<TxList
|
||||
address=''
|
||||
hashes={ localHashes }
|
||||
@ -90,7 +98,10 @@ class RequestsPage extends Component {
|
||||
return (
|
||||
<Container>
|
||||
<div className={ styles.noRequestsMsg }>
|
||||
There are no requests requiring your confirmation.
|
||||
<FormattedMessage
|
||||
id='signer.requestsPage.noPending'
|
||||
defaultMessage='There are no requests requiring your confirmation.'
|
||||
/>
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
@ -99,7 +110,14 @@ class RequestsPage extends Component {
|
||||
const items = pending.sort(this._sortRequests).map(this.renderPending);
|
||||
|
||||
return (
|
||||
<Container title='Pending Requests'>
|
||||
<Container
|
||||
title={
|
||||
<FormattedMessage
|
||||
id='signer.requestsPage.pendingTitle'
|
||||
defaultMessage='Pending Requests'
|
||||
/>
|
||||
}
|
||||
>
|
||||
{ items }
|
||||
</Container>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user