OSDN Git Service

add advanced build transaction options
[bytom/bytom-electron.git] / src / features / transactions / components / New / New.jsx
1 import { BaseNew, FormContainer, FormSection, FieldLabel, JsonField, TextField } from 'features/shared/components'
2 import { DropdownButton, MenuItem } from 'react-bootstrap'
3 import { reduxForm } from 'redux-form'
4 import ActionItem from './FormActionItem'
5 import React from 'react'
6 import styles from './New.scss'
7
8 class Form extends React.Component {
9   constructor(props) {
10     super(props)
11     this.state = {
12       showDropdown: false
13     }
14
15     this.submitWithValidation = this.submitWithValidation.bind(this)
16     this.addActionItem = this.addActionItem.bind(this)
17     this.removeActionItem = this.removeActionItem.bind(this)
18     this.toggleDropwdown = this.toggleDropwdown.bind(this)
19     this.closeDropdown = this.closeDropdown.bind(this)
20     this.disableSubmit = this.disableSubmit.bind(this)
21   }
22
23   toggleDropwdown() {
24     this.setState({ showDropdown: !this.state.showDropdown })
25   }
26
27   closeDropdown() {
28     this.setState({ showDropdown: false })
29   }
30
31   addActionItem(type) {
32     this.props.fields.actions.addField({
33       type: type,
34       referenceData: '{\n\t\n}'
35     })
36     this.closeDropdown()
37   }
38
39   disableSubmit(actions) {
40     return actions.length == 0 & !this.state.showAdvanced
41   }
42
43   removeActionItem(index) {
44     this.props.fields.actions.removeField(index)
45   }
46
47   submitWithValidation(data) {
48     return new Promise((resolve, reject) => {
49       this.props.submitForm(data)
50         .catch((err) => {
51           const response = {}
52
53           if (err.data) {
54             response.actions = []
55
56             err.data.forEach((error) => {
57               response.actions[error.data.actionIndex] = {type: error}
58             })
59           }
60
61           response['_error'] = err
62           return reject(response)
63         })
64     })
65   }
66
67   render() {
68     const {
69       fields: { baseTransaction, actions, submitAction, password },
70       error,
71       handleSubmit,
72       submitting
73     } = this.props
74
75     let submitLabel = 'Submit transaction'
76     if (submitAction.value == 'generate') {
77       submitLabel = 'Generate transaction hex'
78     }
79
80     return(
81       <FormContainer
82         error={error}
83         label='New transaction'
84         submitLabel={submitLabel}
85         onSubmit={handleSubmit(this.submitWithValidation)}
86         showSubmitIndicator={true}
87         submitting={submitting}
88         disabled={this.disableSubmit(actions)} >
89
90         <FormSection title='Actions'>
91           {actions.map((action, index) =>
92             <ActionItem
93               key={index}
94               index={index}
95               fieldProps={action}
96               accounts={this.props.accounts}
97               assets={this.props.assets}
98               remove={this.removeActionItem}
99             />)}
100
101             <div className={`btn-group ${styles.addActionContainer} ${this.state.showDropdown && 'open'}`}>
102               <DropdownButton
103                 className={`btn btn-default ${styles.addAction}`}
104                 id='input-dropdown-addon'
105                 title='+ Add action'
106                 onSelect={this.addActionItem}
107               >
108                 <MenuItem eventKey='issue'>Issue</MenuItem>
109                 <MenuItem eventKey='spend_account'>Spend from account</MenuItem>
110                 {/*<MenuItem eventKey='spend_account_unspent_output'>Spend unspent output</MenuItem>*/}
111                 <MenuItem eventKey='control_account'>Control with account</MenuItem>
112                 <MenuItem eventKey='control_receiver'>Control with receiver</MenuItem>
113                 <MenuItem eventKey='control_address'>Control with address</MenuItem>
114                 <MenuItem eventKey='retire'>Retire</MenuItem>
115                 {/*<MenuItem eventKey='set_transaction_reference_data'>Set transaction reference data</MenuItem>*/}
116               </DropdownButton>
117             </div>
118         </FormSection>
119
120         {!this.state.showAdvanced &&
121           <FormSection>
122             <a href='#'
123               className={styles.showAdvanced}
124               onClick={(e) => {
125                 e.preventDefault()
126                 this.setState({showAdvanced: true})
127               }}
128             >
129               Show advanced options
130             </a>
131           </FormSection>
132         }
133
134         {this.state.showAdvanced && <FormSection title='Advanced Options'>
135           <div>
136             <TextField
137               title='Base transaction'
138               placeholder='Paste transaction hex here...'
139               fieldProps={baseTransaction}
140               autoFocus={true} />
141
142             <FieldLabel>Transaction Build Type</FieldLabel>
143             <table className={styles.submitTable}>
144               <tbody>
145                 <tr>
146                   <td><input id='submit_action_submit' type='radio' {...submitAction} value='submit' checked={submitAction.value == 'submit'} /></td>
147                   <td>
148                     <label htmlFor='submit_action_submit'>Submit transaction to blockchain</label>
149                     <br />
150                     <label htmlFor='submit_action_submit' className={styles.submitDescription}>
151                       This transaction will be signed by the MockHSM and submitted to the blockchain.
152                     </label>
153                   </td>
154                 </tr>
155                 <tr>
156                   <td><input id='submit_action_generate' type='radio' {...submitAction} value='generate' checked={submitAction.value == 'generate'} /></td>
157                   <td>
158                     <label htmlFor='submit_action_generate'>Allow additional actions</label>
159                     <br />
160                     <label htmlFor='submit_action_generate' className={styles.submitDescription}>
161                       These actions will be signed by the MockHSM and returned as a
162                       transaction hex string, which should be used as the base
163                       transaction in a multi-party swap. This transaction will be
164                       valid for one hour.
165                     </label>
166                   </td>
167                 </tr>
168               </tbody>
169             </table>
170           </div>
171         </FormSection>}
172       </FormContainer>
173     )
174   }
175 }
176
177 const validate = values => {
178   const errors = {actions: {}}
179
180   // Base transaction
181   let baseTx = values.baseTransaction || ''
182   if (baseTx.trim().match(/[^0-9a-fA-F]/)) {
183     errors.baseTransaction = 'Base transaction must be a hex string.'
184   }
185
186   // Actions
187   let fieldError
188   values.actions.forEach((action, index) => {
189     fieldError = JsonField.validator(values.actions[index].referenceData)
190     if (fieldError) {
191       errors.actions[index] = {...errors.actions[index], referenceData: fieldError}
192     }
193   })
194
195   return errors
196 }
197
198 export default BaseNew.connect(
199   state => ({
200     ...BaseNew.mapStateToProps('transaction')(state),
201   }),
202   BaseNew.mapDispatchToProps('transaction'),
203   reduxForm({
204     form: 'NewTransactionForm',
205     fields: [
206       'baseTransaction',
207       'actions[].accountId',
208       'actions[].accountAlias',
209       'actions[].assetId',
210       'actions[].assetAlias',
211       'actions[].amount',
212       'actions[].receiver',
213       'actions[].outputId',
214       'actions[].referenceData',
215       'actions[].type',
216       'actions[].address',
217       'actions[].password',
218       'submitAction',
219       'password'
220     ],
221     validate,
222     initialValues: {
223       submitAction: 'submit',
224     },
225   }
226   )(Form)
227 )