<commit_before>Box.Application.addModule('horizon-index', function(context) { //FIXME rename to cloud|summary|?|-index?
  'use strict';

  var moduleElement, windowSvc, d3, cubism, metric, timescale, utils, $, cubismContext;

  var defaultColors = ["#08519c", "#3182bd", "#6baed6", "#bdd7e7", "#bae4b3", "#74c476", "#31a354", "#006d2c"];
  var cpuColors = ["#08519c", "#3182bd", "#6baed6", "#bdd7e7", "#bae4b3", "#006d2c", "#b07635", "#d01717"];
  var metricMap = {
    "cpu" : { "title" : "cpu: ", "format" : ".2f", "extent": [0, 100], colors : cpuColors, height: 50 },
    "mem" : { "title" : "mem: ", "format" : ".2f", "extent": [0, 100], colors : cpuColors, height: 50 },
    "net" : { "title" : "net: ", "format" : ".2f", "extent": undefined, colors : defaultColors, height: 50 },
    "diskio" : { "title" : "io: ", "format" : ".2f", "extent": undefined, colors : defaultColors, height: 50 },
    "tcpinfo" : { "title" : "conn: ", "format" : ".0f", "extent": undefined, colors : defaultColors, height: 50 }
  };

  var deployer_metric = function(name, tag, stop, step) {
    var hostTag = tag;
    return cubismContext.metric(function(start, stop, step, callback) {
      d3.json("metrics/" + name +
      "?start=" + start.getTime() +
      "&stop=" + stop.getTime() +
      "&step=" + step + "&tag=" + hostTag, function(data) {
        if (!data) return callback(new Error("unable to load data"));
        callback(null, data.map(function(d) { return d.value; }));
      });
    }, name += "");
  };

  var resetGraphs = function() {
    var widthInPx = $(window).width();
    var step = parseInt(timescale * 1000 / widthInPx);
    var stop = new Date().getTime();
    var start = stop - (timescale * 1000);

    resetCubismContext(step, widthInPx);
    removeExistingGraphs();
    initGraphLayout(widthInPx);
    initGraphs(metric, start, stop, step);
  };

  function resetCubismContext(step, widthInPixels) {
    if (cubismContext) cubismContext.stop();
    cubismContext = cubism.context()
        .step(step)
        .size(widthInPixels)
        .start();
    cubismContext.on("focus", function(i) {
      d3.selectAll(".horizon .value").style("right", i === null ? null : cubismContext.size() - i + "px");
    });
  }

  function initGraphLayout(widthInPixels) {
    d3.select("#chart").attr("style", "width: " + widthInPixels + "px");
    d3.select("#chart").call(function(container) {
      container.append("div")
          .classed("axis", true)
          .call(cubismContext.axis()
              .orient("top")
              .tickFormat(d3.time.format("%H:%M")));
    });
    d3.select("#chart").call(function(container) {
      container.append("div")
          .classed("rule", true)
          .call(cubismContext.rule());
    });
  }

  function removeExistingGraphs() {
    d3.selectAll(".horizon").call(cubismContext.horizon().remove).remove();
    d3.selectAll(".axis").remove();
    d3.selectAll(".rule").remove();
  }

  var initGraphs = function(metric, start, stop, step) {
    var dataUrl = "metrics/hosts" + "?start=" + start + "&stop=" + stop + "&type=" + metric;
    d3.json(dataUrl, function(data) {
      $(".horizon").unbind("mousedown"); //FIXME should be done somewhere else
      data.sort();
      if (!data) return new Error("unable to load data");
      for (var i=0; i< data.length; i++) {
        var host = data[i].substring(5);
        if ( ! $(".horizon-" + host).length ) {
          var metricSettings = $(metricMap).attr(metric);
          var chart = deployer_metric(metric, data[i], stop, step);
          d3.select("#chart").call(createHorizon, host, chart, metricSettings);
        }
      }
    });
  };

  var createHorizon = function(parentElement, host, chart, metricSettings) {
    var horizonGraphElements = parentElement.selectAll(".horizon-" + host)
        .data([chart])
        .enter().append("div");

    horizonGraphElements.call(appendHorizonGraph, host, metricSettings);
    horizonGraphElements.call(appendTerminalIcon, host);
    horizonGraphElements.call(appendShareRadiatorIcon, host);
    horizonGraphElements.call(appendHostRadiatorLink, metricSettings.title, host);
  };

  function appendHorizonGraph(parentElement, host, metricSettings) {
    return parentElement
        .classed("horizon horizon-" + host + " horizoncpu-" + host, true)
        .attr("data-host", host)
        .call(configureHorizonGraph(host, metricSettings));
  }

  function appendTerminalIcon(parentElement, host) {
    return parentElement.append("svg").attr("viewBox", "0 0 100 100")
        .classed("icon shape-terminal terminal-" + host, true)
        .attr("data-type", "start-terminal")
        .attr("data-host", host)
        .append("use").attr("xlink:href", "#shape-terminal");
  }

  function appendShareRadiatorIcon(parentElement, host) {
    return parentElement.append("svg").attr("viewBox", "0 0 100 100")
        .classed("icon shape-share share-" + host, true)
        .append("use").attr("xlink:href", "#shape-to-radiator");
  }

  function appendHostRadiatorLink(parentElement, title, host) {
    return parentElement.append("div").classed("host-link", true)
        .text(title).append("a")
        .attr("href", "radiator.html?host=" + host)
        .attr("data-host", host)
        .attr("data-type", "host-radiator").text(host);
  }

  function configureHorizonGraph(host, metricSettings) {
    return cubismContext.horizon()
        .height(metricSettings.height)
        .colors(metricSettings.colors)
        .extent(metricSettings.extent)
        .format(d3.format(metricSettings.format))
        .title(null);
  }

  return {
    init: function() {
      moduleElement = context.getElement();
      windowSvc = context.getService("window");
      utils = context.getService("utils");
      d3 = context.getGlobal("d3");
      cubism = context.getGlobal("cubism");
      $ = context.getGlobal("jQuery");
      metric = utils.getHashVariable("metric") || "cpu";
      timescale = utils.getHashVariable("timescale") || 10800;

      $(window).resize(utils.debouncer(resetGraphs));

      resetGraphs();
    },

    destroy: function() {
      moduleElement = null;
    },

    messages: ["timescale-changed", "metric-changed"],

    onclick: function(event, element, elementType) {
      var host = element ? element.getAttribute("data-host") : null;
      var user = element ? (element.getAttribute("data-user") ? element.getAttribute("data-user") : "${admin}") : "$admin";
      switch (elementType) {
        case 'start-terminal':
          windowSvc.openTerminalToHost(user, host);
          break;
        case 'to-radiator':
          // Actually should show a menu to select radiator
          windowSvc.sendGraphToRadiator('{ "type": "horizon", "host": "' + host + '", "metric": "' + metric + '" }', "newradiator");
          break;
        case 'close':
          break;
        case 'host-radiator':
          windowSvc.openRadiatorForHost(host);
          break;
      }
    },

    onmessage: function(name, data) {
      switch (name) {
        case 'timescale-changed':
          this.setTimescale(data);
          break;
        case 'metric-changed':
          this.setMetric(data);
          break;
      }
    },

    setTimescale: function(scale) {
      timescale = scale;
      resetGraphs();
    },

    setMetric: function(metricName) {
      metric = metricName;
      resetGraphs();
    }
  };
});
<commit_msg>move metrics fetch closer to used context<commit_after>Box.Application.addModule('horizon-index', function(context) { //FIXME rename to cloud|summary|?|-index?
  'use strict';

  var moduleElement, windowSvc, d3, cubism, metric, timescale, utils, $, cubismContext;

  var defaultColors = ["#08519c", "#3182bd", "#6baed6", "#bdd7e7", "#bae4b3", "#74c476", "#31a354", "#006d2c"];
  var cpuColors = ["#08519c", "#3182bd", "#6baed6", "#bdd7e7", "#bae4b3", "#006d2c", "#b07635", "#d01717"];
  var metricMap = {
    "cpu" : { "title" : "cpu: ", "format" : ".2f", "extent": [0, 100], colors : cpuColors, height: 50 },
    "mem" : { "title" : "mem: ", "format" : ".2f", "extent": [0, 100], colors : cpuColors, height: 50 },
    "net" : { "title" : "net: ", "format" : ".2f", "extent": undefined, colors : defaultColors, height: 50 },
    "diskio" : { "title" : "io: ", "format" : ".2f", "extent": undefined, colors : defaultColors, height: 50 },
    "tcpinfo" : { "title" : "conn: ", "format" : ".0f", "extent": undefined, colors : defaultColors, height: 50 }
  };

  var resetGraphs = function() {
    var widthInPx = $(window).width();
    var step = parseInt(timescale * 1000 / widthInPx);
    var stop = new Date().getTime();
    var start = stop - (timescale * 1000);

    resetCubismContext(step, widthInPx);
    removeExistingGraphs();
    initGraphLayout(widthInPx);
    initGraphs(metric, start, stop, step);
  };

  function resetCubismContext(step, widthInPixels) {
    if (cubismContext) cubismContext.stop();
    cubismContext = cubism.context()
        .step(step)
        .size(widthInPixels)
        .start();
    cubismContext.on("focus", function(i) {
      d3.selectAll(".horizon .value").style("right", i === null ? null : cubismContext.size() - i + "px");
    });
  }

  function initGraphLayout(widthInPixels) {
    d3.select("#chart").attr("style", "width: " + widthInPixels + "px");
    d3.select("#chart").call(function(container) {
      container.append("div")
          .classed("axis", true)
          .call(cubismContext.axis()
              .orient("top")
              .tickFormat(d3.time.format("%H:%M")));
    });
    d3.select("#chart").call(function(container) {
      container.append("div")
          .classed("rule", true)
          .call(cubismContext.rule());
    });
  }

  function removeExistingGraphs() {
    d3.selectAll(".horizon").call(cubismContext.horizon().remove).remove();
    d3.selectAll(".axis").remove();
    d3.selectAll(".rule").remove();
  }

  var initGraphs = function(metric, start, stop, step) {
    var dataUrl = "metrics/hosts" + "?start=" + start + "&stop=" + stop + "&type=" + metric;
    d3.json(dataUrl, function(data) {
      $(".horizon").unbind("mousedown"); //FIXME should be done somewhere else
      data.sort();
      if (!data) return new Error("unable to load data");
      for (var i=0; i< data.length; i++) {
        var host = data[i].substring(5);
        if ( ! $(".horizon-" + host).length ) {
          var metricSettings = $(metricMap).attr(metric);
          var chart = deployer_metric(metric, data[i], stop, step);
          d3.select("#chart").call(createHorizon, host, chart, metricSettings);
        }
      }
    });
  };
  function fetchMetric(type, instanceTag, stop, step) {
    return cubismContext.metric(function(start, stop, step, callback) {
      var dataUrl = "metrics/" + type +
          "?start=" + start.getTime() +
          "&stop=" + stop.getTime() +
          "&step=" + step +
          "&tag=" + instanceTag;
      d3.json(dataUrl, function(data) {
        if (!data) return callback(new Error("unable to load data"));
        callback(null, data.map(function(d) { return d.value; }));
      });
    }, String(type));
  }

  var createHorizon = function(parentElement, host, chart, metricSettings) {
    var horizonGraphElements = parentElement.selectAll(".horizon-" + host)
        .data([chart])
        .enter().append("div");

    horizonGraphElements.call(appendHorizonGraph, host, metricSettings);
    horizonGraphElements.call(appendTerminalIcon, host);
    horizonGraphElements.call(appendShareRadiatorIcon, host);
    horizonGraphElements.call(appendHostRadiatorLink, metricSettings.title, host);
  };

  function appendHorizonGraph(parentElement, host, metricSettings) {
    return parentElement
        .classed("horizon horizon-" + host + " horizoncpu-" + host, true)
        .attr("data-host", host)
        .call(configureHorizonGraph(host, metricSettings));
  }

  function appendTerminalIcon(parentElement, host) {
    return parentElement.append("svg").attr("viewBox", "0 0 100 100")
        .classed("icon shape-terminal terminal-" + host, true)
        .attr("data-type", "start-terminal")
        .attr("data-host", host)
        .append("use").attr("xlink:href", "#shape-terminal");
  }

  function appendShareRadiatorIcon(parentElement, host) {
    return parentElement.append("svg").attr("viewBox", "0 0 100 100")
        .classed("icon shape-share share-" + host, true)
        .append("use").attr("xlink:href", "#shape-to-radiator");
  }

  function appendHostRadiatorLink(parentElement, title, host) {
    return parentElement.append("div").classed("host-link", true)
        .text(title).append("a")
        .attr("href", "radiator.html?host=" + host)
        .attr("data-host", host)
        .attr("data-type", "host-radiator").text(host);
  }

  function configureHorizonGraph(host, metricSettings) {
    return cubismContext.horizon()
        .height(metricSettings.height)
        .colors(metricSettings.colors)
        .extent(metricSettings.extent)
        .format(d3.format(metricSettings.format))
        .title(null);
  }

  return {
    init: function() {
      moduleElement = context.getElement();
      windowSvc = context.getService("window");
      utils = context.getService("utils");
      d3 = context.getGlobal("d3");
      cubism = context.getGlobal("cubism");
      $ = context.getGlobal("jQuery");
      metric = utils.getHashVariable("metric") || "cpu";
      timescale = utils.getHashVariable("timescale") || 10800;

      $(window).resize(utils.debouncer(resetGraphs));

      resetGraphs();
    },

    destroy: function() {
      moduleElement = null;
    },

    messages: ["timescale-changed", "metric-changed"],

    onclick: function(event, element, elementType) {
      var host = element ? element.getAttribute("data-host") : null;
      var user = element ? (element.getAttribute("data-user") ? element.getAttribute("data-user") : "${admin}") : "$admin";
      switch (elementType) {
        case 'start-terminal':
          windowSvc.openTerminalToHost(user, host);
          break;
        case 'to-radiator':
          // Actually should show a menu to select radiator
          windowSvc.sendGraphToRadiator('{ "type": "horizon", "host": "' + host + '", "metric": "' + metric + '" }', "newradiator");
          break;
        case 'close':
          break;
        case 'host-radiator':
          windowSvc.openRadiatorForHost(host);
          break;
      }
    },

    onmessage: function(name, data) {
      switch (name) {
        case 'timescale-changed':
          this.setTimescale(data);
          break;
        case 'metric-changed':
          this.setMetric(data);
          break;
      }
    },

    setTimescale: function(scale) {
      timescale = scale;
      resetGraphs();
    },

    setMetric: function(metricName) {
      metric = metricName;
      resetGraphs();
    }
  };
});
<|endoftext|>


