<commit_before>// geojson.js - v0.1.1
// (c) 2012 Casey Thomas, MIT License
(function(e){function r(e,t){var n=e||{};for(var r in t)t.hasOwnProperty(r)&&!n[r]&&(n[r]=t[r]);return n}function i(e,t){t.crs&&(e.crs={type:"name",properties:{name:t.crs}}),t.bbox&&(e.bbox=t.bbox)}function s(e){e.geom={};for(var n in e)e.hasOwnProperty(n)&&t.indexOf(n)!==-1&&(e.geom[n]=e[n],delete e[n]);o(e.geom)}function o(e){for(var t in e)e.hasOwnProperty(t)&&(typeof e[t]=="string"?n.push(e[t]):typeof e[t]=="object"&&(n.push(e[t][0]),n.push(e[t][1])));if(n.length===0)throw new Error("No geometry attributes specified")}function u(e,t){var n={type:"Feature"};return n.geometry=a(e,t),n.properties=f(e,t),n}function a(e,t){var r={};for(var i in e)if(e.hasOwnProperty(i)&&n.indexOf(i)!==-1)for(var s in t.geom)if(t.geom.hasOwnProperty(s)&&(i===t.geom[s]||i===t.geom[s][0]))return r.type=s,typeof t.geom[s]=="string"?r.coordinates=e[t.geom[s]]:r.coordinates=[e[t.geom[s][1]],e[t.geom[s][0]]],r}function f(e,t){var r={},i;if(!t.exclude&&!t.include)for(i in e)e.hasOwnProperty(i)&&n.indexOf(i)===-1&&(r[i]=e[i]);else if(t.include)t.include.forEach(function(t){r[t]=e[t]});else if(t.exclude)for(i in e)e.hasOwnProperty(i)&&n.indexOf(i)===-1&&t.exclude.indexOf(i)===-1&&(r[i]=e[i]);return t.extra&&l(r,t.extra),r}function l(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}e.version="0.1.1",e.defaults={},e.parse=function(e,t){if(e.length===0)throw new Error("No data found");var o={type:"FeatureCollection",features:[]},a=r(t,this.defaults);return n.length=0,s(a),e.forEach(function(e){o.features.push(u(e,a))}),i(o,a),o};var t=["Point","MultiPoint","LineString","MultiLineString","Polygon","MultiPolygon"],n=[]})(typeof module=="object"?module.exports:window.GeoJSON={});<commit_msg>Updated minified version<commit_after>// geojson.js - v0.1.2
// (c) 2012 Casey Thomas, MIT License
(function(e){function r(e,t){var n=e||{};for(var r in t)t.hasOwnProperty(r)&&!n[r]&&(n[r]=t[r]);return n}function i(e,t){t.crs&&(e.crs={type:"name",properties:{name:t.crs}}),t.bbox&&(e.bbox=t.bbox)}function s(e){e.geom={};for(var n in e)e.hasOwnProperty(n)&&t.indexOf(n)!==-1&&(e.geom[n]=e[n],delete e[n]);o(e.geom)}function o(e){for(var t in e)e.hasOwnProperty(t)&&(typeof e[t]=="string"?n.push(e[t]):typeof e[t]=="object"&&(n.push(e[t][0]),n.push(e[t][1])));if(n.length===0)throw new Error("No geometry attributes specified")}function u(e,t,n){var r={type:"Feature"};return r.geometry=a(e,t),r.properties=n.call(e),r}function a(e,t){var n={},r;for(var i in t.geom)r=typeof t.geom[i]=="object"?t.geom[i][0]:t.geom[i],t.geom.hasOwnProperty(i)&&e[r]&&(n.type=i,typeof t.geom[i]=="string"?n.coordinates=e[t.geom[i]]:n.coordinates=[e[t.geom[i][1]],e[t.geom[i][0]]]);return n}function f(e){var t;return!e.exclude&&!e.include?t=function(e){for(var t in this)this.hasOwnProperty(t)&&n.indexOf(t)===-1&&(e[t]=this[t])}:e.include?t=function(t){e.include.forEach(function(e){t[e]=this[e]},this)}:e.exclude&&(t=function(t){for(var r in this)this.hasOwnProperty(r)&&n.indexOf(r)===-1&&e.exclude.indexOf(r)===-1&&(t[r]=this[r])}),function(){var n={};return t.call(this,n),e.extra&&l(n,e.extra),n}}function l(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}e.version="0.1.2",e.defaults={},e.parse=function(e,t){if(e.length===0)throw new Error("No data found");var o={type:"FeatureCollection",features:[]},a=r(t,this.defaults),l;return n.length=0,s(a),l=f(a),e.forEach(function(e){o.features.push(u(e,a,l))}),i(o,a),o};var t=["Point","MultiPoint","LineString","MultiLineString","Polygon","MultiPolygon"],n=[]})(typeof module=="object"?module.exports:window.GeoJSON={});<|endoftext|>


<commit_before>define(['app/module'], function (module) {
  'use strict';

  module
    .controller('setupCtlr', [
      '$modal', '$scope', 'ServerConfig',
      '$window', 'MLSearchFactory',
      'newRangeIndexDialog', 'editRangeIndexDialog',
      'newChartWidgetDialog',
      function (
        $modal, $scope, ServerConfig,
        win, searchFactory,
        newRangeIndexDialog, editRangeIndexDialog,
        newChartWidgetDialog
      ) {
      var model = {};
      var mlSearch = searchFactory.newContext();

      function updateSearchResults() {
        return mlSearch.setPageLength(5).search().then(
          function(data) {
            model.isInErrorState = false;
            model.search = data;
          },
          function() {
            model.isInErrorState = true;
          });
      }

      updateSearchResults();

      ServerConfig.get().then(function(config){
        model.charts = [];
        model.fields = config.fields;
        model.rangeIndexes = config.rangeIndexes;
        model.searchOptions = config.searchOptions;
        model.constraints = config.searchOptions.options.constraint;
      });
      angular.extend($scope, {
        model: model,
        state: 'indexes',
        loadData: function() {
          ServerConfig.loadData($scope.loadDirectory).then(function() {
            updateSearchResults().then(function() {
              $scope.state = 'appearance';
            });
          });
        },
        removeIndex: function(indexPosition) {
          model.rangeIndexes.rangeindexList.splice(indexPosition, 1);
          ServerConfig.setRangeIndexes(model.rangeIndexes).then(updateSearchResults);
        },
        editIndex: function(index) {
          var indexValue,
            indexType;
          angular.forEach(index, function(val, keyName){
            if (keyName === 'rangeElementIndex' || keyName === 'rangeElementAttributeIndex' || keyName === 'rangeFieldIndex') {
              indexType = keyName;
              indexValue = val;
            }
          });
          editRangeIndexDialog(indexValue, indexType).then(function(index) {
            if (index) {
              ServerConfig.setRangeIndexes(model.rangeIndexes).then(updateSearchResults);
            }
          });
        },
        addChart: function() {
          newChartWidgetDialog(model.search.facets).then(function(chart) {
            model.charts.push(chart);
            //ServerConfig.setRangeIndexes(model.rangeIndexes).then(updateSearchResults);
          });
        },
        addIndex: function() {
          newRangeIndexDialog().then(function(index) {
            model.rangeIndexes.rangeindexList.push(index);
            ServerConfig.setRangeIndexes(model.rangeIndexes).then(updateSearchResults);
          });
        },
        removeField: function(fieldPosition) {
          model.fields.fieldList.splice(fieldPosition, 1);
          ServerConfig.setFields(model.fields).then(updateSearchResults);
        },
        addField: function(field) {
          model.fields.fieldList.push(field);
          ServerConfig.setFields(model.fields).then(updateSearchResults);
        },
        submitConstraints: function() {
          model.searchOptions.options.constraint = model.constraints;
          ServerConfig.setSearchOptions(model.searchOptions).then(function() {
            updateSearchResults().then(function() {
              $scope.state = 'appearance';
            });
          });
        },
        resampleConstraints: function() {
          model.constraints = [];
          angular.forEach(model.rangeIndexes.rangeindexList, function(val){
            var value = val.rangeElementIndex || val.rangeElementAttributeIndex || val.fieldIndex;
            var constraint =
              {
                'name': value.localname,
                'range':
                  {
                    'type': 'xs:'+ value.scalarType,
                    'facet': true,
                    'facet-option' : [
                      'limit=10',
                      'frequency-order',
                      'descending'
                    ],
                    'collation': value.collation
                }
              };
            if (value.localname) {
              constraint.range.element = {
                  'name': (value.parentLocalname || value.localname),
                  'ns': (value.parentNamespaceUri || value.namespaceUri)
                };
            }
            if (value['parent-localname']) {
              constraint.range.attribute = {
                  'name': value.localname,
                  'ns': value.namespaceUri
                };
            }
            model.constraints.push(constraint);
          });
          angular.forEach(model.fields.fieldList, function(value){
            var constraint =
              {
                'name': value.field.fieldName,
                'facet': false,
                'word':
                  {
                    'field': {
                      'name': value.field.fieldName,
                      'collation': value.field.collation
                    }
                }
              };
            model.constraints.push(constraint);
          });
        }
      });
    }]);
});
<commit_msg>Fix editIndex modal<commit_after>define(['app/module'], function (module) {
  'use strict';

  module
    .controller('setupCtlr', [
      '$modal', '$scope', 'ServerConfig',
      '$window', 'MLSearchFactory',
      'newRangeIndexDialog', 'editRangeIndexDialog',
      'newChartWidgetDialog',
      function (
        $modal, $scope, ServerConfig,
        win, searchFactory,
        newRangeIndexDialog, editRangeIndexDialog,
        newChartWidgetDialog
      ) {
      var model = {};
      var mlSearch = searchFactory.newContext();

      function updateSearchResults() {
        return mlSearch.setPageLength(5).search().then(
          function(data) {
            model.isInErrorState = false;
            model.search = data;
          },
          function() {
            model.isInErrorState = true;
          });
      }

      updateSearchResults();

      ServerConfig.get().then(function(config){
        model.charts = [];
        model.fields = config.fields;
        model.rangeIndexes = config.rangeIndexes;
        model.searchOptions = config.searchOptions;
        model.constraints = config.searchOptions.options.constraint;
      });
      angular.extend($scope, {
        model: model,
        state: 'indexes',
        loadData: function() {
          ServerConfig.loadData($scope.loadDirectory).then(function() {
            updateSearchResults().then(function() {
              $scope.state = 'appearance';
            });
          });
        },
        removeIndex: function(indexPosition) {
          model.rangeIndexes.rangeindexList.splice(indexPosition, 1);
          ServerConfig.setRangeIndexes(model.rangeIndexes).then(updateSearchResults);
        },
        editIndex: function(index) {
          editRangeIndexDialog(index).then(function(index) {
            if (index) {
              ServerConfig.setRangeIndexes(model.rangeIndexes).then(updateSearchResults);
            }
          });
        },
        addChart: function() {
          newChartWidgetDialog(model.search.facets).then(function(chart) {
            model.charts.push(chart);
            //ServerConfig.setRangeIndexes(model.rangeIndexes).then(updateSearchResults);
          });
        },
        addIndex: function() {
          newRangeIndexDialog().then(function(index) {
            model.rangeIndexes.rangeindexList.push(index);
            ServerConfig.setRangeIndexes(model.rangeIndexes).then(updateSearchResults);
          });
        },
        removeField: function(fieldPosition) {
          model.fields.fieldList.splice(fieldPosition, 1);
          ServerConfig.setFields(model.fields).then(updateSearchResults);
        },
        addField: function(field) {
          model.fields.fieldList.push(field);
          ServerConfig.setFields(model.fields).then(updateSearchResults);
        },
        submitConstraints: function() {
          model.searchOptions.options.constraint = model.constraints;
          ServerConfig.setSearchOptions(model.searchOptions).then(function() {
            updateSearchResults().then(function() {
              $scope.state = 'appearance';
            });
          });
        },
        resampleConstraints: function() {
          model.constraints = [];
          angular.forEach(model.rangeIndexes.rangeindexList, function(val){
            var value = val.rangeElementIndex || val.rangeElementAttributeIndex || val.fieldIndex;
            var constraint =
              {
                'name': value.localname,
                'range':
                  {
                    'type': 'xs:'+ value.scalarType,
                    'facet': true,
                    'facet-option' : [
                      'limit=10',
                      'frequency-order',
                      'descending'
                    ],
                    'collation': value.collation
                }
              };
            if (value.localname) {
              constraint.range.element = {
                  'name': (value.parentLocalname || value.localname),
                  'ns': (value.parentNamespaceUri || value.namespaceUri)
                };
            }
            if (value['parent-localname']) {
              constraint.range.attribute = {
                  'name': value.localname,
                  'ns': value.namespaceUri
                };
            }
            model.constraints.push(constraint);
          });
          angular.forEach(model.fields.fieldList, function(value){
            var constraint =
              {
                'name': value.field.fieldName,
                'facet': false,
                'word':
                  {
                    'field': {
                      'name': value.field.fieldName,
                      'collation': value.field.collation
                    }
                }
              };
            model.constraints.push(constraint);
          });
        }
      });
    }]);
});
<|endoftext|>


