diff --git a/app/actions/account.js b/app/actions/account.js index 7aabf36..d788aa0 100644 --- a/app/actions/account.js +++ b/app/actions/account.js @@ -4,6 +4,10 @@ import { Asset, Price, Client } from 'dsteem' import type { accountStateType } from '../reducers/account'; import * as ProcessingActions from './processing'; +export const ACCOUNT_CUSTOM_JSON_STARTED = 'ACCOUNT_CUSTOM_JSON_STARTED'; +export const ACCOUNT_CUSTOM_JSON_RESOLVED = 'ACCOUNT_CUSTOM_JSON_RESOLVED'; +export const ACCOUNT_CUSTOM_JSON_FAILED = 'ACCOUNT_CUSTOM_JSON_FAILED'; +export const ACCOUNT_CUSTOM_JSON_COMPLETED = 'ACCOUNT_CUSTOM_JSON_COMPLETED'; export const ACCOUNT_DATA_MINIMUM_ACCOUNT_DELEGATION = 'ACCOUNT_DATA_MINIMUM_ACCOUNT_DELEGATION'; export const ACCOUNT_DATA_UPDATE = 'ACCOUNT_DATA_UPDATE'; export const ACCOUNT_DATA_UPDATE_FAILED = 'ACCOUNT_DATA_UPDATE_FAILED'; @@ -422,3 +426,32 @@ export function cancelWithdrawVesting(wif, params) { }); }; } + +export function customJson(wif, params) { + return (dispatch: () => void) => { + const { account, id, json } = params + dispatch({ + type: ACCOUNT_CUSTOM_JSON_STARTED + }) + steem.broadcast.customJson(wif, [], [account], id, json, function(err, result) { + if(result) { + dispatch({ + type: ACCOUNT_CUSTOM_JSON_RESOLVED + }) + } + if(err) { + dispatch({ + type: ACCOUNT_CUSTOM_JSON_FAILED, + payload: err + }) + } + }); + }; +} + + +export function customJsonCompleted() { + return { + type: ACCOUNT_CUSTOM_JSON_COMPLETED, + } +} diff --git a/app/components/Accounts/CustomJSON.js b/app/components/Accounts/CustomJSON.js new file mode 100644 index 0000000..89514ef --- /dev/null +++ b/app/components/Accounts/CustomJSON.js @@ -0,0 +1,142 @@ +// @flow +import React, { Component } from 'react'; +import { Grid, Header, Message, Segment, Select, Table } from 'semantic-ui-react'; + +import { Form, Input } from 'formsy-semantic-ui-react'; + +import AccountName from '../global/AccountName'; + +export default class AccountsCustomJSON extends Component { + constructor(props) { + super(props) + this.state = { + account: props.keys.names[0], + id: '', + json: '', + message: false + } + } + + resetState(extraState) { + this.setState(Object.assign({}, { + id: '', + json: '' + }, extraState)) + } + + + handleIdChange = (e: SyntheticEvent, { value }: { value: any }) => { + this.setState({ + id: value + }) + } + + handleJsonChange = (e: SyntheticEvent, { value }: { value: any }) => { + this.setState({ + json: value.trim() + }) + } + + handleAccountChange = (e: SyntheticEvent, { value }: { value: any }) => { + this.setState({ + account: value + }) + } + + onValidSubmit = ( + e: SyntheticEvent + ) => { + const { account, id, json } = this.state + this.setState({message: false}) + this.props.actions.useKey('customJson', { account, id, json }, this.props.keys.permissions[account]); + } + + componentWillReceiveProps = (nextProps) => { + if (nextProps.processing.account_custom_json_resolved) { + nextProps.actions.customJsonCompleted(); + this.resetState({ + 'message': 'Your transaction was successfully broadcast.' + }); + } + } + + render() { + const { + account_custom_json_error, + account_custom_json_pending, + account_custom_json_resolved + } = this.props.processing; + const keys = this.props.keys; + const availableFrom = keys.names.map((name) => { + const hasPermission = (keys.permissions[name].type === 'active' || keys.permissions[name].type === 'owner'); + return hasPermission ? { + key: name, + text: name, + value: name + } : { + key: name, + disabled: true, + text: name + ' (unavailable - active/owner key not loaded)' + }; + }); + let message = false + if(this.state.message) { + message = ( + + ) + } + return ( + +
+ + Broadcast a Custom JSON operation to the Steem blockchain. + +
+ {message} +
+ + + + + + +
+ ); + } +} diff --git a/app/components/Settings.js b/app/components/Settings.js index 5e1164b..3b5f200 100644 --- a/app/components/Settings.js +++ b/app/components/Settings.js @@ -16,7 +16,6 @@ export default class Settings extends Component { onValidSubmit = ( e: SyntheticEvent ) => { - console.log(e) const { setPreference } = this.props.actions; setPreference('steemd_node', e.steemd_node); } diff --git a/app/containers/AdvancedPage.js b/app/containers/AdvancedPage.js new file mode 100644 index 0000000..1826971 --- /dev/null +++ b/app/containers/AdvancedPage.js @@ -0,0 +1,83 @@ +// @flow +import React, { Component } from 'react'; +import { bindActionCreators } from 'redux'; +import { Redirect } from 'react-router'; +import { connect } from 'react-redux'; +import { Button, Header, Icon, Menu, Modal, Segment, Table } from 'semantic-ui-react'; + +import AccountsCustomJson from '../components/Accounts/CustomJSON.js'; +import * as AccountActions from '../actions/account'; +import * as KeyActions from '../actions/keys'; +import * as ProcessingActions from '../actions/processing'; +import MenuBar from './MenuBar'; +import ContentBar from '../components/ContentBar'; + +class AccountsPage extends Component { + + state = { + activeItem: 'custom_json' + }; + + handleItemClick = (e, { name }) => this.setState({ activeItem: name }) + + render() { + if (!this.props.keys.isUser) { + return ; + } + const { activeItem } = this.state; + let activeTab = ; + switch (activeItem) { + default: { + activeTab = ; + break; + } + } + return ( + + +
+ + + Advanced Operations + + This section can be used to perform more advanced operations using the loaded accounts. + + +
+
+ + + + {activeTab} + +
+ ); + } +} + +function mapStateToProps(state) { + return { + account: state.account, + keys: state.keys, + processing: state.processing, + steem: state.steem + }; +} + +function mapDispatchToProps(dispatch) { + return { + actions: bindActionCreators({ + ...AccountActions, + ...KeyActions, + ...ProcessingActions, + }, dispatch) + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(AccountsPage); diff --git a/app/containers/MenuBar.js b/app/containers/MenuBar.js index 0689cca..bfc069b 100644 --- a/app/containers/MenuBar.js +++ b/app/containers/MenuBar.js @@ -75,6 +75,10 @@ class MenuBar extends Component { Settings + + + Advanced + + );