<commit_before>/**
 * Organized grunt task configuration
 *
 * Licensed under MIT.
 * Copyright (c) 2013 David Smith <https://github.com/codeactual/>
 */

/*jshint node:true*/
'use strict';

/**
 * Reference to GruntHorde.
 */
exports.GruntHorde = GruntHorde;

/**
 * Create a new GruntHorde.
 *
 * @return {object}
 */
exports.create = function() { return new GruntHorde(); };

/**
 * Extend GruntHorde.prototype.
 *
 * @param {object} ext
 * @return {object} Merge result.
 */
exports.extend = function(ext) { return extend(GruntHorde.prototype, ext); };

var requireComponent = require('../component/require');
var mergeDeep = requireComponent('assimilate').withStrategy('deep');
var clone = requireComponent('clone');
var extend = requireComponent('extend');

var path = require('path');
var shelljs = require('shelljs');

/**
 * GruntHorde constructor.
 *
 * Usage:
 *
 *     // Gruntfile.js
 *
 *     module.exports = function(grunt) {
 *       var horde = GruntHorde.create();
 *       horde
 *         .follow(grunt)
 *         .loot('my-base-config-module')
 *         .loot('./config/grunt')
 *         .attack();
 *     };
 *
 * Required before calling `attack()`:
 *
 * - `follow()`
 *
 * Properties:
 *
 * - `{object} config` Gruntfile.js sections
 *   - `{object} initConfig`
 *   - `{object} loadNpmTasks`
 *   - `{object} loadTasks`
 *   - `{object} registerMultiTask`
 *   - `{object} registerTask`
 * - `{object} grunt` Module collected from Gruntfile.js
 * - `{string} home` Absolute path to project root dir w/out trailing slash
 */
function GruntHorde() {
  this.home = process.cwd();
  this.grunt = null;
  this.config = {
    initConfig: {},
    loadNpmTasks: {},
    loadTasks: {},
    registerMultiTask: {},
    registerTask: {}
  };
}

GruntHorde.prototype.attack = function() {
  var self = this;

  var required = ['grunt'];
  required.forEach(function(name) {
    if (!self[name]) {
      throw new Error(name + '() value is missing');
    }
  });

  this.grunt.initConfig(this.config.initConfig);

  Object.keys(this.config.loadTasks).forEach(function(name) {
    if (self.config.loadTasks[name]) {
      self.grunt.loadTasks(self.config.loadTasks[name]);
    }
  });

  Object.keys(this.config.loadNpmTasks).forEach(function(name) {
    if (self.config.loadNpmTasks[name]) {
      self.grunt.loadNpmTasks(self.config.loadNpmTasks[name]);
    }
  });

  Object.keys(this.config.registerTask).forEach(function(name) {
    self.grunt.registerTask.apply(self.grunt, self.config.registerTask[name]);
  });

  Object.keys(this.config.registerMultiTask).forEach(function(name) {
    self.grunt.registerMultiTask.apply(self.grunt, self.config.registerMultiTask[name]);
  });
};

GruntHorde.prototype.follow = function(grunt) {
  this.grunt = grunt;
};

GruntHorde.prototype.home = function(home) {
  this.home = home;
};

/**
 * Add a config module.
 *
 * Module payloads are merged recursively, last wins.
 *
 * Usage:
 *
 *     horde.home('/proj/home');
 *     horde.loot('base'); // require('/proj/home/node_modules/base');
 *     horde.loot('./base'); // require('/proj/home/base.js');
 *     horde.loot('/path/to/base'); // require('/path/to/base');
 *
 * @param {string} name `require()` path, see `Usage`
 * @see GruntHorde.prototype.home
 */
GruntHorde.prototype.loot = function(name) {
  this.config = mergeDeep(this.config, this.dirToConfigObj(name));
};

GruntHorde.prototype.requireConfigModule = function(name) {
  if (/^\.\//.test(name)) {
    name = this.home + '/' + name;
  } else if (/^[^\/]/.test(name)) {
    name = this.home + '/node_modules/' + name;
  }

  return this.require(name);
};

GruntHorde.prototype.require = function(name) {
  return require(name).apply(GruntHorde.createModuleContext(), this.grunt);
};

GruntHorde.prototype.requireIfExists = function(name) {
  if (shelljs.test('-e', name)) {
    return this.require(name);
  } else {
    return {};
  }
};

GruntHorde.prototype.requireDir = function(name) {
  var self = this;
  var index = {};
  var categorized = {};
  shelljs.ls(name + '/*.js').forEach(function(file) {
    if ('index.js' === file) { // Let it hold top-level keys
      index = self.require(file);
    } else { // All others go under top-level keys named after their files
      categorized = mergeDeep(categorized, self.require(file));
    }
  });
  return mergeDeep(index, categorized);
};

GruntHorde.prototype.requireDirIfExists = function(name) {
  if (shelljs.test('-e', name)) {
    return this.requireDir(name);
  } else {
    return {};
  }
};

GruntHorde.prototype.createModuleContext = function() {
  return {
    config: clone(this.grunt.config.getRaw()),
    path: path,
    require: this.require.bind(this),
    requireDir: this.requireDir.bind(this),
    shelljs: shelljs,
    t: this.t.bind(this)
  };
};

/**
 * Alias for `grunt.template.process()`.
 *
 * @see process http://gruntjs.com/api/grunt.template#grunt.template.process
 */
GruntHorde.prototype.t = function() {
  return this.grunt.template.process.apply(this.grunt, arguments);
};

/**
 * Using file layout conventions, convert a directory's contents into an
 * object for later merging into `this.config`.
 *
 * Directory types:
 *
 * - Base config module, ex. `node_modules/my-base-config`
 * - Project-local config module, ex. `config/grunt/`
 *
 * @param {string} name Absolute path to directory w/out trailing slash
 * @return {object}
 */
GruntHorde.prototype.dirToConfigObj = function(name) {
  var obj = {
    initConfig: this.requireDirIfExists(name + '/initConfig')
  };
  var files = ['loadTasks', 'loadNpmTasks', 'registerTask', 'registerMultiTask'];
  files.forEach(function(file) {
    obj[file] = this.requireIfExists(name + '/' + file + '.js');
  });
  return obj;
};
<commit_msg>docs(api): Privatize some methods<commit_after>/**
 * Organized grunt task configuration
 *
 * Licensed under MIT.
 * Copyright (c) 2013 David Smith <https://github.com/codeactual/>
 */

/*jshint node:true*/
'use strict';

/**
 * Reference to GruntHorde.
 */
exports.GruntHorde = GruntHorde;

/**
 * Create a new GruntHorde.
 *
 * @return {object}
 */
exports.create = function() { return new GruntHorde(); };

/**
 * Extend GruntHorde.prototype.
 *
 * @param {object} ext
 * @return {object} Merge result.
 */
exports.extend = function(ext) { return extend(GruntHorde.prototype, ext); };

var requireComponent = require('../component/require');
var mergeDeep = requireComponent('assimilate').withStrategy('deep');
var clone = requireComponent('clone');
var extend = requireComponent('extend');

var path = require('path');
var shelljs = require('shelljs');

/**
 * GruntHorde constructor.
 *
 * Usage:
 *
 *     // Gruntfile.js
 *
 *     module.exports = function(grunt) {
 *       var horde = GruntHorde.create();
 *       horde
 *         .follow(grunt)
 *         .loot('my-base-config-module')
 *         .loot('./config/grunt')
 *         .attack();
 *     };
 *
 * Required before calling `attack()`:
 *
 * - `follow()`
 *
 * Properties:
 *
 * - `{object} config` Gruntfile.js sections
 *   - `{object} initConfig`
 *   - `{object} loadNpmTasks`
 *   - `{object} loadTasks`
 *   - `{object} registerMultiTask`
 *   - `{object} registerTask`
 * - `{object} grunt` Module collected from Gruntfile.js
 * - `{string} home` Absolute path to project root dir w/out trailing slash
 */
function GruntHorde() {
  this.home = process.cwd();
  this.grunt = null;
  this.config = {
    initConfig: {},
    loadNpmTasks: {},
    loadTasks: {},
    registerMultiTask: {},
    registerTask: {}
  };
}

GruntHorde.prototype.attack = function() {
  var self = this;

  var required = ['grunt'];
  required.forEach(function(name) {
    if (!self[name]) {
      throw new Error(name + '() value is missing');
    }
  });

  this.grunt.initConfig(this.config.initConfig);

  Object.keys(this.config.loadTasks).forEach(function(name) {
    if (self.config.loadTasks[name]) {
      self.grunt.loadTasks(self.config.loadTasks[name]);
    }
  });

  Object.keys(this.config.loadNpmTasks).forEach(function(name) {
    if (self.config.loadNpmTasks[name]) {
      self.grunt.loadNpmTasks(self.config.loadNpmTasks[name]);
    }
  });

  Object.keys(this.config.registerTask).forEach(function(name) {
    self.grunt.registerTask.apply(self.grunt, self.config.registerTask[name]);
  });

  Object.keys(this.config.registerMultiTask).forEach(function(name) {
    self.grunt.registerMultiTask.apply(self.grunt, self.config.registerMultiTask[name]);
  });
};

