<commit_before>const config = require('config');
const insights = require('../lib/insights.js');
const synthetics = require('../lib/synthetics.js');
const helper = require('../lib/helper.js');
const json2csv = require('json2csv');
const fs = require('fs');

// This NRQL can be used for 1 month, 1 week, 1 day
const nrql = 'SELECT count(*) FROM SyntheticCheck WHERE type != \'SIMPLE\' FACET monitorName LIMIT 1000';
var since = ' SINCE 1 month ago';

// Global counters
var accountPlannedCount = 0;
var accountUsageCount = 0;
var usedResult = [];
var plannedResult = [];

// Array of accounts to parse through
var configArr = ['newrelic'];
var accountLen = configArr.length;

// This gets run at the end to write out the complete CSV
var finalizeUsage = function() {
  console.log('Usage data found for ' + usedResult.length + ' monitors');
  var input = {
    data: usedResult,
    fields: ['account', 'monitorName', 'usageCount'],
    fieldNames: ['Account', 'Monitor Name', 'Usage in Last Month']
  }
  json2csv(input, function(csvErr, csvData) {
    if (csvErr) {
      console.log('ERROR preparing CSV file!');
      console.log(csvErr);
    } else {
      var fname = 'usage-' + (new Date).getTime() + '.csv';
      console.log('Writing usage data to: ' + fname);
      fs.writeFile(fname, csvData, function(fileErr) {
        if(fileErr) {
          return console.log(fileErr);
        }
      });
    }
  });
}

// Run the historical usage query
var runUsageQuery = function(fullNrql, configId) {
  insights.query(fullNrql, configId, function(error, response, body) {
    var resultBody = helper.handleCB(error, response, body);
    var accountResult = {};

    var facets = resultBody.facets;
    var monitorCount = facets.length;
    console.log(configId + ' has ' + monitorCount + ' total monitors that have run in the last month');
    for (var f = monitorCount - 1; f >= 0; f--) {
      var usedInfo = {
        'account': configId,
        'monitorName': facets[f].name,
        'usageCount': facets[f].results[0].count
      }
      usedResult.push(usedInfo);
    };

    // Check if all accounts are finished
    accountUsageCount++;
    if (accountUsageCount == accountLen) {
      finalizeUsage();
    }
  });
}

// We got all the planned accounts, now finalize the data
var finalizePlanned = function() {
  console.log('Data received for ' + plannedResult.length + ' non-simple, not disabled monitors');
  var input = {
    data: plannedResult,
    fields: ['account', 'name', 'checkCount'],
    fieldNames: ['Account', 'Monitor Name', 'Planned Monthly Usage']
  }
  json2csv(input, function(csvErr, csvData) {
    if (csvErr) {
      console.log('ERROR preparing CSV file!');
      console.log(csvErr);
    } else {
      var fname = 'scheduled-' + (new Date).getTime() + '.csv';
      console.log('Writing scheduled data to: ' + fname);
      fs.writeFile(fname, csvData, function(fileErr) {
        if(fileErr) {
          return console.log(fileErr);
        }
      });
    }
  });
}

// The planned query checks the Synthetics API
var runPlannedQuery = function(configId) {
  synthetics.getAllMonitors(configId, function(error, response, body) {
    var resultBody = helper.handleCB(error, response, body);

    var monitorCount = resultBody.count;
    console.log(configId + ' has ' + monitorCount + ' total monitors that have beeen created.');
    for (var i = monitorCount - 1; i >= 0; i--) {
      var monitor = resultBody.monitors[i];
      var type = monitor.type;
      if (type != 'SIMPLE') {
        var status = monitor.status;
        if (status != 'DISABLED') {
          monitor.account = configId;
          var frequency = monitor.frequency;
          var locationCount = monitor.locations.length;
          var checkCount = ((30 * 24 * 60) / frequency) * locationCount;
          monitor.checkCount = checkCount;
          plannedResult.push(monitor);
          // var name = monitor.name;
          // console.log(name + ' checks = ' + checkCount);
        }
      }
    }

    // Check if we got all the planned accounts
    accountPlannedCount++;
    if (accountPlannedCount == accountLen) {
      finalizePlanned();
    }
  })
}

// Loop through the accounts in the config array
var loopAccounts = function(since){
  for (var i = configArr.length - 1; i >= 0; i--) {
    var configId = configArr[i];
    var fullNrql = nrql + since;
    console.log('Query account: ' + configId);
    runUsageQuery(fullNrql, configId);
    runPlannedQuery(configId);
  }
}

loopAccounts(since);
<commit_msg>updating usage script to use array of accounts<commit_after>const config = require('config');
const insights = require('../lib/insights.js');
const synthetics = require('../lib/synthetics.js');
const helper = require('../lib/helper.js');
const json2csv = require('json2csv');
const fs = require('fs');

// This NRQL can be used for 1 month, 1 week, 1 day
const nrql = 'SELECT count(*) FROM SyntheticCheck WHERE type != \'SIMPLE\' FACET monitorName LIMIT 1000';
var since = ' SINCE 1 month ago';

// Global counters
var accountPlannedCount = 0;
var accountUsageCount = 0;
var usedResult = [];
var plannedResult = [];

// Array of accounts to parse through
// var configArr = ['newrelic'];
var configArr = config.get('configArr');
var accountLen = configArr.length;

// This gets run at the end to write out the complete CSV
var finalizeUsage = function() {
  console.log('Usage data found for ' + usedResult.length + ' monitors');
  var input = {
    data: usedResult,
    fields: ['account', 'monitorName', 'usageCount'],
    fieldNames: ['Account', 'Monitor Name', 'Usage in Last Month']
  }
  json2csv(input, function(csvErr, csvData) {
    if (csvErr) {
      console.log('ERROR preparing CSV file!');
      console.log(csvErr);
    } else {
      var fname = 'usage-' + (new Date).getTime() + '.csv';
      console.log('Writing usage data to: ' + fname);
      fs.writeFile(fname, csvData, function(fileErr) {
        if(fileErr) {
          return console.log(fileErr);
        }
      });
    }
  });
}

// Run the historical usage query
var runUsageQuery = function(fullNrql, configId) {
  insights.query(fullNrql, configId, function(error, response, body) {
    var resultBody = helper.handleCB(error, response, body);
    var accountResult = {};

    var facets = resultBody.facets;
    var monitorCount = facets.length;
    console.log(configId + ' has ' + monitorCount + ' total monitors that have run in the last month');
    for (var f = monitorCount - 1; f >= 0; f--) {
      var usedInfo = {
        'account': configId,
        'monitorName': facets[f].name,
        'usageCount': facets[f].results[0].count
      }
      usedResult.push(usedInfo);
    };

    // Check if all accounts are finished
    accountUsageCount++;
    if (accountUsageCount == accountLen) {
      finalizeUsage();
    }
  });
}

// We got all the planned accounts, now finalize the data
var finalizePlanned = function() {
  console.log('Data received for ' + plannedResult.length + ' non-simple, not disabled monitors');
  var input = {
    data: plannedResult,
    fields: ['account', 'name', 'checkCount'],
    fieldNames: ['Account', 'Monitor Name', 'Planned Monthly Usage']
  }
  json2csv(input, function(csvErr, csvData) {
    if (csvErr) {
      console.log('ERROR preparing CSV file!');
      console.log(csvErr);
    } else {
      var fname = 'scheduled-' + (new Date).getTime() + '.csv';
      console.log('Writing scheduled data to: ' + fname);
      fs.writeFile(fname, csvData, function(fileErr) {
        if(fileErr) {
          return console.log(fileErr);
        }
      });
    }
  });
}

// The planned query checks the Synthetics API
var runPlannedQuery = function(configId) {
  synthetics.getAllMonitors(configId, function(error, response, body) {
    var resultBody = helper.handleCB(error, response, body);

    var monitorCount = resultBody.count;
    console.log(configId + ' has ' + monitorCount + ' total monitors that have beeen created.');
    for (var i = monitorCount - 1; i >= 0; i--) {
      var monitor = resultBody.monitors[i];
      var type = monitor.type;
      if (type != 'SIMPLE') {
        var status = monitor.status;
        if (status != 'DISABLED') {
          monitor.account = configId;
          var frequency = monitor.frequency;
          var locationCount = monitor.locations.length;
          var checkCount = ((30 * 24 * 60) / frequency) * locationCount;
          monitor.checkCount = checkCount;
          plannedResult.push(monitor);
          // var name = monitor.name;
          // console.log(name + ' checks = ' + checkCount);
        }
      }
    }

    // Check if we got all the planned accounts
    accountPlannedCount++;
    if (accountPlannedCount == accountLen) {
      finalizePlanned();
    }
  })
}

// Loop through the accounts in the config array
var loopAccounts = function(since){
  for (var i = configArr.length - 1; i >= 0; i--) {
    var configId = configArr[i];
    var fullNrql = nrql + since;
    console.log('Query account: ' + configId);
    runUsageQuery(fullNrql, configId);
    runPlannedQuery(configId);
  }
}

loopAccounts(since);
<|endoftext|>


<commit_before>var eachBlog = require("../each/blog");
var Template = require("../../app/models/template");
var Blog = require("../../app/models/blog");
var fs = require("fs-extra");
var templateDir = require("path").resolve(__dirname + "/../../app/templates");

// This script is used to archive one of Blot's included templates
// It will create a copy of the template for each blog on which it
// is currently used (preserving the existing blog as-is) and then
// drop the template from the list of available templates for new
// users, or for existing users who were not using the template.

if (require.main === module) {
  main(process.argv[2], function(err) {
    if (err) throw err;

    process.exit();
  });
}

function main(name, callback) {
  var templateID = "SITE:" + name;

  if (!fs.statSync(templateDir + "/" + name).isDirectory())
    return callback(new Error("Could not find global template " + name));

  Template.getMetadata(templateID, function(err, template) {
    if (err) return callback(err);

    if (!template)
      return callback(
        new Error("There is no template in the database with id: " + templateID)
      );

    var total = 0;

    console.log(
      "Checking all blogs to see if any use template",
      name,
      "(" + templateID + "):"
    );
    eachBlog(
      function(user, blog, next) {
        if (blog.template !== templateID) return next();

        var newTemplateID = blog.id + ":" + name;

        Template.create(
          blog.id,
          name,
          {
            isPublic: false,
            name: name,
            cloneFrom: blog.template
          },
          function(err) {
            if (err) return next(err);

            // We rename the template to include the case-preserved
            // original name. If we do this initially, there is a strange
            // duplicate template bug for unknown reasons.
            Template.setMetadata(
              newTemplateID,
              { name: template.name },
              function(err) {
                if (err) return next(err);

                Template.getMetadata(newTemplateID, function(err, template) {
                  if (err || !template)
                    return next(err || new Error("no template"));

                  Blog.set(blog.id, { template: newTemplateID }, function(err) {
                    if (err) return next(err);

                    console.log(
                      blog.id,
                      blog.handle,
                      "used", templateID, "so I created a clone",
                      template.id, "\nhttp://" + blog.handle + '.' + process.env.BLOT_HOST
                    );

                    total++;
                    next();
                  });
                });
              }
            );
          }
        );
      },
      function(err) {
        if (err) return callback(err);

        console.log();

        Template.drop("SITE", name, function(err) {
          if (err) return callback(err);
          console.log(
            "\nCloned template",
            templateID,
            "for all",
            total,
            "sites currently using it then removed it from the database."
          );
          console.log(
            "You can now safely archive the files in:\napp/templates/" + name
          );
          callback(null);
        });
      }
    );
  });
}

