github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-supply-chain-master/asset_client/src/views/add_asset_form.js (about) 1 /** 2 * Copyright 2017 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * ---------------------------------------------------------------------------- 16 */ 17 18 const m = require('mithril') 19 20 const api = require('../services/api') 21 const payloads = require('../services/payloads') 22 const transactions = require('../services/transactions') 23 const parsing = require('../services/parsing') 24 const forms = require('../components/forms') 25 const layout = require('../components/layout') 26 27 /** 28 * Possible selection options 29 */ 30 const authorizableProperties = [ 31 ['weight', 'Weight'], 32 ['location', 'Location'], 33 ['temperature', 'Temperature'], 34 ['shock', 'Shock'] 35 ] 36 37 /** 38 * The Form for tracking a new asset. 39 */ 40 const AddAssetForm = { 41 oninit (vnode) { 42 // Initialize the empty reporters fields 43 vnode.state.reporters = [ 44 { 45 reporterKey: '', 46 properties: [] 47 } 48 ] 49 api.get('agents') 50 .then(agents => { 51 const publicKey = api.getPublicKey() 52 vnode.state.agents = agents.filter(agent => agent.key !== publicKey) 53 }) 54 }, 55 56 view (vnode) { 57 const setter = forms.stateSetter(vnode.state) 58 return [ 59 m('.add_asset_form', 60 m('form', { 61 onsubmit: (e) => { 62 e.preventDefault() 63 _handleSubmit(vnode.attrs.signingKey, vnode.state) 64 } 65 }, 66 m('legend', 'Track New Asset'), 67 forms.textInput(setter('serialNumber'), 'Serial Number'), 68 69 layout.row([ 70 forms.textInput(setter('type'), 'Type'), 71 forms.textInput(setter('subtype'), 'Subtype', false) 72 ]), 73 74 forms.group('Weight (kg)', forms.field(setter('weight'), { 75 type: 'number', 76 step: 'any', 77 min: 0, 78 required: false 79 })), 80 81 layout.row([ 82 forms.group('Latitude', forms.field(setter('latitude'), { 83 type: 'number', 84 step: 'any', 85 min: -90, 86 max: 90, 87 required: false 88 })), 89 forms.group('Longitude', forms.field(setter('longitude'), { 90 type: 'number', 91 step: 'any', 92 min: -180, 93 max: 180, 94 required: false 95 })) 96 ]), 97 98 m('.reporters.form-group', 99 m('label', 'Authorize Reporters'), 100 vnode.state.reporters.map((reporter, i) => 101 m('.row.mb-2', 102 m('.col-sm-8', 103 m('input.form-control', { 104 type: 'text', 105 placeholder: 'Add reporter by name or public key...', 106 oninput: m.withAttr('value', (value) => { 107 // clear any previously matched values 108 vnode.state.reporters[i].reporterKey = null 109 const reporter = vnode.state.agents.find(agent => { 110 return agent.name === value || agent.key === value 111 }) 112 if (reporter) { 113 vnode.state.reporters[i].reporterKey = reporter.key 114 } 115 }), 116 onblur: () => _updateReporters(vnode, i) 117 })), 118 119 m('.col-sm-4', 120 m(forms.MultiSelect, { 121 label: 'Select Fields', 122 options: authorizableProperties, 123 selected: reporter.properties, 124 onchange: (selection) => { 125 vnode.state.reporters[i].properties = selection 126 } 127 }))))), 128 129 m('.row.justify-content-end.align-items-end', 130 m('col-2', 131 m('button.btn.btn-primary', 132 'Create Record'))))) 133 ] 134 } 135 } 136 137 /** 138 * Update the reporter's values after a change occurs in the name of the 139 * reporter at the given reporterIndex. If it is empty, and not the only 140 * reporter in the list, remove it. If it is not empty and the last item 141 * in the list, add a new, empty reporter to the end of the list. 142 */ 143 const _updateReporters = (vnode, reporterIndex) => { 144 let reporterInfo = vnode.state.reporters[reporterIndex] 145 let lastIdx = vnode.state.reporters.length - 1 146 if (!reporterInfo.reporterKey && reporterIndex !== lastIdx) { 147 vnode.state.reporters.splice(reporterIndex, 1) 148 } else if (reporterInfo.reporterKey && reporterIndex === lastIdx) { 149 vnode.state.reporters.push({ 150 reporterKey: '', 151 properties: [] 152 }) 153 } 154 } 155 156 /** 157 * Handle the form submission. 158 * 159 * Extract the appropriate values to pass to the create record transaction. 160 */ 161 const _handleSubmit = (signingKey, state) => { 162 const properties = [{ 163 name: 'type', 164 stringValue: state.type, 165 dataType: payloads.createRecord.enum.STRING 166 }] 167 168 if (state.subtype) { 169 properties.push({ 170 name: 'subtype', 171 stringValue: state.subtype, 172 dataType: payloads.createRecord.enum.STRING 173 }) 174 } 175 176 if (state.weight) { 177 properties.push({ 178 name: 'weight', 179 numberValue: parsing.toInt(state.weight), 180 dataType: payloads.createRecord.enum.NUMBER 181 }) 182 } 183 184 if (state.latitude && state.longitude) { 185 properties.push({ 186 name: 'location', 187 locationValue: { 188 latitude: parsing.toInt(state.latitude), 189 longitude: parsing.toInt(state.longitude) 190 }, 191 dataType: payloads.createRecord.enum.LOCATION 192 }) 193 } 194 195 const recordPayload = payloads.createRecord({ 196 recordId: state.serialNumber, 197 recordType: 'asset', 198 properties 199 }) 200 201 const reporterPayloads = state.reporters 202 .filter((reporter) => !!reporter.reporterKey) 203 .map((reporter) => payloads.createProposal({ 204 recordId: state.serialNumber, 205 receivingAgent: reporter.reporterKey, 206 role: payloads.createProposal.enum.REPORTER, 207 properties: reporter.properties 208 })) 209 210 transactions.submit([recordPayload].concat(reporterPayloads), true) 211 .then(() => m.route.set(`/assets/${state.serialNumber}`)) 212 } 213 214 module.exports = AddAssetForm