<commit_before>const Buffer = require('safe-buffer').Buffer
const async = require('async')
const ethUtil = require('ethereumjs-util')
const BN = ethUtil.BN
const fees = require('ethereum-common')
const constants = require('./constants.js')

const ERROR = constants.ERROR

/**
 * runs a CALL operation
 * @method runCall
 * @param opts
 * @param opts.block {Block}
 * @param opts.caller {Buffer}
 * @param opts.code {Buffer} this is for CALLCODE where the code to load is different than the code from the to account.
 * @param opts.data {Buffer}
 * @param opts.gasLimit {Buffer | BN.js }
 * @param opts.gasPrice {Buffer}
 * @param opts.origin {Buffer} []
 * @param opts.to {Buffer}
 * @param opts.value {Buffer}
 */
module.exports = function (opts, cb) {
  var self = this
  var stateManager = self.stateManager

  var vmResults = {}
  var toAccount
  var toAddress = opts.to
  var createdAddress
  var txValue = opts.value || Buffer.from([0])
  var caller = opts.caller
  var account = stateManager.cache.get(caller)
  var block = opts.block
  var code = opts.code
  var txData = opts.data
  var gasLimit = opts.gasLimit || new BN(0xffffff)
  gasLimit = new BN(opts.gasLimit) // make sure is a BN
  var gasPrice = opts.gasPrice
  var gasUsed = new BN(0)
  var origin = opts.origin
  var isCompiled = opts.compiled
  var depth = opts.depth
  // opts.suicides is kept for backward compatiblity with pre-EIP6 syntax
  var selfdestruct = opts.selfdestruct || opts.suicides
  var delegatecall = opts.delegatecall || false
  var isStatic = opts.static || false

  txValue = new BN(txValue)

  stateManager.checkpoint()

  // run and parse
  subTxValue()

  async.series([
    loadToAccount,
    loadCode,
    runCode,
    saveCode
  ], parseCallResult)

  function loadToAccount (done) {
    // get receiver's account
    // toAccount = stateManager.cache.get(toAddress)
    if (!toAddress) {
      // generate a new contract if no `to`
      code = txData
      txData = undefined
      var newNonce = new BN(account.nonce).subn(1)
      createdAddress = toAddress = ethUtil.generateAddress(caller, newNonce.toArray())
      stateManager.getAccount(createdAddress, function (err, account) {
        toAccount = account
        const NONCE_OFFSET = 1
        toAccount.nonce = new BN(toAccount.nonce).addn(NONCE_OFFSET).toArrayLike(Buffer)
        done(err)
      })
    } else {
      // else load the `to` account
      toAccount = stateManager.cache.get(toAddress)
      done()
    }
  }

  function subTxValue () {
    if (delegatecall) {
      return
    }
    account.balance = new BN(account.balance).sub(txValue)
    stateManager.cache.put(caller, account)
  }

  function addTxValue () {
    if (delegatecall) {
      return
    }
    // add the amount sent to the `to` account
    toAccount.balance = new BN(toAccount.balance).add(txValue)
    stateManager.cache.put(toAddress, toAccount)
    stateManager.touched.push(toAddress)
  }

  function loadCode (cb) {
    addTxValue()
    // loads the contract's code if the account is a contract
    if (code || !(toAccount.isContract() || self._precompiled[toAddress.toString('hex')])) {
      cb()
      return
    }

    if (self._precompiled[toAddress.toString('hex')]) {
      isCompiled = true
      code = self._precompiled[toAddress.toString('hex')]
      cb()
      return
    }

    stateManager.getContractCode(toAddress, function (err, c, comp) {
      if (err) return cb(err)
      isCompiled = comp
      code = c
      cb()
    })
  }

  function runCode (cb) {
    if (!code) {
      vmResults.exception = 1
      stateManager.commit(cb)
      return
    }

    var runCodeOpts = {
      code: code,
      data: txData,
      gasLimit: gasLimit,
      gasPrice: gasPrice,
      address: toAddress,
      origin: origin,
      caller: caller,
      value: txValue.toArrayLike(Buffer),
      block: block,
      depth: depth,
      selfdestruct: selfdestruct,
      populateCache: false,
      static: isStatic
    }

    // run Code through vm
    var codeRunner = isCompiled ? self.runJIT : self.runCode
    codeRunner.call(self, runCodeOpts, parseRunResult)

    function parseRunResult (err, results) {
      toAccount = self.stateManager.cache.get(toAddress)
      vmResults = results

      if (createdAddress) {
        // fee for size of the return value
        var totalGas = results.gasUsed
        if (!results.runState.vmError) {
          var returnFee = results.return.length * fees.createDataGas.v
          totalGas = totalGas.addn(returnFee)
        }
        // if not enough gas
        if (totalGas.lte(gasLimit) && results.return.length <= 24576) {
          results.gasUsed = totalGas
        } else {
          results.return = Buffer.from([])
          // since Homestead
          results.exception = 0
          err = results.exceptionError = ERROR.OUT_OF_GAS
          results.gasUsed = gasLimit
        }
      }

      gasUsed = results.gasUsed
      if (err) {
        results.logs = []
        stateManager.revert(cb)
      } else {
        stateManager.commit(cb)
      }
    }
  }

  function saveCode (cb) {
    // store code for a new contract
    if (createdAddress && !vmResults.runState.vmError && vmResults.return.toString() !== '') {
      stateManager.putContractCode(createdAddress, vmResults.return, cb)
    } else {
      cb()
    }
  }

  function parseCallResult (err) {
    if (err) return cb(err)
    var results = {
      gasUsed: gasUsed,
      createdAddress: createdAddress,
      vm: vmResults
    }

    cb(null, results)
  }
}
<commit_msg>don't run precompile if gasLimit=0<commit_after>const Buffer = require('safe-buffer').Buffer
const async = require('async')
const ethUtil = require('ethereumjs-util')
const BN = ethUtil.BN
const fees = require('ethereum-common')
const constants = require('./constants.js')

const ERROR = constants.ERROR

/**
 * runs a CALL operation
 * @method runCall
 * @param opts
 * @param opts.block {Block}
 * @param opts.caller {Buffer}
 * @param opts.code {Buffer} this is for CALLCODE where the code to load is different than the code from the to account.
 * @param opts.data {Buffer}
 * @param opts.gasLimit {Buffer | BN.js }
 * @param opts.gasPrice {Buffer}
 * @param opts.origin {Buffer} []
 * @param opts.to {Buffer}
 * @param opts.value {Buffer}
 */