module.exports = main;
<commit_msg>Updated archive script<commit_after>var eachBlog = require("../each/blog");
var Template = require("../../app/models/template");
var Blog = require("../../app/models/blog");
var fs = require("fs-extra");
var templateDir = require("path").resolve(__dirname + "/../../app/templates");

// This script is used to archive one of Blot's included templates
// It will create a copy of the template for each blog on which it
// is currently used (preserving the existing blog as-is) and then
// drop the template from the list of available templates for new
// users, or for existing users who were not using the template.

if (require.main === module) {
  main(process.argv[2], function(err) {
    if (err) throw err;

    process.exit();
  });
}

function main(name, callback) {
  var templateID = "SITE:" + name;

  if (!fs.statSync(templateDir + "/" + name).isDirectory())
    console.warn("Warning: could not find existing global template directory at app/templates/" + name);

  Template.getMetadata(templateID, function(err, template) {
    if (err) return callback(err);

    if (!template)
      return callback(
        new Error("There is no template in the database with id: " + templateID)
      );

    var total = 0;

    console.log(
      "Checking all blogs to see if any use template",
      name,
      "(" + templateID + "):"
    );
    eachBlog(
      function(user, blog, next) {
        if (blog.template !== templateID) return next();

        var newTemplateID = blog.id + ":" + name;

        Template.create(
          blog.id,
          name,
          {
            isPublic: false,
            name: name,
            cloneFrom: blog.template
          },
          function(err) {
            if (err) return next(err);

            // We rename the template to include the case-preserved
            // original name. If we do this initially, there is a strange
            // duplicate template bug for unknown reasons.
            Template.setMetadata(
              newTemplateID,
              { name: template.name },
              function(err) {
                if (err) return next(err);

                Template.getMetadata(newTemplateID, function(err, template) {
                  if (err || !template)
                    return next(err || new Error("no template"));

                  Blog.set(blog.id, { template: newTemplateID }, function(err) {
                    if (err) return next(err);

                    console.log(
                      blog.id,
                      blog.handle,
                      "used", templateID, "so I created a clone",
                      template.id, "\nhttp://" + blog.handle + '.' + process.env.BLOT_HOST
                    );

                    total++;
                    next();
                  });
                });
              }
            );
          }
        );
      },
      function(err) {
        if (err) return callback(err);

        console.log();

        Template.drop("SITE", name, function(err) {
          if (err) return callback(err);
          console.log(
            "\nCloned template",
            templateID,
            "for all",
            total,
            "sites currently using it then removed it from the database."
          );
          console.log(
            "You can now safely archive the files in:\napp/templates/" + name
          );
          callback(null);
        });
      }
    );
  });
}

module.exports = main;
<|endoftext|>


<commit_before>/*************************
 * TRAVIS DEV BUILD STEPS
 *************************/
const { exec, execSync, spawn } = require('child_process');
const util               = require('util');
const execPromise        = util.promisify(exec);

/* Steps
 ********/
const Steps = (paths, components) => { // :{}
	return {
		// cloneComponentRepos() { // :Promise[{}] - (runs asynchronously)
		// 	const opts     = { cwd: paths.components };
		// 	let promises   = [];
		//
		// 	for (const [i, repoName] of components.repoNames.entries()) {
		// 		console.info(`cloning ${components.names[i]}`.toUpperCase().alert);
		//
		// 		const promise = new Promise((resolve, reject) => {
		// 			const git = spawn('git', ['clone', '--progress', '--depth', '1', repoName], opts);
		//
		// 			git.stdout.on('data', data => {
		// 				console.log(`STDOUT: ${data}`);
		// 			});
		//
		// 			git.stderr.on('data', data => {
		// 				console.log(`STDERR: ${data}`);
		// 			});
		//
		// 			git.on('close', code => {
		// 				console.log(`child process exited with code ${code}`);
		// 				resolve(true);
		// 			});
		//
		// 			git.on('error', err => {
		// 				console.log('Failed to start subprocess.');
		// 				reject(err);
		// 			});
		// 		})
		//
		// 		promises.push(promise);
		// 	}
		//
		// 	return Promise.all(promises);
		// },

		cloneComponentRepos() { // :Promise[{}] - (runs asynchronously)
			const cloneCmd = 'git clone -q --progress --depth 1';
			const opts     = { cwd: paths.components };
			let promises   = [];
			for (const [i, repoName] of components.repoNames.entries()) {
				console.info(`cloning ${components.names[i]}`.toUpperCase().alert);
				const cmd     = `${cloneCmd} ${repoName}`;
				const promise = execPromise(cmd, opts).then(result => {
					console.log('RESULT:', result);
					return result;
				}).catch(error => {
					console.error('error: clone component repos'.toUpperCase().error);
					console.error(error);
					process.exit(1);
				});
				promises.push(promise);
			}
			return Promise.all(promises);
		},

		setupComponents() { // :Promise[{}] - (runs asynchronously)
			const cmd    = 'rapid-build prod publish && npm run link'
			let promises = [];
			for (const name of components.names) {
				console.info(`setup component ${name}`.toUpperCase().alert);
				const opts    = { cwd: `${paths.components}/${name}` };
				const promise = execPromise(cmd, opts).then(result => {
					console.log('RESULT:', result);
					return result;
				}).catch(error => {
					console.error('error: setup components'.toUpperCase().error);
					console.error(error);
					process.exit(1);
				});
				promises.push(promise);
			}
			return Promise.all(promises);
		},

		setupShowcase() { // :void - (runs synchronously)
			const cmd  = 'npm run setup'
			const opts = { cwd: paths.showcase, stdio: [0,1,2] };
			console.info(`setup showcase`.toUpperCase().alert);
			execSync(cmd, opts); console.log();
		},

		buildShowcase() { // :void - (runs synchronously)
			const cmd  = 'rapid-build prod publish'
			const opts = { cwd: paths.showcase, stdio: [0,1,2] };
			console.info(`build showcase`.toUpperCase().alert);
			execSync(cmd, opts); console.log();
		}
	};
};

/* Export It!
 *************/
module.exports = Steps;
<commit_msg>chore(travis): try to clone components asynchronously with node spawn<commit_after>/*************************
 * TRAVIS DEV BUILD STEPS
 *************************/
const { exec, execSync, spawn } = require('child_process');
const util               = require('util');
const execPromise        = util.promisify(exec);

/* Steps
 ********/
const Steps = (paths, components) => { // :{}
	return {
		// cloneComponentRepos() { // :Promise[{}] - (runs asynchronously)
		// 	const opts     = { cwd: paths.components };
		// 	let promises   = [];
		//
		// 	for (const [i, repoName] of components.repoNames.entries()) {
		// 		console.info(`cloning ${components.names[i]}`.toUpperCase().alert);
		//
		// 		const promise = new Promise((resolve, reject) => {
		// 			const git = spawn('git', ['clone', '--progress', '--depth', '1', repoName], opts);
		//
		// 			git.stdout.on('data', data => {
		// 				console.log(`STDOUT: ${data}`);
		// 			});
		//
		// 			git.stderr.on('data', data => {
		// 				console.log(`STDERR: ${data}`);
		// 			});
		//
		// 			git.on('close', code => {
		// 				console.log(`child process exited with code ${code}`);
		// 				resolve(true);
		// 			});
		//
		// 			git.on('error', err => {
		// 				console.log('Failed to start subprocess.');
		// 				reject(err);
		// 			});
		// 		})
		//
		// 		promises.push(promise);
		// 	}
		//
		// 	return Promise.all(promises);
		// },

		cloneComponentRepos() { // :Promise[{}] - (runs asynchronously)
			const cloneCmd = 'git clone -q --depth 1';
			const opts     = { cwd: paths.components };
			let promises   = [];
			for (const [i, repoName] of components.repoNames.entries()) {
				console.info(`cloning ${components.names[i]}`.toUpperCase().alert);
				const cmd     = `${cloneCmd} ${repoName}`;
				const promise = execPromise(cmd, opts).then(result => {
					console.log('RESULT:', result);
					return result;
				}).catch(error => {
					console.error('error: clone component repos'.toUpperCase().error);
					console.error(error);
					process.exit(1);
				});
				promises.push(promise);
			}
			return Promise.all(promises);
		},

		setupComponents() { // :Promise[{}] - (runs asynchronously)
			const cmd    = 'rapid-build prod publish && npm run link'
			let promises = [];
			for (const name of components.names) {
				console.info(`setup component ${name}`.toUpperCase().alert);
				const opts    = { cwd: `${paths.components}/${name}` };
				const promise = execPromise(cmd, opts).then(result => {
					console.log('RESULT:', result);
					return result;
				}).catch(error => {
					console.error('error: setup components'.toUpperCase().error);
					console.error(error);
					process.exit(1);
				});
				promises.push(promise);
			}
			return Promise.all(promises);
		},

		setupShowcase() { // :void - (runs synchronously)
			const cmd  = 'npm run setup'
			const opts = { cwd: paths.showcase, stdio: [0,1,2] };
			console.info(`setup showcase`.toUpperCase().alert);
			execSync(cmd, opts); console.log();
		},

		buildShowcase() { // :void - (runs synchronously)
			const cmd  = 'rapid-build prod publish'
			const opts = { cwd: paths.showcase, stdio: [0,1,2] };
			console.info(`build showcase`.toUpperCase().alert);
			execSync(cmd, opts); console.log();
		}
	};
};

/* Export It!
 *************/
module.exports = Steps;
<|endoftext|>


<commit_before>$(document).ready(function() {
  var peak = 20; // Number of visible pixels

  var hPos = function(pos) {
    var dsize = $(document).height();
    var wsize = $(window).height();
    return Math.round(wsize*(pos/dsize))
  }

  $('h1 > a.headerlink, h2 > a.headerlink').each(function(index){
    var lnk = $(this);
    var pos = lnk.offset().top
    var title = lnk.parent().text().replace('¶','')
    var node = $('<div>')
               .addClass('sidelegend')
               .css('top', hPos(pos)+'px')
               .appendTo('body')
    node.append($('<a>').text(title).attr('href', lnk.attr('href')))
    node.css('right', '-'+(node.outerWidth()-peak)+'px')
    node.mouseenter(function(){
      node.animate({'right': '0px'}, 250)
    })
    node.mouseleave(function(){
      node.stop(true).animate({'right': '-'+(node.outerWidth()-peak)+'px'}, 250)
    })

    $(document).resize(function(){
      var dsize = $(document).height();
      var wsize = $(window).height();
      node.css('top', hPos(pos)+'px')
    })

    $(window).resize(function(){
      var dsize = $(document).height();
      var wsize = $(window).height();
      node.css('top', hPos(pos)+'px')
    })
  })
})
<commit_msg>Improved scrollbar TOC in docs.<commit_after>$(document).ready(function() {
  var peak = 20; // Number of visible pixels

  var hPos = function(pos) {
    var dsize = $(document).height();
    var wsize = $(window).height();
    return Math.round(wsize*(pos/dsize))
  }

  var timeoutId;

  $('h1 > a.headerlink, h2 > a.headerlink').each(function(index){
    var lnk = $(this);
    var pos = lnk.offset().top
    var title = lnk.parent().text().replace('¶','')
    var node = $('<div>')
               .addClass('sidelegend')
               .css('top', hPos(pos)+'px')
               .appendTo('body')
    node.append($('<a>').text(title).attr('href', lnk.attr('href')))
    node.css('right', '-'+(node.outerWidth()-peak)+'px')
    node.mouseenter(function(){
      if(timeoutId) {
          window.clearTimeout(timeoutId);
          timeoutId = null;
      }
      $('div.sidelegend').animate({'right': '0px'}, 250)
    })
    node.mouseleave(function(){
      timeoutId = window.setTimeout(function(){
        $('div.sidelegend').each(function(){
          var n = $(this)
          n.animate({'right': '-'+(n.outerWidth()-peak)+'px'}, 250)
        })
        timeoutId = null;
      }, 1000)
    })

    $(document).resize(function(){
      var dsize = $(document).height();
      var wsize = $(window).height();
      node.css('top', hPos(pos)+'px')
    })

    $(window).resize(function(){
      var dsize = $(document).height();
      var wsize = $(window).height();
      node.css('top', hPos(pos)+'px')
    })
  })
})
<|endoftext|>


