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