module.exports = function (opts, cb) {
  var self = this
  var stateManager = self.stateManager

  var vmResults = {}
  var toAccount
  var toAddress = opts.to
  var createdAddress
  var txValue = opts.value || Buffer.from([0])
  var caller = opts.caller
  var account = stateManager.cache.get(caller)
  var block = opts.block
  var code = opts.code
  var txData = opts.data
  var gasLimit = opts.gasLimit || new BN(0xffffff)
  gasLimit = new BN(opts.gasLimit) // make sure is a BN
  var gasPrice = opts.gasPrice
  var gasUsed = new BN(0)
  var origin = opts.origin
  var isCompiled = opts.compiled
  var depth = opts.depth
  // opts.suicides is kept for backward compatiblity with pre-EIP6 syntax
  var selfdestruct = opts.selfdestruct || opts.suicides
  var delegatecall = opts.delegatecall || false
  var isStatic = opts.static || false

  txValue = new BN(txValue)

  stateManager.checkpoint()

  // run and parse
  subTxValue()

  async.series([
    loadToAccount,
    loadCode,
    runCode,
    saveCode
  ], parseCallResult)

  function loadToAccount (done) {
    // get receiver's account
    // toAccount = stateManager.cache.get(toAddress)
    if (!toAddress) {
      // generate a new contract if no `to`
      code = txData
      txData = undefined
      var newNonce = new BN(account.nonce).subn(1)
      createdAddress = toAddress = ethUtil.generateAddress(caller, newNonce.toArray())
      stateManager.getAccount(createdAddress, function (err, account) {
        toAccount = account
        const NONCE_OFFSET = 1
        toAccount.nonce = new BN(toAccount.nonce).addn(NONCE_OFFSET).toArrayLike(Buffer)
        done(err)
      })
    } else {
      // else load the `to` account
      toAccount = stateManager.cache.get(toAddress)
      done()
    }
  }

  function subTxValue () {
    if (delegatecall) {
      return
    }
    account.balance = new BN(account.balance).sub(txValue)
    stateManager.cache.put(caller, account)
  }

  function addTxValue () {
    if (delegatecall) {
      return
    }
    // add the amount sent to the `to` account
    toAccount.balance = new BN(toAccount.balance).add(txValue)
    stateManager.cache.put(toAddress, toAccount)
    stateManager.touched.push(toAddress)
  }

  function loadCode (cb) {
    addTxValue()
    // loads the contract's code if the account is a contract
    if (code || !(toAccount.isContract() || self._precompiled[toAddress.toString('hex')])) {
      cb()
      return
    }

    if (self._precompiled[toAddress.toString('hex')]) {
      isCompiled = true
      code = self._precompiled[toAddress.toString('hex')]
      cb()
      return
    }

    stateManager.getContractCode(toAddress, function (err, c, comp) {
      if (err) return cb(err)
      isCompiled = comp
      code = c
      cb()
    })
  }

  function runCode (cb) {
    if (!code) {
      vmResults.exception = 1
      stateManager.commit(cb)
      return
    }

    var runCodeOpts = {
      code: code,
      data: txData,
      gasLimit: gasLimit,
      gasPrice: gasPrice,
      address: toAddress,
      origin: origin,
      caller: caller,
      value: txValue.toArrayLike(Buffer),
      block: block,
      depth: depth,
      selfdestruct: selfdestruct,
      populateCache: false,
      static: isStatic
    }

    // run Code through vm
    var codeRunner = isCompiled ? self.runJIT : self.runCode
    if (isCompiled && gasLimit.eq(new BN(0))) {
      let results = {}
      results.gasUsed = opts.gasLimit
      results.exception = 0 // 0 means VM fail (in this case because of OOG)
      results.exceptionError = ERROR.OUT_OF_GAS
      parseRunResult(ERROR.OUT_OF_GAS, results)
    } else {
      codeRunner.call(self, runCodeOpts, parseRunResult)
    }

    function parseRunResult (err, results) {
      toAccount = self.stateManager.cache.get(toAddress)
      vmResults = results

      if (createdAddress) {
        // fee for size of the return value
        var totalGas = results.gasUsed
        if (!results.runState.vmError) {
          var returnFee = results.return.length * fees.createDataGas.v
          totalGas = totalGas.addn(returnFee)
        }
        // if not enough gas
        if (totalGas.lte(gasLimit) && results.return.length <= 24576) {
          results.gasUsed = totalGas
        } else {
          results.return = Buffer.from([])
          // since Homestead
          results.exception = 0
          err = results.exceptionError = ERROR.OUT_OF_GAS
          results.gasUsed = gasLimit
        }
      }

      gasUsed = results.gasUsed
      if (err) {
        results.logs = []
        stateManager.revert(cb)
      } else {
        stateManager.commit(cb)
      }
    }
  }

  function saveCode (cb) {
    // store code for a new contract
    if (createdAddress && !vmResults.runState.vmError && vmResults.return.toString() !== '') {
      stateManager.putContractCode(createdAddress, vmResults.return, cb)
    } else {
      cb()
    }
  }

  function parseCallResult (err) {
    if (err) return cb(err)
    var results = {
      gasUsed: gasUsed,
      createdAddress: createdAddress,
      vm: vmResults
    }

    cb(null, results)
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2019 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import React from 'react'
import {arrayOf, func} from 'prop-types'
import I18n from 'i18n!content_share'
import {Table} from '@instructure/ui-table'
import {Menu} from '@instructure/ui-menu'
import {ScreenReaderContent} from '@instructure/ui-a11y-content'
import {Button} from '@instructure/ui-buttons'
import {IconMoreLine, IconEyeLine, IconImportLine, IconTrashLine} from '@instructure/ui-icons'
import {View} from '@instructure/ui-view'
import FriendlyDatetime from '@canvas/datetime/react/components/FriendlyDatetime'
import {Avatar} from '@instructure/ui-avatar'
import {Text} from '@instructure/ui-text'
import {Tooltip} from '@instructure/ui-tooltip'
import contentShareShape from '@canvas/content-sharing/react/proptypes/contentShare'

const friendlyShareNames = {
  assignment: I18n.t('Assignment'),
  discussion_topic: I18n.t('Discussion Topic'),
  module: I18n.t('Module'),
  page: I18n.t('Page'),
  quiz: I18n.t('Quiz')
}

ReceivedTable.propTypes = {
  shares: arrayOf(contentShareShape),
  onPreview: func,
  onImport: func,
  onRemove: func,
  onUpdate: func
}

export default function ReceivedTable({shares, onPreview, onImport, onRemove, onUpdate}) {
  function renderActionMenu(share) {
    const items = []
    if (share.content_export?.workflow_state === 'exported') {
      items.push(
        <Menu.Item key="prv" data-testid="preview-menu-action" onSelect={() => onPreview(share)}>
          <IconEyeLine /> <View margin="0 0 0 x-small">{I18n.t('Preview')}</View>
        </Menu.Item>
      )
      items.push(
        <Menu.Item key="imp" data-testid="import-menu-action" onSelect={() => onImport(share)}>
          <IconImportLine /> <View margin="0 0 0 x-small">{I18n.t('Import')}</View>
        </Menu.Item>
      )
    }
    items.push(
      <Menu.Item key="rmv" data-testid="remove-menu-action" onSelect={() => onRemove(share)}>
        <IconTrashLine /> <View margin="0 0 0 x-small">{I18n.t('Remove')}</View>
      </Menu.Item>
    )
    return (
      <Menu
        data-testid="action-menu"
        trigger={
          <Button variant="icon" size="small" icon={IconMoreLine}>
            <ScreenReaderContent>
              {I18n.t('Manage options for %{name}', {name: share.name})}
            </ScreenReaderContent>
          </Button>
        }
      >
        {items}
      </Menu>
    )
  }

  function renderUnreadBadge({id, name, read_state}) {
    function setReadState() {
      if (typeof onUpdate === 'function') onUpdate(id, {read_state: 'read'})
    }
    function setUnreadState() {
      if (typeof onUpdate === 'function') onUpdate(id, {read_state: 'unread'})
    }

    function srText() {
      if (read_state === 'unread') {
        return I18n.t('%{name} mark as read', {name})
      }
      return I18n.t('%{name} mark as unread', {name})
    }

    if (read_state !== 'read') {
      return (
        <Tooltip renderTip={srText()}>
          <Button
            variant="link"
            size="small"
            data-testid="received-table-row-unread"
            onClick={setReadState}
            margin="0 x-small 0 0"
          >
            {/* unread indicator, until we can use InstUI Badge for both unread and read indicators */}
            <View
              display="block"
              borderWidth="medium"
              width="1rem"
              height="1rem"
              borderRadius="circle"
              borderColor="info"
              background="info"
            />
            <ScreenReaderContent>{srText()}</ScreenReaderContent>
          </Button>
        </Tooltip>
      )
    } else {
      return (
        <Tooltip renderTip={srText()}>
          <Button
            variant="link"
            size="small"
            data-testid="received-table-row-read"
            onClick={setUnreadState}
            margin="0 x-small 0 0"
          >
            <View
              display="block"
              borderWidth="medium"
              width="1rem"
              height="1rem"
              borderRadius="circle"
              borderColor="info"
            />
            <ScreenReaderContent>{srText()}</ScreenReaderContent>
          </Button>
        </Tooltip>
      )
    }
  }

  function renderReceivedColumn(content_export) {
    if (content_export && content_export.workflow_state === 'exported') {
      return <FriendlyDatetime dateTime={content_export.created_at} />
    } else if (
      !content_export ||
      content_export.workflow_state === 'failed' ||
      content_export.workflow_state === 'deleted'
    ) {
      return (
        <Text color="danger">
          {I18n.t('Failed')}
        </Text>
      )
    } else {
      return (
        <Text color="secondary">
          {I18n.t('Pending')}
        </Text>
      )
    }
  }

  function renderRow(share) {
    return (

{renderUnreadBadge(share)}

{share.name}

          <Text>{friendlyShareNames[share.content_type]}</Text>

          <Avatar
            margin="0 small 0 0"
            size="small"
            name={share.sender.display_name}
            src={share.sender.avatar_image_url}
            data-fs-exclude
          />{' '}
          {share.sender.display_name}

{renderReceivedColumn(share.content_export)}

{renderActionMenu(share)}

    )
  }

  return (

            <ScreenReaderContent>{I18n.t('Status')}</ScreenReaderContent>

{I18n.t('Title')}

{I18n.t('Type')}

{I18n.t('From')}

{I18n.t('Received')}

{I18n.t('Actions')}

{shares.map(share => renderRow(share))}

  )
}
<commit_msg>Remove preview menu item (#3)<commit_after>/*
 * Copyright (C) 2019 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import React from 'react'
import {arrayOf, func} from 'prop-types'
import I18n from 'i18n!content_share'
import {Table} from '@instructure/ui-table'
import {Menu} from '@instructure/ui-menu'
import {ScreenReaderContent} from '@instructure/ui-a11y-content'
import {Button} from '@instructure/ui-buttons'
import {IconMoreLine, IconEyeLine, IconImportLine, IconTrashLine} from '@instructure/ui-icons'
import {View} from '@instructure/ui-view'
import FriendlyDatetime from '@canvas/datetime/react/components/FriendlyDatetime'
import {Avatar} from '@instructure/ui-avatar'
import {Text} from '@instructure/ui-text'
import {Tooltip} from '@instructure/ui-tooltip'
import contentShareShape from '@canvas/content-sharing/react/proptypes/contentShare'

const friendlyShareNames = {
  assignment: I18n.t('Assignment'),
  discussion_topic: I18n.t('Discussion Topic'),
  module: I18n.t('Module'),
  page: I18n.t('Page'),
  quiz: I18n.t('Quiz')
}

ReceivedTable.propTypes = {
  shares: arrayOf(contentShareShape),
  onPreview: func,
  onImport: func,
  onRemove: func,
  onUpdate: func
}

export default function ReceivedTable({shares, onPreview, onImport, onRemove, onUpdate}) {
  function renderActionMenu(share) {
    const items = []
    if (share.content_export?.workflow_state === 'exported') {
      /* SFU MOD - Remove Preview menu item (Received Content page).
      items.push(
        <Menu.Item key="prv" data-testid="preview-menu-action" onSelect={() => onPreview(share)}>
          <IconEyeLine /> <View margin="0 0 0 x-small">{I18n.t('Preview')}</View>
        </Menu.Item>
      )
      END SFU MOD - Remove Preview menu item (Received Content page). */
      items.push(
        <Menu.Item key="imp" data-testid="import-menu-action" onSelect={() => onImport(share)}>
          <IconImportLine /> <View margin="0 0 0 x-small">{I18n.t('Import')}</View>
        </Menu.Item>
      )
    }
    items.push(
      <Menu.Item key="rmv" data-testid="remove-menu-action" onSelect={() => onRemove(share)}>
        <IconTrashLine /> <View margin="0 0 0 x-small">{I18n.t('Remove')}</View>
      </Menu.Item>
    )
    return (
      <Menu
        data-testid="action-menu"
        trigger={
          <Button variant="icon" size="small" icon={IconMoreLine}>
            <ScreenReaderContent>
              {I18n.t('Manage options for %{name}', {name: share.name})}
            </ScreenReaderContent>
          </Button>
        }
      >
        {items}
      </Menu>
    )
  }

  function renderUnreadBadge({id, name, read_state}) {
    function setReadState() {
      if (typeof onUpdate === 'function') onUpdate(id, {read_state: 'read'})
    }
    function setUnreadState() {
      if (typeof onUpdate === 'function') onUpdate(id, {read_state: 'unread'})
    }

    function srText() {
      if (read_state === 'unread') {
        return I18n.t('%{name} mark as read', {name})
      }
      return I18n.t('%{name} mark as unread', {name})
    }

    if (read_state !== 'read') {
      return (
        <Tooltip renderTip={srText()}>
          <Button
            variant="link"
            size="small"
            data-testid="received-table-row-unread"
            onClick={setReadState}
            margin="0 x-small 0 0"
          >
            {/* unread indicator, until we can use InstUI Badge for both unread and read indicators */}
            <View
              display="block"
              borderWidth="medium"
              width="1rem"
              height="1rem"
              borderRadius="circle"
              borderColor="info"
              background="info"
            />
            <ScreenReaderContent>{srText()}</ScreenReaderContent>
          </Button>
        </Tooltip>
      )
    } else {
      return (
        <Tooltip renderTip={srText()}>
          <Button
            variant="link"
            size="small"
            data-testid="received-table-row-read"
            onClick={setUnreadState}
            margin="0 x-small 0 0"
          >
            <View
              display="block"
              borderWidth="medium"
              width="1rem"
              height="1rem"
              borderRadius="circle"
              borderColor="info"
            />
            <ScreenReaderContent>{srText()}</ScreenReaderContent>
          </Button>
        </Tooltip>
      )
    }
  }

  function renderReceivedColumn(content_export) {
    if (content_export && content_export.workflow_state === 'exported') {
      return <FriendlyDatetime dateTime={content_export.created_at} />
    } else if (
      !content_export ||
      content_export.workflow_state === 'failed' ||
      content_export.workflow_state === 'deleted'
    ) {
      return (
        <Text color="danger">
          {I18n.t('Failed')}
        </Text>
      )
    } else {
      return (
        <Text color="secondary">
          {I18n.t('Pending')}
        </Text>
      )
    }
  }

  function renderRow(share) {
    return (

{renderUnreadBadge(share)}

{share.name}

          <Text>{friendlyShareNames[share.content_type]}</Text>

          <Avatar
            margin="0 small 0 0"
            size="small"
            name={share.sender.display_name}
            src={share.sender.avatar_image_url}
            data-fs-exclude
          />{' '}
          {share.sender.display_name}

{renderReceivedColumn(share.content_export)}

{renderActionMenu(share)}

    )
  }

  return (

            <ScreenReaderContent>{I18n.t('Status')}</ScreenReaderContent>

{I18n.t('Title')}

{I18n.t('Type')}

{I18n.t('From')}

{I18n.t('Received')}

{I18n.t('Actions')}

{shares.map(share => renderRow(share))}

  )
}
<|endoftext|>


<commit_before>#!/usr/bin/env bash
# -*- bash -*-
#
#

# Array is used.
# Inspired from: http://stackoverflow.com/a/3811396/841803
restart_args=("$@")

action="$1"
layout="Public/applets/MUE/layout.mustache"
shift

set -u -e -o pipefail

# ==============================================================
# === Color codes: =============================================

# FROM: http://www.ibm.com/developerworks/aix/library/au-learningtput/
# FROM: http://stackoverflow.com/questions/5947742/how-to-change-the-output-color-of-echo-in-linux
GREEN=$(tput setaf 2)
GREEN_BG=$(tput setb 2)
WHITE=$(tput setaf 7)
BOLD_WHITE_ON_GREEN=$(tput bold)${WHITE}${GREEN_BG}
BOLD_WHITE=$(tput bold)${WHITE}
RESET_COLOR=$(tput sgr0)
ORANGE='\e[0;33m'
RED='\e[0;31m'
BG_RED='\e[1;31m'
# ==============================================================

case "$action" in

  "help")
    echo ""
    echo "  $ bin/megauni.js  watch"
    echo "  $ bin/megauni.js  watch   fast"
    echo "  $ bin/megauni.js  deploy"
    echo ""
    echo "  $ bin/megauni.js  render_stylus"
    echo "  $ bin/megauni.js  render_html    file/path/mustache.mustache"
    echo "  $ bin/megauni.js  render_all_html"
    echo "  $ bin/megauni.js  render   path/to/file.rb"
    echo ""
    exit 0
    ;;

  "deploy")
    bin/megauni npm install
    node_modules/bower/bin/bower install
    ;;

  "render_stylus")
    for f in ./Public/applets/*/*.styl
    do
      if [[ ! "$f" =~ "vars.styl" ]] ; then
        bin/megauni.js stylus $f
      fi
    done
    ;;

  "render")
    echo "Rendering: $1"
    name="$1"
    shift

    if [[ -f "$name" ]]; then
      dir="$(dirname "$name")"
      name="$(basename "$dir")"
    else
      dir="./Public/applets/$name"
    fi

    markup="$dir/markup.html"

    if [[ ! -d "$dir" ]]; then
      echo "Not found: $dir" 1>&2
      exit 1
    fi

    err=""
    ruby -r"./Public/applets/MUE/layout" -r"${dir}/markup.rb" -e "
      File.write(\"$markup\", HTML);
    " || err="true"

    if [[ -z "$err" ]]; then
      if [[ -f "$markup" ]]; then
        echo "$markup"
      fi

      if [[ "$@" =~ "print" ]]; then
        cat "$markup"
      fi
    fi # === if no err

    ;;

  "render_all_html")
    for file in Public/applets/*/*.mustache
    do
      if [[ ! ( "$file" =~ "layout.mustache" ) ]]; then
        $0 render_html "$file"
      fi
    done
    ;;

  "render_html")
    render_html () {
      local file="$1"
      echo "=== Rendering: $file"
      local results="$(iojs render.js $layout $file)"
      local html_file="$(echo "$results" | head -n 1)"
      local contents="$(echo "$results" | tail -n +2)"
      local html_valid="true"
      local html_dir="$(dirname $html_file)"

      if [[ ! -d "$html_dir" ]]; then
        mkdir -p "$html_dir"
        echo "=== Created dir: ${html_dir}"
      fi

      ( echo "$contents" | tidy -config tidy.configs.txt -output "$html_file" ) || html_valid=""

      if [[ ! -z "$html_valid" ]]; then
        echo "=== Wrote: $html_file"
      fi
    }

    render_html "$@"
    ;;

  "procs")
    ps aux | grep -E "node|megauni|pm2|inotif" --color
    ;;

  "__watch")
    js_files="$(echo -e ./*.js specs/*.js Public/applets/*/*.js)"

    jshint () {
      echo -n "=== Running jshint: $1: "
      set +e
      js_hint_results="$($0 jshint "$1" 2>&1)"
      js_hint_exit_code="$?"
      set -e
      if [[ js_hint_exit_code -eq "0" ]]; then
        echo -e "${GREEN}Passed${RESET_COLOR}"
      else
        echo -e "${RED}Fail${RESET_COLOR}"
        echo "$js_hint_results"
      fi
    }

    echo "=== Watching $(basename $0) (proc group ${$})..."
    IFS=$' '
    while read CHANGE
    do
      IFS=$'\n'
      dir=$(echo "$CHANGE" | cut -d' ' -f 1)
      op=$(echo "$CHANGE" | cut -d' ' -f 2)
      path="${dir}$(echo "$CHANGE" | cut -d' ' -f 3)"
      file="$(basename $path)"

      echo -e "=== $CHANGE (${path})"

      if [[ "$path" =~ ".html" ]]; then
        tidy -config tidy.configs.txt -output "$path" "$path"|| echo "FAILED"
      fi

      if [[ "$path" =~ "$0" ]]; then
        echo ""
        echo "=== Reloading: $0 ${restart_args[@]}"
        exec $0 ${restart_args[@]}
      fi

      if [[ "$file" =~ ".mustache" ]]; then
        if [[ "$file" == "layout.mustache" ]]; then
          $0 render_all_html
        else
          $0 render_html "$path"
        fi
      fi

      if [[ "$path" =~ ".js" && ! "$path" =~ "bin/" ]]; then
        jshint $path

        if [[ js_hint_exit_code -eq "0" ]]; then
          if [[ "$file" == "render.js" ]]; then
            $0 render_all_html
          fi
        fi

        echo ""

      fi
    done < <(
     inotifywait \
       --quiet   \
       --monitor \
       --event close_write \
       "$0" $js_files Public/applets/*/*.mustache
     )

    ;;

  "watch")
    on_exit () {
      echo ""
      echo -e "${GREEN}=== Waiting for child/bg procs for group ${$}...${RESET_COLOR}"
      wait
      echo -e "${GREEN}=== Done.${RESET_COLOR}"
    }

    on_err () {
      exit_code="$1"
      line="$2"
      echo -e    "!!! ERROR: line: ${RED}${line}${RESET_COLOR} exit: ${RED}${exit_code}${RESET_COLOR}"
      echo -e    "!!! Running: KILL -SIGINT -$$"
      trap "exit ${exit_code}" INT
      kill -SIGINT -$$
    }

    trap 'on_err $? $LINENO' ERR
    trap 'on_exit'           EXIT

    do_linting="true"
    do_server="true"
    if [[ "$@" =~ "fast" ]]; then
      do_linting=""
    fi

    if [[ "$@" =~ "no_server" ]]; then
      do_server=""
    fi

    # === Regular expression:
    IFS=$' '

    if [[ ! -z "$do_linting" ]]; then

      for file in $js_files
      do
        if [[ -f "$file" ]]; then
          jshint "$file"
        fi
      done

      $0 render_all_html
    fi

    re='^[0-9]+$'
    (
      cd ../megauni
      bin/megauni watch
    ) &
    echo "=== sub-shell: $! in proc group: $$"

    $0 __watch ${restart_args[@]}

    ;;

  *)

    file="$( echo node_modules/*/bin/$action )"

    if [[ -f "$file"  ]]; then
      $file "$@"
      exit 0
    fi

    echo "Unknown action: $action" 1>&2
    exit 1
    ;;