<commit_before>/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, no-param-reassign, quotes, yoda, no-else-return, consistent-return, comma-dangle, semi, object-shorthand, prefer-template, one-var, one-var-declaration-per-line, no-unused-vars, max-len, vars-on-top, padded-blocks */
/* global Breakpoints */
/* global Turbolinks */

(function() {
  var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  var AUTO_SCROLL_OFFSET = 75;

  this.Build = (function() {
    Build.interval = null;

    Build.state = null;

    function Build(options) {
      options = options || $('.js-build-options').data();
      this.pageUrl = options.pageUrl;
      this.buildUrl = options.buildUrl;
      this.buildStatus = options.buildStatus;
      this.state = options.logState;
      this.buildStage = options.buildStage;
      this.updateDropdown = bind(this.updateDropdown, this);
      this.$document = $(document);
      this.$body = $('body');
      this.$buildTrace = $('#build-trace');
      this.$autoScrollContainer = $('.autoscroll-container');
      this.$autoScrollStatus = $('#autoscroll-status');
      this.$autoScrollStatusText = this.$autoScrollStatus.find('.status-text');
      this.$upBuildTrace = $('#up-build-trace');
      this.$downBuildTrace = $('#down-build-trace');
      this.$scrollTopBtn = $('#scroll-top');
      this.$scrollBottomBtn = $('#scroll-bottom');
      this.$buildRefreshAnimation = $('.js-build-refresh');

      clearInterval(Build.interval);
      // Init breakpoint checker
      this.bp = Breakpoints.get();

      this.initSidebar();
      this.$buildScroll = $('#js-build-scroll');

      this.populateJobs(this.buildStage);
      this.updateStageDropdownText(this.buildStage);
      this.sidebarOnResize();

      this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.sidebarOnClick.bind(this));
      this.$document.off('click', '.stage-item').on('click', '.stage-item', this.updateDropdown);
      this.$document.on('scroll', this.initScrollMonitor.bind(this));
      $(window).off('resize.build').on('resize.build', this.sidebarOnResize.bind(this));
      $('a', this.$buildScroll).off('click.stepTrace').on('click.stepTrace', this.stepTrace);
      this.updateArtifactRemoveDate();
      if ($('#build-trace').length) {
        this.getInitialBuildTrace();
        this.initScrollButtonAffix();
      }
      if (this.buildStatus === "running" || this.buildStatus === "pending") {
        Build.interval = setInterval((function(_this) {
          // Check for new build output if user still watching build page
          // Only valid for runnig build when output changes during time
          return function() {
            if (_this.location() === _this.pageUrl) {
              return _this.getBuildTrace();
            }
          };
        })(this), 4000);
      }
    }

    Build.prototype.initSidebar = function() {
      this.$sidebar = $('.js-build-sidebar');
      this.sidebarTranslationLimits = {
        min: $('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight()
      }
      this.sidebarTranslationLimits.max = this.sidebarTranslationLimits.min + $('.scrolling-tabs-container').outerHeight();
      this.$sidebar.css({
        top: this.sidebarTranslationLimits.max
      });
      this.$sidebar.niceScroll();
      this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.toggleSidebar);
      this.$document.off('scroll.translateSidebar').on('scroll.translateSidebar', this.translateSidebar.bind(this));
    };

    Build.prototype.location = function() {
      return window.location.href.split("#")[0];
    };

    Build.prototype.getInitialBuildTrace = function() {
      var removeRefreshStatuses = ['success', 'failed', 'canceled', 'skipped']

      return $.ajax({
        url: this.buildUrl,
        dataType: 'json',
        success: function(buildData) {
          $('.js-build-output').html(buildData.trace_html);
          if (removeRefreshStatuses.indexOf(buildData.status) >= 0) {
            this.initScrollMonitor();
            return this.$buildRefreshAnimation.remove();
          }
        }.bind(this)
      });
    };

    Build.prototype.getBuildTrace = function() {
      return $.ajax({
        url: this.pageUrl + "/trace.json?state=" + (encodeURIComponent(this.state)),
        dataType: "json",
        success: (function(_this) {
          return function(log) {
            if (log.state) {
              _this.state = log.state;
            }
            if (log.status === "running") {
              if (log.append) {
                $('.js-build-output').append(log.html);
              } else {
                $('.js-build-output').html(log.html);
              }
              return _this.checkAutoscroll();
            } else if (log.status !== _this.buildStatus) {
              return Turbolinks.visit(_this.pageUrl);
            }
          };
        })(this)
      });
    };

    Build.prototype.checkAutoscroll = function() {
      if (this.$autoScrollStatus.data("state") === "enabled") {
        return $("html,body").scrollTop(this.$buildTrace.height());
      }

      // Handle a situation where user started new build
      // but never scrolled a page
      if (!this.$scrollTopBtn.is(':visible') &&
          !this.$scrollBottomBtn.is(':visible') &&
          !gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
        this.$scrollBottomBtn.show();
      }
    };

    Build.prototype.initScrollButtonAffix = function() {
      // Hide everything initially
      this.$scrollTopBtn.hide();
      this.$scrollBottomBtn.hide();
      this.$autoScrollContainer.hide();
    }

    // Page scroll listener to detect if user has scrolling page
    // and handle following cases
    // 1) User is at Top of Build Log;
    //      - Hide Top Arrow button
    //      - Show Bottom Arrow button
    //      - Disable Autoscroll and hide indicator (when build is running)
    // 2) User is at Bottom of Build Log;
    //      - Show Top Arrow button
    //      - Hide Bottom Arrow button
    //      - Enable Autoscroll and show indicator (when build is running)
    // 3) User is somewhere in middle of Build Log;
    //      - Show Top Arrow button
    //      - Show Bottom Arrow button
    //      - Disable Autoscroll and hide indicator (when build is running)
    Build.prototype.initScrollMonitor = function() {
      if (!gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
        // User is somewhere in middle of Build Log

        this.$scrollTopBtn.show();

        if (this.buildStatus === 'success' || this.buildStatus === 'failed') { // Check if Build is completed
          this.$scrollBottomBtn.show();
        } else if (this.$buildRefreshAnimation.is(':visible') && !gl.utils.isInViewport(this.$buildRefreshAnimation.get(0))) {
          this.$scrollBottomBtn.show();
        } else {
          this.$scrollBottomBtn.hide();
        }

        // Hide Autoscroll Status Indicator
        if (this.$scrollBottomBtn.is(':visible')) {
          this.$autoScrollContainer.hide();
          this.$autoScrollStatusText.removeClass('animate');
        } else {
          this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).show();
          this.$autoScrollStatusText.addClass('animate');
        }
      } else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
        // User is at Top of Build Log

        this.$scrollTopBtn.hide();
        this.$scrollBottomBtn.show();

        this.$autoScrollContainer.hide();
        this.$autoScrollStatusText.removeClass('animate');
      } else if ((!gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) ||
                 (this.$buildRefreshAnimation.is(':visible') && gl.utils.isInViewport(this.$buildRefreshAnimation.get(0)))) {
        // User is at Bottom of Build Log

        this.$scrollTopBtn.show();
        this.$scrollBottomBtn.hide();

        // Show and Reposition Autoscroll Status Indicator
        this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).show();
        this.$autoScrollStatusText.addClass('animate');
      } else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
        // Build Log height is small

        this.$scrollTopBtn.hide();
        this.$scrollBottomBtn.hide();

        // Hide Autoscroll Status Indicator
        this.$autoScrollContainer.hide();
        this.$autoScrollStatusText.removeClass('animate');
      }

      if (this.buildStatus === "running" || this.buildStatus === "pending") {
        // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise.
        this.$autoScrollStatus.data("state", gl.utils.isInViewport(this.$buildRefreshAnimation.get(0)) ? 'enabled' : 'disabled');
      }
    };

    Build.prototype.shouldHideSidebarForViewport = function() {
      var bootstrapBreakpoint;
      bootstrapBreakpoint = this.bp.getBreakpointSize();
      return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm';
    };

    Build.prototype.translateSidebar = function(e) {
      var newPosition = this.sidebarTranslationLimits.max - (document.body.scrollTop || document.documentElement.scrollTop);
      if (newPosition < this.sidebarTranslationLimits.min) newPosition = this.sidebarTranslationLimits.min;
      this.$sidebar.css({
        top: newPosition
      });
    };

    Build.prototype.toggleSidebar = function(shouldHide) {
      var shouldShow = typeof shouldHide === 'boolean' ? !shouldHide : undefined;
      this.$buildScroll.toggleClass('sidebar-expanded', shouldShow)
        .toggleClass('sidebar-collapsed', shouldHide);
      this.$sidebar.toggleClass('right-sidebar-expanded', shouldShow)
        .toggleClass('right-sidebar-collapsed', shouldHide);
    };

    Build.prototype.sidebarOnResize = function() {
      this.toggleSidebar(this.shouldHideSidebarForViewport());
    };

    Build.prototype.sidebarOnClick = function() {
      if (this.shouldHideSidebarForViewport()) this.toggleSidebar();
    };

    Build.prototype.updateArtifactRemoveDate = function() {
      var $date, date;
      $date = $('.js-artifacts-remove');
      if ($date.length) {
        date = $date.text();
        return $date.text(gl.utils.timeFor(new Date(date.replace(/([0-9]+)-([0-9]+)-([0-9]+)/g, '$1/$2/$3')), ' '));
      }
    };

    Build.prototype.populateJobs = function(stage) {
      $('.build-job').hide();
      $('.build-job[data-stage="' + stage + '"]').show();
    };

    Build.prototype.updateStageDropdownText = function(stage) {
      $('.stage-selection').text(stage);
    };

    Build.prototype.updateDropdown = function(e) {
      e.preventDefault();
      var stage = e.currentTarget.text;
      this.updateStageDropdownText(stage);
      this.populateJobs(stage);
    };

    Build.prototype.stepTrace = function(e) {
      var $currentTarget;
      e.preventDefault();
      $currentTarget = $(e.currentTarget);
      $.scrollTo($currentTarget.attr('href'), {
        offset: -($('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight())
      });
    };

    return Build;

  })();

}).call(this);
<commit_msg>Hide Scroll Top for failed build<commit_after>/* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, no-param-reassign, quotes, yoda, no-else-return, consistent-return, comma-dangle, semi, object-shorthand, prefer-template, one-var, one-var-declaration-per-line, no-unused-vars, max-len, vars-on-top, padded-blocks */
/* global Breakpoints */
/* global Turbolinks */

