github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-supply-chain-master/fish_client/src/views/property_detail.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  'use strict'
    18  
    19  const m = require('mithril')
    20  const _ = require('lodash')
    21  
    22  const api = require('../services/api')
    23  const payloads = require('../services/payloads')
    24  const parsing = require('../services/parsing')
    25  const transactions = require('../services/transactions')
    26  const layout = require('../components/layout')
    27  const { LineGraphWidget, MapWidget } = require('../components/data')
    28  const { Table, PagingButtons } = require('../components/tables')
    29  
    30  const PAGE_SIZE = 50
    31  
    32  const withIntVal = fn => m.withAttr('value', v => fn(parsing.toInt(v)))
    33  
    34  const typedWidget = state => {
    35    const property = _.get(state, 'property', {})
    36  
    37    if (property.dataType === 'LOCATION') {
    38      return m(MapWidget, {
    39        coordinates: property.updates.map(update => update.value)
    40      })
    41    }
    42  
    43    if (property.dataType === 'NUMBER') {
    44      return m(LineGraphWidget, { updates: property.updates })
    45    }
    46  
    47    if (property.name === 'tilt') {
    48      return m(LineGraphWidget, {
    49        updates: property.updates.map(update => {
    50          const amplitude = Math.sqrt(update.value.x ** 2 + update.value.y ** 2)
    51          return _.assign({}, update, {value: amplitude.toFixed(3)})
    52        })
    53      })
    54    }
    55  
    56    if (property.name === 'shock') {
    57      return m(LineGraphWidget, {
    58        updates: property.updates.map(update => {
    59          const degree = update.value.duration === 0
    60            ? 0
    61            : update.value.accel / update.value.duration
    62          return _.assign({}, update, {value: degree.toFixed(3)})
    63        })
    64      })
    65    }
    66  
    67    return null
    68  }
    69  
    70  const updateSubmitter = state => e => {
    71    e.preventDefault()
    72    const { name, dataType, recordId } = state.property
    73  
    74    let value = null
    75    if (state.update) {
    76      value = state.update
    77    } else if (name === 'tilt' || name === 'shock') {
    78      value = JSON.stringify(state.tmp)
    79    } else {
    80      value = state.tmp
    81    }
    82  
    83    const update = { name }
    84    update.dataType = payloads.updateProperties.enum[dataType]
    85    update[`${dataType.toLowerCase()}Value`] = value
    86  
    87    const payload = payloads.updateProperties({
    88      recordId,
    89      properties: [update]
    90    })
    91  
    92    transactions.submit(payload, true)
    93      .then(() => api.get(`records/${recordId}/${name}`))
    94      .then(property => {
    95        _.each(e.target.elements, el => { el.value = null })
    96        state.update = null
    97        state.tmp = {}
    98        property.updates.forEach(update => {
    99          update.value = parsing.floatifyValue(update.value)
   100        })
   101        state.property = property
   102      })
   103  }
   104  
   105  // Produces custom input fields for location, tilt, and shock
   106  const typedInput = state => {
   107    const { dataType, name } = state.property
   108  
   109    if (dataType === 'LOCATION') {
   110      return [
   111        m('.col.md-4.mr-1',
   112          m('input.form-control', {
   113            placeholder: 'Enter Latitude...',
   114            oninput: withIntVal(value => { state.tmp.latitude = value })
   115          })),
   116        m('.col.md-4',
   117          m('input.form-control', {
   118            placeholder: 'Enter Longitude...',
   119            oninput: withIntVal(value => { state.tmp.longitude = value })
   120          }))
   121      ]
   122    }
   123  
   124    if (name === 'tilt') {
   125      return [
   126        m('.col.md-4.mr-1',
   127          m('input.form-control', {
   128            placeholder: 'Enter X...',
   129            oninput: withIntVal(value => { state.tmp.x = value })
   130          })),
   131        m('.col.md-4',
   132          m('input.form-control', {
   133            placeholder: 'Enter Y...',
   134            oninput: withIntVal(value => { state.tmp.y = value })
   135          }))
   136      ]
   137    }
   138  
   139    if (name === 'shock') {
   140      return [
   141        m('.col.md-4.mr-1',
   142          m('input.form-control', {
   143            placeholder: 'Enter Acceleration...',
   144            oninput: withIntVal(value => { state.tmp.accel = value })
   145          })),
   146        m('.col.md-4',
   147          m('input.form-control', {
   148            placeholder: 'Enter Duration...',
   149            oninput: withIntVal(value => { state.tmp.duration = value })
   150          }))
   151      ]
   152    }
   153  
   154    if (name === 'temperature') {
   155      return m('.col-md-8', [
   156        m('input.form-control', {
   157          placeholder: 'Enter Temperature...',
   158          oninput: withIntVal(value => { state.update = value })
   159        })
   160      ])
   161    }
   162  
   163    return null
   164  }
   165  
   166  const updateForm = state => {
   167    const inputField = typedInput(state)
   168    if (!inputField) return null
   169  
   170    return m('form.my-5', {
   171      onsubmit: updateSubmitter(state)
   172    }, [
   173      m('.container',
   174        m('.row.justify-content-center',
   175          inputField,
   176          m('.col-md-2',
   177            m('button.btn.btn-primary', { type: 'submit' }, 'Update'))))
   178    ])
   179  }
   180  
   181  /**
   182   * Displays updates to a property, and form for submitting new updates.
   183   */
   184  const PropertyDetailPage = {
   185    oninit (vnode) {
   186      vnode.state.currentPage = 0
   187      vnode.state.tmp = {}
   188  
   189      const refresh = () => {
   190        api.get(`records/${vnode.attrs.recordId}/${vnode.attrs.name}`)
   191          .then(property => {
   192            property.updates.forEach(update => {
   193              update.value = parsing.floatifyValue(update.value)
   194            })
   195            vnode.state.property = property
   196          })
   197          .then(() => { vnode.state.refreshId = setTimeout(refresh, 2000) })
   198      }
   199  
   200      refresh()
   201    },
   202  
   203    onbeforeremove (vnode) {
   204      clearTimeout(vnode.state.refreshId)
   205    },
   206  
   207    view (vnode) {
   208      const name = _.capitalize(vnode.attrs.name)
   209      const record = vnode.attrs.recordId
   210  
   211      const reporters = _.get(vnode.state, 'property.reporters', [])
   212      const isReporter = reporters.includes(api.getPublicKey())
   213  
   214      const updates = _.get(vnode.state, 'property.updates', [])
   215      const page = updates.slice(vnode.state.currentPage * PAGE_SIZE,
   216                                 (vnode.state.currentPage + 1) * PAGE_SIZE)
   217  
   218      return [
   219        layout.title(`${name} of ${record}`),
   220        typedWidget(vnode.state),
   221        isReporter ? updateForm(vnode.state) : null,
   222        m('.container',
   223          layout.row([
   224            m('h5.mr-auto', 'Update History'),
   225            m(PagingButtons, {
   226              setPage: page => { vnode.state.currentPage = page },
   227              currentPage: vnode.state.currentPage,
   228              maxPage: updates.length / PAGE_SIZE
   229            })
   230          ]),
   231          m(Table, {
   232            headers: ['Value', 'Reporter', 'Time'],
   233            rows: page.map(update => {
   234              return [
   235                parsing.stringifyValue(update.value,
   236                                       vnode.state.property.dataType,
   237                                       vnode.state.property.name),
   238                update.reporter.name,
   239                parsing.formatTimestamp(update.timestamp)
   240              ]
   241            }),
   242            noRowsText: 'This property has never been updated'
   243          }))
   244      ]
   245    }
   246  }
   247  
   248  module.exports = PropertyDetailPage