esac # === case $action
<commit_msg>Dev. checkpoint: Touchups.<commit_after>#!/usr/bin/env bash
# -*- bash -*-
#
#

# Array is used.
# Inspired from: http://stackoverflow.com/a/3811396/841803
restart_args=("$@")

action="$1"
layout="Public/applets/MUE/layout.mustache"
shift

set -u -e -o pipefail

# ==============================================================
# === Color codes: =============================================

# FROM: http://www.ibm.com/developerworks/aix/library/au-learningtput/
# FROM: http://stackoverflow.com/questions/5947742/how-to-change-the-output-color-of-echo-in-linux
GREEN=$(tput setaf 2)
GREEN_BG=$(tput setb 2)
WHITE=$(tput setaf 7)
BOLD_WHITE_ON_GREEN=$(tput bold)${WHITE}${GREEN_BG}
BOLD_WHITE=$(tput bold)${WHITE}
RESET_COLOR=$(tput sgr0)
ORANGE='\e[0;33m'
RED='\e[0;31m'
BG_RED='\e[1;31m'
# ==============================================================

case "$action" in

  "help")
    echo ""
    echo "  $ bin/megauni.js  watch"
    echo "  $ bin/megauni.js  watch   fast"
    echo "  $ bin/megauni.js  deploy"
    echo ""
    echo "  $ bin/megauni.js  render_stylus"
    echo "  $ bin/megauni.js  render_html    file/path/mustache.mustache"
    echo "  $ bin/megauni.js  render_all_html"
    echo "  $ bin/megauni.js  render   path/to/file.rb"
    echo ""
    exit 0
    ;;

  "deploy")
    bin/megauni npm install
    node_modules/bower/bin/bower install
    ;;

  "render_stylus")
    for f in ./Public/applets/*/*.styl
    do
      if [[ ! "$f" =~ "vars.styl" ]] ; then
        bin/megauni.js stylus $f
      fi
    done
    ;;

  "render")
    echo "Rendering: $1"
    name="$1"
    shift

    if [[ -f "$name" ]]; then
      dir="$(dirname "$name")"
      name="$(basename "$dir")"
    else
      dir="./Public/applets/$name"
    fi

    markup="$dir/markup.html"

    if [[ ! -d "$dir" ]]; then
      echo "Not found: $dir" 1>&2
      exit 1
    fi

    err=""
    ruby -r"./Public/applets/MUE/layout" -r"${dir}/markup.rb" -e "
      File.write(\"$markup\", HTML);
    " || err="true"

    if [[ -z "$err" ]]; then
      if [[ -f "$markup" ]]; then
        echo "$markup"
      fi

      if [[ "$@" =~ "print" ]]; then
        cat "$markup"
      fi
    fi # === if no err

    ;;

  "render_all_html")
    for file in Public/applets/*/*.mustache
    do
      if [[ ! ( "$file" =~ "layout.mustache" ) ]]; then
        $0 render_html "$file"
      fi
    done
    ;;

  "render_html")
    render_html () {
      local file="$1"
      echo "=== Rendering: $file"
      local results="$(iojs render.js $layout $file)"
      local html_file="$(echo "$results" | head -n 1)"
      local contents="$(echo "$results" | tail -n +2)"
      local html_valid="true"
      local html_dir="$(dirname $html_file)"

      if [[ ! -d "$html_dir" ]]; then
        mkdir -p "$html_dir"
        echo "=== Created dir: ${html_dir}"
      fi

      ( echo "$contents" | tidy -config tidy.configs.txt -output "$html_file" ) || html_valid=""

      if [[ ! -z "$html_valid" ]]; then
        echo "=== Wrote: $html_file"
      fi
    }

    render_html "$@"
    ;;

  "procs")
    ps aux | grep -E "node|megauni|pm2|inotif" --color
    ;;

  "__watch")
    js_files="$(echo -e ./*.js specs/*.js Public/applets/*/*.js)"

    jshint () {
      echo -n "=== Running jshint: $1: "
      set +e
      js_hint_results="$($0 jshint "$1" 2>&1)"
      js_hint_exit_code="$?"
      set -e
      if [[ js_hint_exit_code -eq "0" ]]; then
        echo -e "${GREEN}Passed${RESET_COLOR}"
      else
        echo -e "${RED}Fail${RESET_COLOR}"
        echo "$js_hint_results"
      fi
    }

    echo -e "=== Watching ${ORANGE}$(basename $0)${RESET_COLOR} (proc group ${$})..."
    IFS=$' '
    while read CHANGE
    do
      IFS=$'\n'
      dir=$(echo "$CHANGE" | cut -d' ' -f 1)
      op=$(echo "$CHANGE" | cut -d' ' -f 2)
      path="${dir}$(echo "$CHANGE" | cut -d' ' -f 3)"
      file="$(basename $path)"

      echo -e "=== $CHANGE (${path})"

      if [[ "$path" =~ ".html" ]]; then
        tidy -config tidy.configs.txt -output "$path" "$path"|| echo "FAILED"
      fi

      if [[ "$path" =~ "$0" ]]; then
        echo ""
        echo "=== ${GREEN}Reloading${RESET_COLOR}: $0 ${restart_args[@]}"
        exec $0 ${restart_args[@]}
      fi

      if [[ "$file" =~ ".mustache" ]]; then
        if [[ "$file" == "layout.mustache" ]]; then
          $0 render_all_html
        else
          $0 render_html "$path"
        fi
      fi

      if [[ "$path" =~ ".js" && ! "$path" =~ "bin/" ]]; then
        jshint $path

        if [[ js_hint_exit_code -eq "0" ]]; then
          if [[ "$file" == "render.js" ]]; then
            $0 render_all_html
          fi
        fi

        echo ""

      fi
    done < <(
     inotifywait \
       --quiet   \
       --monitor \
       --event close_write \
       "$0" $js_files Public/applets/*/*.mustache
     )

    ;;

  "watch")
    on_exit () {
      echo ""
      echo -e "=== ${GREEN}Waiting${RESET_COLOR} for proc group: ${$}..."
      wait
      echo -e "=== ${GREEN}Done${RESET_COLOR} ($(basename $0) $$)"
    }

    on_err () {
      exit_code="$1"
      line="$2"
      echo -e    "!!! ERROR: line: ${RED}${line}${RESET_COLOR} exit: ${RED}${exit_code}${RESET_COLOR}"
      echo -e    "!!! Running: KILL -SIGINT -$$"
      trap "exit ${exit_code}" INT
      kill -SIGINT -$$
    }

    trap 'on_err $? $LINENO' ERR
    trap 'on_exit'           EXIT

    do_linting="true"
    do_server="true"
    if [[ "$@" =~ "fast" ]]; then
      do_linting=""
    fi

    if [[ "$@" =~ "no_server" ]]; then
      do_server=""
    fi

    # === Regular expression:
    IFS=$' '

    if [[ ! -z "$do_linting" ]]; then

      for file in $js_files
      do
        if [[ -f "$file" ]]; then
          jshint "$file"
        fi
      done

      $0 render_all_html
    fi

    re='^[0-9]+$'
    (
      cd ../megauni
      bin/megauni watch
    ) &
    echo "=== sub-shell: $! in proc group: $$"

    $0 __watch ${restart_args[@]}

    ;;

  *)

    file="$( echo node_modules/*/bin/$action )"

    if [[ -f "$file"  ]]; then
      $file "$@"
      exit 0
    fi

    echo "Unknown action: $action" 1>&2
    exit 1
    ;;