(function() {
  var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  var AUTO_SCROLL_OFFSET = 75;

  this.Build = (function() {
    Build.interval = null;

    Build.state = null;

    function Build(options) {
      options = options || $('.js-build-options').data();
      this.pageUrl = options.pageUrl;
      this.buildUrl = options.buildUrl;
      this.buildStatus = options.buildStatus;
      this.state = options.logState;
      this.buildStage = options.buildStage;
      this.updateDropdown = bind(this.updateDropdown, this);
      this.$document = $(document);
      this.$body = $('body');
      this.$buildTrace = $('#build-trace');
      this.$autoScrollContainer = $('.autoscroll-container');
      this.$autoScrollStatus = $('#autoscroll-status');
      this.$autoScrollStatusText = this.$autoScrollStatus.find('.status-text');
      this.$upBuildTrace = $('#up-build-trace');
      this.$downBuildTrace = $('#down-build-trace');
      this.$scrollTopBtn = $('#scroll-top');
      this.$scrollBottomBtn = $('#scroll-bottom');
      this.$buildRefreshAnimation = $('.js-build-refresh');

      clearInterval(Build.interval);
      // Init breakpoint checker
      this.bp = Breakpoints.get();

      this.initSidebar();
      this.$buildScroll = $('#js-build-scroll');

      this.populateJobs(this.buildStage);
      this.updateStageDropdownText(this.buildStage);
      this.sidebarOnResize();

      this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.sidebarOnClick.bind(this));
      this.$document.off('click', '.stage-item').on('click', '.stage-item', this.updateDropdown);
      this.$document.on('scroll', this.initScrollMonitor.bind(this));
      $(window).off('resize.build').on('resize.build', this.sidebarOnResize.bind(this));
      $('a', this.$buildScroll).off('click.stepTrace').on('click.stepTrace', this.stepTrace);
      this.updateArtifactRemoveDate();
      if ($('#build-trace').length) {
        this.getInitialBuildTrace();
        this.initScrollButtonAffix();
      }
      if (this.buildStatus === "running" || this.buildStatus === "pending") {
        Build.interval = setInterval((function(_this) {
          // Check for new build output if user still watching build page
          // Only valid for runnig build when output changes during time
          return function() {
            if (_this.location() === _this.pageUrl) {
              return _this.getBuildTrace();
            }
          };
        })(this), 4000);
      }
    }

    Build.prototype.initSidebar = function() {
      this.$sidebar = $('.js-build-sidebar');
      this.sidebarTranslationLimits = {
        min: $('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight()
      }
      this.sidebarTranslationLimits.max = this.sidebarTranslationLimits.min + $('.scrolling-tabs-container').outerHeight();
      this.$sidebar.css({
        top: this.sidebarTranslationLimits.max
      });
      this.$sidebar.niceScroll();
      this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.toggleSidebar);
      this.$document.off('scroll.translateSidebar').on('scroll.translateSidebar', this.translateSidebar.bind(this));
    };

    Build.prototype.location = function() {
      return window.location.href.split("#")[0];
    };

    Build.prototype.getInitialBuildTrace = function() {
      var removeRefreshStatuses = ['success', 'failed', 'canceled', 'skipped']

      return $.ajax({
        url: this.buildUrl,
        dataType: 'json',
        success: function(buildData) {
          $('.js-build-output').html(buildData.trace_html);
          if (removeRefreshStatuses.indexOf(buildData.status) >= 0) {
            this.$buildRefreshAnimation.remove();
            return this.initScrollMonitor();
          }
        }.bind(this)
      });
    };

    Build.prototype.getBuildTrace = function() {
      return $.ajax({
        url: this.pageUrl + "/trace.json?state=" + (encodeURIComponent(this.state)),
        dataType: "json",
        success: (function(_this) {
          return function(log) {
            if (log.state) {
              _this.state = log.state;
            }
            if (log.status === "running") {
              if (log.append) {
                $('.js-build-output').append(log.html);
              } else {
                $('.js-build-output').html(log.html);
              }
              return _this.checkAutoscroll();
            } else if (log.status !== _this.buildStatus) {
              return Turbolinks.visit(_this.pageUrl);
            }
          };
        })(this)
      });
    };

    Build.prototype.checkAutoscroll = function() {
      if (this.$autoScrollStatus.data("state") === "enabled") {
        return $("html,body").scrollTop(this.$buildTrace.height());
      }

      // Handle a situation where user started new build
      // but never scrolled a page
      if (!this.$scrollTopBtn.is(':visible') &&
          !this.$scrollBottomBtn.is(':visible') &&
          !gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
        this.$scrollBottomBtn.show();
      }
    };

    Build.prototype.initScrollButtonAffix = function() {
      // Hide everything initially
      this.$scrollTopBtn.hide();
      this.$scrollBottomBtn.hide();
      this.$autoScrollContainer.hide();
    }

    // Page scroll listener to detect if user has scrolling page
    // and handle following cases
    // 1) User is at Top of Build Log;
    //      - Hide Top Arrow button
    //      - Show Bottom Arrow button
    //      - Disable Autoscroll and hide indicator (when build is running)
    // 2) User is at Bottom of Build Log;
    //      - Show Top Arrow button
    //      - Hide Bottom Arrow button
    //      - Enable Autoscroll and show indicator (when build is running)
    // 3) User is somewhere in middle of Build Log;
    //      - Show Top Arrow button
    //      - Show Bottom Arrow button
    //      - Disable Autoscroll and hide indicator (when build is running)
    Build.prototype.initScrollMonitor = function() {
      if (!gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
        // User is somewhere in middle of Build Log

        this.$scrollTopBtn.show();

        if (this.buildStatus === 'success' || this.buildStatus === 'failed') { // Check if Build is completed
          this.$scrollBottomBtn.show();
        } else if (this.$buildRefreshAnimation.is(':visible') && !gl.utils.isInViewport(this.$buildRefreshAnimation.get(0))) {
          this.$scrollBottomBtn.show();
        } else {
          this.$scrollBottomBtn.hide();
        }

        // Hide Autoscroll Status Indicator
        if (this.$scrollBottomBtn.is(':visible')) {
          this.$autoScrollContainer.hide();
          this.$autoScrollStatusText.removeClass('animate');
        } else {
          this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).show();
          this.$autoScrollStatusText.addClass('animate');
        }
      } else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
        // User is at Top of Build Log

        this.$scrollTopBtn.hide();
        this.$scrollBottomBtn.show();

        this.$autoScrollContainer.hide();
        this.$autoScrollStatusText.removeClass('animate');
      } else if ((!gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) ||
                 (this.$buildRefreshAnimation.is(':visible') && gl.utils.isInViewport(this.$buildRefreshAnimation.get(0)))) {
        // User is at Bottom of Build Log

        this.$scrollTopBtn.show();
        this.$scrollBottomBtn.hide();

        // Show and Reposition Autoscroll Status Indicator
        this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).show();
        this.$autoScrollStatusText.addClass('animate');
      } else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
        // Build Log height is small

        this.$scrollTopBtn.hide();
        this.$scrollBottomBtn.hide();

        // Hide Autoscroll Status Indicator
        this.$autoScrollContainer.hide();
        this.$autoScrollStatusText.removeClass('animate');
      }

      if (this.buildStatus === "running" || this.buildStatus === "pending") {
        // Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise.
        this.$autoScrollStatus.data("state", gl.utils.isInViewport(this.$buildRefreshAnimation.get(0)) ? 'enabled' : 'disabled');
      }
    };

    Build.prototype.shouldHideSidebarForViewport = function() {
      var bootstrapBreakpoint;
      bootstrapBreakpoint = this.bp.getBreakpointSize();
      return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm';
    };

    Build.prototype.translateSidebar = function(e) {
      var newPosition = this.sidebarTranslationLimits.max - (document.body.scrollTop || document.documentElement.scrollTop);
      if (newPosition < this.sidebarTranslationLimits.min) newPosition = this.sidebarTranslationLimits.min;
      this.$sidebar.css({
        top: newPosition
      });
    };

    Build.prototype.toggleSidebar = function(shouldHide) {
      var shouldShow = typeof shouldHide === 'boolean' ? !shouldHide : undefined;
      this.$buildScroll.toggleClass('sidebar-expanded', shouldShow)
        .toggleClass('sidebar-collapsed', shouldHide);
      this.$sidebar.toggleClass('right-sidebar-expanded', shouldShow)
        .toggleClass('right-sidebar-collapsed', shouldHide);
    };

    Build.prototype.sidebarOnResize = function() {
      this.toggleSidebar(this.shouldHideSidebarForViewport());
    };

    Build.prototype.sidebarOnClick = function() {
      if (this.shouldHideSidebarForViewport()) this.toggleSidebar();
    };

    Build.prototype.updateArtifactRemoveDate = function() {
      var $date, date;
      $date = $('.js-artifacts-remove');
      if ($date.length) {
        date = $date.text();
        return $date.text(gl.utils.timeFor(new Date(date.replace(/([0-9]+)-([0-9]+)-([0-9]+)/g, '$1/$2/$3')), ' '));
      }
    };

    Build.prototype.populateJobs = function(stage) {
      $('.build-job').hide();
      $('.build-job[data-stage="' + stage + '"]').show();
    };

    Build.prototype.updateStageDropdownText = function(stage) {
      $('.stage-selection').text(stage);
    };

    Build.prototype.updateDropdown = function(e) {
      e.preventDefault();
      var stage = e.currentTarget.text;
      this.updateStageDropdownText(stage);
      this.populateJobs(stage);
    };

    Build.prototype.stepTrace = function(e) {
      var $currentTarget;
      e.preventDefault();
      $currentTarget = $(e.currentTarget);
      $.scrollTo($currentTarget.attr('href'), {
        offset: -($('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight())
      });
    };

    return Build;

  })();

}).call(this);
<|endoftext|>


<commit_before>// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the rails generate channel command.
//
//= require action_cable
//= require_self
//= require_tree ./channels

(function() {
  if (!this.App) {
    this.App = {}
  };

  App.cable = ActionCable.createConsumer();

}).call(this);
<commit_msg>remove unecessary code<commit_after>// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the rails generate channel command.
//
//= require action_cable
//= require_self
//= require_tree ./channels

(function() {
  if (!this.App) {
    this.App = {}
  }

  App.cable = ActionCable.createConsumer();

}).call(this);
<|endoftext|>


<commit_before>import Category from '../models/category'
import Domain from '../models/domain'
import Header from '../models/header'
import CspHeader from '../models/csp-header'

function fetchModel(category_id, domain_id) {
  return () => {
    return Discourse.ajax('/security-headers/categories/' + category_id + '/domains/' + domain_id);
  };
}