GruntHorde.prototype.follow = function(grunt) {
  this.grunt = grunt;
};

GruntHorde.prototype.home = function(home) {
  this.home = home;
};

/**
 * Add a config module.
 *
 * Module payloads are merged recursively, last wins.
 *
 * Usage:
 *
 *     horde.home('/proj/home');
 *     horde.loot('base'); // require('/proj/home/node_modules/base');
 *     horde.loot('./base'); // require('/proj/home/base.js');
 *     horde.loot('/path/to/base'); // require('/path/to/base');
 *
 * @param {string} name `require()` path, see `Usage`
 * @see GruntHorde.prototype.home
 */
GruntHorde.prototype.loot = function(name) {
  this.config = mergeDeep(this.config, this.dirToConfigObj(name));
};

/**
 *
 * @api private
 */
GruntHorde.prototype.requireConfigModule = function(name) {
  if (/^\.\//.test(name)) {
    name = this.home + '/' + name;
  } else if (/^[^\/]/.test(name)) {
    name = this.home + '/node_modules/' + name;
  }

  return this.require(name);
};

/**
 *
 * @api private
 */
GruntHorde.prototype.require = function(name) {
  return require(name).apply(GruntHorde.createModuleContext(), this.grunt);
};

GruntHorde.prototype.requireIfExists = function(name) {
  if (shelljs.test('-e', name)) {
    return this.require(name);
  } else {
    return {};
  }
};

/**
 *
 * @api private
 */
GruntHorde.prototype.requireDir = function(name) {
  var self = this;
  var index = {};
  var categorized = {};
  shelljs.ls(name + '/*.js').forEach(function(file) {
    if ('index.js' === file) { // Let it hold top-level keys
      index = self.require(file);
    } else { // All others go under top-level keys named after their files
      categorized = mergeDeep(categorized, self.require(file));
    }
  });
  return mergeDeep(index, categorized);
};

/**
 *
 * @api private
 */
GruntHorde.prototype.requireDirIfExists = function(name) {
  if (shelljs.test('-e', name)) {
    return this.requireDir(name);
  } else {
    return {};
  }
};

/**
 *
 * @api private
 */
GruntHorde.prototype.createModuleContext = function() {
  return {
    config: clone(this.grunt.config.getRaw()),
    path: path,
    require: this.require.bind(this),
    requireDir: this.requireDir.bind(this),
    shelljs: shelljs,
    t: this.t.bind(this)
  };
};

/**
 * Alias for `grunt.template.process()`.
 *
 * @see process http://gruntjs.com/api/grunt.template#grunt.template.process
 * @api private
 */
GruntHorde.prototype.t = function() {
  return this.grunt.template.process.apply(this.grunt, arguments);
};

/**
 * Using file layout conventions, convert a directory's contents into an
 * object for later merging into `this.config`.
 *
 * Directory types:
 *
 * - Base config module, ex. `node_modules/my-base-config`
 * - Project-local config module, ex. `config/grunt/`
 *
 * @param {string} name Absolute path to directory w/out trailing slash
 * @return {object}
 * @api private
 */
GruntHorde.prototype.dirToConfigObj = function(name) {
  var obj = {
    initConfig: this.requireDirIfExists(name + '/initConfig')
  };
  var files = ['loadTasks', 'loadNpmTasks', 'registerTask', 'registerMultiTask'];
  files.forEach(function(file) {
    obj[file] = this.requireIfExists(name + '/' + file + '.js');
  });
  return obj;
};
<|endoftext|>


<commit_before>const keystone			= require( 'keystone' ),
	  moment			= require( 'moment' ),
	  userService		= require( '../middleware/service_user' ),
	  eventService		= require( '../middleware/service_event' ),
	  donationService	= require( '../middleware/service_donation' ),
	  listsService		= require( '../middleware/service_lists' ),
	  pageService		= require( '../middleware/service_page' ),
	  mailingListService		= require( '../middleware/service_mailing-list' );

exports = module.exports = ( req, res ) => {
    'use strict';

	const
		view						= new keystone.View( req, res ),
		locals						= res.locals,
		userType					= req.user ? req.user.userType : '', // knowing the type of user visiting the page will allow us to display extra relevant information
		userID						= req.user ? req.user._id : '',

		// find the field the user belongs to in the event model based on their user type
		eventGroup					= eventService.getEventGroup( userType ),

		// Options for fetching
		stateOptions     		   	= { default: 'Massachusetts' },
		raceOptions        			= { other: true },

		// fetch all data needed to render this page
		fetchEvents					= eventService.getActiveEventsByUserId( userID, eventGroup ),

		fetchCitiesAndTowns			= listsService.getAllCitiesAndTowns(),
		fetchDisabilities			= listsService.getAllDisabilities(),
		fetchGenders				= listsService.getAllGenders(),
		fetchLanguages				= listsService.getAllLanguages(),
		fetchLegalStatuses			= listsService.getAllLegalStatuses(),
		fetchOtherConsiderations	= listsService.getAllOtherConsiderations(),
		fetchRaces					= listsService.getAllRaces( raceOptions ),
		fetchStates					= listsService.getAllStates( stateOptions ),
		fetchChildTypes				= listsService.getChildTypesForWebsite(),
		fetchMailingLists			= mailingListService.getRegistrationMailingLists()
	;

	// check to see if the Children tab should be rendered
	locals.shouldRenderChildrenSection = ( userType === 'social worker' || userType === 'family' );

	// check to see if the page is being loaded for a newly registered user
	if ( req.query.newUser ) {

		// display the succesful registration flash message
		req.flash( 'success', { title: 'Your account has been successfully created' } );
	}

	Promise.all( [ fetchEvents, fetchCitiesAndTowns, fetchDisabilities, fetchGenders, fetchLanguages, fetchLegalStatuses,
		fetchOtherConsiderations, fetchRaces, fetchStates, fetchChildTypes, fetchMailingLists ] )
		.then( values => {

			// assign local variables to the values returned by the promises
			const [ events, citiesAndTowns, disabilities, genders, languages, legalStatuses,
				otherConsiderations, races, states, childTypes, mailingLists ] = values;

			// options to define how truncation will be handled
			const truncateOptions = { targetLength: 400 };

			// loop through all the events
			for( let event of events ) {
				// determine whether or not address information exists for the event, which is helpful during rendering
				// street1 is required, so this is enough to tell us if the address has been populated
				event.hasAddress = event.address && event.address.street1;

				// check to see if the event spans multiple days
				const multidayEvent = event.startDate.getTime() !== event.endDate.getTime();

				// Pull the date and time into a string for easier templating
				if( multidayEvent ) {
					event.dateString = `${ moment( event.startDate ).format( 'dddd MMMM Do, YYYY' ) } to ${ moment( event.endDate ).format( 'dddd MMMM Do, YYYY' ) }`;
				} else {
					event.dateString = moment( event.startDate ).format( 'dddd MMMM Do, YYYY' );
				}
			}

			// assign properties to locals for access during templating
			locals.user					= req.user;
			locals.events				= events;
			locals.hasNoEvents			= events.length === 0;
			locals.citiesAndTowns		= citiesAndTowns;
			locals.disabilities			= disabilities;
			locals.genders				= genders;
			locals.languages			= languages;
			locals.legalStatuses		= legalStatuses;
			locals.otherConsiderations	= otherConsiderations;
			locals.races				= races;
			locals.states				= states;
			locals.childTypes			= childTypes;
			locals.mailingLists			= mailingLists;

			// set the layout to render without the right sidebar
			locals[ 'render-with-sidebar' ] = false;

			// render the view using the account.hbs template
			view.render( 'account' );
		})
		.catch( err => {
			// log an error for debugging purposes
			console.error( `there was an error loading data for the account page - ${ err }` );
			// set the layout to render without the right sidebar
			locals[ 'render-with-sidebar' ] = false;
			// render the view using the account.hbs template
			view.render( 'account' );
		});
};<commit_msg>enables bookmarking functionality on the account children gallery<commit_after>const keystone			= require( 'keystone' ),
	  moment			= require( 'moment' ),
	  userService		= require( '../middleware/service_user' ),
	  eventService		= require( '../middleware/service_event' ),
	  donationService	= require( '../middleware/service_donation' ),
	  familyService		= require( '../middleware/service_family' ),
	  listsService		= require( '../middleware/service_lists' ),
	  pageService		= require( '../middleware/service_page' ),
	  mailingListService		= require( '../middleware/service_mailing-list' );

exports = module.exports = ( req, res ) => {
    'use strict';

	const
		view						= new keystone.View( req, res ),
		locals						= res.locals,
		userType					= req.user ? req.user.userType : '', // knowing the type of user visiting the page will allow us to display extra relevant information
		userID						= req.user ? req.user._id : '',

		// find the field the user belongs to in the event model based on their user type
		eventGroup					= eventService.getEventGroup( userType ),

		// Options for fetching
		stateOptions     		   	= { default: 'Massachusetts' },
		raceOptions        			= { other: true },

		// fetch all data needed to render this page
		fetchEvents					= eventService.getActiveEventsByUserId( userID, eventGroup ),

		fetchCitiesAndTowns			= listsService.getAllCitiesAndTowns(),
		fetchDisabilities			= listsService.getAllDisabilities(),
		fetchGenders				= listsService.getAllGenders(),
		fetchLanguages				= listsService.getAllLanguages(),
		fetchLegalStatuses			= listsService.getAllLegalStatuses(),
		fetchOtherConsiderations	= listsService.getAllOtherConsiderations(),
		fetchRaces					= listsService.getAllRaces( raceOptions ),
		fetchStates					= listsService.getAllStates( stateOptions ),
		fetchChildTypes				= listsService.getChildTypesForWebsite(),
		fetchMailingLists			= mailingListService.getRegistrationMailingLists()
	;

	// check to see if the Children tab should be rendered
	locals.shouldRenderChildrenSection = ( userType === 'social worker' || userType === 'family' );
	// determine if the user has permissions for bookmarking functionality
	familyService.setGalleryPermissions( req, res );

	// check to see if the page is being loaded for a newly registered user
	if ( req.query.newUser ) {

		// display the succesful registration flash message
		req.flash( 'success', { title: 'Your account has been successfully created' } );
	}

	Promise.all( [ fetchEvents, fetchCitiesAndTowns, fetchDisabilities, fetchGenders, fetchLanguages, fetchLegalStatuses,
		fetchOtherConsiderations, fetchRaces, fetchStates, fetchChildTypes, fetchMailingLists ] )
		.then( values => {

			// assign local variables to the values returned by the promises
			const [ events, citiesAndTowns, disabilities, genders, languages, legalStatuses,
				otherConsiderations, races, states, childTypes, mailingLists ] = values;

			// options to define how truncation will be handled
			const truncateOptions = { targetLength: 400 };

			// loop through all the events
			for( let event of events ) {
				// determine whether or not address information exists for the event, which is helpful during rendering
				// street1 is required, so this is enough to tell us if the address has been populated
				event.hasAddress = event.address && event.address.street1;

				// check to see if the event spans multiple days
				const multidayEvent = event.startDate.getTime() !== event.endDate.getTime();

				// Pull the date and time into a string for easier templating
				if( multidayEvent ) {
					event.dateString = `${ moment( event.startDate ).format( 'dddd MMMM Do, YYYY' ) } to ${ moment( event.endDate ).format( 'dddd MMMM Do, YYYY' ) }`;
				} else {
					event.dateString = moment( event.startDate ).format( 'dddd MMMM Do, YYYY' );
				}
			}

			// assign properties to locals for access during templating
			locals.user					= req.user;
			locals.events				= events;
			locals.hasNoEvents			= events.length === 0;
			locals.citiesAndTowns		= citiesAndTowns;
			locals.disabilities			= disabilities;
			locals.genders				= genders;
			locals.languages			= languages;
			locals.legalStatuses		= legalStatuses;
			locals.otherConsiderations	= otherConsiderations;
			locals.races				= races;
			locals.states				= states;
			locals.childTypes			= childTypes;
			locals.mailingLists			= mailingLists;

			// set the layout to render without the right sidebar
			locals[ 'render-with-sidebar' ] = false;

			// render the view using the account.hbs template
			view.render( 'account' );
		})
		.catch( err => {
			// log an error for debugging purposes
			console.error( `there was an error loading data for the account page - ${ err }` );
			// set the layout to render without the right sidebar
			locals[ 'render-with-sidebar' ] = false;
			// render the view using the account.hbs template
			view.render( 'account' );
		});
};<|endoftext|>