esac # === case $action
<|endoftext|>


<commit_before>/*License (MIT)

Copyright © 2013 Matt Diamond

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of
the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

// 2017-10-29 robert@fromont.net.nz Implement as a Cordova plugin for the 'browser' platform

// Public:

function initialize(success, error, opts) {
    console.log("AudioInputCaptureProxy: initialize: " + JSON.stringify(opts));
    onInitialized = success;
    if (!intialized) {
	sampleRate = opts[0] || sampleRate;
        bufferSize = opts[1] || bufferSize;
        channels = opts[2] || channels;
        format = opts[3] || format;
        audioSourceType = opts[4] || audioSourceType;
	fileUrl = opts[5] || fileUrl;

	if (fileUrl) {
	    window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;
	    if (window.webkitStorageInfo && window.webkitStorageInfo.requestQuota) {
		// Chrome/Android requires calling requestQuota first
		window.webkitStorageInfo.requestQuota(
			/file:\/\/\/temporary.*/.test(fileUrl)?window.TEMPORARY:window.PERSISTENT,
		    10*1024*1024,
		    function(grantedBytes) {
			console.log("AudioInputCaptureProxy: Granted " + grantedBytes + " bytes storage");
			window.requestFileSystem(
				/file:\/\/\/temporary.*/.test(fileUrl)?window.TEMPORARY:window.PERSISTENT,
			    10*1024*1024,
			    function(fs) {
				console.log("AudioInputCaptureProxy: Got file system: " + fs.name);
				fileSystem = fs;
				intialized = true;
				onInitialized();
			    }, error);
		    }, error);
	    } else {
		// Firefox and Safari/iOS require calling requestFileSystem directly
		window.requestFileSystem(
			/file:\/\/\/temporary.*/.test(fileUrl)?window.TEMPORARY:window.PERSISTENT,
		    10*1024*1024,
		    function(fs) {
			console.log("AudioInputCaptureProxy: Got file system: " + fs.name);
			fileSystem = fs;
			intialized = true;
			onInitialized();
		    }, error);
	    }
	    return;
	} // fileUrl set
	intialized = true;
    } // !initialized
    onInitialized();
}
function checkMicrophonePermission(success, error, opts) {
    console.log("AudioInputCaptureProxy: checkMicrophonePermission");
    success(microphonePermission);
}
function getMicrophonePermission(success, error, opts) {
    console.log("AudioInputCaptureProxy: getMicrophonePermission");
    if (microphonePermission) { // already got permission
	success(microphonePermission);
    } else { // start audio processing
	initAudio(success, error);
    }
}
function start(success, error, opts) {
    console.log("AudioInputCaptureProxy: start: " + JSON.stringify(opts));
    sampleRate = opts[0] || sampleRate;
    bufferSize = opts[1] || bufferSize;
    channels = opts[2] || channels;
    format = opts[3] || format;
    audioSourceType = opts[4] || audioSourceType;
    fileUrl = opts[5] || fileUrl;
    console.log("AudioInputCaptureProxy: start - fileUrl: " + fileUrl);

    if (!audioRecorder) {
	error("Not initialized");
	return;
    }
    audioRecorder.clear();
    audioRecorder.record();

}
function stop(success, error, opts) {
    console.log("AudioInputCaptureProxy: stop");
    onStopped = success;
    onStopError = error;
    audioRecorder.stop();
    audioRecorder.getBuffers(gotBuffers);
}

// Private:

var sampleRate = 44100;
var bufferSize = 1024;
var channels = 1;
var format = null;
var audioSourceType = null;
var fileUrl = null;
var intialized = false;
var microphonePermission = false;
var audioContext = null;
var onInitialized = null;
var onSuccessGotStream = null;
var onStopped = null;
var onStopError = null;
var audioRecorder = null;
var fileSystem = null;

function initAudio(onSuccess, onError) {
    console.log("AudioInputCaptureProxy: initAudio");
    audioContext = new window.AudioContext();
    if (!navigator.getUserMedia) {
        navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
    }
    if (!navigator.getUserMedia)
    {
	onSuccess(false, "getUserMedia not supported");
	return;
    }
    onSuccessGotStream = onSuccess;
    navigator.getUserMedia(
        {
	    "audio": {
                "mandatory": {
		    "googEchoCancellation": "false",
		    "googAutoGainControl": "false",
		    "googNoiseSuppression": "false",
		    "googHighpassFilter": "false"
                },
                "optional": []
	    },
        }, gotStream, function(e) {
	    console.log("AudioInputCaptureProxy: " + e);
	    onSuccess(false, e);
        });
} // initiAudio