function wrapDomain(domain) {
  return Domain.create({
    id: domain.id,
    name: domain.name,
    country: domain.country,
    sslEnabled: domain.sslEnabled,
    score: domain.score,
    http_score: domain.http_score,
    csp_score: domain.csp_score,
    category: Category.create(domain.category),
    httpHeaders: _.map(domain.http_headers, (header) => { return Header.create(header); }),
    cspHeader: CspHeader.createFromJson(domain.csp_header)
  });
}

export default Discourse.Route.extend({
  model(params) {
    return PreloadStore.getAndRemove('domain_scan', fetchModel(params.category_id, params.id)).then(wrapDomain);
  },

  setupController(controller, model) {
    controller.set('model', model);
    this.controllerFor('application').set('showFooter', true);
  }
})
<commit_msg>Fix ssl_enabled option<commit_after>import Category from '../models/category'
import Domain from '../models/domain'
import Header from '../models/header'
import CspHeader from '../models/csp-header'

function fetchModel(category_id, domain_id) {
  return () => {
    return Discourse.ajax('/security-headers/categories/' + category_id + '/domains/' + domain_id);
  };
}

function wrapDomain(domain) {
  return Domain.create({
    id: domain.id,
    name: domain.name,
    country: domain.country,
    sslEnabled: domain.ssl_enabled,
    score: domain.score,
    http_score: domain.http_score,
    csp_score: domain.csp_score,
    category: Category.create(domain.category),
    httpHeaders: _.map(domain.http_headers, (header) => { return Header.create(header); }),
    cspHeader: CspHeader.createFromJson(domain.csp_header)
  });
}

export default Discourse.Route.extend({
  model(params) {
    return PreloadStore.getAndRemove('domain_scan', fetchModel(params.category_id, params.id)).then(wrapDomain);
  },

  setupController(controller, model) {
    controller.set('model', model);
    this.controllerFor('application').set('showFooter', true);
  }
})
<|endoftext|>