<commit_before>var window = require("global/window")
var ReadySignal = require("ready-signal")
var uuid = require("node-uuid")

var slice = Array.prototype.slice
var prefix = "~track-event/lib/handlePostMessage~"
var functionHash = {}

/* Custom RPC over postMessage >_<

In future write postMessage stream and use dnode.
*/
module.exports = handlePostMessage

function handlePostMessage(options, onCommand) {
    var functionHash = {}
    var onMessageOptions = options.onMessage
    var postMessageOptions = options.postMessage
    if (onMessageOptions || postMessageOptions) {
        var origin = extractOrigin(onMessageOptions, postMessageOptions)

        setupMessage(origin, onCommand)
    }

    if (postMessageOptions) {
        return setupPostMessage(postMessageOptions)
    }
}

function extractOrigin(onMessageOptions, postMessageOptions) {
    if (Array.isArray(onMessageOptions)) {
        onMessageOptions = { origin: onMessageOptions }
    } else if (typeof onMessageOptions === "string") {
        onMessageOptions = { origin: [onMessageOptions] }
    } else if (!onMessageOptions) {
        onMessageOptions = { origin: [] }
    }

    var origin = onMessageOptions.origin
    if (postMessageOptions) {
        origin = origin.concat(postMessageOptions.origin)
    }

    return origin
}

function setupMessage(origin, onCommand) {
    var allowAll = origin.indexOf("*") !== -1

    window.addEventListener("message", function (ev) {
        if (!allowAll && origin.indexOf(ev.origin) === -1) {
            return
        }

        var command = unpack(ev)

        if (command === null) {
            return
        }

        var functionName = command.functionName
        var args = command.args
        var func = functionHash[functionName]

        func ? func.apply(null, args) : onCommand(functionName, args)
    })
}

function unpack(ev) {
    var command = parse(ev.data)

    if (!command || command.type !== "track-event~message") {
        return null
    }

    var functionName = command.functionName

    var args = command.args.map(function (arg) {
        if (!arg || (arg.indexOf && arg.indexOf(prefix) !== 0)) {
            return arg
        }

        var functionId = arg

        return proxy

        function proxy() {
            var args = slice.call(arguments)
            ev.source.postMessage(pack(functionId, args), ev.origin)
        }
    })

    return { functionName: functionName, args: args }
}

function setupPostMessage(postMessageOptions) {
    var ready = ReadySignal()
    var iframe = postMessageOptions.iframe
    var targetOrigin = postMessageOptions.origin

    iframe.addEventListener("load", ready)

    return callPostMessage

    function callPostMessage(functionName, args) {
        ready(function (ev) {
            var target = iframe.contentWindow

            target.postMessage(pack(functionName, args), targetOrigin)
        })
    }
}

function pack(functionName, args) {
    args = args.map(function (arg) {
        if (typeof arg !== "function") {
            return arg
        }

        var id = prefix + uuid()
        functionHash[id] = arg
        return id
    })

    return JSON.stringify({
        functionName: functionName
        , args: args
        , type: "track-event~message"
    })
}

function parse(x) {
    var json
    try {
        json = JSON.parse(x)
    } catch (err) {
        return null
    }

    return json
}
<commit_msg>fix unpack algorithm<commit_after>var window = require("global/window")
var ReadySignal = require("ready-signal")
var uuid = require("node-uuid")

var slice = Array.prototype.slice
var prefix = "~track-event/lib/handlePostMessage~"
var functionHash = {}

/* Custom RPC over postMessage >_<

In future write postMessage stream and use dnode.
*/
module.exports = handlePostMessage

function handlePostMessage(options, onCommand) {
    var functionHash = {}
    var onMessageOptions = options.onMessage
    var postMessageOptions = options.postMessage
    if (onMessageOptions || postMessageOptions) {
        var origin = extractOrigin(onMessageOptions, postMessageOptions)

        setupMessage(origin, onCommand)
    }

    if (postMessageOptions) {
        return setupPostMessage(postMessageOptions)
    }
}

function extractOrigin(onMessageOptions, postMessageOptions) {
    if (Array.isArray(onMessageOptions)) {
        onMessageOptions = { origin: onMessageOptions }
    } else if (typeof onMessageOptions === "string") {
        onMessageOptions = { origin: [onMessageOptions] }
    } else if (!onMessageOptions) {
        onMessageOptions = { origin: [] }
    }

    var origin = onMessageOptions.origin
    if (postMessageOptions) {
        origin = origin.concat(postMessageOptions.origin)
    }

    return origin
}

function setupMessage(origin, onCommand) {
    var allowAll = origin.indexOf("*") !== -1

    window.addEventListener("message", function (ev) {
        if (!allowAll && origin.indexOf(ev.origin) === -1) {
            return
        }

        var command = unpack(ev)

        if (command === null) {
            return
        }

        var functionName = command.functionName
        var args = command.args
        var func = functionHash[functionName]

        func ? func.apply(null, args) : onCommand(functionName, args)
    })
}

function unpack(ev) {
    var command = parse(ev.data)

    if (!command || command.type !== "track-event~message") {
        return null
    }

    var functionName = command.functionName

    var args = command.args.map(function (arg) {
        if (typeof arg !== "string" || arg.indexOf(prefix) !== 0) {
            return arg
        }

        var functionId = arg

        return proxy

        function proxy() {
            var args = slice.call(arguments)
            ev.source.postMessage(pack(functionId, args), ev.origin)
        }
    })

    return { functionName: functionName, args: args }
}

function setupPostMessage(postMessageOptions) {
    var ready = ReadySignal()
    var iframe = postMessageOptions.iframe
    var targetOrigin = postMessageOptions.origin

    iframe.addEventListener("load", ready)

    return callPostMessage

    function callPostMessage(functionName, args) {
        ready(function (ev) {
            var target = iframe.contentWindow

            target.postMessage(pack(functionName, args), targetOrigin)
        })
    }
}

function pack(functionName, args) {
    args = args.map(function (arg) {
        if (typeof arg !== "function") {
            return arg
        }

        var id = prefix + uuid()
        functionHash[id] = arg
        return id
    })

    return JSON.stringify({
        functionName: functionName
        , args: args
        , type: "track-event~message"
    })
}

function parse(x) {
    var json
    try {
        json = JSON.parse(x)
    } catch (err) {
        return null
    }

    return json
}
<|endoftext|>


<commit_before>import Image from './util/canvas/image';
import {load} from 'vega-loader';

export default function ImageLoader(loadConfig) {
  this._pending = 0;
  this._config = loadConfig || ImageLoader.Config;
}

// Overridable global default load configuration
ImageLoader.Config = {};

var prototype = ImageLoader.prototype;

prototype.pending = function() {
  return this._pending;
};

prototype.imageURL = function(uri) {
  return load.sanitize(uri, this._config);
};

prototype.loadImage = function(uri) {
  var url = this.imageURL(uri);

  if (!url || !Image) {
    return {loaded: false, width: 0, height: 0};
  }

  var loader = this,
      image = new Image();

  loader._pending += 1;

  image.onload = function() {
    loader._pending -= 1;
    image.loaded = true;
  };

  image.onerror = function() {
    loader._pending -= 1;
    image.loaded = false;
  }

  image.src = url;

  return image;
};

prototype.ready = function() {
  var loader = this;
  return new Promise(function(accept) {
    function poll(value) {
      if (!loader._pending) accept(value);
      else setTimeout(function() { poll(true); }, 10);
    }
    poll(false);
  });
};
<commit_msg>Rename ImageLoader load options.<commit_after>import Image from './util/canvas/image';
import {load} from 'vega-loader';

export default function ImageLoader(loadOptions) {
  this._pending = 0;
  this._options = loadOptions || ImageLoader.Options;
}

// Overridable global default load configuration
ImageLoader.Options = {};

var prototype = ImageLoader.prototype;

prototype.pending = function() {
  return this._pending;
};

prototype.imageURL = function(uri) {
  return load.sanitize(uri, this._options);
};

prototype.loadImage = function(uri) {
  var url = this.imageURL(uri);

  if (!url || !Image) {
    return {loaded: false, width: 0, height: 0};
  }

  var loader = this,
      image = new Image();

  loader._pending += 1;

  image.onload = function() {
    loader._pending -= 1;
    image.loaded = true;
  };

  image.onerror = function() {
    loader._pending -= 1;
    image.loaded = false;
  }

  image.src = url;

  return image;
};

prototype.ready = function() {
  var loader = this;
  return new Promise(function(accept) {
    function poll(value) {
      if (!loader._pending) accept(value);
      else setTimeout(function() { poll(true); }, 10);
    }
    poll(false);
  });
};
<|endoftext|>


<commit_before>import { moduleForComponent, test } from 'ember-qunit';

moduleForComponent( 'sl-calendar-year', 'Unit | Component | sl calendar year', {
    unit: true
});

test( 'Default state is not active, new, or old', function( assert ) {
    const component = this.subject();

    assert.strictEqual(
        component.get( 'active' ),
        false,
        'Default component is not active'
    );

    assert.strictEqual(
        component.get( 'new' ),
        false,
        'Default component is not in new state'
    );

    assert.strictEqual(
        component.get( 'old' ),
        false,
        'Default component is not in old state'
    );

    assert.strictEqual(
        this.$().hasClass( 'active' ),
        false,
        'Default rendered component does not have class "active"'
    );

    assert.strictEqual(
        this.$().hasClass( 'new' ),
        false,
        'Default rendered component does not have class "new"'
    );

    assert.strictEqual(
        this.$().hasClass( 'old' ),
        false,
        'Default rendered component does not have class "old"'
    );
});

test( 'Click event sends action with year value', function( assert ) {
    const exampleYear = 2000;

    const done = assert.async();

    assert.expect( 1 );

    this.subject({
        action: 'test',

        targetObject: {
            test: ( year ) => {
                assert.strictEqual(
                    year,
                    exampleYear,
                    'Received year'
                );

                done();
            }
        },

        year: exampleYear
    });

    this.$().trigger( 'click' );
});
<commit_msg>refactored sequence of assert calls in sl-calender-year-test<commit_after>import { moduleForComponent, test } from 'ember-qunit';

moduleForComponent( 'sl-calendar-year', 'Unit | Component | sl calendar year', {
    unit: true
});

test( 'Default state is not active, new, or old', function( assert ) {
    const component = this.subject();

    assert.strictEqual(
        component.get( 'active' ),
        false,
        'Default component is not active'
    );

    assert.strictEqual(
        component.get( 'new' ),
        false,
        'Default component is not in new state'
    );

    assert.strictEqual(
        component.get( 'old' ),
        false,
        'Default component is not in old state'
    );

    assert.strictEqual(
        this.$().hasClass( 'active' ),
        false,
        'Default rendered component does not have class "active"'
    );

    assert.strictEqual(
        this.$().hasClass( 'new' ),
        false,
        'Default rendered component does not have class "new"'
    );

    assert.strictEqual(
        this.$().hasClass( 'old' ),
        false,
        'Default rendered component does not have class "old"'
    );
});