// callback by web audio when access to the microphone is gained (browser platform)
function gotStream(stream) {
    console.log("AudioInputCaptureProxy: gotStream");

    inputPoint = audioContext.createGain();

    // Create an AudioNode from the stream.
    audioStream = stream;
    realAudioInput = audioContext.createMediaStreamSource(stream);
    if (channels = 1) {
	audioInput = convertToMono( realAudioInput );
    } else {
	audioInput = realAudioInput;
    }

    // we will end up downsampling, but recorderWorker.js does this by simply dropping samples
    // so we use a low pass filter to prevent aliasing of higher frequencies
    if (sampleRate < audioContext.sampleRate) {
	var lowPassFilter = audioContext.createBiquadFilter();
	audioInput.connect(lowPassFilter);
	lowPassFilter.connect(inputPoint);
	lowPassFilter.type = lowPassFilter.LOWPASS||"lowpass";
	lowPassFilter.frequency.value = sampleRate/2;
	lowPassFilter.connect(inputPoint);
    } else {
	audioInput.connect(inputPoint);
    }

    console.log("AudioInputCaptureProxy: creating audioRecorder");
    audioRecorder = new Recorder( inputPoint, { sampleRate: sampleRate } );

    // pump through zero gain so that the microphone input doesn't play out the speakers causing feedback
    zeroGain = audioContext.createGain();
    zeroGain.gain.value = 0.0;
    inputPoint.connect( zeroGain );
    zeroGain.connect( audioContext.destination );

    microphonePermission = true;
    onSuccessGotStream(microphonePermission);
} // gotStream

function convertToMono( input ) {
    var splitter = audioContext.createChannelSplitter(2);
    var merger = audioContext.createChannelMerger(2);

    input.connect( splitter );
    splitter.connect( merger, 0, 0 );
    splitter.connect( merger, 0, 1 );
    return merger;
}

// callback from recorder invoked when recordin is finished
function gotBuffers(wav) {
    if (channels == 1) {
	audioRecorder.exportMonoWAV(doneEncoding, wav);
    } else {
	audioRecorder.exportWAV(doneEncoding, wav);
    }
}