<commit_before>var sketchPad;
$(function() {

    $('#start-draw').on('click', function(e) {
        var size = "size=" + "640x480&";
        if (map.streetView.pano == null) {
            alert('Please switch to Street View first!');
        } else {
            var pano = "pano=" + map.streetView.location.pano + "&";
            var heading = "heading=" + map.streetView.pov.heading + "&";
            var pitch = "pitch=" + map.streetView.pov.pitch;         // var zoom = "zoom=" + map.streetView.location.pov.zoom + "&";

            var url = "http://maps.googleapis.com/maps/api/streetview?" + size + pano + heading + pitch;
            $('#street-view-image').attr("src", url);
            $('.metro').hide();
            $('.draw').show();
        }
    });

    sketchPad = createSketchpad();

    startDrawing(sketchPad);

    // Default lat and long for map on load
    var latitude = 41.881487;
    var longitude = -87.631219;

    // Set options for base google map
    var mapOptions = {
        center: new google.maps.LatLng(latitude, longitude),
        zoom: 12
    };

  // Set options for marker clusterer map
  var clusterOptions = {
    gridSize: 70,
    maxZoom: 14
  };

  var chartData;
  var dates;

  convertToX = function(date, dates) {
    return dates.indexOf(date);
  }

  resetChart = function(numDates) {
    chartData = [];
    for (var i = 0; i < numDates; i++) {
      chartData.push({
        x: i,
        report: 0,
        patch: 0
      });
    }
  }

  insertData = function(hole, data, dates) {
    completeX = convertToX(hole.completion_date, dates);
    createdX = convertToX(hole.creation_date, dates);
    var numComplete = 0;
    var numCreate = 0;
    if (completeX > -1 && completeX < dates.length) {
      numComplete = ++data[completeX].patch;
    }
    if (createdX > -1 && createdX < dates.length) {
      numCreate = ++data[createdX].report;
    }
    return [numCreate, numComplete];
  }

  var map = initialize(mapOptions);

  var mc = new MarkerClusterer(map, [], clusterOptions);

  // Search
  var infowindow = new google.maps.InfoWindow();
  var marker = "";
  var unfilled_markers = [];
  var filled_markers = [];
  var geocoder = new google.maps.Geocoder();

  function makeInfoWindowEvent(map, infowindow, contentString, marker) {
    google.maps.event.addListener(marker, 'click', function() {
      infowindow.setContent(contentString);
      infowindow.open(map, marker);
    });
  };

  function clearMarkers() {
    for (var i = 0; i < unfilled_markers.length; i++) {
      unfilled_markers[i].setMap(null);
    }
    for (var i = 0; i < filled_markers.length; i++) {
      filled_markers[i].setMap(null);
    }
  }

  function makeReportEvent(map, infowindow, event) {
    var lat = parseFloat(event.latLng.lat());
    var lng = parseFloat(event.latLng.lng());
    var latlng = new google.maps.LatLng(lat, lng);

    geocoder.geocode({
      'latLng': latlng
    }, function(results, status) {
      var address = String("'" + results[0].formatted_address + "'");
      var dropDownForm = "
Submit a report for this location
\
                <form id='reportSubmit' enctype='multipart/form-data'>\
                  <input type='hidden' name='latitude' value=" + lat + ">\
                  <input type='hidden' name='longitude' value=" + lng + ">\
                  <input type='hidden' name='address' value=" + address + ">\
                  Where is the pothole located? \
                  <select name='attribute'>\
                    <option value='CURB'>Curb Lane</option>\
                    <option value='CROSS'>Crosswalk</option>\
                    <option value='INTERSEC'>Intersection</option>\
                    <option value='TRAFFIC'>Traffic Lane</option>\
                  </select>\
                  Write a description of the pothole below (optional):\
                  <textarea name='description' cols='40' rows='4' maxLength='500' placeholder='Description here...'></textarea>\
                  Upload an image of this pothole (optional):\
                  <input type='file' name='picture'>\
                  Phone # to receive text updates about your request (optional):\
                  <input type='text' pattern='[0-9]{3}-[0-9]{3}-[0-9]{4}' name='phone' placeholder='###-###-####'>\

\

<input type='submit' value='Submit'>\
                </form>"

      infowindow.setContent(dropDownForm);
      infowindow.setPosition(event.latLng);
      infowindow.open(map);
    });
  };

  $('#map-canvas').on('submit', '#reportSubmit', function(event) {
    event.preventDefault();
    infowindow.setContent("");
    var form = $(this).serializeArray();

    $.post('/submitReport', form, function(data, textStatus, xhr) {
      if (xhr.status === 200) {
        infowindow.setContent("Your request has been submitted");
        setTimeout(function() {
          infowindow.close();
        }, 3000);
      } else {
        infowindow.setContent("Unable to process your request");
        setTimeout(function() {
          infowindow.close();
        }, 4000);
      }
    }, 'json');

  });

  getDatesBetween = function(startDate, endDate) {
    var start = new Date(startDate);
    var end = new Date(endDate);
    var between = [];
    while (start <= end) {
      start.setDate(start.getDate() + 1);
      between.push(new Date(start));
    }

    return between.map(function(date) {
      return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).slice(-2) + "-" + ("0" + date.getDate()).slice(-2);
    });
  }

  getPotholesByDate = function(startDate, endDate) {
    var dates = getDatesBetween(startDate, endDate);
    filled_markers = [];
    unfilled_markers = [];
    mc.clearMarkers();

    $.ajax({
      url: "/potholes.json",
      data: {
        all_dates: dates
      },
      success: function(data) {
        if (data == null || data.length == 0) {
          alert("There is no data for this period. Please choose another date");
        } else {
          clearMarkers();
          resetChart(dates.length);
          var yMax = 0;
          var y2Max = 0;
          for (var i = 0; i < data.length; i++) {
            var counts = insertData(data[i], chartData, dates);
            yMax = Math.max(yMax, counts[0]);
            y2Max = Math.max(y2Max, counts[1]);
            if (data[i].completion_date === null) {
              marker = new google.maps.Marker({
                position: new google.maps.LatLng(data[i].latitude, data[i].longitude),
                map: map,
                icon: '/assets/red_MarkerA.png',
                optimized: false
              });
              makeInfoWindowEvent(map, infowindow, "Reported on: " + data[i].creation_date + "
" + "Street Address: " + data[i].street_address, marker);
              unfilled_markers.push(marker);
            } else {
              marker = new google.maps.Marker({
                position: new google.maps.LatLng(data[i].latitude, data[i].longitude),
                map: map,
                icon: '/assets/green_MarkerA.png',
                optimized: false
              });
              makeInfoWindowEvent(map, infowindow, "Reported on: " + data[i].creation_date + "
" + "Completed Date: " + data[i].completion_date + "
" + "Street Address: " + data[i].street_address, marker);
              filled_markers.push(marker);
            }
          }

          mc.addMarkers(unfilled_markers.concat(filled_markers));

          angular.element(document.getElementById('chart')).scope().$apply(function(scope) {
            scope.dates = dates.map(function(date) {
              return date.substring(5, 10);
            });
            scope.options.axes.y.max = Math.max(yMax, y2Max);
            scope.options.axes.y2.max = Math.max(yMax, y2Max);
            scope.data = chartData;
          });
        }
      },
      dataType: "json"
    });
  }

  // Remove all markers from map if you zoom out too far, put them back when zoomed back in
  // google.maps.event.addListener(map, 'zoom_changed', function(){
  //   if (map.zoom < 7) {
  //     mc.clearMarkers();
  //   } else if (map.zoom >= 7 && mc.a.length === 0) {
  //     mc.addMarkers(unfilled_markers.concat(filled_markers));
  //   }
  // });

  // Open report form when map is clicked if zoomed in far enough
  // If report form is already open, close it on next map click
  google.maps.event.addListener(map, 'click', function(event) {
    if (map.zoom > 14 && infowindow.getContent()) {
      infowindow.close();
      infowindow.setContent("");
    } else if (map.zoom > 14) {
      makeReportEvent(map, infowindow, event);
    } else {
      infowindow.close();
    }
  });

  $("#date-pick").on('submit', function(event) {
    event.preventDefault();
    getPotholesByDate($('#start-date').val(), $('#end-date').val());
  });

  $("#filled").on('click', function() {

    if ($("#filled").prop("checked")) {
      for (var i = 0; i < filled_markers.length; ++i) {
        filled_markers[i].setVisible(false);
      }
    } else {
      for (var i = 0; i < filled_markers.length; ++i) {
        filled_markers[i].setVisible(true);
      }
    }
  });

  function search(e) {
    var code = (e.keyCode ? e.keyCode : e.which);
    var target = document.getElementById('pac-input');
    if (code == 13) { //Enter keycode
      e.preventDefault();
      geocoder.geocode({
          'address': target.value
        },
        function(results, status) {
          if (status == google.maps.GeocoderStatus.OK) {
            var loc = results[0].geometry.location;
            map.setZoom(17);
            map.panTo(new google.maps.LatLng(loc.lat(), loc.lng()));
          } else {
            alert("Not found: " + status);
          }
        }
      );

    }
  };

  $("#pac-input").bind("keypress", {}, search);

});
<commit_msg>Set optimization to true on markers<commit_after>var sketchPad;
$(function() {

    $('#start-draw').on('click', function(e) {
        var size = "size=" + "640x480&";
        if (map.streetView.pano == null) {
            alert('Please switch to Street View first!');
        } else {
            var pano = "pano=" + map.streetView.location.pano + "&";
            var heading = "heading=" + map.streetView.pov.heading + "&";
            var pitch = "pitch=" + map.streetView.pov.pitch;         // var zoom = "zoom=" + map.streetView.location.pov.zoom + "&";

            var url = "http://maps.googleapis.com/maps/api/streetview?" + size + pano + heading + pitch;
            $('#street-view-image').attr("src", url);
            $('.metro').hide();
            $('.draw').show();
        }
    });

    sketchPad = createSketchpad();

    startDrawing(sketchPad);

    // Default lat and long for map on load
    var latitude = 41.881487;
    var longitude = -87.631219;

    // Set options for base google map
    var mapOptions = {
        center: new google.maps.LatLng(latitude, longitude),
        zoom: 12
    };

  // Set options for marker clusterer map
  var clusterOptions = {
    gridSize: 70,
    maxZoom: 14
  };

  var chartData;
  var dates;

  convertToX = function(date, dates) {
    return dates.indexOf(date);
  }

  resetChart = function(numDates) {
    chartData = [];
    for (var i = 0; i < numDates; i++) {
      chartData.push({
        x: i,
        report: 0,
        patch: 0
      });
    }
  }

  insertData = function(hole, data, dates) {
    completeX = convertToX(hole.completion_date, dates);
    createdX = convertToX(hole.creation_date, dates);
    var numComplete = 0;
    var numCreate = 0;
    if (completeX > -1 && completeX < dates.length) {
      numComplete = ++data[completeX].patch;
    }
    if (createdX > -1 && createdX < dates.length) {
      numCreate = ++data[createdX].report;
    }
    return [numCreate, numComplete];
  }

  var map = initialize(mapOptions);

  var mc = new MarkerClusterer(map, [], clusterOptions);

  // Search
  var infowindow = new google.maps.InfoWindow();
  var marker = "";
  var unfilled_markers = [];
  var filled_markers = [];
  var geocoder = new google.maps.Geocoder();

  function makeInfoWindowEvent(map, infowindow, contentString, marker) {
    google.maps.event.addListener(marker, 'click', function() {
      infowindow.setContent(contentString);
      infowindow.open(map, marker);
    });
  };

  function clearMarkers() {
    for (var i = 0; i < unfilled_markers.length; i++) {
      unfilled_markers[i].setMap(null);
    }
    for (var i = 0; i < filled_markers.length; i++) {
      filled_markers[i].setMap(null);
    }
  }

  function makeReportEvent(map, infowindow, event) {
    var lat = parseFloat(event.latLng.lat());
    var lng = parseFloat(event.latLng.lng());
    var latlng = new google.maps.LatLng(lat, lng);

    geocoder.geocode({
      'latLng': latlng
    }, function(results, status) {
      var address = String("'" + results[0].formatted_address + "'");
      var dropDownForm = "
Submit a report for this location
\
                <form id='reportSubmit' enctype='multipart/form-data'>\
                  <input type='hidden' name='latitude' value=" + lat + ">\
                  <input type='hidden' name='longitude' value=" + lng + ">\
                  <input type='hidden' name='address' value=" + address + ">\
                  Where is the pothole located? \
                  <select name='attribute'>\
                    <option value='CURB'>Curb Lane</option>\
                    <option value='CROSS'>Crosswalk</option>\
                    <option value='INTERSEC'>Intersection</option>\
                    <option value='TRAFFIC'>Traffic Lane</option>\
                  </select>\
                  Write a description of the pothole below (optional):\
                  <textarea name='description' cols='40' rows='4' maxLength='500' placeholder='Description here...'></textarea>\
                  Upload an image of this pothole (optional):\
                  <input type='file' name='picture'>\
                  Phone # to receive text updates about your request (optional):\
                  <input type='text' pattern='[0-9]{3}-[0-9]{3}-[0-9]{4}' name='phone' placeholder='###-###-####'>\

\

<input type='submit' value='Submit'>\
                </form>"

      infowindow.setContent(dropDownForm);
      infowindow.setPosition(event.latLng);
      infowindow.open(map);
    });
  };

  $('#map-canvas').on('submit', '#reportSubmit', function(event) {
    event.preventDefault();
    infowindow.setContent("");
    var form = $(this).serializeArray();

    $.post('/submitReport', form, function(data, textStatus, xhr) {
      if (xhr.status === 200) {
        infowindow.setContent("Your request has been submitted");
        setTimeout(function() {
          infowindow.close();
        }, 3000);
      } else {
        infowindow.setContent("Unable to process your request");
        setTimeout(function() {
          infowindow.close();
        }, 4000);
      }
    }, 'json');

  });

  getDatesBetween = function(startDate, endDate) {
    var start = new Date(startDate);
    var end = new Date(endDate);
    var between = [];
    while (start <= end) {
      start.setDate(start.getDate() + 1);
      between.push(new Date(start));
    }

    return between.map(function(date) {
      return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).slice(-2) + "-" + ("0" + date.getDate()).slice(-2);
    });
  }

  getPotholesByDate = function(startDate, endDate) {
    var dates = getDatesBetween(startDate, endDate);
    filled_markers = [];
    unfilled_markers = [];
    mc.clearMarkers();

    $.ajax({
      url: "/potholes.json",
      data: {
        all_dates: dates
      },
      success: function(data) {
        if (data == null || data.length == 0) {
          alert("There is no data for this period. Please choose another date");
        } else {
          clearMarkers();
          resetChart(dates.length);
          var yMax = 0;
          var y2Max = 0;
          for (var i = 0; i < data.length; i++) {
            var counts = insertData(data[i], chartData, dates);
            yMax = Math.max(yMax, counts[0]);
            y2Max = Math.max(y2Max, counts[1]);
            if (data[i].completion_date === null) {
              marker = new google.maps.Marker({
                position: new google.maps.LatLng(data[i].latitude, data[i].longitude),
                map: map,
                icon: '/assets/red_MarkerA.png',
                optimized: true
              });
              makeInfoWindowEvent(map, infowindow, "Reported on: " + data[i].creation_date + "
" + "Street Address: " + data[i].street_address, marker);
              unfilled_markers.push(marker);
            } else {
              marker = new google.maps.Marker({
                position: new google.maps.LatLng(data[i].latitude, data[i].longitude),
                map: map,
                icon: '/assets/green_MarkerA.png',
                optimized: true
              });
              makeInfoWindowEvent(map, infowindow, "Reported on: " + data[i].creation_date + "
" + "Completed Date: " + data[i].completion_date + "
" + "Street Address: " + data[i].street_address, marker);
              filled_markers.push(marker);
            }
          }

          mc.addMarkers(unfilled_markers.concat(filled_markers));

          angular.element(document.getElementById('chart')).scope().$apply(function(scope) {
            scope.dates = dates.map(function(date) {
              return date.substring(5, 10);
            });
            scope.options.axes.y.max = Math.max(yMax, y2Max);
            scope.options.axes.y2.max = Math.max(yMax, y2Max);
            scope.data = chartData;
          });
        }
      },
      dataType: "json"
    });
  }

  // Remove all markers from map if you zoom out too far, put them back when zoomed back in
  // google.maps.event.addListener(map, 'zoom_changed', function(){
  //   if (map.zoom < 7) {
  //     mc.clearMarkers();
  //   } else if (map.zoom >= 7 && mc.a.length === 0) {
  //     mc.addMarkers(unfilled_markers.concat(filled_markers));
  //   }
  // });

  // Open report form when map is clicked if zoomed in far enough
  // If report form is already open, close it on next map click
  google.maps.event.addListener(map, 'click', function(event) {
    if (map.zoom > 14 && infowindow.getContent()) {
      infowindow.close();
      infowindow.setContent("");
    } else if (map.zoom > 14) {
      makeReportEvent(map, infowindow, event);
    } else {
      infowindow.close();
    }
  });

  $("#date-pick").on('submit', function(event) {
    event.preventDefault();
    getPotholesByDate($('#start-date').val(), $('#end-date').val());
  });

  $("#filled").on('click', function() {

    if ($("#filled").prop("checked")) {
      for (var i = 0; i < filled_markers.length; ++i) {
        filled_markers[i].setVisible(false);
      }
    } else {
      for (var i = 0; i < filled_markers.length; ++i) {
        filled_markers[i].setVisible(true);
      }
    }
  });

  function search(e) {
    var code = (e.keyCode ? e.keyCode : e.which);
    var target = document.getElementById('pac-input');
    if (code == 13) { //Enter keycode
      e.preventDefault();
      geocoder.geocode({
          'address': target.value
        },
        function(results, status) {
          if (status == google.maps.GeocoderStatus.OK) {
            var loc = results[0].geometry.location;
            map.setZoom(17);
            map.panTo(new google.maps.LatLng(loc.lat(), loc.lng()));
          } else {
            alert("Not found: " + status);
          }
        }
      );

    }
  };

  $("#pac-input").bind("keypress", {}, search);

});
<|endoftext|>


<commit_before>$(document).ready(function() {

  $('.post-like').show();

  $('.post-like').on('ajax:success', function(event, data) {
    var likeControl = $('#post-' + data.id + ' .post-like');

    $('#post-' + data.id + ' .like-count').text(data.description);
    if (data.liked_by_member) {
      likeControl.data('method', 'delete');
      likeControl.attr('href', data.url);
      likeControl.text('Unlike');
    } else {
      likeControl.data('method', 'post');
      likeControl.attr('href', '/likes.json?post_id=' + data.id);
      likeControl.text('Like');
    }
  });

  $('.photo-like').show();

  $('.photo-like').on('ajax:success', function(event, data) {
    var likeControl = $('.photo-like');

    $('.like-count').text(data.description);
    if (data.liked_by_member) {
      likeControl.data('method', 'delete');
      likeControl.attr('href', data.url);
      likeControl.text('Unlike');
    } else {
      likeControl.data('method', 'post');
      likeControl.attr('href', '/likes.json?photo_id=' + data.id);
      likeControl.text('Like');
    }
  });
});
<commit_msg>[CodeFactor] Apply fixes<commit_after>$(document).ready(function() {
  $('.post-like').show();

  $('.post-like').on('ajax:success', function(event, data) {
    var likeControl = $('#post-' + data.id + ' .post-like');

    $('#post-' + data.id + ' .like-count').text(data.description);
    if (data.liked_by_member) {
      likeControl.data('method', 'delete');
      likeControl.attr('href', data.url);
      likeControl.text('Unlike');
    } else {
      likeControl.data('method', 'post');
      likeControl.attr('href', '/likes.json?post_id=' + data.id);
      likeControl.text('Like');
    }
  });

  $('.photo-like').show();

  $('.photo-like').on('ajax:success', function(event, data) {
    var likeControl = $('.photo-like');

    $('.like-count').text(data.description);
    if (data.liked_by_member) {
      likeControl.data('method', 'delete');
      likeControl.attr('href', data.url);
      likeControl.text('Unlike');
    } else {
      likeControl.data('method', 'post');
      likeControl.attr('href', '/likes.json?photo_id=' + data.id);
      likeControl.text('Like');
    }
  });
});
<|endoftext|>


<commit_before>/*
*   Behavior for the slider component is located in:
*     app/assets/javascripts/components/react-slider.js
*/

var myApp = {

  Model: function() {
    var _markers = {};

    return ({

      getMarkers: function() {return _markers; },

      getMarkersByUserId: function(userId) {
        return (
          _markers[userId] ?
          _markers[userId] :
          false
        );
      },

      storeMarkerById: function(userId, marker) {
        _markers[userId] ?
        _markers[userId].push(marker) :
        _markers[userId] = [marker]
      },

      clearMarkerData: function() { _markers = {}; }

    });

  },

  View: function(model) {

    return ({
      createMarker: function(LatLng, userId){
        var map = myApp.map;
        var marker = new google.maps.Marker({
              position: LatLng,
              animation: google.maps.Animation.DROP,
              map: map
            });
        // Animating Listener:
        google.maps.event.addListener(marker, 'click', this.toggleBounce);
        // store in markers object for easy removal by batch
        model.storeMarkerById(userId, marker);
      },

      setMarkers: function(locations) {
        for (var i = 0, len = locations.length; i < len; i++) {
          var loc = locations[i],
              position = new google.maps.LatLng(loc.latitude, loc.longitude),
              marker = this.createMarker(position, loc.user_id);
        }
      },

      clearMarkers: function() {
        var markers = model.getMarkers();

        for (var userId in markers) {
          if (markers.hasOwnProperty(userId)) {
            var currentSet = markers[userId],
                len = currentSet.length;
            for (var i=0; i < len; i++) {
              currentSet[i].setMap(null);
            }
          }
        }
      },

      toggleBounce: function() {
        this.getAnimation() !== null ?
        this.setAnimation(null) :
        this.setAnimation(google.maps.Animation.BOUNCE);
      }

    });
  },

  Controller: function(model, view) {

    function _toggleBounceByUserId(userId) {
      var markersWithId = model.getMarkersByUserId(userId);
      if (markersWithId) {
        for (var i=0, len = markersWithId.length; i < len; i++) {
          view.toggleBounce.call(markersWithId[i]);
        }
      }
    }

    function _locationResponseHandler(locations) {
      for (var property in locations) {
        if (locations.hasOwnProperty(property)) {
          view.setMarkers(locations[property]);
        }
      }
    }

    function _transactionsResponseHandler(transactions) {
      var html = "";
      function formatCurrency(transactions) {
        return (transactions.map(
          function(transaction) {
            return "$" + transaction.amount;
        }));
      }
      // clear the list
      $('#results').html("");

      for (var userInfo in transactions) {
        if (transactions.hasOwnProperty(userInfo)) {
          var usersTransactions = transactions[userInfo],
              amounts = formatCurrency(usersTransactions),
              userInfoArray = JSON.parse(userInfo),
              userId = userInfoArray[0],
              userName = userInfoArray[1],
              opacityClass = _getOpacityClass(usersTransactions);

          html += (
            "
" +
              userName + " - " + amounts.join(", ") +
            "
"
          );
        }
      }
      if (html.length === 0) {
        $('#results')
          .append(
            '
' +
              'There is no transaction data of the selected type for this date' +
            '
'
          );
      } else {
        $('#no-trans-notification').remove();
        $('#results').append(html);
      }
      // BIND EVENT HANDLERS HERE
      $('.result').click(function() {
        if (model.getMarkersByUserId(this.id))
          _toggleBounceByUserId(this.id);
      });

      $('.result').on('mouseenter', function() {
        if (!(model.getMarkersByUserId(this.id)) &&
          this.id !== "no-trans-notification") {
          $('#results')
            .append(
              '
' +
                'There is no location data for this person on this date' +
              '
'
            );
        }
      });

      $('.result').on('mouseleave', function() {
        $('#no-loc-notification').remove();
      });
    }

    var _responseHandler = function(response) {
      _locationResponseHandler(response.locations);
      _transactionsResponseHandler(response.transactions);
    };

    var _getRequestFactory = function(data, url) {
      $.ajax({
        type: 'GET',
        url: url,
        data: data
      }).success(_responseHandler);
    };

    // the results returned at any time aren't huge, so this is okay
    var _getOpacityClass = function(group) {
      var total = 0;
      for (var i=0, len = group.length; i<len; i++) {
        total += parseFloat(group[i].amount);
      }
      if (total < 50) {
        return "light";
      } else if (total < 100) {
        return "medium-light";
      } else if (total < 150) {
        return "medium";
      } else if (total < 150) {
        return "medium-dark";
      } else if (total >= 150) {
        return "dark";
      }
    };

    var _makeRequest = function() {
      var filter = model.filter,
          date = $('#date').html();

      view.clearMarkers();
      model.clearMarkerData();

      if (filter !== "all") {
        _getRequestFactory({date: date, filter: filter}, '/results');
      } else if (filter === "all") {
        _getRequestFactory({}, '/all');
      }
    };

    return ({
      request: _makeRequest,

      setFilter: function(event) {
        event.preventDefault();

        // From UX perspective,
        // makes sense to clear current markers when changing filter
        view.clearMarkers();
        model.clearMarkerData();

        var filter = this.innerHTML.toLowerCase();

        model.filter = filter;
        if (filter === "all")
          _makeRequest();
      }
    });
  }

};

<commit_msg>Create _informNoLocationData and _informNoTransactionData to slim down _transactionResponseHandler<commit_after>/*
*   Behavior for the slider component is located in:
*     app/assets/javascripts/components/react-slider.js
*/

var myApp = {

  Model: function() {
    var _markers = {};

    return ({

      getMarkers: function() {return _markers; },

      getMarkersByUserId: function(userId) {
        return (
          _markers[userId] ?
          _markers[userId] :
          false
        );
      },

      storeMarkerById: function(userId, marker) {
        _markers[userId] ?
        _markers[userId].push(marker) :
        _markers[userId] = [marker]
      },

      clearMarkerData: function() { _markers = {}; }

    });

  },

  View: function(model) {

    return ({
      createMarker: function(LatLng, userId){
        var map = myApp.map;
        var marker = new google.maps.Marker({
              position: LatLng,
              animation: google.maps.Animation.DROP,
              map: map
            });
        // Animating Listener:
        google.maps.event.addListener(marker, 'click', this.toggleBounce);
        // store in markers object for easy removal by batch
        model.storeMarkerById(userId, marker);
      },

      setMarkers: function(locations) {
        for (var i = 0, len = locations.length; i < len; i++) {
          var loc = locations[i],
              position = new google.maps.LatLng(loc.latitude, loc.longitude),
              marker = this.createMarker(position, loc.user_id);
        }
      },

      clearMarkers: function() {
        var markers = model.getMarkers();

        for (var userId in markers) {
          if (markers.hasOwnProperty(userId)) {
            var currentSet = markers[userId],
                len = currentSet.length;
            for (var i=0; i < len; i++) {
              currentSet[i].setMap(null);
            }
          }
        }
      },

      toggleBounce: function() {
        this.getAnimation() !== null ?
        this.setAnimation(null) :
        this.setAnimation(google.maps.Animation.BOUNCE);
      }

    });
  },

  Controller: function(model, view) {

    function _toggleBounceByUserId(userId) {
      var markersWithId = model.getMarkersByUserId(userId);
      if (markersWithId) {
        for (var i=0, len = markersWithId.length; i < len; i++) {
          view.toggleBounce.call(markersWithId[i]);
        }
      }
    }

    function _locationResponseHandler(locations) {
      for (var property in locations) {
        if (locations.hasOwnProperty(property)) {
          view.setMarkers(locations[property]);
        }
      }
    }

    function _informNoTransactionData() {
      $('#results')
          .append(
            '
' +
              'There is no transaction data of the selected type for this date' +
            '
'
          );
    }

    function _informNoLocationData() {
      $('#results')
            .append(
              '
' +
                'There is no location data for this person on this date' +
              '
'
            );
    }

    function _transactionsResponseHandler(transactions) {
      var html = "";
      function formatCurrency(transactions) {
        return (transactions.map(
          function(transaction) {
            return "$" + transaction.amount;
        }));
      }
      // clear the list
      $('#results').html("");

      for (var userInfo in transactions) {
        if (transactions.hasOwnProperty(userInfo)) {
          var usersTransactions = transactions[userInfo],
              amounts = formatCurrency(usersTransactions),
              userInfoArray = JSON.parse(userInfo),
              userId = userInfoArray[0],
              userName = userInfoArray[1],
              opacityClass = _getOpacityClass(usersTransactions);

          html += (
            "
" +
              userName + " - " + amounts.join(", ") +
            "
"
          );
        }
      }
      if (html.length === 0) {
        _informNoTransactionData();
      } else {
        $('#no-trans-notification').remove();
        $('#results').append(html);
      }
      // BIND EVENT HANDLERS HERE
      $('.result').click(function() {
        if (model.getMarkersByUserId(this.id))
          _toggleBounceByUserId(this.id);
      });

      $('.result').on('mouseenter', function() {
        if (!(model.getMarkersByUserId(this.id)) &&
          (this.id !== "no-trans-notification"))
          _informNoLocationData();
      });

      $('.result').on('mouseleave', function() {
        $('#no-loc-notification').remove();
      });
    }

    var _responseHandler = function(response) {
      _locationResponseHandler(response.locations);
      _transactionsResponseHandler(response.transactions);
    };

    var _getRequestFactory = function(data, url) {
      $.ajax({
        type: 'GET',
        url: url,
        data: data
      }).success(_responseHandler);
    };

    // the results returned at any time aren't huge, so this is okay
    var _getOpacityClass = function(group) {
      var total = 0;
      for (var i=0, len = group.length; i<len; i++) {
        total += parseFloat(group[i].amount);
      }
      if (total < 50) {
        return "light";
      } else if (total < 100) {
        return "medium-light";
      } else if (total < 150) {
        return "medium";
      } else if (total < 150) {
        return "medium-dark";
      } else if (total >= 150) {
        return "dark";
      }
    };

    var _makeRequest = function() {
      var filter = model.filter,
          date = $('#date').html();

      view.clearMarkers();
      model.clearMarkerData();

      if (filter !== "all") {
        _getRequestFactory({date: date, filter: filter}, '/results');
      } else if (filter === "all") {
        _getRequestFactory({}, '/all');
      }
    };

    return ({
      request: _makeRequest,

      setFilter: function(event) {
        event.preventDefault();

        // From UX perspective,
        // makes sense to clear current markers when changing filter
        view.clearMarkers();
        model.clearMarkerData();

        var filter = this.innerHTML.toLowerCase();

        model.filter = filter;
        if (filter === "all")
          _makeRequest();
      }
    });
  }

};

<|endoftext|>


<commit_before>function nextPost() {
  $(".js-next").on("click", function(event) {
    event.preventDefault();
    var nextId = parseInt($(".js-next").attr("data-id")) + 1;
    $.get("/posts/" + nextId + ".json", function(post) {
      renderPost(post);
      renderComments(post.comments);
    }).fail(function() {
      $('#flash').append("
Sorry, there are more posts on the way!
");
    });
  });
}

function renderComments(comments) {
  $('.comments').empty()
  $.each(comments, function(index, comment){
    if (comment.user != null) {
      $('.comments').append(
        "
" + comment['user'].first_name + " " + comment['user'].last_name + " says:
",
        "
" + comment.content + "
"
      );
    }
  });
}

function renderPost(post) {
  $(".postTitle").text(post.title);
  $(".postContent").text(post.content);
  // re-set the id to current on the link
  $(".js-next").attr("data-id", post.id);
}
<commit_msg>remove unnecessary validation check in js comments method<commit_after>function nextPost() {
  $(".js-next").on("click", function(event) {
    event.preventDefault();
    var nextId = parseInt($(".js-next").attr("data-id")) + 1;
    $.get("/posts/" + nextId + ".json", function(post) {
      renderPost(post);
      renderComments(post.comments);
    }).fail(function() {
      $('#flash').append("
Sorry, there are more posts on the way!
");
    });
  });
}

function renderComments(comments) {
  $('.comments').empty()
  $.each(comments, function(index, comment){
    $('.comments').append(
      "
" + comment['user'].first_name + " " + comment['user'].last_name + " says:
",
      "
" + comment.content + "
"
    );
  });
}

function renderPost(post) {
  $(".postTitle").text(post.title);
  $(".postContent").text(post.content);
  // re-set the id to current on the link
  $(".js-next").attr("data-id", post.id);
}
<|endoftext|>


<commit_before>var PT = PT || {};

PT.renderCartoDBMap = function(containerId){
  var url, mapOptions;
  url = "http://cfcm.cartodb.com/api/v2/viz/21e86fd4-5887-11e4-b28c-0e018d66dc29/viz.json";
  mapOptions = {
    zoom: 15,
    center_lat: -19.9540425000,
    center_lon: -43.9385429000,
    scrollwheel: false,
    zoomControl: false,
    shareable: false,
    searchControl: false
  };

  $.getScript("http://libs.cartocdn.com/cartodb.js/v3/cartodb.js", function(){
    cartodb.createVis('map-viz', url, mapOptions)
    .done(function(){
      $(".cartodb-searchbox").hide();
    });
  });
};

PT.populateImages = function(responses, containerId){
  var $container = $(containerId), images, image;
  var images = [];
  responses.forEach(function(response){
    response.answers.forEach(function(answer){

      if(answer.input_type == "image" && answer.value){
        images.push(answer.value);
      }
    })
  });

  $container.empty();
  images.forEach(function(url){
    image = '';
    $container.append(image);
  })
};

PT.renderGoogleMap = function(serverResponse){
  var markers = [];
  var surveyDefinition = {};
  var map = null,
      infoWindow = null;

  var attachMarkerClickEvent = function(marker, response){
    var image = null;
    var displayableAnswers = {};
    // 1. browse through answers, put all images to $image and displayable answers to $displayableAnswers.
    for(var i=0,len=response.answers.length;i<len;i++){
      var answer = response.answers[i];
      switch(answer.input_type){
        case 'location':
          break;
        case 'image':
          if(typeof answer.value!=='undefined' && answer.value){
            image = answer.value;
          }
          break;
        default:
          if(typeof answer.value!=='undefined' && answer.value){
            displayableAnswers[surveyDefinition[answer.id]] = answer.value;
          }
      }
    }
    // 2. construct infoWindow string
    var infoWindowImageHtml='';
    if(image !== null){
      infoWindowImageHtml =
      '
'+
        ''+
      '
';
    }
    var infoWindowTableHtml = '';
    if(Object.keys(displayableAnswers).length > 0){
      infoWindowTableHtml = '

';
      for(var i in displayableAnswers){
        infoWindowTableHtml += '
'+i+'

'+displayableAnswers[i]+'
';
      }
      infoWindowTableHtml += '

';
    }
    var infoWindowContentHtml =
      '
'+
        infoWindowImageHtml+
        infoWindowTableHtml+
      '
';

    google.maps.event.addListener(marker, 'click', function(){
      infoWindow.setContent(infoWindowContentHtml);
      infoWindow.open(map, marker);
    });
  };  // func attachMarkerClickEvent

  window.mapInit = function(){
    // start initialization
    // create map
    var mapOptions = {
      zoom: 8,
      center: new google.maps.LatLng(-34.397, 150.644),
      scrollwheel: false
    };
    map = new google.maps.Map(document.getElementById('map-viz'), mapOptions);
    infoWindow = new google.maps.InfoWindow({
        content: ''
    });

    // store survey definition
    var surveyInputs = serverResponse.survey.inputs;
    for(var i=0,len=surveyInputs.length;i<len;i++){
      var input = surveyInputs[i];
      surveyDefinition[input.id] = input.label;
    }

    // create map markers
    var surveyResponses = serverResponse.responses;
    for(var i=0,len=surveyResponses.length;i<len;i++){
      var response = surveyResponses[i];

      // 1 find geo location
      var lat = null,
          lon = null;
      for(var j=0,len2=response.answers.length;j<len2;j++){
        var answer = response.answers[j];
        if(typeof answer.input_type!=='undefined' && answer.input_type=='location' && typeof answer.value!=='undefined' && typeof answer.value.lon!=='undefined'){
          lat = answer.value.lat;
          lon = answer.value.lon;
          break;
        }
      }
      if(lat==null || lon==null){
        if(response.locationstamp && response.locationstamp.lat !== 'undefined' && response.locationstamp.long !== 'undefined'){
          lat = response.locationstamp.lat;
          lon = response.locationstamp.lon;
        } else {
          continue; // find if next response is a geolocation
        }
      }

      // 2. create that marker;
      if(lat && lon){
        var marker = new google.maps.Marker({
          map: map,
          position: new google.maps.LatLng(lat, lon)
        });
        markers.push(marker);

        // 3. attach onclick event
        attachMarkerClickEvent(marker, response);
      }
    } // for surveyResponses - created map markers

    // scale map viewport to include all the markers.
    var points = $.map(markers, function(a){
        return a.getPosition();
    });
    var bounds = new google.maps.LatLngBounds();
    for(var i=0;i<points.length;i++){
        bounds.extend(points[i]);
    }

    map.fitBounds(bounds);

  };  // func mapInit

  // load map script

  if(typeof google === 'undefined'){
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp&' +
        'callback=mapInit';
    document.body.appendChild(script);
  } else {
    window.mapInit();
  }
};

$(function(){
  dispatcher.subscribe('sharedataloaded', function(data){
    PT.populateImages(PT.responses, "#image-viz");
    PT.renderGoogleMap(data);
  })
});
<commit_msg>Add response mongo id to map info window html on share<commit_after>var PT = PT || {};

PT.renderCartoDBMap = function(containerId){
  var url, mapOptions;
  url = "http://cfcm.cartodb.com/api/v2/viz/21e86fd4-5887-11e4-b28c-0e018d66dc29/viz.json";
  mapOptions = {
    zoom: 15,
    center_lat: -19.9540425000,
    center_lon: -43.9385429000,
    scrollwheel: false,
    zoomControl: false,
    shareable: false,
    searchControl: false
  };

  $.getScript("http://libs.cartocdn.com/cartodb.js/v3/cartodb.js", function(){
    cartodb.createVis('map-viz', url, mapOptions)
    .done(function(){
      $(".cartodb-searchbox").hide();
    });
  });
};

PT.populateImages = function(responses, containerId){
  var $container = $(containerId), images, image;
  var images = [];
  responses.forEach(function(response){
    response.answers.forEach(function(answer){

      if(answer.input_type == "image" && answer.value){
        images.push(answer.value);
      }
    })
  });

  $container.empty();
  images.forEach(function(url){
    image = '';
    $container.append(image);
  })
};

PT.renderGoogleMap = function(serverResponse){
  var markers = [];
  var surveyDefinition = {};
  var map = null,
      infoWindow = null;

  var attachMarkerClickEvent = function(marker, response){
    var image = null;
    var displayableAnswers = {};
    // 1. browse through answers, put all images to $image and displayable answers to $displayableAnswers.
    for(var i=0,len=response.answers.length;i<len;i++){
      var answer = response.answers[i];
      switch(answer.input_type){
        case 'location':
          break;
        case 'image':
          if(typeof answer.value!=='undefined' && answer.value){
            image = answer.value;
          }
          break;
        default:
          if(typeof answer.value!=='undefined' && answer.value){
            displayableAnswers[surveyDefinition[answer.id]] = answer.value;
          }
      }
    }
    // 2. construct infoWindow string
    var infoWindowImageHtml='';
    if(image !== null){
      infoWindowImageHtml =
      '
'+
        ''+
      '
';
    }
    var infoWindowTableHtml = '';
    if(Object.keys(displayableAnswers).length > 0){
      infoWindowTableHtml = '

';
      for(var i in displayableAnswers){
        infoWindowTableHtml += '
'+i+'

'+displayableAnswers[i]+'
';
      }
      infoWindowTableHtml += '

';
    }
    var infoWindowContentHtml =
      '
'+
        infoWindowImageHtml+
        infoWindowTableHtml+
      '
';

    google.maps.event.addListener(marker, 'click', function(){
      infoWindow.setContent(infoWindowContentHtml);
      infoWindow.open(map, marker);
    });
  };  // func attachMarkerClickEvent

  window.mapInit = function(){
    // start initialization
    // create map
    var mapOptions = {
      zoom: 8,
      center: new google.maps.LatLng(-34.397, 150.644),
      scrollwheel: false
    };
    map = new google.maps.Map(document.getElementById('map-viz'), mapOptions);
    infoWindow = new google.maps.InfoWindow({
        content: ''
    });

    // store survey definition
    var surveyInputs = serverResponse.survey.inputs;
    for(var i=0,len=surveyInputs.length;i<len;i++){
      var input = surveyInputs[i];
      surveyDefinition[input.id] = input.label;
    }

    // create map markers
    var surveyResponses = serverResponse.responses;
    for(var i=0,len=surveyResponses.length;i<len;i++){
      var response = surveyResponses[i];

      // 1 find geo location
      var lat = null,
          lon = null;
      for(var j=0,len2=response.answers.length;j<len2;j++){
        var answer = response.answers[j];
        if(typeof answer.input_type!=='undefined' && answer.input_type=='location' && typeof answer.value!=='undefined' && typeof answer.value.lon!=='undefined'){
          lat = answer.value.lat;
          lon = answer.value.lon;
          break;
        }
      }
      if(lat==null || lon==null){
        if(response.locationstamp && response.locationstamp.lat !== 'undefined' && response.locationstamp.long !== 'undefined'){
          lat = response.locationstamp.lat;
          lon = response.locationstamp.lon;
        } else {
          continue; // find if next response is a geolocation
        }
      }

      // 2. create that marker;
      if(lat && lon){
        var marker = new google.maps.Marker({
          map: map,
          position: new google.maps.LatLng(lat, lon)
        });
        markers.push(marker);

        // 3. attach onclick event
        attachMarkerClickEvent(marker, response);
      }
    } // for surveyResponses - created map markers

    // scale map viewport to include all the markers.
    var points = $.map(markers, function(a){
        return a.getPosition();
    });
    var bounds = new google.maps.LatLngBounds();
    for(var i=0;i<points.length;i++){
        bounds.extend(points[i]);
    }

    map.fitBounds(bounds);

  };  // func mapInit

  // load map script

  if(typeof google === 'undefined'){
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp&' +
        'callback=mapInit';
    document.body.appendChild(script);
  } else {
    window.mapInit();
  }
};

$(function(){
  dispatcher.subscribe('sharedataloaded', function(data){
    PT.populateImages(PT.responses, "#image-viz");
    PT.renderGoogleMap(data);
  })
});
<|endoftext|>