test( 'Click event sends action with year value', function( assert ) {
    assert.expect( 1 );

    const done = assert.async();

    const exampleYear = 2000;

    this.subject({
        action: 'test',

        targetObject: {
            test: ( year ) => {
                assert.strictEqual(
                    year,
                    exampleYear,
                    'Received year'
                );

                done();
            }
        },

        year: exampleYear
    });

    this.$().trigger( 'click' );
});
<|endoftext|>


<commit_before>module.exports = {
  'env': {
    'es6': false
  },
  'ecmaFeatures': {
    'arrowFunctions': true,
    'blockBindings': true,
    'classes': true,
    'defaultParams': true,
    'destructuring': true,
    'forOf': true,
    'generators': false,
    'modules': true,
    'objectLiteralComputedProperties': true,
    'objectLiteralDuplicateProperties': false,
    'objectLiteralShorthandMethods': true,
    'objectLiteralShorthandProperties': true,
    'restParams': true,
    'spread': true,
    'superInFunctions': true,
    'templateStrings': true,
    'jsx': true
  },
  'rules': {
    // require parens in arrow function arguments
    'arrow-parens': 0,
    // require space before/after arrow function's arrow
    // https://github.com/eslint/eslint/blob/master/docs/rules/arrow-spacing.md
    'arrow-spacing': [2, { 'before': true, 'after': true }],
    // verify super() callings in constructors
    'constructor-super': 0,
    // enforce the spacing around the * in generator functions
    'generator-star-spacing': 0,
    // disallow modifying variables of class declarations
    'no-class-assign': 0,
    // disallow modifying variables that are declared using const
    'no-const-assign': 2,
    // disallow to use this/super before super() calling in constructors.
    'no-this-before-super': 0,
    // require let or const instead of var
    'no-var': 2,
    // require method and property shorthand syntax for object literals
    // https://github.com/eslint/eslint/blob/master/docs/rules/object-shorthand.md
    'object-shorthand': [2, 'always'],
    // suggest using arrow functions as callbacks
    'prefer-arrow-callback': 2,
    // suggest using of const declaration for variables that are never modified after declared
    'prefer-const': 2,
    // suggest using the spread operator instead of .apply()
    'prefer-spread': 0,
    // suggest using Reflect methods where applicable
    'prefer-reflect': 0,
    // disallow generator functions that do not have yield
    'require-yield': 0
  }
};
<commit_msg>Add missing ES6 rules to ESLint config.<commit_after>module.exports = {
  'env': {
    'es6': false
  },
  'ecmaFeatures': {
    'arrowFunctions': true,
    'blockBindings': true,
    'classes': true,
    'defaultParams': true,
    'destructuring': true,
    'forOf': true,
    'generators': false,
    'modules': true,
    'objectLiteralComputedProperties': true,
    'objectLiteralDuplicateProperties': false,
    'objectLiteralShorthandMethods': true,
    'objectLiteralShorthandProperties': true,
    'restParams': true,
    'spread': true,
    'superInFunctions': true,
    'templateStrings': true,
    'jsx': true
  },
  'rules': {
    // enforces no braces where they can be omitted
    // http://eslint.org/docs/rules/arrow-body-style
    'arrow-body-style': [2, 'as-needed'],
    // require parens in arrow function arguments
    'arrow-parens': 0,
    // require space before/after arrow function's arrow
    // https://github.com/eslint/eslint/blob/master/docs/rules/arrow-spacing.md
    'arrow-spacing': [2, { 'before': true, 'after': true }],
    // verify super() callings in constructors
    'constructor-super': 0,
    // enforce the spacing around the * in generator functions
    'generator-star-spacing': 0,
    // disallow modifying variables of class declarations
    'no-class-assign': 0,
    // disallow modifying variables that are declared using const
    'no-const-assign': 2,
    // disallow to use this/super before super() calling in constructors.
    'no-this-before-super': 0,
    // require let or const instead of var
    'no-var': 2,
    // require method and property shorthand syntax for object literals
    // https://github.com/eslint/eslint/blob/master/docs/rules/object-shorthand.md
    'object-shorthand': [2, 'always'],
    // suggest using arrow functions as callbacks
    'prefer-arrow-callback': 2,
    // suggest using of const declaration for variables that are never modified after declared
    'prefer-const': 2,
    // suggest using the spread operator instead of .apply()
    'prefer-spread': 0,
    // suggest using Reflect methods where applicable
    'prefer-reflect': 0,
    // suggest using template literals instead of string concatenation
    // http://eslint.org/docs/rules/prefer-template
    'prefer-template': 2,
    // disallow generator functions that do not have yield
    'require-yield': 0
  }
};
<|endoftext|>


