<commit_before>var request = require('request')
  , settings = require('./settings')
  , Address = require('../models/address');

var base_url = 'http://127.0.0.1:' + settings.port + '/api/';

// returns coinbase total sent as current coin supply
function coinbase_supply(cb) {
  Address.findOne({a_id: 'coinbase'}, function(err, address) {
    if (address) {
      return cb(address.sent);
    } else {
      return cb();
    }
  });
}

module.exports = {

  convert_to_satoshi: function(amount, cb) {
    // fix to 8dp & convert to string
    var fixed = amount.toFixed(8).toString();
    // remove decimal (.) and return integer
    return cb(parseInt(fixed.replace('.', '')));
  },

  get_hashrate: function(cb) {
    if (settings.nethash == 'netmhashps') {
      var uri = base_url + 'getmininginfo';
      request({uri: uri, json: true}, function (error, response, body) { //returned in mhash
        if (body.netmhashps) {
          if (settings.nethash_units == 'K') {
            return cb((body.netmhashps * 1000).toFixed(4));
          } else if (settings.nethash_units == 'G') {
            return cb((body / 1000).toFixed(4));
          } else if (settings.nethash_units == 'H') {
            return cb((body * 1000000).toFixed(4));
          } else if (settings.nethash_units == 'T') {
            return cb((body / 1000000).toFixed(4));
          } else if (settings.nethash_units == 'P') {
            return cb((body / 1000000000).toFixed(4));
          } else {
            return cb(body.netmhashps.toFixed(4));
          }
        } else {
          return cb('-');
        }
      });
    } else {
      var uri = base_url + 'getnetworkhashps';
      request({uri: uri, json: true}, function (error, response, body) {
        if (body == 'There was an error. Check your console.') {
          return cb('-');
        } else {
          if (settings.nethash_units == 'K') {
            return cb((body / 1000).toFixed(4));
          } else if (settings.nethash_units == 'M'){
            return cb((body / 1000000).toFixed(4));
          } else if (settings.nethash_units == 'G') {
            return cb((body / 1000000000).toFixed(4));
          } else if (settings.nethash_units == 'T') {
            return cb((body / 1000000000000).toFixed(4));
          } else if (settings.nethash_units == 'P') {
            return cb((body / 1000000000000000).toFixed(4));
          } else {
            return cb((body).toFixed(4));
          }
        }
      });
    }
  },

  get_difficulty: function(cb) {
    var uri = base_url + 'getdifficulty';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_connectioncount: function(cb) {
    var uri = base_url + 'getconnectioncount';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_blockcount: function(cb) {
    var uri = base_url + 'getblockcount';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_blockhash: function(height, cb) {
    var uri = base_url + 'getblockhash?height=' + height;
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_block: function(hash, cb) {
    var uri = base_url + 'getblock?hash=' + hash;
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_rawtransaction: function(hash, cb) {
    var uri = base_url + 'getrawtransaction?txid=' + hash + '&decrypt=1';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_maxmoney: function(cb) {
    var uri = base_url + 'getmaxmoney';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_maxvote: function(cb) {
    var uri = base_url + 'getmaxvote';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_vote: function(cb) {
    var uri = base_url + 'getvote';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_phase: function(cb) {
    var uri = base_url + 'getphase';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_reward: function(cb) {
    var uri = base_url + 'getreward';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_estnext: function(cb) {
    var uri = base_url + 'getnextrewardestimate';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_nextin: function(cb) {
    var uri = base_url + 'getnextrewardwhenstr';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  // synchonous loop used to interate through an array,
  // avoid use unless absolutely neccessary
  syncLoop: function(iterations, process, exit){
    var index = 0,
        done = false,
        shouldExit = false;
    var loop = {
      next:function(){
          if(done){
              if(shouldExit && exit){
                  exit(); // Exit if we're done
              }
              return; // Stop the loop if we're done
          }
          // If we're not finished
          if(index < iterations){
              index++; // Increment our index
              if (index % 100 === 0) { //clear stack
                setTimeout(function() {
                  process(loop); // Run our process, pass in the loop
                }, 1);
              } else {
                 process(loop); // Run our process, pass in the loop
              }
          // Otherwise we're done
          } else {
              done = true; // Make sure we say we're done
              if(exit) exit(); // Call the callback on exit
          }
      },
      iteration:function(){
          return index - 1; // Return the loop number we're on
      },
      break:function(end){
          done = true; // End the loop
          shouldExit = end; // Passing end as true means we still call the exit callback
      }
    };
    loop.next();
    return loop;
  },

  balance_supply: function(cb) {
    Address.find({}, 'balance').where('balance').gt(0).exec(function(err, docs) {
      var count = 0;
      module.exports.syncLoop(docs.length, function (loop) {
        var i = loop.iteration();
        count = count + docs[i].balance;
        loop.next();
      }, function(){
        return cb(count);
      });
    });
  },

  get_supply: function(cb) {
    if ( settings.supply == 'HEAVY' ) {
      var uri = base_url + 'getsupply';
      request({uri: uri, json: true}, function (error, response, body) {
        return cb(body);
      });
    } else if (settings.supply == 'GETINFO') {
      var uri = base_url + 'getinfo';
      request({uri: uri, json: true}, function (error, response, body) {
        return cb(body.moneysupply);
      });
    } else if (settings.supply == 'BALANCES') {
      module.exports.balance_supply(function(supply) {
        return cb(supply/100000000);
      });
    } else {
      coinbase_supply(function(supply) {
        return cb(supply/100000000);
      });
    }
  },

  is_unique: function(array, object, cb) {
    var unique = true;
    var index = null;
    module.exports.syncLoop(array.length, function (loop) {
      var i = loop.iteration();
      if (array[i].addresses == object) {
        unique = false;
        index = i;
        loop.break(true);
        loop.next();
      } else {
        loop.next();
      }
    }, function(){
      return cb(unique, index);
    });
  },

  calculate_total: function(vout, cb) {
    var total = 0;
    module.exports.syncLoop(vout.length, function (loop) {
      var i = loop.iteration();
      //module.exports.convert_to_satoshi(parseFloat(vout[i].amount), function(amount_sat){
        total = total + vout[i].amount;
        loop.next();
      //});
    }, function(){
      return cb(total);
    });
  },

  prepare_vout: function(vout, txid, vin, cb) {
    var arr_vout = [];
    var arr_vin = [];
    arr_vin = vin;
    module.exports.syncLoop(vout.length, function (loop) {
      var i = loop.iteration();
      // make sure vout has an address
      if (vout[i].scriptPubKey.type != 'nonstandard' && vout[i].scriptPubKey.type != 'nulldata') {
        // check if vout address is unique, if so add it array, if not add its amount to existing index
        //console.log('vout:' + i + ':' + txid);
        module.exports.is_unique(arr_vout, vout[i].scriptPubKey.addresses[0], function(unique, index) {
          if (unique == true) {
            // unique vout
            module.exports.convert_to_satoshi(parseFloat(vout[i].value), function(amount_sat){
              arr_vout.push({addresses: vout[i].scriptPubKey.addresses[0], amount: amount_sat});
              loop.next();
            });
          } else {
            // already exists
            module.exports.convert_to_satoshi(parseFloat(vout[i].value), function(amount_sat){
              arr_vout[index].amount = arr_vout[index].amount + amount_sat;
              loop.next();
            });
          }
        });
      } else {
        // no address, move to next vout
        loop.next();
      }
    }, function(){
      if (vout[0].scriptPubKey.type == 'nonstandard') {
        if ( arr_vin.length > 0 && arr_vout.length > 0 ) {
          if (arr_vin[0].addresses == arr_vout[0].addresses) {
            //PoS
            arr_vout[0].amount = arr_vout[0].amount - arr_vin[0].amount;
            arr_vin.shift();
            return cb(arr_vout, arr_vin);
          } else {
            return cb(arr_vout, arr_vin);
          }
        } else {
          return cb(arr_vout, arr_vin);
        }
      } else {
        return cb(arr_vout, arr_vin);
      }
    });
  },

  get_input_addresses: function(input, vout, cb) {
    var addresses = [];
    if (input.coinbase) {
      var amount = 0;
      module.exports.syncLoop(vout.length, function (loop) {
        var i = loop.iteration();
          amount = amount + parseFloat(vout[i].value);
          loop.next();
      }, function(){
        addresses.push({hash: 'coinbase', amount: amount});
        return cb(addresses);
      });
    } else {
      module.exports.get_rawtransaction(input.txid, function(tx){
        if (tx) {
          module.exports.syncLoop(tx.vout.length, function (loop) {
            var i = loop.iteration();
            if (tx.vout[i].n == input.vout) {
              //module.exports.convert_to_satoshi(parseFloat(tx.vout[i].value), function(amount_sat){
                addresses.push({hash: tx.vout[i].scriptPubKey.addresses[0], amount:tx.vout[i].value});
                loop.break(true);
                loop.next();
              //});
            } else {
              loop.next();
            }
          }, function(){
            return cb(addresses);
          });
        } else {
          return cb();
        }
      });
    }
  },

  prepare_vin: function(tx, cb) {
    var arr_vin = [];
    module.exports.syncLoop(tx.vin.length, function (loop) {
      var i = loop.iteration();
      module.exports.get_input_addresses(tx.vin[i], tx.vout, function(addresses){
        if (addresses) {
          //console.log('vin');
          module.exports.is_unique(arr_vin, addresses[0].hash, function(unique, index) {
            if (unique == true) {
              module.exports.convert_to_satoshi(parseFloat(addresses[0].amount), function(amount_sat){
                arr_vin.push({addresses:addresses[0].hash, amount:amount_sat});
                loop.next();
              });
            } else {
              module.exports.convert_to_satoshi(parseFloat(addresses[0].amount), function(amount_sat){
                arr_vin[index].amount = arr_vin[index].amount + amount_sat;
                loop.next();
              });
            }
          });
        } else {
          loop.next();
        }
      });
    }, function(){
      return cb(arr_vin);
    });
  }
};
<commit_msg>return "-" fast if show_hashrate == false<commit_after>var request = require('request')
  , settings = require('./settings')
  , Address = require('../models/address');

var base_url = 'http://127.0.0.1:' + settings.port + '/api/';

// returns coinbase total sent as current coin supply
function coinbase_supply(cb) {
  Address.findOne({a_id: 'coinbase'}, function(err, address) {
    if (address) {
      return cb(address.sent);
    } else {
      return cb();
    }
  });
}

module.exports = {

  convert_to_satoshi: function(amount, cb) {
    // fix to 8dp & convert to string
    var fixed = amount.toFixed(8).toString();
    // remove decimal (.) and return integer
    return cb(parseInt(fixed.replace('.', '')));
  },

  get_hashrate: function(cb) {
    if (settings.index.show_hashrate == false) return cb('-');
    if (settings.nethash == 'netmhashps') {
      var uri = base_url + 'getmininginfo';
      request({uri: uri, json: true}, function (error, response, body) { //returned in mhash
        if (body.netmhashps) {
          if (settings.nethash_units == 'K') {
            return cb((body.netmhashps * 1000).toFixed(4));
          } else if (settings.nethash_units == 'G') {
            return cb((body / 1000).toFixed(4));
          } else if (settings.nethash_units == 'H') {
            return cb((body * 1000000).toFixed(4));
          } else if (settings.nethash_units == 'T') {
            return cb((body / 1000000).toFixed(4));
          } else if (settings.nethash_units == 'P') {
            return cb((body / 1000000000).toFixed(4));
          } else {
            return cb(body.netmhashps.toFixed(4));
          }
        } else {
          return cb('-');
        }
      });
    } else {
      var uri = base_url + 'getnetworkhashps';
      request({uri: uri, json: true}, function (error, response, body) {
        if (body == 'There was an error. Check your console.') {
          return cb('-');
        } else {
          if (settings.nethash_units == 'K') {
            return cb((body / 1000).toFixed(4));
          } else if (settings.nethash_units == 'M'){
            return cb((body / 1000000).toFixed(4));
          } else if (settings.nethash_units == 'G') {
            return cb((body / 1000000000).toFixed(4));
          } else if (settings.nethash_units == 'T') {
            return cb((body / 1000000000000).toFixed(4));
          } else if (settings.nethash_units == 'P') {
            return cb((body / 1000000000000000).toFixed(4));
          } else {
            return cb((body).toFixed(4));
          }
        }
      });
    }
  },

  get_difficulty: function(cb) {
    var uri = base_url + 'getdifficulty';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_connectioncount: function(cb) {
    var uri = base_url + 'getconnectioncount';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_blockcount: function(cb) {
    var uri = base_url + 'getblockcount';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_blockhash: function(height, cb) {
    var uri = base_url + 'getblockhash?height=' + height;
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_block: function(hash, cb) {
    var uri = base_url + 'getblock?hash=' + hash;
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_rawtransaction: function(hash, cb) {
    var uri = base_url + 'getrawtransaction?txid=' + hash + '&decrypt=1';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_maxmoney: function(cb) {
    var uri = base_url + 'getmaxmoney';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_maxvote: function(cb) {
    var uri = base_url + 'getmaxvote';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_vote: function(cb) {
    var uri = base_url + 'getvote';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_phase: function(cb) {
    var uri = base_url + 'getphase';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_reward: function(cb) {
    var uri = base_url + 'getreward';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_estnext: function(cb) {
    var uri = base_url + 'getnextrewardestimate';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  get_nextin: function(cb) {
    var uri = base_url + 'getnextrewardwhenstr';
    request({uri: uri, json: true}, function (error, response, body) {
      return cb(body);
    });
  },

  // synchonous loop used to interate through an array,
  // avoid use unless absolutely neccessary
  syncLoop: function(iterations, process, exit){
    var index = 0,
        done = false,
        shouldExit = false;
    var loop = {
      next:function(){
          if(done){
              if(shouldExit && exit){
                  exit(); // Exit if we're done
              }
              return; // Stop the loop if we're done
          }
          // If we're not finished
          if(index < iterations){
              index++; // Increment our index
              if (index % 100 === 0) { //clear stack
                setTimeout(function() {
                  process(loop); // Run our process, pass in the loop
                }, 1);
              } else {
                 process(loop); // Run our process, pass in the loop
              }
          // Otherwise we're done
          } else {
              done = true; // Make sure we say we're done
              if(exit) exit(); // Call the callback on exit
          }
      },
      iteration:function(){
          return index - 1; // Return the loop number we're on
      },
      break:function(end){
          done = true; // End the loop
          shouldExit = end; // Passing end as true means we still call the exit callback
      }
    };
    loop.next();
    return loop;
  },

  balance_supply: function(cb) {
    Address.find({}, 'balance').where('balance').gt(0).exec(function(err, docs) {
      var count = 0;
      module.exports.syncLoop(docs.length, function (loop) {
        var i = loop.iteration();
        count = count + docs[i].balance;
        loop.next();
      }, function(){
        return cb(count);
      });
    });
  },

  get_supply: function(cb) {
    if ( settings.supply == 'HEAVY' ) {
      var uri = base_url + 'getsupply';
      request({uri: uri, json: true}, function (error, response, body) {
        return cb(body);
      });
    } else if (settings.supply == 'GETINFO') {
      var uri = base_url + 'getinfo';
      request({uri: uri, json: true}, function (error, response, body) {
        return cb(body.moneysupply);
      });
    } else if (settings.supply == 'BALANCES') {
      module.exports.balance_supply(function(supply) {
        return cb(supply/100000000);
      });
    } else {
      coinbase_supply(function(supply) {
        return cb(supply/100000000);
      });
    }
  },

  is_unique: function(array, object, cb) {
    var unique = true;
    var index = null;
    module.exports.syncLoop(array.length, function (loop) {
      var i = loop.iteration();
      if (array[i].addresses == object) {
        unique = false;
        index = i;
        loop.break(true);
        loop.next();
      } else {
        loop.next();
      }
    }, function(){
      return cb(unique, index);
    });
  },

  calculate_total: function(vout, cb) {
    var total = 0;
    module.exports.syncLoop(vout.length, function (loop) {
      var i = loop.iteration();
      //module.exports.convert_to_satoshi(parseFloat(vout[i].amount), function(amount_sat){
        total = total + vout[i].amount;
        loop.next();
      //});
    }, function(){
      return cb(total);
    });
  },

  prepare_vout: function(vout, txid, vin, cb) {
    var arr_vout = [];
    var arr_vin = [];
    arr_vin = vin;
    module.exports.syncLoop(vout.length, function (loop) {
      var i = loop.iteration();
      // make sure vout has an address
      if (vout[i].scriptPubKey.type != 'nonstandard' && vout[i].scriptPubKey.type != 'nulldata') {
        // check if vout address is unique, if so add it array, if not add its amount to existing index
        //console.log('vout:' + i + ':' + txid);
        module.exports.is_unique(arr_vout, vout[i].scriptPubKey.addresses[0], function(unique, index) {
          if (unique == true) {
            // unique vout
            module.exports.convert_to_satoshi(parseFloat(vout[i].value), function(amount_sat){
              arr_vout.push({addresses: vout[i].scriptPubKey.addresses[0], amount: amount_sat});
              loop.next();
            });
          } else {
            // already exists
            module.exports.convert_to_satoshi(parseFloat(vout[i].value), function(amount_sat){
              arr_vout[index].amount = arr_vout[index].amount + amount_sat;
              loop.next();
            });
          }
        });
      } else {
        // no address, move to next vout
        loop.next();
      }
    }, function(){
      if (vout[0].scriptPubKey.type == 'nonstandard') {
        if ( arr_vin.length > 0 && arr_vout.length > 0 ) {
          if (arr_vin[0].addresses == arr_vout[0].addresses) {
            //PoS
            arr_vout[0].amount = arr_vout[0].amount - arr_vin[0].amount;
            arr_vin.shift();
            return cb(arr_vout, arr_vin);
          } else {
            return cb(arr_vout, arr_vin);
          }
        } else {
          return cb(arr_vout, arr_vin);
        }
      } else {
        return cb(arr_vout, arr_vin);
      }
    });
  },

  get_input_addresses: function(input, vout, cb) {
    var addresses = [];
    if (input.coinbase) {
      var amount = 0;
      module.exports.syncLoop(vout.length, function (loop) {
        var i = loop.iteration();
          amount = amount + parseFloat(vout[i].value);
          loop.next();
      }, function(){
        addresses.push({hash: 'coinbase', amount: amount});
        return cb(addresses);
      });
    } else {
      module.exports.get_rawtransaction(input.txid, function(tx){
        if (tx) {
          module.exports.syncLoop(tx.vout.length, function (loop) {
            var i = loop.iteration();
            if (tx.vout[i].n == input.vout) {
              //module.exports.convert_to_satoshi(parseFloat(tx.vout[i].value), function(amount_sat){
                addresses.push({hash: tx.vout[i].scriptPubKey.addresses[0], amount:tx.vout[i].value});
                loop.break(true);
                loop.next();
              //});
            } else {
              loop.next();
            }
          }, function(){
            return cb(addresses);
          });
        } else {
          return cb();
        }
      });
    }
  },

  prepare_vin: function(tx, cb) {
    var arr_vin = [];
    module.exports.syncLoop(tx.vin.length, function (loop) {
      var i = loop.iteration();
      module.exports.get_input_addresses(tx.vin[i], tx.vout, function(addresses){
        if (addresses) {
          //console.log('vin');
          module.exports.is_unique(arr_vin, addresses[0].hash, function(unique, index) {
            if (unique == true) {
              module.exports.convert_to_satoshi(parseFloat(addresses[0].amount), function(amount_sat){
                arr_vin.push({addresses:addresses[0].hash, amount:amount_sat});
                loop.next();
              });
            } else {
              module.exports.convert_to_satoshi(parseFloat(addresses[0].amount), function(amount_sat){
                arr_vin[index].amount = arr_vin[index].amount + amount_sat;
                loop.next();
              });
            }
          });
        } else {
          loop.next();
        }
      });
    }, function(){
      return cb(arr_vin);
    });
  }
};
<|endoftext|>


<commit_before>/*****************************************************************************/
/* Imports */
/*****************************************************************************/
var MiddlewareStack = Iron.MiddlewareStack;
var Url = Iron.Url;
var Layout = Iron.Layout;
var warn = Iron.utils.warn;
var assert = Iron.utils.assert;

Router = function (options) {
  // keep the same api throughout which is:
  // fn(url, context, done);
  function router (req, res, next) {
    //XXX this assumes no other routers on the parent stack which we should probably fix
    router.dispatch(req.url, {
      request: req,
      response: res
    }, next);
  }

  // the main router stack
  router._stack = new MiddlewareStack;

  // for storing global hooks like before, after, etc.
  router._globalHooks = {};

  // backward compat and quicker lookup of Route handlers vs. regular function
  // handlers.
  router.routes = [];

  // to make sure we don't have more than one route per path
  router.routes._byPath = {};

  // always good to have options
  this.configure.call(router, options);

  // add proto properties to the router function
  _.extend(router, this);

  // let client and server side routing doing different things here
  this.init.call(router, options);

  Meteor.startup(function () {
    Meteor.defer(function () {
      if (router.options.autoStart !== false)
        router.start();
    });
  });

  return router;
};

Router.prototype.init = function (options) {};

Router.prototype.configure = function (options) {
  var self = this;

  options = options || {};

  var toArray = function (value) {
    if (!value)
      return [];

    if (_.isArray(value))
      return value;

    return [value];
  };

  // e.g. before: fn OR before: [fn1, fn2]
  _.each(Iron.Router.HOOK_TYPES, function eachHookType (type) {
    if (options[type]) {
      _.each(toArray(options[type]), function eachHook (hook) {
        self.addHook(type, hook);
      });

      delete options[type];
    }
  });

  this.options = this.options || {};
  _.extend(this.options, options);

  return this;
};

/**
 * Just to support legacy calling. Doesn't really serve much purpose.
 */
Router.prototype.map = function (fn) {
  return fn.call(this);
};

/*
 * XXX removing for now until this is thought about more carefully.
Router.prototype.use = function (path, fn, opts) {
  if (typeof path === 'function') {
    opts = fn || {};
    opts.mount = true;
    opts.where = opts.where || 'server';
    this._stack.push(path, opts);
  } else {
    opts = opts || {};
    opts.mount = true;
    opts.where = opts.where || 'server';
    this._stack.push(path, fn, opts);
  }

  return this;
};
*/

//XXX seems like we could put a params method on the route directly and make it reactive
Router.prototype.route = function (path, fn, opts) {
  var typeOf = function (val) { return Object.prototype.toString.call(val); };
  assert(typeOf(path) === '[object String]' || typeOf(path) === '[object RegExp]', "Router.route requires a path that is a string or regular expression.");

  if (typeof fn === 'object') {
    opts = fn;
    fn = opts.action;
  }

  var route = new Route(path, fn, opts);

  opts = opts || {};

  // don't mount the route
  opts.mount = false;

  // stack expects a function which is exactly what a new Route returns!
  var handler = this._stack.push(path, route, opts);

  handler.route = route;
  route.handler = handler;
  route.router = this;

  assert(!this.routes._byPath[handler.path],
    "A route for the path " + JSON.stringify(handler.path) + " already exists by the name of " + JSON.stringify(handler.name) + ".");
  this.routes._byPath[handler.path] = route;

  this.routes.push(route);

  if (typeof handler.name === 'string')
    this.routes[handler.name] = route;

  return route;
};

/**
 * Find the first route for the given url and options.
 */
Router.prototype.findFirstRoute = function (url) {
  for (var i = 0; i < this.routes.length; i++) {
    if (this.routes[i].handler.test(url, {}))
      return this.routes[i];
  }

  return null;
};

Router.prototype.path = function (routeName, params, options) {
  var route = this.routes[routeName];
  warn(route, "You called Router.path for a route named " + JSON.stringify(routeName) + " but that route doesn't seem to exist. Are you sure you created it?");
  return route && route.path(params, options);
};

Router.prototype.url = function (routeName, params, options) {
  var route = this.routes[routeName];
  warn(route, "You called Router.url for a route named " + JSON.stringify(routeName) + " but that route doesn't seem to exist. Are you sure you created it?");
  return route && route.url(params, options);
};

/**
 * Create a new controller for a dispatch.
 */
Router.prototype.createController = function (url, context) {
  // see if there's a route for this url
  var route = this.findFirstRoute(url);
  var controller;

  context = context || {};

  if (route)
    // let the route decide what controller to use
    controller = route.createController({layout: this._layout});
  else
    // create an anonymous controller
    controller = new RouteController({layout: this._layout});

  controller.router = this;
  controller.configureFromUrl(url, context, {reactive: false});
  return controller;
};

Router.prototype.setTemplateNameConverter = function (fn) {
  this._templateNameConverter = fn;
  return this;
};

Router.prototype.setControllerNameConverter = function (fn) {
  this._controllerNameConverter = fn;
  return this;
};

Router.prototype.toTemplateName = function (str) {
  if (this._templateNameConverter)
    return this._templateNameConverter(str);
  else
    return Iron.utils.classCase(str);
};

Router.prototype.toControllerName = function (str) {
  if (this._controllerNameConverter)
    return this._controllerNameConverter(str);
  else
    return Iron.utils.classCase(str) + 'Controller';
};

/**
 *
 * Add a hook to all routes. The hooks will apply to all routes,
 * unless you name routes to include or exclude via `only` and `except` options
 *
 * @param {String} [type] one of 'load', 'unload', 'before' or 'after'
 * @param {Object} [options] Options to controll the hooks [optional]
 * @param {Function} [hook] Callback to run
 * @return {IronRouter}
 * @api public
 *
 */

Router.prototype.addHook = function(type, hook, options) {
  var self = this;

  options = options || {};

  var toArray = function (input) {
    if (!input)
      return [];
    else if (_.isArray(input))
      return input;
    else
      return [input];
  }

  if (options.only)
    options.only = toArray(options.only);
  if (options.except)
    options.except = toArray(options.except);

  var hooks = this._globalHooks[type] = this._globalHooks[type] || [];

  var hookWithOptions = function () {
    var thisArg = this;
    var args = arguments;
    // this allows us to bind hooks to options that get looked up when you call
    // this.lookupOption from within the hook. And it looks better to keep
    // plugin/hook related options close to their definitions instead of
    // Router.configure. But we use a dynamic variable so we don't have to
    // pass the options explicitly as an argument and plugin creators can
    // just use this.lookupOption which will follow the proper lookup chain from
    // "this", local options, dynamic variable options, route, router, etc.
    return CurrentOptions.withValue(options, function () {
      return self.lookupHook(hook).apply(thisArg, args);
    });
  };

  hooks.push({options: options, hook: hookWithOptions});
  return this;
};

/**
 * If the argument is a function return it directly. If it's a string, see if
 * there is a function in the Iron.Router.hooks namespace. Throw an error if we
 * can't find the hook.
 */
Router.prototype.lookupHook = function (nameOrFn) {
  var fn = nameOrFn;

  // if we already have a func just return it
  if (_.isFunction(fn))
    return fn;

  // look up one of the out-of-box hooks like
  // 'loaded or 'dataNotFound' if the nameOrFn is a
  // string
  if (_.isString(fn)) {
    if (_.isFunction(Iron.Router.hooks[fn]))
      return Iron.Router.hooks[fn];
  }

  // we couldn't find it so throw an error
  throw new Error("No hook found named: " + nameOrFn);
};

/**
 *
 * Fetch the list of global hooks that apply to the given route name.
 * Hooks are defined by the .addHook() function above.
 *
 * @param {String} [type] one of IronRouter.HOOK_TYPES
 * @param {String} [name] the name of the route we are interested in
 * @return {[Function]} [hooks] an array of hooks to run
 * @api public
 *
 */

Router.prototype.getHooks = function(type, name) {
  var self = this;
  var hooks = [];

  _.each(this._globalHooks[type], function(hook) {
    var options = hook.options;

    if (options.except && _.include(options.except, name))
      return [];

    if (options.only && ! _.include(options.only, name))
      return [];

    hooks.push(hook.hook);
  });

  return hooks;
};

Router.HOOK_TYPES = [
  'onRun',
  'onRerun',
  'onBeforeAction',
  'onAfterAction',
  'onStop',

  // not technically a hook but we'll use it
  // in a similar way. This will cause waitOn
  // to be added as a method to the Router and then
  // it can be selectively applied to specific routes
  'waitOn',

  // legacy hook types but we'll let them slide
  'load', // onRun
  'before', // onBeforeAction
  'after', // onAfterAction
  'unload' // onStop
];

/**
 * A namespace for hooks keyed by name.
 */
Router.hooks = {};

/**
 * A namespace for plugin functions keyed by name.
 */
Router.plugins = {};

/**
 * Auto add helper mtehods for all the hooks.
 */

Router.HOOK_TYPES.forEach(function (type) {
  Router.prototype[type] = function (hook, options) {
    this.addHook(type, hook, options);
  };
});

/**
 * Add a plugin to the router instance.
 */
Router.prototype.plugin = function (nameOrFn, options) {
  var func;

  if (typeof nameOrFn === 'function')
    func = nameOrFn;
  else if (typeof nameOrFn === 'string')
    func = Iron.Router.plugins[nameOrFn];

  if (!func)
    throw new Error("No plugin found named " + JSON.stringify(nameOrFn));

  // fn(router, options)
  func.call(this, this, options);

  return this;
};

Iron.Router = Router;
<commit_msg>fix remaining forEach call for IE support<commit_after>/*****************************************************************************/
/* Imports */
/*****************************************************************************/
var MiddlewareStack = Iron.MiddlewareStack;
var Url = Iron.Url;
var Layout = Iron.Layout;
var warn = Iron.utils.warn;
var assert = Iron.utils.assert;

Router = function (options) {
  // keep the same api throughout which is:
  // fn(url, context, done);
  function router (req, res, next) {
    //XXX this assumes no other routers on the parent stack which we should probably fix
    router.dispatch(req.url, {
      request: req,
      response: res
    }, next);
  }

  // the main router stack
  router._stack = new MiddlewareStack;

  // for storing global hooks like before, after, etc.
  router._globalHooks = {};

  // backward compat and quicker lookup of Route handlers vs. regular function
  // handlers.
  router.routes = [];

  // to make sure we don't have more than one route per path
  router.routes._byPath = {};

  // always good to have options
  this.configure.call(router, options);

  // add proto properties to the router function
  _.extend(router, this);

  // let client and server side routing doing different things here
  this.init.call(router, options);

  Meteor.startup(function () {
    Meteor.defer(function () {
      if (router.options.autoStart !== false)
        router.start();
    });
  });

  return router;
};

Router.prototype.init = function (options) {};

Router.prototype.configure = function (options) {
  var self = this;

  options = options || {};

  var toArray = function (value) {
    if (!value)
      return [];

    if (_.isArray(value))
      return value;

    return [value];
  };

  // e.g. before: fn OR before: [fn1, fn2]
  _.each(Iron.Router.HOOK_TYPES, function eachHookType (type) {
    if (options[type]) {
      _.each(toArray(options[type]), function eachHook (hook) {
        self.addHook(type, hook);
      });

      delete options[type];
    }
  });

  this.options = this.options || {};
  _.extend(this.options, options);

  return this;
};

/**
 * Just to support legacy calling. Doesn't really serve much purpose.
 */
Router.prototype.map = function (fn) {
  return fn.call(this);
};

/*
 * XXX removing for now until this is thought about more carefully.
Router.prototype.use = function (path, fn, opts) {
  if (typeof path === 'function') {
    opts = fn || {};
    opts.mount = true;
    opts.where = opts.where || 'server';
    this._stack.push(path, opts);
  } else {
    opts = opts || {};
    opts.mount = true;
    opts.where = opts.where || 'server';
    this._stack.push(path, fn, opts);
  }

  return this;
};
*/

//XXX seems like we could put a params method on the route directly and make it reactive
Router.prototype.route = function (path, fn, opts) {
  var typeOf = function (val) { return Object.prototype.toString.call(val); };
  assert(typeOf(path) === '[object String]' || typeOf(path) === '[object RegExp]', "Router.route requires a path that is a string or regular expression.");

  if (typeof fn === 'object') {
    opts = fn;
    fn = opts.action;
  }

  var route = new Route(path, fn, opts);

  opts = opts || {};

  // don't mount the route
  opts.mount = false;

  // stack expects a function which is exactly what a new Route returns!
  var handler = this._stack.push(path, route, opts);

  handler.route = route;
  route.handler = handler;
  route.router = this;

  assert(!this.routes._byPath[handler.path],
    "A route for the path " + JSON.stringify(handler.path) + " already exists by the name of " + JSON.stringify(handler.name) + ".");
  this.routes._byPath[handler.path] = route;

  this.routes.push(route);

  if (typeof handler.name === 'string')
    this.routes[handler.name] = route;

  return route;
};

/**
 * Find the first route for the given url and options.
 */
Router.prototype.findFirstRoute = function (url) {
  for (var i = 0; i < this.routes.length; i++) {
    if (this.routes[i].handler.test(url, {}))
      return this.routes[i];
  }

  return null;
};

Router.prototype.path = function (routeName, params, options) {
  var route = this.routes[routeName];
  warn(route, "You called Router.path for a route named " + JSON.stringify(routeName) + " but that route doesn't seem to exist. Are you sure you created it?");
  return route && route.path(params, options);
};

Router.prototype.url = function (routeName, params, options) {
  var route = this.routes[routeName];
  warn(route, "You called Router.url for a route named " + JSON.stringify(routeName) + " but that route doesn't seem to exist. Are you sure you created it?");
  return route && route.url(params, options);
};

/**
 * Create a new controller for a dispatch.
 */
Router.prototype.createController = function (url, context) {
  // see if there's a route for this url
  var route = this.findFirstRoute(url);
  var controller;

  context = context || {};

  if (route)
    // let the route decide what controller to use
    controller = route.createController({layout: this._layout});
  else
    // create an anonymous controller
    controller = new RouteController({layout: this._layout});

  controller.router = this;
  controller.configureFromUrl(url, context, {reactive: false});
  return controller;
};

Router.prototype.setTemplateNameConverter = function (fn) {
  this._templateNameConverter = fn;
  return this;
};

Router.prototype.setControllerNameConverter = function (fn) {
  this._controllerNameConverter = fn;
  return this;
};

Router.prototype.toTemplateName = function (str) {
  if (this._templateNameConverter)
    return this._templateNameConverter(str);
  else
    return Iron.utils.classCase(str);
};

Router.prototype.toControllerName = function (str) {
  if (this._controllerNameConverter)
    return this._controllerNameConverter(str);
  else
    return Iron.utils.classCase(str) + 'Controller';
};

/**
 *
 * Add a hook to all routes. The hooks will apply to all routes,
 * unless you name routes to include or exclude via `only` and `except` options
 *
 * @param {String} [type] one of 'load', 'unload', 'before' or 'after'
 * @param {Object} [options] Options to controll the hooks [optional]
 * @param {Function} [hook] Callback to run
 * @return {IronRouter}
 * @api public
 *
 */

Router.prototype.addHook = function(type, hook, options) {
  var self = this;

  options = options || {};

  var toArray = function (input) {
    if (!input)
      return [];
    else if (_.isArray(input))
      return input;
    else
      return [input];
  }

  if (options.only)
    options.only = toArray(options.only);
  if (options.except)
    options.except = toArray(options.except);

  var hooks = this._globalHooks[type] = this._globalHooks[type] || [];

  var hookWithOptions = function () {
    var thisArg = this;
    var args = arguments;
    // this allows us to bind hooks to options that get looked up when you call
    // this.lookupOption from within the hook. And it looks better to keep
    // plugin/hook related options close to their definitions instead of
    // Router.configure. But we use a dynamic variable so we don't have to
    // pass the options explicitly as an argument and plugin creators can
    // just use this.lookupOption which will follow the proper lookup chain from
    // "this", local options, dynamic variable options, route, router, etc.
    return CurrentOptions.withValue(options, function () {
      return self.lookupHook(hook).apply(thisArg, args);
    });
  };

  hooks.push({options: options, hook: hookWithOptions});
  return this;
};

/**
 * If the argument is a function return it directly. If it's a string, see if
 * there is a function in the Iron.Router.hooks namespace. Throw an error if we
 * can't find the hook.
 */
Router.prototype.lookupHook = function (nameOrFn) {
  var fn = nameOrFn;

  // if we already have a func just return it
  if (_.isFunction(fn))
    return fn;

  // look up one of the out-of-box hooks like
  // 'loaded or 'dataNotFound' if the nameOrFn is a
  // string
  if (_.isString(fn)) {
    if (_.isFunction(Iron.Router.hooks[fn]))
      return Iron.Router.hooks[fn];
  }

  // we couldn't find it so throw an error
  throw new Error("No hook found named: " + nameOrFn);
};

/**
 *
 * Fetch the list of global hooks that apply to the given route name.
 * Hooks are defined by the .addHook() function above.
 *
 * @param {String} [type] one of IronRouter.HOOK_TYPES
 * @param {String} [name] the name of the route we are interested in
 * @return {[Function]} [hooks] an array of hooks to run
 * @api public
 *
 */

Router.prototype.getHooks = function(type, name) {
  var self = this;
  var hooks = [];

  _.each(this._globalHooks[type], function(hook) {
    var options = hook.options;

    if (options.except && _.include(options.except, name))
      return [];

    if (options.only && ! _.include(options.only, name))
      return [];

    hooks.push(hook.hook);
  });

  return hooks;
};

Router.HOOK_TYPES = [
  'onRun',
  'onRerun',
  'onBeforeAction',
  'onAfterAction',
  'onStop',

  // not technically a hook but we'll use it
  // in a similar way. This will cause waitOn
  // to be added as a method to the Router and then
  // it can be selectively applied to specific routes
  'waitOn',

  // legacy hook types but we'll let them slide
  'load', // onRun
  'before', // onBeforeAction
  'after', // onAfterAction
  'unload' // onStop
];

/**
 * A namespace for hooks keyed by name.
 */
Router.hooks = {};

/**
 * A namespace for plugin functions keyed by name.
 */
Router.plugins = {};

/**
 * Auto add helper mtehods for all the hooks.
 */

_.each(Router.HOOK_TYPES, function (type) {
  Router.prototype[type] = function (hook, options) {
    this.addHook(type, hook, options);
  };
});

/**
 * Add a plugin to the router instance.
 */
Router.prototype.plugin = function (nameOrFn, options) {
  var func;

  if (typeof nameOrFn === 'function')
    func = nameOrFn;
  else if (typeof nameOrFn === 'string')
    func = Iron.Router.plugins[nameOrFn];

  if (!func)
    throw new Error("No plugin found named " + JSON.stringify(nameOrFn));

  // fn(router, options)
  func.call(this, this, options);

  return this;
};

Iron.Router = Router;
<|endoftext|>


<commit_before>import $ from 'jquery';
import { defer } from 'underscore';
import { View } from 'backbone';
import window from 'plug/util/window';
import PluginsGroupView from './PluginsGroupView';

const SettingsView = View.extend({
  className: 'ext-plug section',

  initialize(o) {
    this.plugins = o.plugins;
    this.ext = o.ext;

    this.refresh();

    this.plugins
      .on('change:enabled', this.onEnabledChange, this)
      .on('reset add remove', this.onUpdate, this);
  },

  remove() {
    this.plugins
      .on('change:enabled', this.onEnabledChange)
      .off('reset add remove', this.onUpdate);
  },

  onUpdate() {
    this.refresh();
    this.render();
  },

  onEnabledChange() {
    // TODO only add/remove changed groups
    this.onUpdate();
  },

  refresh() {
    this.groups = [];
    this.addGroup('Plugins', this.createPluginsGroup(), 1000);
    this.addGroup('ExtPlug', this.createExtPlugGroup(), 999);
    this.plugins.forEach((plugin) => {
      // add plugin settings group for stuff that was already enabled
      if (plugin.get('enabled')) {
        const pluginSettings = this.createSettingsGroup(plugin);
        if (pluginSettings) {
          this.addGroup(plugin.get('name'), pluginSettings);
        }
      }
    });
  },

  render() {
    if (this.scrollPane) {
      this.scrollPane.destroy();
      defer(() => {
        const size = window.getSize();
        this.onResize(size.width, size.height);
      });
    }
    this.$container = $('<div>').addClass('container');
    this.$el.empty().append(this.$container);

    this.sort();
    this.groups.forEach((group) => {
      const header = $('<div />').addClass('header')
        .append($('<span>').text(group.name));
      group.view.render();
      this.$container
        .append(header)
        .append(group.view.$el);
    });

    this.$container.jScrollPane();
    this.scrollPane = this.$container.data('jsp');

    return this;
  },

  createPluginsGroup() {
    const pluginsGroup = new PluginsGroupView({
      collection: this.plugins,
    });
    return pluginsGroup;
  },
  createExtPlugGroup() {
    return this.ext.getSettingsView();
  },

  createSettingsGroup(pluginMeta) {
    const plugin = pluginMeta.get('instance');
    if (!plugin._settings) { // eslint-disable-line no-underscore-dangle
      return null;
    }

    return plugin.getSettingsView();
  },

  sort() {
    this.groups.sort((a, b) => {
      let c = b.priority - a.priority;
      if (c === 0) {
        if (a.name > b.name) {
          c = 1;
        } else if (a.name < b.name) {
          c = -1;
        }
      }
      return c;
    });
  },

  onResize(w, h) {
    this.$container.height(h - this.$container.offset().top);
    if (this.scrollPane) {
      this.scrollPane.reinitialise();
    }
  },

  addGroup(name, view, priority) {
    this.groups.push({
      name,
      view,
      priority: typeof priority === 'number' ? priority : 0,
    });
  },

  getGroup(name) {
    for (let i = 0, l = this.groups.length; i < l; i += 1) {
      if (this.groups[i].name === name) {
        return this.groups[i].view;
      }
    }
    return null;
  },

  hasGroup(name) {
    return this.groups.some(group => group.name === name);
  },

  removeGroup(name) {
    for (let i = 0, l = this.groups.length; i < l; i += 1) {
      if (this.groups[i].name === name) {
        return this.groups.splice(i, 1);
      }
    }
    return null;
  },
});

export default SettingsView;
<commit_msg>settings: fix rerender errors when plugins are disabled<commit_after>import $ from 'jquery';
import { defer } from 'underscore';
import { View } from 'backbone';
import window from 'plug/util/window';
import PluginsGroupView from './PluginsGroupView';

const SettingsView = View.extend({
  className: 'ext-plug section',

  initialize(o) {
    this.plugins = o.plugins;
    this.ext = o.ext;

    this.refresh();

    this.plugins
      .on('change:enabled', this.onEnabledChange, this)
      .on('reset add remove', this.onUpdate, this);
  },

  remove() {
    this.plugins
      .off('change:enabled', this.onEnabledChange)
      .off('reset add remove', this.onUpdate);
  },

  onUpdate() {
    this.refresh();
    this.render();
  },

  onEnabledChange() {
    // TODO only add/remove changed groups
    this.onUpdate();
  },

  refresh() {
    this.groups = [];
    this.addGroup('Plugins', this.createPluginsGroup(), 1000);
    this.addGroup('ExtPlug', this.createExtPlugGroup(), 999);
    this.plugins.forEach((plugin) => {
      // add plugin settings group for stuff that was already enabled
      if (plugin.get('enabled')) {
        const pluginSettings = this.createSettingsGroup(plugin);
        if (pluginSettings) {
          this.addGroup(plugin.get('name'), pluginSettings);
        }
      }
    });
  },

  render() {
    if (this.scrollPane) {
      this.scrollPane.destroy();
      defer(() => {
        const size = window.getSize();
        this.onResize(size.width, size.height);
      });
    }
    this.$container = $('<div>').addClass('container');
    this.$el.empty().append(this.$container);

    this.sort();
    this.groups.forEach((group) => {
      const header = $('<div />').addClass('header')
        .append($('<span>').text(group.name));
      group.view.render();
      this.$container
        .append(header)
        .append(group.view.$el);
    });

    this.$container.jScrollPane();
    this.scrollPane = this.$container.data('jsp');

    return this;
  },

  createPluginsGroup() {
    const pluginsGroup = new PluginsGroupView({
      collection: this.plugins,
    });
    return pluginsGroup;
  },
  createExtPlugGroup() {
    return this.ext.getSettingsView();
  },

  createSettingsGroup(pluginMeta) {
    const plugin = pluginMeta.get('instance');
    if (!plugin._settings) { // eslint-disable-line no-underscore-dangle
      return null;
    }

    return plugin.getSettingsView();
  },

  sort() {
    this.groups.sort((a, b) => {
      let c = b.priority - a.priority;
      if (c === 0) {
        if (a.name > b.name) {
          c = 1;
        } else if (a.name < b.name) {
          c = -1;
        }
      }
      return c;
    });
  },

  onResize(w, h) {
    this.$container.height(h - this.$container.offset().top);
    if (this.scrollPane) {
      this.scrollPane.reinitialise();
    }
  },

  addGroup(name, view, priority) {
    this.groups.push({
      name,
      view,
      priority: typeof priority === 'number' ? priority : 0,
    });
  },

  getGroup(name) {
    for (let i = 0, l = this.groups.length; i < l; i += 1) {
      if (this.groups[i].name === name) {
        return this.groups[i].view;
      }
    }
    return null;
  },

  hasGroup(name) {
    return this.groups.some(group => group.name === name);
  },

  removeGroup(name) {
    for (let i = 0, l = this.groups.length; i < l; i += 1) {
      if (this.groups[i].name === name) {
        return this.groups.splice(i, 1);
      }
    }
    return null;
  },
});

export default SettingsView;
<|endoftext|>


<commit_before>/*global Router, Receipts*/

/* require login */
var OnBeforeActions;

OnBeforeActions = {
    loginRequired: function(pause) {
      if (!Meteor.userId()) {
        this.render('landing');
      } else {
        this.next();
      }
    }
};

Router.onBeforeAction(OnBeforeActions.loginRequired, {
    only: ['home']
});

Router.route('/', {
  waitOn: function() {
    Meteor.subscribe('allUsers');
    return Meteor.subscribe('currentReceipts');
  },
  action: function() {
    this.render("home");
  }
}, {
  name: "home"
});<commit_msg>Fix landing page<commit_after>/*global Router*/

/* require login */
var OnBeforeActions;

OnBeforeActions = {
    loginRequired: function() {
      if (!Meteor.userId()) {
        this.render('landing');
      } else {
        this.next();
      }
    }
};

Router.onBeforeAction(OnBeforeActions.loginRequired);

Router.route('/', {
  waitOn: function() {
    Meteor.subscribe('allUsers');
    return Meteor.subscribe('currentReceipts');
  },
  action: function() {
    this.render("home");
  }
}, {
  name: "home"
});<|endoftext|>


<commit_before>(function (templateLayout) {

    var compiler, log, rootTemplate;
    log = wef.logger("templateLayout.compiler");

    log.info("load compiler module");

    function template(preProcessTemplate) {
        function gridSlot(slotText) {
            log.info("creating new slot...");

            var that = {
                slotText:slotText
            };

            log.info("slot: ", that);
            return that;
        }

        function gridRow(rowText) {
            log.info("creating new row...");

            var that = {
                rowText:rowText,
                slotIdentifier:[],
                length:rowText.length
            };

            (function init() {
                that.slotIdentifier = Array.prototype.map.call(rowText, function (slot) {
                    return gridSlot(slot.charAt(0));
                });
            })();

            log.info("row: ", that);
            return that;
        }

        function grid(display) {
            log.info("creating new grid...");

            var slots = {}, that = {
                rows:[],
                slots:slots,
                //getTemplate
                setTemplate:setTemplate
            };

            (function init() {
                if (display.grid !== null) {
                    that.rows = display.grid.map(function (row) {
                        return gridRow(row);
                    });
                }
            })();

            function hasSlot(slotIdentifier) {
                log.debug("hasSlot ? ", slotIdentifier);
                return that.rows.some(function (row) {
                    var regExp = new RegExp(slotIdentifier);
                    return regExp.exec(row.rowText);
                });
            }

            function setTemplate(aTemplate) {
                var slot, tmp;
                if (hasSlot(aTemplate.position.position)) {
                    log.debug("insert here");
                    tmp = slots[aTemplate.position.position] || [];
                    tmp.push(aTemplate);
                    slots[aTemplate.position.position] = tmp;
                    log.debug("at ", slots[aTemplate.position.position]);
                    return true;
                }

                //forEach non leaf template in slots
                for (slot in slots) {
                    if (slots[slot].some(function (currentTemplate) {
                        return !currentTemplate.isLeaf() && currentTemplate.insert(aTemplate);
                    })) {
                        return true;
                    }
                }

                log.debug("parent template not found");
                return false;
            }

            log.info("grid: ", that);
            return that;
        }

        var that = {
            parentTemplate:null,
            selectorText:preProcessTemplate.selectorText,
            selector:null,
            display:preProcessTemplate.display,
            position:preProcessTemplate.position,
            grid:null,
            isRoot:isRoot,
            isLeaf:isLeaf,
            insert:insert
        };

        (function init() {
            log.debug("creating template...");
            that.grid = grid(preProcessTemplate.display);
        })();

        function isLeaf() {
            return that.display.grid === null;
        }

        function isRoot() {
            return that.position.position === null;
        }

        function insert(aTemplate) {
            log.debug("trying to insert into ", that);
            return that.grid.setTemplate(aTemplate);
        }

        log.info("new template:  ", that);
        return that;
    }

    rootTemplate = function () {
        var that = {
            insert:insert,
            rows:[]
        };

        function insert(preProcessTemplate) {
            log.info("inserting ", preProcessTemplate.selectorText);
            var aTemplate = template(preProcessTemplate);

            if (aTemplate.isRoot()) {
                log.debug("inserting at root", aTemplate);
                that.rows.push(aTemplate);
                return true;
            } else {
                log.debug("searching parent: ", aTemplate.position.position);
                //insert in children
                return that.rows.some(function (element) {
                    return element.insert(aTemplate);
                });
            }
        }

        return that;
    }();

    function parseDisplay(displayValue) {
        /**
         * Name:    ‘display’
         * New value:    <display-type>? && [ [ <string> [ / <row-height> ]? ]+ ] <col-width>*
         * Percentages:    N/A
         * Computed value:    specified value
         *
         * The <display-type> is one of the following keywords. An omitted keyword is equivalent to ‘block’.
         * <display-type> = inline | block | list-item | inline-block | table | inline-table
         * | table-row-group | table-header-group | table-footer-group | table-row
         * | table-column-group | table-column | table-cell | table-caption | none
         *
         * Each <string> consist of one or more at signs (“@”), letters (or digits, see <letter> below),
         * periods (“.”) and spaces
         *
         * Each <row-height> sets the height of the preceding row. The default is ‘auto’.
         * The values can be as follows:
         * <length> An explicit height for that row. Negative values make the template illegal. If the length is
         * expressed in ‘gr’ units, these refer to the inherited grid, not the grid defined by the template itself.
         * auto The row's height is determined by its contents.
         * * (asterisk) All rows with an asterisk will be of equal height.
         *
         * Each <col-width> can be one of the following:
         * <length> An explicit width for that column. Negative values make the template illegal.
         * * (asterisk.) All columns with a ‘*’ have the same width. See the algorithm below.
         * max-content, min-content, minmax(p,q), fit-content
         */
        log.info("compiling display...");
        log.debug("display source: ", displayValue);
        var displayMetadata = {
            displayType:null,
            grid:null
        }, displayTypeRegExp = /^\s*(inline|block|list-item|inline-block|table|inline-table|table-row-group|table-header-group|table-footer-group|table-row|table-column-group|table-column|table-cell|table-caption|none)?/ig, stringRegExp = /\s*"([a-zA-Z0-9.@ ])+"/ig;
        if (displayValue !== undefined) {
            //TODO: check invalid values
            displayMetadata.displayType = displayValue.match(displayTypeRegExp);
            displayMetadata.grid = displayValue.match(stringRegExp).map(function (element) {
                return element.replace(/"/g, "").replace(/\s*/, "");
            });
        }
        log.info("display result: ", displayMetadata);
        return displayMetadata;
    }

    function parsePosition(positionValue) {
        /**
         * Name:    position
         * New value:    <letter> | same
         * Percentages:    N/A
         * Computed value:    ‘<letter>’ or ‘static’; see text
         *
         * <letter> must be a single letter or digit, with category Lu, Ll, Lt or Nd in Unicode [UNICODE]),
         * or a “@” symbol
         */
        log.info("compiling position...");
        log.debug("position source: ", positionValue);
        var positionMetadata = {
            position:null
        };
        var matched;
        var positionRegExp = /^\s*([a-zA-Z0-9]+|same)\s*/i;
        if (positionValue !== undefined) {
            matched = positionValue.match(positionRegExp);
            if (matched === null) {
                log.error("Error: unexpected value at ", positionValue);
                throw new that.UnexpectedValueException("Error: unexpected value at ", positionValue);
            }
            positionMetadata.position = matched[1];
        }
        log.info("position result: ", positionMetadata);
        return positionMetadata;
    }

    function parseProperties(rule) {
        var preProcessTemplate = {};
        log.info("compiling properties...");
        log.debug("properties source: ", rule);

        preProcessTemplate.selectorText = rule.selectorText;

        //log.debug("* ", templateLayout.fn.constants.DISPLAY, rule.declaration[templateLayout.fn.constants.DISPLAY]);
        preProcessTemplate.display = parseDisplay(rule.declaration[templateLayout.fn.constants.DISPLAY]);

        //log.debug("* ", templateLayout.fn.constants.POSITION, rule.declaration[templateLayout.fn.constants.POSITION]);
        preProcessTemplate.position = parsePosition(rule.declaration[templateLayout.fn.constants.POSITION]);

        log.info("properties result: ", preProcessTemplate);
        return preProcessTemplate;
    }

    compiler = function () {
        return new compiler.prototype.init();
    };

    compiler.fn = compiler.prototype;

    compiler.prototype = {
        constructor: compiler,
        init: function() {
            return this;
        },
        compile:function (buffer) {
            var selectorText, preProcessTemplate, inserted;
            log.info("compile...");
            log.debug("buffer: ", buffer);

            for (selectorText in buffer) {
                log.debug("next buffer element: ", selectorText);
                log.group();
                preProcessTemplate = parseProperties(buffer[selectorText]);
                log.debug("preProcess: ", preProcessTemplate);
                inserted = rootTemplate.insert(preProcessTemplate);
                log.groupEnd();
                log.info("element insertion...", inserted ? "[OK]" : "ERROR!");
            }
            log.debug("compile... OK");
            return rootTemplate;

        }
    };

    compiler.prototype.init.prototype = compiler.prototype;

    templateLayout.fn.compiler = compiler;

    log.info("compiler module load... [OK]");

})(window.templateLayout);
<commit_msg>Add gridRow colspan detection<commit_after>(function (templateLayout) {

    var compiler, log, rootTemplate;
    log = wef.logger("templateLayout.compiler");

    log.info("load compiler module");

    function template(preProcessTemplate) {
        function gridSlot(slotText) {
            log.info("creating new slot...");

            var that = {
                slotText:slotText
            };

            log.info("slot: ", that);
            return that;
        }

        function gridRow(rowText) {
            log.info("creating new row...");
            function markColSpan(id) {
                return "+";
            }

            var that = {
                rowText:rowText,
                slotIdentifier:[],
                length:rowText.length,
                colspan:1
            };

            (function init() {
                var lastId={}, currentId, colspan = 1;
                that.slotIdentifier = Array.prototype.map.call(rowText, function (slot) {
                    currentId = gridSlot(slot.charAt(0));
                    if(lastId && lastId.slotText === currentId.slotText) {
                        colspan++;
                    }
                    lastId.slotText = currentId.slotText;
                    return markColSpan(currentId.slotText);
                });
                that.colspan = colspan;
            })();

            log.info("row: ", that);
            return that;
        }

        function grid(display) {
            log.info("creating new grid...");

            var slots = {}, that = {
                rows:[],
                slots:slots,
                //getTemplate
                setTemplate:setTemplate
            };

            (function init() {
                if (display.grid !== null) {
                    that.rows = display.grid.map(function (row) {
                        return gridRow(row);
                    });
                }
            })();

            function hasSlot(slotIdentifier) {
                log.debug("hasSlot ? ", slotIdentifier);
                return that.rows.some(function (row) {
                    var regExp = new RegExp(slotIdentifier);
                    return regExp.exec(row.rowText);
                });
            }

            function setTemplate(aTemplate) {
                var slot, tmp;
                if (hasSlot(aTemplate.position.position)) {
                    log.debug("insert here");
                    tmp = slots[aTemplate.position.position] || [];
                    tmp.push(aTemplate);
                    slots[aTemplate.position.position] = tmp;
                    log.debug("at ", slots[aTemplate.position.position]);
                    return true;
                }

                //forEach non leaf template in slots
                for (slot in slots) {
                    if (slots[slot].some(function (currentTemplate) {
                        return !currentTemplate.isLeaf() && currentTemplate.insert(aTemplate);
                    })) {
                        return true;
                    }
                }

                log.debug("parent template not found");
                return false;
            }

            log.info("grid: ", that);
            return that;
        }

        var that = {
            parentTemplate:null,
            selectorText:preProcessTemplate.selectorText,
            selector:null,
            display:preProcessTemplate.display,
            position:preProcessTemplate.position,
            grid:null,
            isRoot:isRoot,
            isLeaf:isLeaf,
            insert:insert
        };

        (function init() {
            log.debug("creating template...");
            that.grid = grid(preProcessTemplate.display);
        })();

        function isLeaf() {
            return that.display.grid === null;
        }

        function isRoot() {
            return that.position.position === null;
        }

        function insert(aTemplate) {
            log.debug("trying to insert into ", that);
            return that.grid.setTemplate(aTemplate);
        }

        log.info("new template:  ", that);
        return that;
    }

    rootTemplate = function () {
        var that = {
            insert:insert,
            rows:[]
        };

        function insert(preProcessTemplate) {
            log.info("inserting ", preProcessTemplate.selectorText);
            var aTemplate = template(preProcessTemplate);

            if (aTemplate.isRoot()) {
                log.debug("inserting at root", aTemplate);
                that.rows.push(aTemplate);
                return true;
            } else {
                log.debug("searching parent: ", aTemplate.position.position);
                //insert in children
                return that.rows.some(function (element) {
                    return element.insert(aTemplate);
                });
            }
        }

        return that;
    }();

    function parseDisplay(displayValue) {
        /**
         * Name:    ‘display’
         * New value:    <display-type>? && [ [ <string> [ / <row-height> ]? ]+ ] <col-width>*
         * Percentages:    N/A
         * Computed value:    specified value
         *
         * The <display-type> is one of the following keywords. An omitted keyword is equivalent to ‘block’.
         * <display-type> = inline | block | list-item | inline-block | table | inline-table
         * | table-row-group | table-header-group | table-footer-group | table-row
         * | table-column-group | table-column | table-cell | table-caption | none
         *
         * Each <string> consist of one or more at signs (“@”), letters (or digits, see <letter> below),
         * periods (“.”) and spaces
         *
         * Each <row-height> sets the height of the preceding row. The default is ‘auto’.
         * The values can be as follows:
         * <length> An explicit height for that row. Negative values make the template illegal. If the length is
         * expressed in ‘gr’ units, these refer to the inherited grid, not the grid defined by the template itself.
         * auto The row's height is determined by its contents.
         * * (asterisk) All rows with an asterisk will be of equal height.
         *
         * Each <col-width> can be one of the following:
         * <length> An explicit width for that column. Negative values make the template illegal.
         * * (asterisk.) All columns with a ‘*’ have the same width. See the algorithm below.
         * max-content, min-content, minmax(p,q), fit-content
         */
        log.info("compiling display...");
        log.debug("display source: ", displayValue);
        var displayMetadata = {
            displayType:null,
            grid:null
        }, displayTypeRegExp = /^\s*(inline|block|list-item|inline-block|table|inline-table|table-row-group|table-header-group|table-footer-group|table-row|table-column-group|table-column|table-cell|table-caption|none)?/ig, stringRegExp = /\s*"([a-zA-Z0-9.@ ])+"/ig;
        if (displayValue !== undefined) {
            //TODO: check invalid values
            displayMetadata.displayType = displayValue.match(displayTypeRegExp);
            displayMetadata.grid = displayValue.match(stringRegExp).map(function (element) {
                return element.replace(/"/g, "").replace(/\s*/, "");
            });
        }
        log.info("display result: ", displayMetadata);
        return displayMetadata;
    }

    function parsePosition(positionValue) {
        /**
         * Name:    position
         * New value:    <letter> | same
         * Percentages:    N/A
         * Computed value:    ‘<letter>’ or ‘static’; see text
         *
         * <letter> must be a single letter or digit, with category Lu, Ll, Lt or Nd in Unicode [UNICODE]),
         * or a “@” symbol
         */
        log.info("compiling position...");
        log.debug("position source: ", positionValue);
        var positionMetadata = {
            position:null
        };
        var matched;
        var positionRegExp = /^\s*([a-zA-Z0-9]+|same)\s*/i;
        if (positionValue !== undefined) {
            matched = positionValue.match(positionRegExp);
            if (matched === null) {
                log.error("Error: unexpected value at ", positionValue);
                throw new that.UnexpectedValueException("Error: unexpected value at ", positionValue);
            }
            positionMetadata.position = matched[1];
        }
        log.info("position result: ", positionMetadata);
        return positionMetadata;
    }

    function parseProperties(rule) {
        var preProcessTemplate = {};
        log.info("compiling properties...");
        log.debug("properties source: ", rule);

        preProcessTemplate.selectorText = rule.selectorText;

        //log.debug("* ", templateLayout.fn.constants.DISPLAY, rule.declaration[templateLayout.fn.constants.DISPLAY]);
        preProcessTemplate.display = parseDisplay(rule.declaration[templateLayout.fn.constants.DISPLAY]);

        //log.debug("* ", templateLayout.fn.constants.POSITION, rule.declaration[templateLayout.fn.constants.POSITION]);
        preProcessTemplate.position = parsePosition(rule.declaration[templateLayout.fn.constants.POSITION]);

        log.info("properties result: ", preProcessTemplate);
        return preProcessTemplate;
    }

    compiler = function () {
        return new compiler.prototype.init();
    };

    compiler.fn = compiler.prototype;

    compiler.prototype = {
        constructor: compiler,
        init: function() {
            return this;
        },
        compile:function (buffer) {
            var selectorText, preProcessTemplate, inserted;
            log.info("compile...");
            log.debug("buffer: ", buffer);

            for (selectorText in buffer) {
                log.debug("next buffer element: ", selectorText);
                log.group();
                preProcessTemplate = parseProperties(buffer[selectorText]);
                log.debug("preProcess: ", preProcessTemplate);
                inserted = rootTemplate.insert(preProcessTemplate);
                log.groupEnd();
                log.info("element insertion...", inserted ? "[OK]" : "ERROR!");
            }
            log.debug("compile... OK");
            return rootTemplate;

        }
    };

    compiler.prototype.init.prototype = compiler.prototype;

    templateLayout.fn.compiler = compiler;

    log.info("compiler module load... [OK]");

})(window.templateLayout);
<|endoftext|>


<commit_before>var path = require("path");
var config = require("./data/config.json");
var debug = require("./debug");

var options = {
    root: process.env.PUBLIC_DIR,
    dotfiles: 'deny',
    headers: {
        'x-timestamp': Date.now(),
        'x-sent': true
    }
}

function processRoute(req, res) {

    // Cache the file
    var file = req.path.substring(1, req.path.indexOf(".html"));

    // Try getting the router module
    var route = require(process.env.ROUTER_DIR + file + ".js");

    // Run the router module
    route(req, res, function (data) {

        // And run the renderer
        res.render(file, data, function (err, html) {

            // Check if there's renderer error
            if (err) {

                // The renderer has error
                debug.log("Render Error: \n" + err);
                res.error(500, "Internal Server Error");
            }
            else {

                // Send the rendered html
                debug.log(file + ".html successfully rendered");
                res.send(html);
            }
        });
    });
}

function sendStaticHtml(req, res) {

    // Cache the file
    var file = req.path.substring(1, req.path.indexOf(".html"));

    // Try sending the static html
    res.render(file, {}, function (err, html) {

        // Check if there's an error rendering the static file
        if (err) {

            //
            debug.log("Static html not found. Redirecting to 404");

            // Avoid infinity redirecting
            if (file === "error") {
                res.send("
Error 404: Page not found.
");
            }
            else {
                res.error(404, "Page not found");
            }
        }
        else {

            // Directly send the rendered html
            res.send(html);
            debug.log("Directly sent static html " + file);
        }
    });
}

module.exports = {
    preprocess: function (req, res, next) {

        // Wrap error function for response
        res.error = function (code, msg) {
            res.redirect("/" + config.error_page + ".html?code=" + code + "&msg=" + msg);
        };

        // Pass to next middleware
        next();
    },
    router: function (req, res) {

        // Cache the file
        var file = req.path.substring(1, req.path.indexOf(".html"));

        // Try to process the router
        try {
            processRoute(req, res);
        }
        catch (err) {

            // Check if the error is module not found
            if (err.code === "MODULE_NOT_FOUND") {

                // Send static html if the module not found
                sendStaticHtml(req, res);
            }
            else {

                // Then the router file might have error
                debug.log("Router " + file + " Error: \n" + err);
                res.error(500, "Internal Server Error");
            }
        }
    }
}
<commit_msg>Tempting to debug<commit_after>var path = require("path");
var config = require("./data/config.json");
var debug = require("./debug");

var options = {
    root: process.env.PUBLIC_DIR,
    dotfiles: 'deny',
    headers: {
        'x-timestamp': Date.now(),
        'x-sent': true
    }
}

function processRoute(req, res) {

    // Cache the file
    var file = req.path.substring(1, req.path.indexOf(".html"));

    // Try getting the router module
    var route = require(process.env.ROUTER_DIR + file + ".js");

    // Run the router module
    route(req, res, function (data) {

        // And run the renderer
        res.render(file, data, function (err, html) {

            // Check if there's renderer error
            if (err) {

                // The renderer has error
                debug.log("Render Error: \n" + err);
                res.error(500, "Internal Server Error");
            }
            else {

                // Send the rendered html
                debug.log(file + ".html successfully rendered");
                res.send(html);
            }
        });
    });
}

function sendStaticHtml(req, res) {

    // Cache the file
    var file = req.path.substring(1, req.path.indexOf(".html"));

    // Try sending the static html
    res.render(file, {}, function (err, html) {

        // Check if there's an error rendering the static file
        if (err) {

            //
            debug.log("Static html not found. Redirecting to 404");

            // Avoid infinity redirecting
            if (file === "error") {

                if (req.query.code) {
                    res.send("
Error " + req.query.code + ": " + req.query.msg + "
");
                }
                else {
                    res.send("
Error 404: Page not found.
");
                }
            }
            else {
                res.error(404, "Page not found");
            }
        }
        else {

            // Directly send the rendered html
            res.send(html);
            debug.log("Directly sent static html " + file);
        }
    });
}

module.exports = {
    preprocess: function (req, res, next) {

        debug.log("TADSFADSADFS");

        // Wrap error function for response
        res.error = function (code, msg) {
            res.redirect("/" + config.error_page + ".html?code=" + code + "&msg=" + msg);
        };

        // Pass to next middleware
        next();
    },
    router: function (req, res) {

        // Cache the file
        var file = req.path.substring(1, req.path.indexOf(".html"));

        // Try to process the router
        try {
            processRoute(req, res);
        }
        catch (err) {

            // Check if the error is module not found
            if (err.code === "MODULE_NOT_FOUND") {

                // Send static html if the module not found
                sendStaticHtml(req, res);
            }
            else {

                // Then the router file might have error
                debug.log("Router " + file + " Error: \n" + err);
                res.error(500, "Internal Server Error");
            }
        }
    }
}
<|endoftext|>


<commit_before>Router.configure({
  layoutTemplate: 'layout',
  loadingTemplate: 'loading',
  notFoundTemplate: 'notFound',
  waitOn: function() {
    Meteor.subscribe('bets');
    Meteor.subscribe('betNotifications');
  },
});

var notLoggedIn = function(){
  if( !Meteor.user() ){
    Router.go('welcome');
  } else {
    this.next();
  }
};

Router.onBeforeAction('dataNotFound', { only: 'singleBet' });
Router.onBeforeAction(notLoggedIn, { except: [ 'welcome' ] })

Router.map(function(){
  this.route('home', {
    path: '/',
    waitOn: function(){
      Meteor.subscribe('betNotifications');
    }
  });

  this.route('welcome', {
    path: '/welcome'
  });

  this.route('betsList', {
    path: '/bets'
  });

  this.route('dashboard', {
    path: 'dashboard',
    waitOn: function(){
      Meteor.subscribe('betNotifications');
    },
  });

  this.route('createBetForm', {
    path: 'bet',
    data: function(){
      Meteor.subscribe('allUsernames');
      Meteor.subscribe('images');
    }
  });

  this.route('/bets/:_id', {
    name: 'singleBet',
    waitOn: function(){
      Meteor.subscribe('messages');
      Meteor.subscribe('images');
    },
    data: function(){
      return Bets.findOne(this.params._id);
    }
  });

  this.route('/notifications', {
    name: 'notifications',
    waitOn: function(){
      Meteor.subscribe('betNotifications');
    },
  });

  this.route('/messages', {
    name: 'messages',
    waitOn: function(){
      Meteor.subscribe('messages');
    },
  });
});

<commit_msg>Redirect to home instead of welcome partial.<commit_after>Router.configure({
  layoutTemplate: 'layout',
  loadingTemplate: 'loading',
  notFoundTemplate: 'notFound',
  waitOn: function() {
    Meteor.subscribe('bets');
    Meteor.subscribe('betNotifications');
  },
});

var notLoggedIn = function(){
  if( !Meteor.user() ){
    Router.go('home');
  } else {
    this.next();
  }
};

Router.onBeforeAction('dataNotFound', { only: 'singleBet' });
Router.onBeforeAction(notLoggedIn, { except: [ 'home' ] })

Router.map(function(){
  this.route('home', {
    path: '/',
    waitOn: function(){
      Meteor.subscribe('betNotifications');
    }
  });

  this.route('welcome', {
    path: '/welcome'
  });

  this.route('betsList', {
    path: '/bets'
  });

  this.route('dashboard', {
    path: 'dashboard',
    waitOn: function(){
      Meteor.subscribe('betNotifications');
    },
  });

  this.route('createBetForm', {
    path: 'bet',
    data: function(){
      Meteor.subscribe('allUsernames');
      Meteor.subscribe('images');
    }
  });

  this.route('/bets/:_id', {
    name: 'singleBet',
    waitOn: function(){
      Meteor.subscribe('messages');
      Meteor.subscribe('images');
    },
    data: function(){
      return Bets.findOne(this.params._id);
    }
  });

  this.route('/notifications', {
    name: 'notifications',
    waitOn: function(){
      Meteor.subscribe('betNotifications');
    },
  });

  this.route('/messages', {
    name: 'messages',
    waitOn: function(){
      Meteor.subscribe('messages');
    },
  });
});

<|endoftext|>


<commit_before>FlowRouter.route('/', {
    name: "home",
    action: function() {
        BlazeLayout.render("master_layout", {main: "home"});
    }
});

FlowRouter.route('/addNewRiskGroup', {
    name: "addNewRiskGroup",
    action: function() {
    	if(Meteor.user() != null ) {
    		BlazeLayout.render("master_layout", {main: "addNewRiskGroup"});
    	}
    }
});

FlowRouter.route('/uploadDNA', {
    name: "uploadDNA",
    action: function() {
    	if(Meteor.user() != null) {
    		BlazeLayout.render("master_layout", {main: "uploadDNA"});
    	}
    }
});<commit_msg>fixed navbar<commit_after>FlowRouter.route('/', {
    name: "home",
    action: function() {
        BlazeLayout.render("master_layout", {main: "home"});
    }
});

FlowRouter.route('/addNewRiskGroup', {
    name: "addNewRiskGroup",
    action: function() {
    	if(Meteor.user() != null ) {
    		BlazeLayout.render("master_layout", {main: "addNewRiskGroup"});
    	}else {
            BlazeLayout.render("master_layout", {main: "home"});
        }
    }
});

FlowRouter.route('/uploadDNA', {
    name: "uploadDNA",
    action: function() {
    	if(Meteor.user() != null) {
    		BlazeLayout.render("master_layout", {main: "uploadDNA"});
    	}else {
            BlazeLayout.render("master_layout", {main: "home"});
        }
    }
});<|endoftext|>