function doneEncoding( blob ) {
    console.log("AudioInputCaptureProxy: doneEncoding - write to: " + fileUrl);
    var fileName = fileUrl.replace(/.*\//,"");
    console.log("AudioInputCaptureProxy: doneEncoding - write to file: " + fileName);
    fileSystem.root.getFile(fileName, {create: true}, function(fileEntry) {
	fileEntry.createWriter(function(fileWriter) {
	    fileWriter.onwriteend = function(e) {
		onStopped(fileUrl);
	    };
	    fileWriter.onerror = function(e) {
		console.log("AudioInputCaptureProxy: " + fileUrl + " failed");
		onStopError(e);
	    };
	    console.log("AudioInputCaptureProxy: Saving " + fileUrl);
	    fileWriter.write(blob);
	}, function(e) {
	    console.log("AudioInputCaptureProxy: Could not create writer for " + fileUrl);
	    onStopError(e);
	}); // createWriter .wav
    }, function(e) {
	console.log("AudioInputCaptureProxy: Could not get "+fileUrl+ " -  " + e.toString());
	onStopError(e);
    }); // getFile .wav
}

// 2015-01-28 robert@fromont.net.nz Adding a unique query string ensures it's loaded
// which in turn ensures the workers starts (in Firefox)
var WORKER_PATH = 'RecorderWorker.js?' + new Date();

var Recorder = function(source, cfg){
    var config = cfg || {};
    var bufferLen = config.bufferLen || 4096;
    this.context = source.context;
    if(!this.context.createScriptProcessor){
	this.node = this.context.createJavaScriptNode(bufferLen, 2, 2);
    } else {
	this.node = this.context.createScriptProcessor(bufferLen, 2, 2);
    }
    var worker = new Worker(config.workerPath || WORKER_PATH);
    worker.postMessage({
	command: 'init',
	config: {
            sampleRate: this.context.sampleRate,
            downsampleRate: config.sampleRate || this.context.sampleRate
	}
    });
    var recording = false,
	currCallback;

    this.node.onaudioprocess = function(e){
	if (!recording) return;
	worker.postMessage({
            command: 'record',
            buffer: [
		e.inputBuffer.getChannelData(0),
		e.inputBuffer.getChannelData(1)
            ]
	});
    }

    this.configure = function(cfg){
	for (var prop in cfg){
            if (cfg.hasOwnProperty(prop)){
		config[prop] = cfg[prop];
            }
	}
    }

    this.record = function(){
	recording = true;
    }

    this.stop = function(){
	recording = false;
    }

    this.clear = function(){
	worker.postMessage({ command: 'clear' });
    }

    this.getBuffers = function(cb) {
	currCallback = cb || config.callback;
	worker.postMessage({ command: 'getBuffers' })
    }

    this.exportWAV = function(cb){
	currCallback = cb || config.callback;
	type = config.type || 'audio/wav';
	if (!currCallback) throw new Error('Callback not set');
	worker.postMessage({
            command: 'exportWAV',
            type: type
	});
    }

    this.exportMonoWAV = function(cb){
	currCallback = cb || config.callback;
	type = config.type || 'audio/wav';
	if (!currCallback) throw new Error('Callback not set');
	worker.postMessage({
            command: 'exportMonoWAV',
            type: type
	});
    }

    worker.onmessage = function(e){
	var blob = e.data;
	currCallback(blob);
    }

    source.connect(this.node);
    this.node.connect(this.context.destination);   // if the script node is not connected to an output the "onaudioprocess" event is not triggered in chrome.
};

// 2017-10-29 robert@fromont.net.nz Implement as a Cordova plugin for the 'browser' platform
// Define module exports:
module.exports = {
    initialize: initialize,
    checkMicrophonePermission: checkMicrophonePermission,
    getMicrophonePermission: getMicrophonePermission,
    start: start,
    stop: stop
};
require('cordova/exec/proxy').add('AudioInputCapture', module.exports);
<commit_msg>Get fileUrl usage working on Chrome by ensuring URL is of the form cdvfile://localhost/...<commit_after>/*License (MIT)

Copyright © 2013 Matt Diamond

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of
the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

// 2017-10-29 robert@fromont.net.nz Implement as a Cordova plugin for the 'browser' platform

// Public:

function initialize(success, error, opts) {
    console.log("AudioInputCaptureProxy: initialize: " + JSON.stringify(opts));
    onInitialized = success;
    if (!intialized) {
	sampleRate = opts[0] || sampleRate;
        bufferSize = opts[1] || bufferSize;
        channels = opts[2] || channels;
        format = opts[3] || format;
        audioSourceType = opts[4] || audioSourceType;
	fileUrl = opts[5] || fileUrl;

	if (fileUrl) {
	    window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;
	    if (window.webkitStorageInfo && window.webkitStorageInfo.requestQuota) {
		// Chrome/Android requires calling requestQuota first
		window.webkitStorageInfo.requestQuota(
			/file:\/\/\/temporary.*/.test(fileUrl)?window.TEMPORARY:window.PERSISTENT,
		    10*1024*1024,
		    function(grantedBytes) {
			console.log("AudioInputCaptureProxy: Granted " + grantedBytes + " bytes storage");
			window.requestFileSystem(
				/file:\/\/\/temporary.*/.test(fileUrl)?window.TEMPORARY:window.PERSISTENT,
			    10*1024*1024,
			    function(fs) {
				console.log("AudioInputCaptureProxy: Got file system: " + fs.name);
				fileSystem = fs;
				intialized = true;
				onInitialized();
			    }, error);
		    }, error);
	    } else {
		// Firefox and Safari/iOS require calling requestFileSystem directly
		window.requestFileSystem(
			/file:\/\/\/temporary.*/.test(fileUrl)?window.TEMPORARY:window.PERSISTENT,
		    10*1024*1024,
		    function(fs) {
			console.log("AudioInputCaptureProxy: Got file system: " + fs.name);
			fileSystem = fs;
			intialized = true;
			onInitialized();
		    }, error);
	    }
	    return;
	} // fileUrl set
	intialized = true;
    } // !initialized
    onInitialized();
}
function checkMicrophonePermission(success, error, opts) {
    console.log("AudioInputCaptureProxy: checkMicrophonePermission");
    success(microphonePermission);
}
function getMicrophonePermission(success, error, opts) {
    console.log("AudioInputCaptureProxy: getMicrophonePermission");
    if (microphonePermission) { // already got permission
	success(microphonePermission);
    } else { // start audio processing
	initAudio(success, error);
    }
}
function start(success, error, opts) {
    console.log("AudioInputCaptureProxy: start: " + JSON.stringify(opts));
    sampleRate = opts[0] || sampleRate;
    bufferSize = opts[1] || bufferSize;
    channels = opts[2] || channels;
    format = opts[3] || format;
    audioSourceType = opts[4] || audioSourceType;
    fileUrl = opts[5] || fileUrl;
    // the URL must be converted to a cdvfile:... URL to ensure it's readable from the outside
    fileUrl = fileUrl.replace("filesystem:file:///", "cdvfile://localhost/");
    console.log("AudioInputCaptureProxy: start - fileUrl: " + fileUrl);

    if (!audioRecorder) {
	error("Not initialized");
	return;
    }
    audioRecorder.clear();
    audioRecorder.record();

}
function stop(success, error, opts) {
    console.log("AudioInputCaptureProxy: stop");
    onStopped = success;
    onStopError = error;
    audioRecorder.stop();
    audioRecorder.getBuffers(gotBuffers);
}

// Private:

var sampleRate = 44100;
var bufferSize = 1024;
var channels = 1;
var format = null;
var audioSourceType = null;
var fileUrl = null;
var intialized = false;
var microphonePermission = false;
var audioContext = null;
var onInitialized = null;
var onSuccessGotStream = null;
var onStopped = null;
var onStopError = null;
var audioRecorder = null;
var fileSystem = null;

function initAudio(onSuccess, onError) {
    console.log("AudioInputCaptureProxy: initAudio");
    audioContext = new window.AudioContext();
    if (!navigator.getUserMedia) {
        navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
    }
    if (!navigator.getUserMedia)
    {
	onSuccess(false, "getUserMedia not supported");
	return;
    }
    onSuccessGotStream = onSuccess;
    navigator.getUserMedia(
        {
	    "audio": {
                "mandatory": {
		    "googEchoCancellation": "false",
		    "googAutoGainControl": "false",
		    "googNoiseSuppression": "false",
		    "googHighpassFilter": "false"
                },
                "optional": []
	    },
        }, gotStream, function(e) {
	    console.log("AudioInputCaptureProxy: " + e);
	    onSuccess(false, e);
        });
} // initiAudio

// callback by web audio when access to the microphone is gained (browser platform)
function gotStream(stream) {
    console.log("AudioInputCaptureProxy: gotStream");

    inputPoint = audioContext.createGain();

    // Create an AudioNode from the stream.
    audioStream = stream;
    realAudioInput = audioContext.createMediaStreamSource(stream);
    if (channels = 1) {
	audioInput = convertToMono( realAudioInput );
    } else {
	audioInput = realAudioInput;
    }

    // we will end up downsampling, but recorderWorker.js does this by simply dropping samples
    // so we use a low pass filter to prevent aliasing of higher frequencies
    if (sampleRate < audioContext.sampleRate) {
	var lowPassFilter = audioContext.createBiquadFilter();
	audioInput.connect(lowPassFilter);
	lowPassFilter.connect(inputPoint);
	lowPassFilter.type = lowPassFilter.LOWPASS||"lowpass";
	lowPassFilter.frequency.value = sampleRate/2;
	lowPassFilter.connect(inputPoint);
    } else {
	audioInput.connect(inputPoint);
    }

    console.log("AudioInputCaptureProxy: creating audioRecorder");
    audioRecorder = new Recorder( inputPoint, { sampleRate: sampleRate } );

    // pump through zero gain so that the microphone input doesn't play out the speakers causing feedback
    zeroGain = audioContext.createGain();
    zeroGain.gain.value = 0.0;
    inputPoint.connect( zeroGain );
    zeroGain.connect( audioContext.destination );

    microphonePermission = true;
    onSuccessGotStream(microphonePermission);
} // gotStream

function convertToMono( input ) {
    var splitter = audioContext.createChannelSplitter(2);
    var merger = audioContext.createChannelMerger(2);

    input.connect( splitter );
    splitter.connect( merger, 0, 0 );
    splitter.connect( merger, 0, 1 );
    return merger;
}

// callback from recorder invoked when recordin is finished
function gotBuffers(wav) {
    if (channels == 1) {
	audioRecorder.exportMonoWAV(doneEncoding, wav);
    } else {
	audioRecorder.exportWAV(doneEncoding, wav);
    }
}

function doneEncoding( blob ) {
    console.log("AudioInputCaptureProxy: doneEncoding - write to: " + fileUrl);
    var fileName = fileUrl.replace(/.*\//,"");
    console.log("AudioInputCaptureProxy: doneEncoding - write to file: " + fileName);
    fileSystem.root.getFile(fileName, {create: true}, function(fileEntry) {
	fileEntry.createWriter(function(fileWriter) {
	    fileWriter.onwriteend = function(e) {
		onStopped(fileUrl);
	    };
	    fileWriter.onerror = function(e) {
		console.log("AudioInputCaptureProxy: " + fileUrl + " failed");
		onStopError(e);
	    };
	    console.log("AudioInputCaptureProxy: Saving " + fileUrl);
	    fileWriter.write(blob);
	}, function(e) {
	    console.log("AudioInputCaptureProxy: Could not create writer for " + fileUrl);
	    onStopError(e);
	}); // createWriter .wav
    }, function(e) {
	console.log("AudioInputCaptureProxy: Could not get "+fileUrl+ " -  " + e.toString());
	onStopError(e);
    }); // getFile .wav
}

// 2015-01-28 robert@fromont.net.nz Adding a unique query string ensures it's loaded
// which in turn ensures the workers starts (in Firefox)
var WORKER_PATH = 'RecorderWorker.js?' + new Date();

var Recorder = function(source, cfg){
    var config = cfg || {};
    var bufferLen = config.bufferLen || 4096;
    this.context = source.context;
    if(!this.context.createScriptProcessor){
	this.node = this.context.createJavaScriptNode(bufferLen, 2, 2);
    } else {
	this.node = this.context.createScriptProcessor(bufferLen, 2, 2);
    }
    var worker = new Worker(config.workerPath || WORKER_PATH);
    worker.postMessage({
	command: 'init',
	config: {
            sampleRate: this.context.sampleRate,
            downsampleRate: config.sampleRate || this.context.sampleRate
	}
    });
    var recording = false,
	currCallback;

    this.node.onaudioprocess = function(e){
	if (!recording) return;
	worker.postMessage({
            command: 'record',
            buffer: [
		e.inputBuffer.getChannelData(0),
		e.inputBuffer.getChannelData(1)
            ]
	});
    }

    this.configure = function(cfg){
	for (var prop in cfg){
            if (cfg.hasOwnProperty(prop)){
		config[prop] = cfg[prop];
            }
	}
    }

    this.record = function(){
	recording = true;
    }

    this.stop = function(){
	recording = false;
    }

    this.clear = function(){
	worker.postMessage({ command: 'clear' });
    }

    this.getBuffers = function(cb) {
	currCallback = cb || config.callback;
	worker.postMessage({ command: 'getBuffers' })
    }

    this.exportWAV = function(cb){
	currCallback = cb || config.callback;
	type = config.type || 'audio/wav';
	if (!currCallback) throw new Error('Callback not set');
	worker.postMessage({
            command: 'exportWAV',
            type: type
	});
    }

    this.exportMonoWAV = function(cb){
	currCallback = cb || config.callback;
	type = config.type || 'audio/wav';
	if (!currCallback) throw new Error('Callback not set');
	worker.postMessage({
            command: 'exportMonoWAV',
            type: type
	});
    }

    worker.onmessage = function(e){
	var blob = e.data;
	currCallback(blob);
    }

    source.connect(this.node);
    this.node.connect(this.context.destination);   // if the script node is not connected to an output the "onaudioprocess" event is not triggered in chrome.
};

// 2017-10-29 robert@fromont.net.nz Implement as a Cordova plugin for the 'browser' platform
// Define module exports:
module.exports = {
    initialize: initialize,
    checkMicrophonePermission: checkMicrophonePermission,
    getMicrophonePermission: getMicrophonePermission,
    start: start,
    stop: stop
};
require('cordova/exec/proxy').add('AudioInputCapture', module.exports);
<|endoftext|>


<commit_before><commit_msg>build<commit_after><|endoftext|>


<commit_before>define([
    'knockout',
    'underscore',
    'viewmodels/alert',
    'bindings/scrollTo'
], function(ko, _, AlertViewModel) {
    return function(params) {
        var self = this;
        var getTiles = function(tile, tiles) {
            tiles = tiles || [tile];
            tile.cards.forEach(function(card) {
                card.tiles().forEach(function(tile) {
                    tiles.push(tile);
                    getTiles(tile, tiles);
                });
            });
            return tiles;
        };
        this.showIds = params.showIds || false;
        this.state = params.state || 'form';
        this.preview = params.preview;
        this.loading = params.loading || ko.observable(false);
        this.card = params.card;
        this.tile = params.tile;
        this.reportExpanded = ko.observable(true);
        if (this.preview) {
            if (!this.card.newTile) {
                this.card.newTile = this.card.getNewTile();
            }
            this.tile = this.card.newTile;
        }
        this.form = params.form;
        this.provisionalTileViewModel = params.provisionalTileViewModel;
        this.reviewer = params.reviewer;
        this.expanded = ko.observable(true);
        this.beforeMove = function(e) {
            e.cancelDrop = (e.sourceParent!==e.targetParent);
        };
        this.startDrag = function(e, ui) {
            ko.utils.domData.get(ui.item[0], 'ko_sortItem').selected(true);
        };
        this.config = this.card.model ? this.card.model.get('config') : {};
        _.each(this.configKeys, function(key) {
            self[key] = self.config[key];
        });
        this.showChildCards = ko.computed(function() {
            return this.card.widgets().length === 0;
        }, this);
        this.getValuesByDatatype = function(type) {
            var values = {};
            if (self.tile && self.form) {
                var data = self.tile.getAttributes().data;
                _.each(data, function(value, key) {
                    var node = self.form.nodeLookup[key];
                    if (node && ko.unwrap(node.datatype) === type){
                        values[ko.unwrap(node.id)] = {
                            name: ko.unwrap(node.name),
                            value: value
                        };
                    }
                });
            }
            return values;
        };
        this.showHeaderLine = params.showHeaderLine;
        this.tiles = ko.computed(function() {
            var tiles = [];
            if (self.tile) {
                return getTiles(self.tile);
            } else {
                self.card.tiles().forEach(function(tile) {
                    getTiles(tile, tiles);
                });
            }
            return tiles;
        }, this);
        this.saveTile = function() {
            self.loading(true);
            self.tile.save(function(response) {
                self.loading(false);
                params.pageVm.alert(
                    new AlertViewModel(
                        'ep-alert-red',
                        response.responseJSON.message[0],
                        response.responseJSON.message[1],
                        null,
                        function(){}
                    )
                );
                if (params.form.onSaveError) {
                    params.form.onSaveError(self.tile);
                }
            }, function() {
                self.loading(false);
                if (params.form.onSaveSuccess) {
                    params.form.onSaveSuccess(self.tile);
                }
            });
        };
        this.deleteTile = function() {
            self.loading(true);
            self.tile.deleteTile(function(response) {
                self.loading(false);
                params.pageVm.alert(
                    new AlertViewModel(
                        'ep-alert-red',
                        response.responseJSON.message[0],
                        response.responseJSON.message[1],
                        null,
                        function(){}
                    )
                );
                if (params.form.onDeleteError) {
                    params.form.onDeleteError(self.tile);
                }
            }, function() {
                self.loading(false);
                if (params.form.onDeleteSuccess) {
                    params.form.onDeleteSuccess(self.tile);
                }
            });
        };
    };
});
<commit_msg>Re-adds mistakenly deleted config array, re #5108<commit_after>define([
    'knockout',
    'underscore',
    'viewmodels/alert',
    'bindings/scrollTo'
], function(ko, _, AlertViewModel) {
    return function(params) {
        var self = this;
        var getTiles = function(tile, tiles) {
            tiles = tiles || [tile];
            tile.cards.forEach(function(card) {
                card.tiles().forEach(function(tile) {
                    tiles.push(tile);
                    getTiles(tile, tiles);
                });
            });
            return tiles;
        };
        this.configKeys = params.configKeys || [];
        this.showIds = params.showIds || false;
        this.state = params.state || 'form';
        this.preview = params.preview;
        this.loading = params.loading || ko.observable(false);
        this.card = params.card;
        this.tile = params.tile;
        this.reportExpanded = ko.observable(true);
        if (this.preview) {
            if (!this.card.newTile) {
                this.card.newTile = this.card.getNewTile();
            }
            this.tile = this.card.newTile;
        }
        this.form = params.form;
        this.provisionalTileViewModel = params.provisionalTileViewModel;
        this.reviewer = params.reviewer;
        this.expanded = ko.observable(true);
        this.beforeMove = function(e) {
            e.cancelDrop = (e.sourceParent!==e.targetParent);
        };
        this.startDrag = function(e, ui) {
            ko.utils.domData.get(ui.item[0], 'ko_sortItem').selected(true);
        };
        this.config = this.card.model ? this.card.model.get('config') : {};
        _.each(this.configKeys, function(key) {
            self[key] = self.config[key];
        });
        this.showChildCards = ko.computed(function() {
            return this.card.widgets().length === 0;
        }, this);
        this.getValuesByDatatype = function(type) {
            var values = {};
            if (self.tile && self.form) {
                var data = self.tile.getAttributes().data;
                _.each(data, function(value, key) {
                    var node = self.form.nodeLookup[key];
                    if (node && ko.unwrap(node.datatype) === type){
                        values[ko.unwrap(node.id)] = {
                            name: ko.unwrap(node.name),
                            value: value
                        };
                    }
                });
            }
            return values;
        };
        this.showHeaderLine = params.showHeaderLine;
        this.tiles = ko.computed(function() {
            var tiles = [];
            if (self.tile) {
                return getTiles(self.tile);
            } else {
                self.card.tiles().forEach(function(tile) {
                    getTiles(tile, tiles);
                });
            }
            return tiles;
        }, this);
        this.saveTile = function() {
            self.loading(true);
            self.tile.save(function(response) {
                self.loading(false);
                params.pageVm.alert(
                    new AlertViewModel(
                        'ep-alert-red',
                        response.responseJSON.message[0],
                        response.responseJSON.message[1],
                        null,
                        function(){}
                    )
                );
                if (params.form.onSaveError) {
                    params.form.onSaveError(self.tile);
                }
            }, function() {
                self.loading(false);
                if (params.form.onSaveSuccess) {
                    params.form.onSaveSuccess(self.tile);
                }
            });
        };
        this.deleteTile = function() {
            self.loading(true);
            self.tile.deleteTile(function(response) {
                self.loading(false);
                params.pageVm.alert(
                    new AlertViewModel(
                        'ep-alert-red',
                        response.responseJSON.message[0],
                        response.responseJSON.message[1],
                        null,
                        function(){}
                    )
                );
                if (params.form.onDeleteError) {
                    params.form.onDeleteError(self.tile);
                }
            }, function() {
                self.loading(false);
                if (params.form.onDeleteSuccess) {
                    params.form.onDeleteSuccess(self.tile);
                }
            });
        };
    };
});
<|endoftext|>