<commit_before>var config = {
	"title": "Bootleaf template map",
	"start": {
		// "maxZoom": 16,
		"center": [38.203,-99.799],
		"zoom": 5,
		"attributionControl": false,
		"zoomControl": false
	},
	"about": {
		"title": "Bootleaf application template",
		"contents": "
This is an open-source version of the excellent Bootleaf map started by Bryan McBride.

It's designed for rapid web map development. See https://github.com/iag-geo/bootleaf for more information.

Chage this message in the config file
"
	},
	"controls": {
		"zoom": {
			"position": "topleft"
		},
		"leafletGeocoder": {
			//https://github.com/perliedman/leaflet-control-geocoder
			"collapsed": false,
			"position": "topleft",
			"placeholder": "Search for a location",
			"type": "Google", // OpenStreetMap, Google, ArcGIS
			"suffix": "Australia" // optional keyword to append to every search
		},
		"TOC": {
			//http://leafletjs.com/reference-1.0.2.html#control-layers-option
			"collapsed": false,
			"uncategorisedLabel": "Layers",
			"position": "topright"
		},
		"history": {
			"position": "bottomleft"
		},
		"bookmarks": {
			"position": "bottomright",
			"places": [
				{
				"latlng": [
					22.245598601926222,
					114.17609095573425
				],
				"zoom": 5,
				"name": "Ocean Park",
				"id": "a148fa354ba3",
				"editable": true,
				"removable": true
				}
			]
		}
	},
	// "activeTool": "identify", // options are identify/coordinates/queryWidget
	"basemaps": ['esriGray', 'esriDarkGray', 'esriStreets', 'OpenStreetMap'],
	"bing_key": "enter your Bing Maps key",
	"mapboxKey": "enter your MapBox key",
	// "defaultIcon": {
	// 	"imagePath": "http://leafletjs.com/examples/custom-icons/",
	// 	"iconUrl": "leaf-green.png",
	// 	"shadowUrl": "leaf-shadow.png",
	// 	"iconSize":     [38, 95],
	// 		"shadowSize":   [50, 64],
	// 		"iconAnchor":   [22, 94],
	// 		"shadowAnchor": [4, 62],
	// 		"popupAnchor":  [-3, -76]
	// },
	"tocCategories": [
		{
			"name": "GeoJSON layers",
			"layers": ["theatres", "museums"]
		},
		{
			"name": "ArcGIS Layers",
			"layers" : ["trees", "counties", "railways", "us_states"]
		},
		{
			"name": "WMS/WFS layers",
			"layers": ["nearmap", "US_population"],
			"exclusive": false
		}
	],
	"projections": [
		{4269: '+proj=longlat +ellps=GRS80 +datum=NAD83 +no_defs '}
	],
	"highlightStyle": {
		"weight": 2,
		"opacity": 1,
		"color": 'white',
		"dashArray": '3',
		"fillOpacity": 0.5,
		"fillColor": '#E31A1C',
		"stroke": true
	},
	"layers": [
		{
			"id": "trees",
			"name": "Heritage trees",
			"type": "agsFeatureLayer",
			"cluster": true,
			"showCoverageOnHover": false,
			"removeOutsideVisibleBounds": true,
			"url": "https://services.arcgis.com/rOo16HdIMeOBI4Mb/arcgis/rest/services/Heritage_Trees_Portland/FeatureServer/0",
			"popup": true,
			"tooltipField": "COMMON_NAM",
			"outFields": [
				{"type": "OID",	"name": "FID"},
				{"name": "COMMON_NAM", "alias": "Common Name"},
				{"name": "SCIENTIFIC", "alias": "Scientific Name"},
				{"name": "ADDRESS", "alias": "Address"},
				{"name": "HEIGHT", "alias": "Height (m)", "decimals": 2},
				{"name": "CIRCUMFERE", "alias": "Circumerence (m)"},
				{"name": "YEAR", "alias": "Year"},
				{"name": "OWNER", "alias": "Owner"},
				{"name": "NOTES", "alias": "Notes"}
			],
			"visible": true,
			"queryWidget": {
				"queries" : [
					{"name": "COMMON_NAM", "alias": "Common name", "defaultOperator": "starts with", "defaultQuery": "A"},
					{"name": "SCIENTIFIC", "alias": "Scientific name"}
				],
				"outFields": [
					{"name": "COMMON_NAM", "alias": "Name"},
					{"name": "SCIENTIFIC", "alias": "Sci. name"},
					{"name": "HEIGHT", hidden: true},
					{"name": "DIAMETER", "hidden": true}
				]
			},
			"style": {
				"stroke": true,
		    "fillColor": "#00FFFF",
		    "fillOpacity": 0.5,
		    "radius": 10,
		    "weight": 0.5,
		    "opacity": 1,
		    "color": '#727272'
		  },
			"minZoom": 7
		},
		{
			"id": "railways",
			"name": "USA Railways",
			"type": "agsFeatureLayer",
			"url": "https://services.arcgis.com/rOo16HdIMeOBI4Mb/ArcGIS/rest/services/USA_Rail_Network/FeatureServer/0",
			"visible": false,
			"useCors": false,
			"popup": true,
			"fields": ["FID","RROWNER1","RR_CLASS", "RAILROAD", "ABANDONED"],
			"style": {
				"stroke": true,
		    "radius": 10,
		    "weight": 2,
		    "opacity": 1,
		    "color": "#FF0000"
		  },
			"queryWidget": {
				"queries" : [
					{"name": "RAILROAD", "alias": "Name"}
				],
				"outFields": [
					{"name": "RAILROAD", "alias": "Name"},
					{"name": "RROWNER1", "alias": "Owner"}
				],
				"maxAllowableOffset": 10
			}
		},
		{
			"id": "counties",
			"name": "Counties",
			"type": "agsDynamicLayer",
			"url": "https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/",
			"layers": [3],
			"format": 'png24',
			"transparent": true,
			"layerDefs": {3:"POP2000 > 1000000"},
			"useCors": false,
			"visible": false,
			"identify": {
				"layerLabel": "Census counties",
				"layerName": "Coarse Counties",
				"primaryField": "NAME",
				"fields": [
					{"name": "STATE_NAME", "alias": "State"},
					{"name": "POP2007", "alias": "Population"}
				],
				"maxAllowableOffset": 0.001
			},
			"queryWidget": {
				"queries" : [
					{"name": "NAME", "alias": "County name"},
					{"name": "STATE_NAME", "alias": "State name"},
					{"name": "POP2000", "alias": "Population", "type": "numeric"}
				],
				"outFields": [
					{"name": "NAME", "alias": "County name"},
					{"name": "STATE_NAME", "alias": "State name"},
					{"name": "POP2000", "alias": "Population", "thousands": true, "hidden": true}
				],
				"layerIndex": 3,
				"maxAllowableOffset": 0.001
			}
		},
		{
			"id": "us_states",
			"name": "US States",
			"type": "agsDynamicLayer",
			"url": "https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/",
			"layers": [5],
			"format": 'png24',
			"transparent": true,
			// "layerDefs": {3:"POP2000 > 1000000"},
			"useCors": false,
			"visible": true,
			"identify": {
				"layerName": "states",
				"primaryField": "STATE_NAME",
				"fields": [
					{"name": "STATE_NAME", "alias": "State"},
					{"name": "POP2007", "alias": "Population", "thousands": true},
					{"name": "POP07_SQMI", "alias": "Population density", "decimals": 0}
				],
				"maxAllowableOffset": 0.001
			},
			"queryWidget": {
				"queries" : [
					{"name": "STATE_NAME", "alias": "State name"},
					{"name": "POP2000", "alias": "Population", "type": "numeric"}
				],
				"outFields": [
					{"name": "STATE_NAME", "alias": "State name"},
					{"name": "POP2000", "alias": "Population", "thousands": true},
					{"name": "MALES", "alias": "No. Males", "thousands": true},
					{"name": "FEMALES", "alias": "No. Females", "thousands": true},
					{"name": "SQMI", "alias": "Area (sqmi)", "thousands": true, "decimals": 1}
				],
				"layerIndex": 5,
				"maxAllowableOffset": 0.001,
			},
			"maxZoom": 10,
		},
		{
			"id": "US_population",
			"name": "US Population",
			"type": "wmsTiledLayer",
			"url": "https://demo.geo-solutions.it/geoserver/topp/wms",
			"layers": "topp:states",
      "visible": false,
      "transparent": true,
      "geomField": "the_geom",
      "queryWidget": {
				"queries" : [
					{"name": "STATE_NAME", "alias": "Name"},
					{"name": "STATE_ABBR", "alias": "Abbreviation"}
				]
			},
			"identify": {
				"layerName": "states",
				"buffer": 10,
				"outFields": [
					{"name": "STATE_NAME", "alias": "Name"},
					{"name": "STATE_ABBR", "alias": "Abbreviation"},
					{"name": "FAMILIES", "alias": "Num families", "thousands": true}
				]
			},
			"outFields": [
				{"name": "STATE_NAME", "alias": "Name X"},
				{"name": "STATE_ABBR", "alias": "Abbreviation"},
				{"name": "FAMILIES", "alias": "No. Families", "thousands": true},
				{"name": "LAND_KM", "alias": "sq. km", "thousands": true, "decimals": 1, "hidden": true},
			]
		}
	]
}
<commit_msg>Remove Australian suffix from address search<commit_after>var config = {
	"title": "Bootleaf template map",
	"start": {
		// "maxZoom": 16,
		"center": [38.203,-99.799],
		"zoom": 5,
		"attributionControl": false,
		"zoomControl": false
	},
	"about": {
		"title": "Bootleaf application template",
		"contents": "
This is an open-source version of the excellent Bootleaf map started by Bryan McBride.

It's designed for rapid web map development. See https://github.com/iag-geo/bootleaf for more information.

Chage this message in the config file
"
	},
	"controls": {
		"zoom": {
			"position": "topleft"
		},
		"leafletGeocoder": {
			//https://github.com/perliedman/leaflet-control-geocoder
			"collapsed": false,
			"position": "topleft",
			"placeholder": "Search for a location",
			"type": "Google", // OpenStreetMap, Google, ArcGIS
			//"suffix": "Australia" // optional keyword to append to every search
		},
		"TOC": {
			//http://leafletjs.com/reference-1.0.2.html#control-layers-option
			"collapsed": false,
			"uncategorisedLabel": "Layers",
			"position": "topright"
		},
		"history": {
			"position": "bottomleft"
		},
		"bookmarks": {
			"position": "bottomright",
			"places": [
				{
				"latlng": [
					22.245598601926222,
					114.17609095573425
				],
				"zoom": 5,
				"name": "Ocean Park",
				"id": "a148fa354ba3",
				"editable": true,
				"removable": true
				}
			]
		}
	},
	// "activeTool": "identify", // options are identify/coordinates/queryWidget
	"basemaps": ['esriGray', 'esriDarkGray', 'esriStreets', 'OpenStreetMap'],
	"bing_key": "enter your Bing Maps key",
	"mapboxKey": "enter your MapBox key",
	// "defaultIcon": {
	// 	"imagePath": "http://leafletjs.com/examples/custom-icons/",
	// 	"iconUrl": "leaf-green.png",
	// 	"shadowUrl": "leaf-shadow.png",
	// 	"iconSize":     [38, 95],
	// 		"shadowSize":   [50, 64],
	// 		"iconAnchor":   [22, 94],
	// 		"shadowAnchor": [4, 62],
	// 		"popupAnchor":  [-3, -76]
	// },
	"tocCategories": [
		{
			"name": "GeoJSON layers",
			"layers": ["theatres", "museums"]
		},
		{
			"name": "ArcGIS Layers",
			"layers" : ["trees", "counties", "railways", "us_states"]
		},
		{
			"name": "WMS/WFS layers",
			"layers": ["nearmap", "US_population"],
			"exclusive": false
		}
	],
	"projections": [
		{4269: '+proj=longlat +ellps=GRS80 +datum=NAD83 +no_defs '}
	],
	"highlightStyle": {
		"weight": 2,
		"opacity": 1,
		"color": 'white',
		"dashArray": '3',
		"fillOpacity": 0.5,
		"fillColor": '#E31A1C',
		"stroke": true
	},
	"layers": [
		{
			"id": "trees",
			"name": "Heritage trees",
			"type": "agsFeatureLayer",
			"cluster": true,
			"showCoverageOnHover": false,
			"removeOutsideVisibleBounds": true,
			"url": "https://services.arcgis.com/rOo16HdIMeOBI4Mb/arcgis/rest/services/Heritage_Trees_Portland/FeatureServer/0",
			"popup": true,
			"tooltipField": "COMMON_NAM",
			"outFields": [
				{"type": "OID",	"name": "FID"},
				{"name": "COMMON_NAM", "alias": "Common Name"},
				{"name": "SCIENTIFIC", "alias": "Scientific Name"},
				{"name": "ADDRESS", "alias": "Address"},
				{"name": "HEIGHT", "alias": "Height (m)", "decimals": 2},
				{"name": "CIRCUMFERE", "alias": "Circumerence (m)"},
				{"name": "YEAR", "alias": "Year"},
				{"name": "OWNER", "alias": "Owner"},
				{"name": "NOTES", "alias": "Notes"}
			],
			"visible": true,
			"queryWidget": {
				"queries" : [
					{"name": "COMMON_NAM", "alias": "Common name", "defaultOperator": "starts with", "defaultQuery": "A"},
					{"name": "SCIENTIFIC", "alias": "Scientific name"}
				],
				"outFields": [
					{"name": "COMMON_NAM", "alias": "Name"},
					{"name": "SCIENTIFIC", "alias": "Sci. name"},
					{"name": "HEIGHT", hidden: true},
					{"name": "DIAMETER", "hidden": true}
				]
			},
			"style": {
				"stroke": true,
		    "fillColor": "#00FFFF",
		    "fillOpacity": 0.5,
		    "radius": 10,
		    "weight": 0.5,
		    "opacity": 1,
		    "color": '#727272'
		  },
			"minZoom": 7
		},
		{
			"id": "railways",
			"name": "USA Railways",
			"type": "agsFeatureLayer",
			"url": "https://services.arcgis.com/rOo16HdIMeOBI4Mb/ArcGIS/rest/services/USA_Rail_Network/FeatureServer/0",
			"visible": false,
			"useCors": false,
			"popup": true,
			"fields": ["FID","RROWNER1","RR_CLASS", "RAILROAD", "ABANDONED"],
			"style": {
				"stroke": true,
		    "radius": 10,
		    "weight": 2,
		    "opacity": 1,
		    "color": "#FF0000"
		  },
			"queryWidget": {
				"queries" : [
					{"name": "RAILROAD", "alias": "Name"}
				],
				"outFields": [
					{"name": "RAILROAD", "alias": "Name"},
					{"name": "RROWNER1", "alias": "Owner"}
				],
				"maxAllowableOffset": 10
			}
		},
		{
			"id": "counties",
			"name": "Counties",
			"type": "agsDynamicLayer",
			"url": "https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/",
			"layers": [3],
			"format": 'png24',
			"transparent": true,
			"layerDefs": {3:"POP2000 > 1000000"},
			"useCors": false,
			"visible": false,
			"identify": {
				"layerLabel": "Census counties",
				"layerName": "Coarse Counties",
				"primaryField": "NAME",
				"fields": [
					{"name": "STATE_NAME", "alias": "State"},
					{"name": "POP2007", "alias": "Population"}
				],
				"maxAllowableOffset": 0.001
			},
			"queryWidget": {
				"queries" : [
					{"name": "NAME", "alias": "County name"},
					{"name": "STATE_NAME", "alias": "State name"},
					{"name": "POP2000", "alias": "Population", "type": "numeric"}
				],
				"outFields": [
					{"name": "NAME", "alias": "County name"},
					{"name": "STATE_NAME", "alias": "State name"},
					{"name": "POP2000", "alias": "Population", "thousands": true, "hidden": true}
				],
				"layerIndex": 3,
				"maxAllowableOffset": 0.001
			}
		},
		{
			"id": "us_states",
			"name": "US States",
			"type": "agsDynamicLayer",
			"url": "https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/",
			"layers": [5],
			"format": 'png24',
			"transparent": true,
			// "layerDefs": {3:"POP2000 > 1000000"},
			"useCors": false,
			"visible": true,
			"identify": {
				"layerName": "states",
				"primaryField": "STATE_NAME",
				"fields": [
					{"name": "STATE_NAME", "alias": "State"},
					{"name": "POP2007", "alias": "Population", "thousands": true},
					{"name": "POP07_SQMI", "alias": "Population density", "decimals": 0}
				],
				"maxAllowableOffset": 0.001
			},
			"queryWidget": {
				"queries" : [
					{"name": "STATE_NAME", "alias": "State name"},
					{"name": "POP2000", "alias": "Population", "type": "numeric"}
				],
				"outFields": [
					{"name": "STATE_NAME", "alias": "State name"},
					{"name": "POP2000", "alias": "Population", "thousands": true},
					{"name": "MALES", "alias": "No. Males", "thousands": true},
					{"name": "FEMALES", "alias": "No. Females", "thousands": true},
					{"name": "SQMI", "alias": "Area (sqmi)", "thousands": true, "decimals": 1}
				],
				"layerIndex": 5,
				"maxAllowableOffset": 0.001,
			},
			"maxZoom": 10,
		},
		{
			"id": "US_population",
			"name": "US Population",
			"type": "wmsTiledLayer",
			"url": "https://demo.geo-solutions.it/geoserver/topp/wms",
			"layers": "topp:states",
      "visible": false,
      "transparent": true,
      "geomField": "the_geom",
      "queryWidget": {
				"queries" : [
					{"name": "STATE_NAME", "alias": "Name"},
					{"name": "STATE_ABBR", "alias": "Abbreviation"}
				]
			},
			"identify": {
				"layerName": "states",
				"buffer": 10,
				"outFields": [
					{"name": "STATE_NAME", "alias": "Name"},
					{"name": "STATE_ABBR", "alias": "Abbreviation"},
					{"name": "FAMILIES", "alias": "Num families", "thousands": true}
				]
			},
			"outFields": [
				{"name": "STATE_NAME", "alias": "Name X"},
				{"name": "STATE_ABBR", "alias": "Abbreviation"},
				{"name": "FAMILIES", "alias": "No. Families", "thousands": true},
				{"name": "LAND_KM", "alias": "sq. km", "thousands": true, "decimals": 1, "hidden": true},
			]
		}
	]
}
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes/index')
  , api = require('./routes/api')
  , stylus = require('stylus');

var app = express();

// Configuration

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.set(express.favicon(__dirname + '/public/favicon.ico'));

  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser(process.env.COOKIESECRET || 'your secret here'));
  app.use(express.session({ secret: process.env.SESSIONSECRET || 'your secret here'}));
  app.use(stylus.middleware({ src: __dirname + '/css' }));
  app.use(app.router);
  app.use(express.static(__dirname));
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.use(express.errorHandler());
});

// Routes
app.get('/', routes.index);
app.use(routes.index);
app.get('/partials/:name', routes.partials);
app.use(routes.partials);

