OSDN Git Service

correct build transaction
[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     // if (this.props.replicationLag === null || this.props.replicationLag >= lagThreshold) {
49     //   return Promise.reject({
50     //     _error: `Replication lag must be less than ${lagThreshold} to submit transactions via the dashboard. Please wait for the local core to catch up to the generator.`
51     //   })
52     // }
53
54     return new Promise((resolve, reject) => {
55       this.props.submitForm(data)
56         .catch((err) => {
57           const response = {}
58
59           if (err.data) {
60             response.actions = []
61
62             err.data.forEach((error) => {
63               response.actions[error.data.actionIndex] = {type: error}
64             })
65           }
66
67           response['_error'] = err
68           return reject(response)
69         })
70     })
71   }
72
73   render() {
74     const {
75       fields: { baseTransaction, actions, submitAction },
76       error,
77       handleSubmit,
78       submitting
79     } = this.props
80
81     let submitLabel = 'Submit transaction'
82     if (submitAction.value == 'generate') {
83       submitLabel = 'Generate transaction hex'
84     }
85
86     return(
87       <FormContainer
88         error={error}
89         label='New transaction'
90         submitLabel={submitLabel}
91         onSubmit={handleSubmit(this.submitWithValidation)}
92         showSubmitIndicator={true}
93         submitting={submitting}
94         disabled={this.disableSubmit(actions)} >
95
96         <FormSection title='Actions'>
97           {actions.map((action, index) =>
98             <ActionItem
99               key={index}
100               index={index}
101               fieldProps={action}
102               accounts={this.props.accounts}
103               assets={this.props.assets}
104               remove={this.removeActionItem}
105             />)}
106
107             <div className={`btn-group ${styles.addActionContainer} ${this.state.showDropdown && 'open'}`}>
108               <DropdownButton
109                 className={`btn btn-default ${styles.addAction}`}
110                 id='input-dropdown-addon'
111                 title='+ Add action'
112                 onSelect={this.addActionItem}
113               >
114                 <MenuItem eventKey='issue'>Issue</MenuItem>
115                 <MenuItem eventKey='spend_account'>Spend from account</MenuItem>
116                 {/*<MenuItem eventKey='spend_account_unspent_output'>Spend unspent output</MenuItem>*/}
117                 <MenuItem eventKey='control_account'>Control with account</MenuItem>
118                 <MenuItem eventKey='control_receiver'>Control with receiver</MenuItem>
119                 {/*<MenuItem eventKey='retire'>Retire</MenuItem>*/}
120                 {/*<MenuItem eventKey='set_transaction_reference_data'>Set transaction reference data</MenuItem>*/}
121               </DropdownButton>
122             </div>
123         </FormSection>
124
125         {false && !this.state.showAdvanced &&
126           <FormSection>
127             <a href='#'
128               className={styles.showAdvanced}
129               onClick={(e) => {
130                 e.preventDefault()
131                 this.setState({showAdvanced: true})
132               }}
133             >
134               Show advanced options
135             </a>
136           </FormSection>
137         }
138
139         {false && this.state.showAdvanced && <FormSection title='Advanced Options'>
140           <div>
141             <TextField
142               title='Base transaction'
143               placeholder='Paste transaction hex here...'
144               fieldProps={baseTransaction}
145               autoFocus={true} />
146
147             <FieldLabel>Transaction Build Type</FieldLabel>
148             <table className={styles.submitTable}>
149               <tbody>
150                 <tr>
151                   <td><input id='submit_action_submit' type='radio' {...submitAction} value='submit' checked={submitAction.value == 'submit'} /></td>
152                   <td>
153                     <label htmlFor='submit_action_submit'>Submit transaction to blockchain</label>
154                     <br />
155                     <label htmlFor='submit_action_submit' className={styles.submitDescription}>
156                       This transaction will be signed by the MockHSM and submitted to the blockchain.
157                     </label>
158                   </td>
159                 </tr>
160                 <tr>
161                   <td><input id='submit_action_generate' type='radio' {...submitAction} value='generate' checked={submitAction.value == 'generate'} /></td>
162                   <td>
163                     <label htmlFor='submit_action_generate'>Allow additional actions</label>
164                     <br />
165                     <label htmlFor='submit_action_generate' className={styles.submitDescription}>
166                       These actions will be signed by the MockHSM and returned as a
167                       transaction hex string, which should be used as the base
168                       transaction in a multi-party swap. This transaction will be
169                       valid for one hour.
170                     </label>
171                   </td>
172                 </tr>
173               </tbody>
174             </table>
175           </div>
176         </FormSection>}
177       </FormContainer>
178     )
179   }
180 }
181
182 const validate = values => {
183   const errors = {actions: {}}
184
185   // Base transaction
186   let baseTx = values.baseTransaction || ''
187   if (baseTx.trim().match(/[^0-9a-fA-F]/)) {
188     errors.baseTransaction = 'Base transaction must be a hex string.'
189   }
190
191   // Actions
192   let fieldError
193   values.actions.forEach((action, index) => {
194     fieldError = JsonField.validator(values.actions[index].referenceData)
195     if (fieldError) {
196       errors.actions[index] = {...errors.actions[index], referenceData: fieldError}
197     }
198   })
199
200   return errors
201 }
202
203 export default BaseNew.connect(
204   state => ({
205     ...BaseNew.mapStateToProps('transaction')(state),
206   }),
207   BaseNew.mapDispatchToProps('transaction'),
208   reduxForm({
209     form: 'NewTransactionForm',
210     fields: [
211       'baseTransaction',
212       'actions[].accountId',
213       'actions[].accountAlias',
214       'actions[].assetId',
215       'actions[].assetAlias',
216       'actions[].amount',
217       'actions[].receiver',
218       'actions[].outputId',
219       'actions[].referenceData',
220       'actions[].type',
221       'submitAction',
222     ],
223     validate,
224     initialValues: {
225       submitAction: 'submit',
226     },
227   }
228   )(Form)
229 )