github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-supply-chain-master/fish_client/src/views/add_fish_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 {MultiSelect} = require('../components/forms') 25 const layout = require('../components/layout') 26 27 /** 28 * Possible selection options 29 */ 30 const authorizableProperties = [ 31 ['location', 'Location'], 32 ['temperature', 'Temperature'], 33 ['tilt', 'Tilt'], 34 ['shock', 'Shock'] 35 ] 36 37 /** 38 * The Form for tracking a new fish. 39 */ 40 const AddFishForm = { 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 return m('.fish_form', 58 m('form', { 59 onsubmit: (e) => { 60 e.preventDefault() 61 _handleSubmit(vnode.attrs.signingKey, vnode.state) 62 } 63 }, 64 m('legend', 'Track New Fish'), 65 _formGroup('Serial Number', m('input.form-control', { 66 type: 'text', 67 oninput: m.withAttr('value', (value) => { 68 vnode.state.serialNumber = value 69 }), 70 value: vnode.state.serialNumber 71 })), 72 _formGroup('Species (ASFIS 3-letter code)', m('input.form-control', { 73 type: 'text', 74 oninput: m.withAttr('value', (value) => { 75 vnode.state.species = value 76 }), 77 value: vnode.state.species 78 })), 79 80 layout.row([ 81 _formGroup('Length (m)', m('input.form-control', { 82 type: 'number', 83 min: 0, 84 step: 'any', 85 oninput: m.withAttr('value', (value) => { 86 vnode.state.lengthInCM = value 87 }), 88 value: vnode.state.lengthInCM 89 })), 90 _formGroup('Weight (kg)', m('input.form-control', { 91 type: 'number', 92 step: 'any', 93 oninput: m.withAttr('value', (value) => { 94 vnode.state.weightInKg = value 95 }), 96 value: vnode.state.weightInKg 97 })) 98 ]), 99 100 layout.row([ 101 _formGroup('Latitude', m('input.form-control', { 102 type: 'number', 103 step: 'any', 104 min: -90, 105 max: 90, 106 oninput: m.withAttr('value', (value) => { 107 vnode.state.latitude = value 108 }), 109 value: vnode.state.latitude 110 })), 111 _formGroup('Longitude', m('input.form-control', { 112 type: 'number', 113 step: 'any', 114 min: -180, 115 max: 180, 116 oninput: m.withAttr('value', (value) => { 117 vnode.state.longitude = value 118 }), 119 value: vnode.state.longitude 120 })) 121 ]), 122 123 m('.reporters.form-group', 124 m('label', 'Authorize Reporters'), 125 126 vnode.state.reporters.map((reporter, i) => 127 m('.row.mb-2', 128 m('.col-sm-8', 129 m('input.form-control', { 130 type: 'text', 131 placeholder: 'Add reporter by name or public key...', 132 oninput: m.withAttr('value', (value) => { 133 // clear any previously matched values 134 vnode.state.reporters[i].reporterKey = null 135 const reporter = vnode.state.agents.find(agent => { 136 return agent.name === value || agent.key === value 137 }) 138 if (reporter) { 139 vnode.state.reporters[i].reporterKey = reporter.key 140 } 141 }), 142 onblur: () => _updateReporters(vnode, i) 143 })), 144 145 m('.col-sm-4', 146 m(MultiSelect, { 147 label: 'Select Fields', 148 options: authorizableProperties, 149 selected: reporter.properties, 150 onchange: (selection) => { 151 vnode.state.reporters[i].properties = selection 152 } 153 }))))), 154 155 m('.row.justify-content-end.align-items-end', 156 m('col-2', 157 m('button.btn.btn-primary', 158 'Create Record'))))) 159 } 160 } 161 162 /** 163 * Update the reporter's values after a change occurs in the name of the 164 * reporter at the given reporterIndex. If it is empty, and not the only 165 * reporter in the list, remove it. If it is not empty and the last item 166 * in the list, add a new, empty reporter to the end of the list. 167 */ 168 const _updateReporters = (vnode, reporterIndex) => { 169 let reporterInfo = vnode.state.reporters[reporterIndex] 170 let lastIdx = vnode.state.reporters.length - 1 171 if (!reporterInfo.reporterKey && reporterIndex !== lastIdx) { 172 vnode.state.reporters.splice(reporterIndex, 1) 173 } else if (reporterInfo.reporterKey && reporterIndex === lastIdx) { 174 vnode.state.reporters.push({ 175 reporterKey: '', 176 properties: [] 177 }) 178 } 179 } 180 181 /** 182 * Handle the form submission. 183 * 184 * Extract the appropriate values to pass to the create record transaction. 185 */ 186 const _handleSubmit = (signingKey, state) => { 187 const recordPayload = payloads.createRecord({ 188 recordId: state.serialNumber, 189 recordType: 'fish', 190 properties: [ 191 { 192 name: 'species', 193 stringValue: state.species, 194 dataType: payloads.createRecord.enum.STRING 195 }, 196 { 197 name: 'length', 198 numberValue: parsing.toInt(state.lengthInCM), 199 dataType: payloads.createRecord.enum.NUMBER 200 }, 201 { 202 name: 'weight', 203 numberValue: parsing.toInt(state.weightInKg), 204 dataType: payloads.createRecord.enum.NUMBER 205 }, 206 { 207 name: 'location', 208 locationValue: { 209 latitude: parsing.toInt(state.latitude), 210 longitude: parsing.toInt(state.longitude) 211 }, 212 dataType: payloads.createRecord.enum.LOCATION 213 } 214 ] 215 }) 216 217 const reporterPayloads = state.reporters 218 .filter((reporter) => !!reporter.reporterKey) 219 .map((reporter) => payloads.createProposal({ 220 recordId: state.serialNumber, 221 receivingAgent: reporter.reporterKey, 222 role: payloads.createProposal.enum.REPORTER, 223 properties: reporter.properties 224 })) 225 226 transactions.submit([recordPayload].concat(reporterPayloads), true) 227 .then(() => m.route.set(`/fish/${state.serialNumber}`)) 228 } 229 230 /** 231 * Create a form group (this is a styled form-group with a label). 232 */ 233 const _formGroup = (label, formEl) => 234 m('.form-group', 235 m('label', label), 236 formEl) 237 238 module.exports = AddFishForm