//JSON API
app.get('/api/posts', api.posts);
app.get('/api/post/:id', api.post);
app.post('/api/post', api.addPost);
app.put('/api/post/:id', api.editPost);
app.delete('/api/post/:id', api.deletePost);
app.get('/api/date', api.getDate);
app.post('/api/user/register', api.registerUser);
app.post('/api/user/login', api.loginUser)

app.listen(process.env.PORT || 3000, function(){
  console.log("Express server listening on port %d", app.get('port'));
});
<commit_msg>Added Express logging<commit_after>/**
 * Module dependencies.
 */

var fs = require('fs')
  , express = require('express')
  , routes = require('./routes/index')
  , api = require('./routes/api')
  , stylus = require('stylus');

var today = new Date();
var loggingStream = fs.createWriteStream('./logs/' + today.toDateString() + '-express-logs.txt');

var app = express();

// Configuration
app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.set(express.favicon(__dirname + '/public/favicon.ico'));

  app.use(express.logger('dev'));

  // Middleware
  // Prevent cross-site scripting
  // app.use(express.csrf('my secret here.'));

  // body parsing middleware
  app.use(express.json());
  app.use(express.urlencoded());

  // Authentication middleware
  //app.use(express.basicAuth(function(req, res, next) {
  //  next();
  //  return true;
  //}));

  // Logging middleware
  app.use(express.logger({ stream: loggingStream }));

  app.use(express.cookieParser(process.env.COOKIESECRET || 'your secret here'));
  app.use(express.session({ secret: process.env.SESSIONSECRET || 'your secret here'}));
  app.use(stylus.middleware({ src: __dirname + '/css' }));
  app.use(app.router);
  app.use(express.static(__dirname));
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.use(express.errorHandler());
});

// Routes
app.get('/', routes.index);
app.use(routes.index);
app.get('/partials/:name', routes.partials);
app.use(routes.partials);

//JSON API
app.get('/api/posts', api.posts);
app.get('/api/post/:id', api.post);
app.post('/api/post', api.addPost);
app.put('/api/post/:id', api.editPost);
app.delete('/api/post/:id', api.deletePost);
app.get('/api/date', api.getDate);
app.post('/api/user/register', api.registerUser);
app.post('/api/user/login', api.loginUser)

app.listen(process.env.PORT || 3000, function(){
  console.log("Express server listening on port %d", app.get('port'));
});
<|endoftext|>


<commit_before>var express = require("express");
var Neo4j = require("node-neo4j");
var dbUtils = require("../db/utils");
var router = express.Router(); // eslint-disable-line new-cap
var db = (function validateEnvironmentAndConnect() {
  dbUtils.validateEnvironment("bin/www");
  return new Neo4j(dbUtils.createConnectionString());
}());

/* GET home page. */

router.get("/", function handleIndexRequest(req, res) {
  res.render("visualize");
});

/**
 * generateQueryForVisualization
 *
 * Given a @chartName generate a Neo4j query which will yield tuples
 * generating that chart. @arguments is applied to the function generating
 * the query.
 *
 * @chartName {string}: The chart name to generate
 * @filterString {string}: A string which may be used to filter on
 * @filterType {string}: What we are filtering for
 * @returns {array}: An array of tuples of (string, value)
 */
function generateQueryForVisualization(filterString, filterType) {
  var filterTypeDispatch = {
    country: "MATCH(c:Country { name: '" + filterString + "' })-[ra]-(a:Article)-[rt]-(t:Topic) RETURN c, ra, a, rt, t",
    topic: "MATCH(t:Topic { name: '" + filterString + "' })-[ra]-(a:Article)-[rt]-(c:Country) RETURN t, ra, a, rt, c"
  };
  return filterTypeDispatch[filterType] + " LIMIT 75";
}

/**
 * rowsToGraphNodes
 *
 * @param rows {array} - An odd-sized array, even elements representing nodes
 *                       and odd elements representing elements (0-indexing)
 * @param specification {array} An array the same size as rows describing each
 *                              node or edge
 * @returns {object} - An alchemy-friendly object with a relationship graph
 */
function rowsToGraphNodes(rows, specification) {
  var edges = [];
  var nodes = {};

  if (specification.length % 2 === 0) {
    throw new Error("Specification must be odd-sized");
  }

  rows.forEach(function onEachRow(row) {
    if (row.length !== specification.length) {
      throw new Error("Must provide specification with the same length as rows");
    }

    for (var i = 0; i < row.length; ++i) {
      /* Even index -> this is a node */
      if (i % 2 === 0) {
        /* Use a map here to deduplicate rows */
        nodes[row[i]._id] = {
          type: specification[i],
          label: row[i].name,
          id: row[i]._id  // eslint-disable-line no-underscore-dangle
        };
      } else {
        edges.push({
          from: row[i - 1]._id,  // eslint-disable-line no-underscore-dangle
          to: row[i + 1]._id  // eslint-disable-line no-underscore-dangle
        });
      }
    }
  });

  return {
    nodes: Object.keys(nodes).map(function onEachNodeKey(k) {
      return nodes[k];
    }),
    edges: edges
  };
}

/* API endpoint for the frontend to get a particular
 * chart.
 *
 * Parameters include 'name', which specifies the name
 * of the chart that we want to get.
 */
router.get("/get_visualisation", function onGetBarChart(req, res) {
  var query = null;
  try {
    query = generateQueryForVisualization(req.query.filterString,
                                          req.query.filterType);
  } catch (e) {
    res.json({
      result: "failure",
      reason: String(e)
    });
    return;
  }

  db.cypherQuery(query, function handleQueryRes(err, result) {
    if (err) {
      res.json({
        result: "failure",
        reason: String(err)
      });
      return;
    }

    res.json({
      result: "success",
      data: rowsToGraphNodes(result.data, ["Country", "Published In", "Article", "About", "Topic"])
    });
  });
});

module.exports = router;
<commit_msg>visualization: Remove warning about the usage of ++<commit_after>var express = require("express");
var Neo4j = require("node-neo4j");
var dbUtils = require("../db/utils");
var router = express.Router(); // eslint-disable-line new-cap
var db = (function validateEnvironmentAndConnect() {
  dbUtils.validateEnvironment("bin/www");
  return new Neo4j(dbUtils.createConnectionString());
}());

/* GET home page. */

router.get("/", function handleIndexRequest(req, res) {
  res.render("visualize");
});

/**
 * generateQueryForVisualization
 *
 * Given a @chartName generate a Neo4j query which will yield tuples
 * generating that chart. @arguments is applied to the function generating
 * the query.
 *
 * @chartName {string}: The chart name to generate
 * @filterString {string}: A string which may be used to filter on
 * @filterType {string}: What we are filtering for
 * @returns {array}: An array of tuples of (string, value)
 */
function generateQueryForVisualization(filterString, filterType) {
  var filterTypeDispatch = {
    country: "MATCH(c:Country { name: '" + filterString + "' })-[ra]-(a:Article)-[rt]-(t:Topic) RETURN c, ra, a, rt, t",
    topic: "MATCH(t:Topic { name: '" + filterString + "' })-[ra]-(a:Article)-[rt]-(c:Country) RETURN t, ra, a, rt, c"
  };
  return filterTypeDispatch[filterType] + " LIMIT 75";
}

/**
 * rowsToGraphNodes
 *
 * @param rows {array} - An odd-sized array, even elements representing nodes
 *                       and odd elements representing elements (0-indexing)
 * @param specification {array} An array the same size as rows describing each
 *                              node or edge
 * @returns {object} - An alchemy-friendly object with a relationship graph
 */
function rowsToGraphNodes(rows, specification) {
  var edges = [];
  var nodes = {};

  if (specification.length % 2 === 0) {
    throw new Error("Specification must be odd-sized");
  }

  rows.forEach(function onEachRow(row) {
    if (row.length !== specification.length) {
      throw new Error("Must provide specification with the same length as rows");
    }

    for (var i = 0; i < row.length; ++i) {  // eslint-disable-line no-plusplus
      /* Even index -> this is a node */
      if (i % 2 === 0) {
        /* Use a map here to deduplicate rows */
        nodes[row[i]._id] = {
          type: specification[i],
          label: row[i].name,
          id: row[i]._id  // eslint-disable-line no-underscore-dangle
        };
      } else {
        edges.push({
          from: row[i - 1]._id,  // eslint-disable-line no-underscore-dangle
          to: row[i + 1]._id  // eslint-disable-line no-underscore-dangle
        });
      }
    }
  });

  return {
    nodes: Object.keys(nodes).map(function onEachNodeKey(k) {
      return nodes[k];
    }),
    edges: edges
  };
}

/* API endpoint for the frontend to get a particular
 * chart.
 *
 * Parameters include 'name', which specifies the name
 * of the chart that we want to get.
 */
router.get("/get_visualisation", function onGetBarChart(req, res) {
  var query = null;
  try {
    query = generateQueryForVisualization(req.query.filterString,
                                          req.query.filterType);
  } catch (e) {
    res.json({
      result: "failure",
      reason: String(e)
    });
    return;
  }

  db.cypherQuery(query, function handleQueryRes(err, result) {
    if (err) {
      res.json({
        result: "failure",
        reason: String(err)
      });
      return;
    }

    res.json({
      result: "success",
      data: rowsToGraphNodes(result.data, ["Country", "Published In", "Article", "About", "Topic"])
    });
  });
});

module.exports = router;
<|endoftext|>


<commit_before>/*!
 * @license deepcopy.js Copyright(c) 2013 sasa+1
 * https://github.com/sasaplus1/deepcopy.js
 * Released under the MIT License.
 */
!function(){function r(r,t){var n,o;if(!e.isArray(r))throw new TypeError("parameter type is not an Array");for(n=0,o=r.length;o>n;++n)if(r[n]===t)return n;return-1}function deepcopy(n){function o(n,i,u,a){var c,f,p,s,y,l,b,j;if(null===n||"object"!=typeof n)return n;if(e.isDate(n))return new Date(Number(n));if(e.isRegExp(n))return new RegExp(n.source,String(n).slice(n.source.length+2));for(c=t(n),f=0,p=c.length;p>f;++f)s=c[f],y=n[s],y instanceof Object&&(l=r(u,y),-1===l?(b=e.isArray(y)?[]:{},u.push(y),a.push(b)):j=a[l]),i[s]=j||o(y,b,u,a),l=b=j=null;return i}var i=e.isArray(n)?[]:{},u=[n],a=[i];return o(n,i,u,a)}var e=function(){function r(r){return"object"==typeof r&&"[object Array]"===n.call(r)}function e(r){return"object"==typeof r&&"[object Date]"===n.call(r)}function t(r){return"object"==typeof r&&"[object RegExp]"===n.call(r)}var n=Object.prototype.toString;return{isArray:Array.isArray||r,isDate:e,isRegExp:t}}(),t=Object.keys||function(r){var e,t=[];if(null===r||"object"!=typeof r)throw new TypeError("parameter type is not an Object");for(e in r)r.hasOwnProperty(e)&&t.push(e);return t};this.deepcopy=deepcopy}();<commit_msg>Minify source<commit_after>/*!
 * @license deepcopy.js Copyright(c) 2013 sasa+1
 * https://github.com/sasaplus1/deepcopy.js
 * Released under the MIT License.
 */