<commit_before>_.extend(Meteor, {
  setTimeout: function (f, duration) {
    return setTimeout(Meteor.bindEnvironment(f, function (e) {
      // XXX report nicely (or, should we catch it at all?)
      Meteor._debug("Exception from setTimeout callback:", e.stack);
    }), duration);
  },

  setInterval: function (f, duration) {
    return setInterval(Meteor.bindEnvironment(f, function (e) {
      // XXX report nicely (or, should we catch it at all?)
      Meteor._debug("Exception from setInterval callback:", e.stack);
    }), duration);
  },

  clearInterval: _.bind(clearInterval, null),

  clearTimeout: _.bind(clearTimeout, null),

  // won't be necessary once we clobber the global setTimeout
  defer: function (f) {
    Meteor.setTimeout(f, 0);
  }
});<commit_msg>fix new timers API for IE (fixes tests)<commit_after>_.extend(Meteor, {
  setTimeout: function (f, duration) {
    return setTimeout(Meteor.bindEnvironment(f, function (e) {
      // XXX report nicely (or, should we catch it at all?)
      Meteor._debug("Exception from setTimeout callback:", e.stack);
    }), duration);
  },

  setInterval: function (f, duration) {
    return setInterval(Meteor.bindEnvironment(f, function (e) {
      // XXX report nicely (or, should we catch it at all?)
      Meteor._debug("Exception from setInterval callback:", e.stack);
    }), duration);
  },

  clearInterval: function(x) {
    return clearInterval(x);
  },

  clearTimeout: function(x) {
    return clearTimeout(x);
  },

  // won't be necessary once we clobber the global setTimeout
  defer: function (f) {
    Meteor.setTimeout(f, 0);
  }
});<|endoftext|>


<commit_before>

define([], function() {

    var // keypaths to vertices objects in ajax responses
        VERTICES_RESPONSE_KEYPATHS = ['vertices', 'data.vertices'],

        // Custom converters for routes that are more complicated than above,
        // call updateCacheWithVertex and append to updated, return
        // true if handled
        JSON_CONVERTERS = [

            function vertexProperties(json, updated) {
                var cache;
                if (_.isString(json.id) && _.isObject(json.properties)) {
                    cache = this.updateCacheWithVertex(json);
                    $.extend(true, json, cache);
                    updated.push(cache);

                    updated = true;
                }
                return updated;
            },

            function vertexRelationships(json, updated) {
                var self = this;

                if (json.relationships) {
                    json.relationships.forEach(function(relationship) {
                        if (relationship.vertex) {
                            var cache = self.updateCacheWithVertex(relationship.vertex);
                            $.extend(true, relationship.vertex, cache);
                            updated.push(cache);
                        }
                    });
                }
            },

            function vertexProperties(json, updated) {
                if (json.vertex && json.vertex.graphVertexId && json.properties) {
                    var cache = this.updateCacheWithVertex({
                        id: json.vertex.graphVertexId,
                        properties: json.vertex
                    }, {
                        deletedProperty: json.deletedProperty
                    });
                    $.extend(true, json.vertex, cache.properties);
                    $.extend(true, json.properties, cache.properties);
                    updated.push(cache);
                    return true;
                }
            },

            function verticesRoot(json, updated) {
                var self = this;

                if (_.isArray(json) && json.length && json[0].id && json[0].properties) {
                    json.forEach(function(vertex) {
                        var cache = self.updateCacheWithVertex(vertex);
                        cache.properties._refreshedFromServer = true;
                        $.extend(true, vertex, cache);
                        updated.push(cache);
                    });
                    return true;
                }
            }

        ];

    return withCacheUpdatingAjaxFilters;

    function withCacheUpdatingAjaxFilters() {

        this.after('initialize', function() {
            this.setupAjaxPrefilter();
        });

        this.setupAjaxPrefilter = function() {
            var self = this;

            // Attach converter to ajax requests to merge with cachedVertices,
            // sending updateVertices events
            $.ajaxPrefilter(function(options, originalOptions, xhr) {
                var jsonConverter = options.converters['text json'];
                options.converters['text json'] = function(data) {

                    var json = jsonConverter(data);

                    try {
                        var updated = [],
                            converterFound = _.any(JSON_CONVERTERS, function(c) {
                                if (!json) return;

                                var result = c.call(self, json, updated);
                                return result === true;
                            });

                        if (!converterFound) {
                            VERTICES_RESPONSE_KEYPATHS.forEach(function(paths) {
                                var val = json,
                                    components = paths.split('.');

                                while (val && components.length) {
                                    val = val[components.shift()];
                                }

                                // Found vertices
                                if (val && self.resemblesVertices(val)) {
                                    val.forEach(function(v) {
                                        updated.push( $.extend(true, v, self.updateCacheWithVertex(v)) );
                                    });
                                }
                            });
                        }

                        if (updated.length) {
                            _.defer(function() {
                                self.trigger('verticesUpdated', {
                                    vertices:updated.map(function(v) {
                                        var vertex = $.extend(true, {}, v);
                                        vertex.workspace = {};
                                        return Object.freeze(vertex);
                                    })
                                });
                            });
                        }
                    } catch(e) {
                        console.error('Request failed in prefilter cache phase', e && e.message || e);
                    }
                    return json;
                };
            });
        };
    }
});
<commit_msg>New Property support<commit_after>

define([], function() {

    var // keypaths to vertices objects in ajax responses
        VERTICES_RESPONSE_KEYPATHS = ['vertices', 'data.vertices'],

        // Custom converters for routes that are more complicated than above,
        // call updateCacheWithVertex and append to updated, return
        // true if handled
        JSON_CONVERTERS = [

            function vertexProperties(json, updated) {
                var cache;
                if (_.isString(json.id) && _.isObject(json.properties)) {
                    cache = this.updateCacheWithVertex(json);
                    $.extend(true, json, cache);
                    updated.push(cache);

                    updated = true;
                }
                return updated;
            },

            function vertexRelationships(json, updated) {
                var self = this;

                if (json.relationships) {
                    json.relationships.forEach(function(relationship) {
                        if (relationship.vertex) {
                            var cache = self.updateCacheWithVertex(relationship.vertex);
                            $.extend(true, relationship.vertex, cache);
                            updated.push(cache);
                        }
                    });
                }
            },

            function vertexProperties(json, updated) {
                if (json.vertex && json.vertex.graphVertexId && json.properties) {
                    var cache = this.updateCacheWithVertex({
                        id: json.vertex.graphVertexId,
                        properties: json.properties
                    }, {
                        deletedProperty: json.deletedProperty
                    });
                    updated.push(cache);
                    return true;
                }
            },

            function verticesRoot(json, updated) {
                var self = this;

                if (_.isArray(json) && json.length && json[0].id && json[0].properties) {
                    json.forEach(function(vertex) {
                        var cache = self.updateCacheWithVertex(vertex);
                        cache.properties._refreshedFromServer = true;
                        $.extend(true, vertex, cache);
                        updated.push(cache);
                    });
                    return true;
                }
            }

        ];

    return withCacheUpdatingAjaxFilters;

    function withCacheUpdatingAjaxFilters() {

        this.after('initialize', function() {
            this.setupAjaxPrefilter();
        });

        this.setupAjaxPrefilter = function() {
            var self = this;

            // Attach converter to ajax requests to merge with cachedVertices,
            // sending updateVertices events
            $.ajaxPrefilter(function(options, originalOptions, xhr) {
                var jsonConverter = options.converters['text json'];
                options.converters['text json'] = function(data) {

                    var json = jsonConverter(data);

                    try {
                        var updated = [],
                            converterFound = _.any(JSON_CONVERTERS, function(c) {
                                if (!json) return;

                                var result = c.call(self, json, updated);
                                return result === true;
                            });

                        if (!converterFound) {
                            VERTICES_RESPONSE_KEYPATHS.forEach(function(paths) {
                                var val = json,
                                    components = paths.split('.');

                                while (val && components.length) {
                                    val = val[components.shift()];
                                }

                                // Found vertices
                                if (val && self.resemblesVertices(val)) {
                                    val.forEach(function(v) {
                                        updated.push( $.extend(true, v, self.updateCacheWithVertex(v)) );
                                    });
                                }
                            });
                        }

                        if (updated.length) {
                            _.defer(function() {
                                self.trigger('verticesUpdated', {
                                    vertices:updated.map(function(v) {
                                        var vertex = $.extend(true, {}, v);
                                        vertex.workspace = {};
                                        return Object.freeze(vertex);
                                    })
                                });
                            });
                        }
                    } catch(e) {
                        console.error('Request failed in prefilter cache phase', e && e.message || e);
                    }
                    return json;
                };
            });
        };
    }
});
<|endoftext|>