!function(){function r(r,t){var n,o;if(!e.isArray(r))throw new TypeError("parameter type is not an Array");for(n=0,o=r.length;o>n;++n)if(r[n]===t)return n;return-1}function deepcopy(n){function o(n,i,u,a){var c,f,p,y,s,l,b,j;if(null===n||"object"!=typeof n)return n;if(e.isDate(n))return new Date(Number(n));if(e.isRegExp(n))return new RegExp(n.source,String(n).slice(n.source.length+2));for(c=t(n),f=0,p=c.length;p>f;++f)y=c[f],s=n[y],null!==s&&"object"==typeof s&&(l=r(u,s),-1===l?(b=e.isArray(s)?[]:{},u.push(s),a.push(b)):j=a[l]),i[y]=j||o(s,b,u,a),l=b=j=null;return i}var i=e.isArray(n)?[]:{},u=[n],a=[i];return o(n,i,u,a)}var e=function(){function r(r){return"object"==typeof r&&"[object Array]"===n.call(r)}function e(r){return"object"==typeof r&&"[object Date]"===n.call(r)}function t(r){return"object"==typeof r&&"[object RegExp]"===n.call(r)}var n=Object.prototype.toString;return{isArray:Array.isArray||r,isDate:e,isRegExp:t}}(),t=Object.keys||function(r){var e,t=[];if(null===r||"object"!=typeof r)throw new TypeError("parameter type is not an Object");for(e in r)r.hasOwnProperty(e)&&t.push(e);return t};this.deepcopy=deepcopy}();<|endoftext|>


<commit_before>var _ = require('lodash');
var configure = require('./configure');
var defaults = require('./defaults');
var onRoute = require('./onRoute');
var addLayoutShim = require('./layoutshim');
var addResViewMethod = require('./res.view');
var render = require('./render');
var implicitActions = require('./actions');

module.exports = function (sails) {

  /**
   * `views` hook
   */
  return {

    defaults: defaults,

    configure: _.partial(configure, sails),

    render: render,

    /**
     * Standard responsibilities of `initialize` are to load middleware methods
     * and listen for events to know when to bind any special routes.
     *
     * @api private
     */
    initialize: function (cb) {

      if (!sails.hooks.http) {
        var err = new Error();
        err.message = '`views` hook requires the `http` hook, but the `http` hook is disabled.  Please enable both or neither.';
        err.type = err.code = 'E_HOOKINIT_DEP';
        err.name = 'failed requires `http` hook';
        err.status = 400;
        return cb(err);
      }

      addResViewMethod._middlewareType = 'VIEWS HOOK: addResViewMethod';

      // Add res.view() method to compatible middleware
      sails.on('router:before', function () {

        // But wait until after internationalization has happened
        // (if applicable)
        if (sails.hooks.i18n) {
          sails.after('hook:i18n:loaded', function () {
            sails.router.bind('/*', addResViewMethod, 'all', { });
          });
        }
        else {
          sails.router.bind('/*', addResViewMethod, 'all');
        }
      });

      // Register `{view:'/foo'}` route syntax
      sails.on('route:typeUnknown', _.partial(onRoute, sails));

      // Declare hook loaded when ejs layouts have been applied,
      // views have been inventoried, and view-serving middleware has been prepared
      addLayoutShim(sails);

      // Detect and prepare implicit actions
      // for each view file so they can be routed to
      // using {view:'...'} syntax in `routes.js`
      implicitActions(sails, this);

      sails.renderView = this.render;
      cb();
    }
  };
};
<commit_msg>add some more inline docs to views hook<commit_after>/**
 * Module dependencies
 */

var _ = require('lodash');
var configure = require('./configure');
var defaults = require('./defaults');
var onRoute = require('./onRoute');
var addLayoutShim = require('./layoutshim');
var addResViewMethod = require('./res.view');
var render = require('./render');
var implicitActions = require('./actions');

module.exports = function (sails) {

  /**
   * `views` hook
   */
  return {

    defaults: defaults,

    configure: _.partial(configure, sails),

    render: render,

    /**
     * Standard responsibilities of `initialize` are to load middleware methods
     * and listen for events to know when to bind any special routes.
     *
     * @api private
     */
    initialize: function (cb) {

      if (!sails.hooks.http) {
        var err = new Error('`views` hook requires the `http` hook, but the `http` hook is disabled.  Please enable both or neither.');
        err.message = '`views` hook requires the `http` hook, but the `http` hook is disabled.  Please enable both or neither.';
        err.type = err.code = 'E_HOOKINIT_DEP';
        err.name = 'failed requires `http` hook';
        err.status = 400;
        return cb(err);
      }

      // Before handing off incoming requests, bind handler that adds the `res.view()` method to `res`.
      // (flagging middleware along the way)
      addResViewMethod._middlewareType = 'VIEWS HOOK: addResViewMethod';
      sails.on('router:before', function () {

        // But wait until after internationalization has happened
        // (if applicable)
        if (sails.hooks.i18n) {
          sails.after('hook:i18n:loaded', function () {
            sails.router.bind('/*', addResViewMethod, 'all', { });
          });
        }
        else {
          sails.router.bind('/*', addResViewMethod, 'all');
        }
      });

      // Register `{view:'/foo'}` route target syntax.
      sails.on('route:typeUnknown', _.partial(onRoute, sails));

      // Declare hook loaded when ejs layouts have been applied,
      // views have been inventoried, and view-serving middleware has been prepared
      addLayoutShim(sails);

      // Detect and prepare implicit actions
      // for each view file so they can be routed to
      // using {view:'...'} syntax in `routes.js`
      implicitActions(sails, this);

      // Expose `sails.renderView()` function to userland.
      sails.renderView = this.render;

      return cb();
    }
  };
};
<|endoftext|>


<commit_before>;(function(){
  'use strict';

  angular.module('libApp', [])
    .controller('LibraryController', function($http){
      var vm = this;

      $http.get('https://jsslibrary.firebaseio.com/list.json')
      .success(function(data){
        vm.books = data;
      })
      .error(function(err){
        console.log(err);
      });

    vm.addNewBook = function(){
      $http.post('https://jsslibrary.firebaseio.com/list.json', vm.newBook)
        .success(function(data){
          vm.books[data.title] = vm.newBook;
          vm.newBook = _freshBook();
        })
        .error(function(err){
          console.log(err);
        });
    };

    vm.removeBook = function(bookId){
      var url = 'https://jsslibrary.firebaseio.com/list/' + bookId + '.json';
      $http.delete(url)
        .success(function(){
          delete vm.books[bookId];
        })
        .error(function(err){
          console.log(err);
        });
    };

    vm.newBook = _freshBook();

    vm.readOptions = {
      all: 'All',
      some: 'Some',
      none: 'None'
    };

      function _freshBook(){
        return {
          read: 'none'
        }
      }

    });

}());

<commit_msg>fixed adding error<commit_after>;(function(){
  'use strict';

  angular.module('libApp', [])
    .controller('LibraryController', function($http){
      var vm = this;

      $http.get('https://jsslibrary.firebaseio.com/books.json')
       .success(function(data){
        vm.books = data;
      })
      .error(function(err){
        console.log(err);
      });

    vm.addNewBook = function(){
      $http.post('https://jsslibrary.firebaseio.com/books.json', vm.newBook)
        .success(function(data){
          vm.books[data.name] = vm.newBook;
          vm.newBook = _freshBook();
        })
        .error(function(err){
          console.log(err);
        });
    };

    vm.removeBook = function(bookId){
      var url = 'https://jsslibrary.firebaseio.com/books/' + bookId + '.json';
      $http.delete(url)
        .success(function(){
          delete vm.books[bookId];
        })
        .error(function(err){
          console.log(err);
        });
    };

    vm.newBook = _freshBook();

    vm.readOptions = {
      all: 'All',
      some: 'Some',
      none: 'None'
    };

      function _freshBook(){
        return {
          read: 'none'
        }
      }

    });

}());

<|endoftext|>


<commit_before>module.exports = {
  extends: ['plugin:@typescript-eslint/recommended', 'plugin:import/typescript'],
  settings: {
    'import/resolver': {
      node: {
        extensions: ['.ts', '.tsx', '.js', '.jsx', '.json', '.mjs']
      },
      webpack: true,
      typescript: true
    }
  },
  rules: {
    // Allow return type to be inferred
    '@typescript-eslint/explicit-function-return-type': 'off',

    // Allow explicitly marking something as 'any'
    '@typescript-eslint/no-explicit-any': 'off',

    // Don't require access modifiers on classes
    '@typescript-eslint/explicit-member-accessibility': 'off',

    // Allow marking something as defined using !
    // Eventually may want this
    '@typescript-eslint/no-non-null-assertion': 'off',

    // Allow type assertion in call and new expression
    '@typescript-eslint/no-object-literal-type-assertion': ['off'],

    // Warn on ts-ignore
    '@typescript-eslint/ban-ts-comment': [
      'error',
      {
        'ts-expect-error': 'allow-with-description',
        'ts-ignore': 'allow-with-description',
        'ts-nocheck': true,
        'ts-check': false
      }
    ],

    // disallow empty functions, except for standalone funcs/arrows
    // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-empty-function.md
    '@typescript-eslint/no-empty-function': [
      'error',
      {
        allow: [
          'arrowFunctions',
          'functions',
          'methods',
          'protected-constructors',
          'private-constructors'
        ]
      }
    ],

    // This rule goes against typescripts inference and adds friction to devs
    '@typescript-eslint/explicit-module-boundary-types': 'off',

    // The object recommendation of using Record is not working as expected
    // and prevents using interfaces
    '@typescript-eslint/ban-types': [
      'error',
      {
        types: {
          object: false
        },
        extendDefaults: true
      }
    ],

    // Prevents conditionals where the type is always truthy or always falsy
    // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unnecessary-condition.md
    '@typescript-eslint/no-unnecessary-condition': 'warn',

    // Use typescript version of this rule
    'no-shadow': 'off',
    '@typescript-eslint/no-shadow': 'error',

    // Use typescript version of this rule
    'no-use-before-define': 'off',
    '@typescript-eslint/no-use-before-define': ['warn', { classes: false, functions: false }],

    // Typescript handles this
    'import/no-unresolved': 'off'
  }
};
<commit_msg>fix: Removed @typescript-eslint/no-unnecessary-condition rule since it requires typechecking<commit_after>module.exports = {
  extends: ['plugin:@typescript-eslint/recommended', 'plugin:import/typescript'],
  settings: {
    'import/resolver': {
      node: {
        extensions: ['.ts', '.tsx', '.js', '.jsx', '.json', '.mjs']
      },
      webpack: true,
      typescript: true
    }
  },
  rules: {
    // Allow return type to be inferred
    '@typescript-eslint/explicit-function-return-type': 'off',

    // Allow explicitly marking something as 'any'
    '@typescript-eslint/no-explicit-any': 'off',

    // Don't require access modifiers on classes
    '@typescript-eslint/explicit-member-accessibility': 'off',

    // Allow marking something as defined using !
    // Eventually may want this
    '@typescript-eslint/no-non-null-assertion': 'off',

    // Allow type assertion in call and new expression
    '@typescript-eslint/no-object-literal-type-assertion': ['off'],

    // Warn on ts-ignore
    '@typescript-eslint/ban-ts-comment': [
      'error',
      {
        'ts-expect-error': 'allow-with-description',
        'ts-ignore': 'allow-with-description',
        'ts-nocheck': true,
        'ts-check': false
      }
    ],

    // disallow empty functions, except for standalone funcs/arrows
    // https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-empty-function.md
    '@typescript-eslint/no-empty-function': [
      'error',
      {
        allow: [
          'arrowFunctions',
          'functions',
          'methods',
          'protected-constructors',
          'private-constructors'
        ]
      }
    ],

    // This rule goes against typescripts inference and adds friction to devs
    '@typescript-eslint/explicit-module-boundary-types': 'off',

    // The object recommendation of using Record is not working as expected
    // and prevents using interfaces
    '@typescript-eslint/ban-types': [
      'error',
      {
        types: {
          object: false
        },
        extendDefaults: true
      }
    ],

    // Use typescript version of this rule
    'no-shadow': 'off',
    '@typescript-eslint/no-shadow': 'error',

    // Use typescript version of this rule
    'no-use-before-define': 'off',
    '@typescript-eslint/no-use-before-define': ['warn', { classes: false, functions: false }],

    // Typescript handles this
    'import/no-unresolved': 'off'
  }
};
<|endoftext|>