<commit_before>var fs = require('fs');
var Shader = {
    compileVertShader: function(text) {
        var stat;
        var vertShader = this.GL.glCreateShader(this.GL.GL_VERTEX_SHADER);
        this.GL.glShaderSource(vertShader, 1, text, null);
        this.GL.glCompileShader(vertShader);
        var stat = this.GL.glGetShaderiv(vertShader, this.GL.GL_COMPILE_STATUS);
        if (!stat) {
            console.log("Error: vertex shader did not compile!\n");
            process.exit(1);
        }
        return vertShader;
    },
    compileFragShader:function(text) {
        var stat;
        var vertShader = this.GL.glCreateShader(this.GL.GL_FRAGMENT_SHADER);
        this.GL.glShaderSource(vertShader, 1, text, null);
        this.GL.glCompileShader(vertShader);
        var stat = this.GL.glGetShaderiv(vertShader, this.GL.GL_COMPILE_STATUS);
        if (!stat) {
            console.log("Error: fragment shader did not compile!\n");
            process.exit(1);
        }
        return vertShader;
    },
    compileProgram:function(shader) {
        var program = this.GL.glCreateProgram();
        if(!shader.frag) throw Error("missing shader.frag");
        if(!shader.vert) throw Error("missing shader.vert");
        this.GL.glAttachShader(program, shader.vert);
        this.GL.glAttachShader(program, shader.frag);
        this.GL.glLinkProgram(program);
        var stat = this.GL.glGetProgramiv(program, this.GL.GL_LINK_STATUS);
        if (!stat) {
            var log = this.GL.glGetProgramInfoLog(program, 1000);//, &len, log);
            console.log("error linking ",log);
            process.exit(1);
        }
        return program;
    },

    build: function() {
        this.vert = this.compileVertShader(this.vertText);
        this.frag = this.compileFragShader(this.fragText);
        this.prog = this.compileProgram(this);
    },

    useProgram: function() {
        this.GL.glUseProgram(this.prog);
    },
    attribs:{},
    uniforms:{},

    locateAttrib: function(name) {
        this.attribs[name] = this.GL.glGetAttribLocation(this.prog, name);
        if(this.attribs[name] == -1) {
            console.log("WARNING. got -1 for location of ", name);
        }
    },

    locateUniform: function(name) {
        this.uniforms[name] = this.GL.glGetUniformLocation(this.prog, name);
        if(this.uniforms[name] == -1) {
            console.log("WARNING. got -1 for location of ", name);
        }
    }

}

function loadShaderCode(path, OS) {
    var src = fs.readFileSync(path).toString();
    if(OS == "RPI" ) {
        src = "#version 100\n" + src;
    }
    return src;
}

exports.init = function(sgtest, OS) {
    var cshader = Object.create(Shader);
    cshader.GL = sgtest;
    console.log("__dirname = ", __dirname);
    cshader.vertText = loadShaderCode(__dirname+"/shaders/color.vert",OS);
    cshader.fragText = loadShaderCode(__dirname+"/shaders/color.frag",OS);
    cshader.build();
    cshader.useProgram();
    cshader.locateAttrib('pos');
    cshader.locateUniform('modelviewProjection');
    cshader.locateUniform('trans');
    cshader.locateUniform('opacity');
    cshader.locateAttrib('color');
    sgtest.initColorShader(cshader.prog,
        cshader.uniforms.modelviewProjection,
        cshader.uniforms.trans,
        cshader.uniforms.opacity,
        cshader.attribs.pos,
        cshader.attribs.color);

    var tshader = Object.create(Shader);
    tshader.GL = sgtest;
    tshader.vertText = loadShaderCode(__dirname+"/shaders/texture.vert");
    tshader.fragText = loadShaderCode(__dirname+"/shaders/texture.frag");
    tshader.build();
    tshader.useProgram();
    tshader.locateUniform('modelviewProjection');
    tshader.locateUniform('trans');
    tshader.locateUniform('opacity');
    tshader.locateAttrib('pos');
    tshader.locateAttrib('texcoords');
    tshader.locateAttrib('tex');

    sgtest.initTextureShader(tshader.prog,
        tshader.uniforms.modelviewProjection,
        tshader.uniforms.trans,
        tshader.uniforms.opacity,
        tshader.attribs.pos,
        tshader.attribs.texcoords,
        tshader.attribs.tex);
}
<commit_msg>documented shader functions<commit_after>'use strict';

/*
 * Shader Tools
 */

var DEBUG = false;

var fs = require('fs');

var Shader = {
    /**
     * Compile and create a vertex shader.
     */
    compileVertShader: function (text) {
        var GL = this.GL;
        var vertShader = GL.glCreateShader(GL.GL_VERTEX_SHADER);

        GL.glShaderSource(vertShader, 1, text, null);
        GL.glCompileShader(vertShader);

        var stat = GL.glGetShaderiv(vertShader, GL.GL_COMPILE_STATUS);

        if (!stat) {
            //exit
            console.log('Error: vertex shader did not compile!\n');
            process.exit(1);
        }

        return vertShader;
    },
    /**
     * Compile and create a fragment shader.
     */
    compileFragShader: function (text) {
        var GL = this.GL;
        var fragShader = GL.glCreateShader(GL.GL_FRAGMENT_SHADER);

        GL.glShaderSource(fragShader, 1, text, null);
        GL.glCompileShader(fragShader);

        var stat = GL.glGetShaderiv(fragShader, GL.GL_COMPILE_STATUS);

        if (!stat) {
            //exit
            console.log('Error: fragment shader did not compile!\n');
            process.exit(1);
        }

        return fragShader;
    },
    /**
     * Compile and create shader program.
     */
    compileProgram: function (shader) {
        var GL = this.GL;
        var program = GL.glCreateProgram();

        //verify params
        if (!shader.frag) {
            throw Error('missing shader.frag');
        }

        if (!shader.vert) {
            throw Error('missing shader.vert');
        }

        GL.glAttachShader(program, shader.vert);
        GL.glAttachShader(program, shader.frag);
        GL.glLinkProgram(program);

        var stat = this.GL.glGetProgramiv(program, this.GL.GL_LINK_STATUS);

        if (!stat) {
            //exit
            var log = this.GL.glGetProgramInfoLog(program, 1000); //, &len, log);

            console.log('error linking ', log);
            process.exit(1);
        }
        return program;
    },

    /**
     * Build shader program.
     */
    build: function () {
        this.vert = this.compileVertShader(this.vertText);
        this.frag = this.compileFragShader(this.fragText);
        this.prog = this.compileProgram(this);
    },

    /**
     * Activate shader program.
     */
    useProgram: function() {
        this.GL.glUseProgram(this.prog);
    },
    attribs:{},
    uniforms:{},

    locateAttrib: function (name) {
        this.attribs[name] = this.GL.glGetAttribLocation(this.prog, name);

        if (this.attribs[name] == -1) {
            console.log('WARNING. got -1 for location of ', name);
        }
    },

    locateUniform: function (name) {
        this.uniforms[name] = this.GL.glGetUniformLocation(this.prog, name);

        if (this.uniforms[name] == -1) {
            console.log('WARNING. got -1 for location of ', name);
        }
    }

}

/**
 * Load shader code from file system.
 */
function loadShaderCode(path, OS) {
    var src = fs.readFileSync(path).toString();

    if (OS == 'RPI') {
        //Raspberry Pi need version number in shader
        src = '#version 100\n' + src;
    }

    return src;
}

/**
 * Initialize the basic aminogfx shaders.
 */
exports.init = function (sgtest, OS) {
    var cshader = Object.create(Shader);

    cshader.GL = sgtest;

    if (DEBUG) {
        console.log('__dirname = ', __dirname);
    }

    //color shader
    cshader.vertText = loadShaderCode(__dirname + '/shaders/color.vert', OS);
    cshader.fragText = loadShaderCode(__dirname + '/shaders/color.frag', OS);
    cshader.build();

    cshader.useProgram();
    cshader.locateAttrib('pos');
    cshader.locateUniform('modelviewProjection');
    cshader.locateUniform('trans');
    cshader.locateUniform('opacity');
    cshader.locateAttrib('color');

    sgtest.initColorShader(cshader.prog,
        cshader.uniforms.modelviewProjection,
        cshader.uniforms.trans,
        cshader.uniforms.opacity,
        cshader.attribs.pos,
        cshader.attribs.color);

    //texture shader
    var tshader = Object.create(Shader);

    tshader.GL = sgtest;
    tshader.vertText = loadShaderCode(__dirname + '/shaders/texture.vert');
    tshader.fragText = loadShaderCode(__dirname + '/shaders/texture.frag');
    tshader.build();

    tshader.useProgram();

    tshader.locateUniform('modelviewProjection');
    tshader.locateUniform('trans');
    tshader.locateUniform('opacity');
    tshader.locateAttrib('pos');
    tshader.locateAttrib('texcoords');
    tshader.locateAttrib('tex');

    sgtest.initTextureShader(tshader.prog,
        tshader.uniforms.modelviewProjection,
        tshader.uniforms.trans,
        tshader.uniforms.opacity,
        tshader.attribs.pos,
        tshader.attribs.texcoords,
        tshader.attribs.tex);
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

// Note: this file does not exist after ejecting.

const fs = require('fs');
const paths = require('../config/paths');

module.exports = (resolve, rootDir, isEjecting) => {
  // Use this instead of `paths.testsSetup` to avoid putting
  // an absolute filename into configuration after ejecting.
  const setupTestsFile = fs.existsSync(paths.testsSetup) ? '<rootDir>/src/setupTests.js' : undefined;

  // TODO: I don't know if it's safe or not to just use / as path separator
  // in Jest configs. We need help from somebody with Windows to determine this.
  const config = {
    collectCoverageFrom: ['src/**/*.{js,jsx}'],
    setupFiles: [resolve('config/polyfills.js')],
    setupTestFrameworkScriptFile: setupTestsFile,
    testPathIgnorePatterns: [
      '<rootDir>[/\\\\](build|docs|node_modules|scripts)[/\\\\]'
    ],
    testEnvironment: 'node',
    testURL: 'http://localhost',
    transform: {
      '^.+\\.(js|jsx)$': isEjecting ?
        process.env.NODE_PATH ? `${process.env.NODE_PATH}/babel-jest` : '<rootDir>/node_modules/babel-jest'
        : resolve('config/jest/babelTransform.js'),
      '^.+\\.css$': resolve(paths.scriptVersionDir+'/config/jest/cssTransform.js'),
      '^(?!.*\\.(js|jsx|css|json)$)': resolve(paths.scriptVersionDir+'/config/jest/fileTransform.js'),
    },
    transformIgnorePatterns: [
      '[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$'
    ],
    moduleNameMapper: {
      '^react-native$': 'react-native-web'
    }
  };
  if (rootDir) {
    config.rootDir = rootDir;
  }
  return config;
};
<commit_msg>Removed unused older configuration<commit_after><|endoftext|>


<commit_before>
var integration = require('../integration')
  , load = require('load-script');

/**
 * Expose `Sentry` integration.
 *
 * http://raven-js.readthedocs.org/en/latest/config/index.html
 */

var Sentry = module.exports = integration('Sentry');

/**
 * Required key.
 */

Sentry.prototype.key = 'config';

/**
 * Default options.
 */

Sentry.prototype.defaults = {
  // your sentry config url (required)
  config: ''
};

/**
 * Initialize.
 *
 * @param {Object} options
 * @param {Function} ready
 */

Sentry.prototype.initialize = function (options, ready) {
  load('//d3nslu0hdya83q.cloudfront.net/dist/1.0/raven.min.js', function () {
    // for now, raven basically requires `install` to be called
    // https://github.com/getsentry/raven-js/blob/master/src/raven.js#L113
    window.Raven.config(options.config).install();
    ready();
  });
};

/**
 * Identify.
 *
 * @param {String} id (optional)
 * @param {Object} traits (optional)
 * @param {Object} options (optional)
 */

Sentry.prototype.identify = function (id, traits, options) {
  if (id) traits.id = id;
  window.Raven.setUser(traits);
};
<commit_msg>sentry: convert to page<commit_after>
var integration = require('../integration');
var load = require('load-script');

/**
 * Expose `Sentry`.
 */

var Sentry = module.exports = integration('Sentry')
  .option('config', '');

/**
 * Initialize.
 *
 * http://raven-js.readthedocs.org/en/latest/config/index.html
 */

Sentry.prototype.initialize = function () {
  var self = this;
  var config = this.options.config;
  this.load(function () {
    // for now, raven basically requires `install` to be called
    // https://github.com/getsentry/raven-js/blob/master/src/raven.js#L113
    window.Raven.config(config).install();
    self.ready();
  });
};

/**
 * Load.
 *
 * @param {Function} callback
 */

Sentry.prototype.load = function (callback) {
  load('//d3nslu0hdya83q.cloudfront.net/dist/1.0/raven.min.js', callback);
};

/**
 * Identify.
 *
 * @param {String} id (optional)
 * @param {Object} traits (optional)
 * @param {Object} options (optional)
 */

Sentry.prototype.identify = function (id, traits, options) {
  if (id) traits.id = id;
  window.Raven.setUser(traits);
};
<|endoftext|>


<commit_before>var util = require('../util/util');
var url = require('url');
var net = require('net');
var dns = require('dns');
var extend = require('util')._extend;

var rules = [];
var hosts = [];

function parse(_hosts) {
	rules = [];
	hosts = [];
	if (_hosts) {
		_hosts.trim().split(/\r\n|\n|\r/g).forEach(parseHost);
	}
}

function parseHost(host) {
	host = host.replace(/#.*$/, '').trim().split(/\s+/);
	var pattern = host[0] && host[0].trim();
	var matcher = host[1] && host[1].trim();

	if (!pattern || !matcher) {
		return;
	}

	if (net.isIP(pattern) || util.isRegExp(matcher) || (util.hasProtocol(pattern) && !/^https?:\/\//.test(pattern))) {
		var tmp = pattern;
		pattern = matcher;
		matcher = tmp;
	}

	var isIP = net.isIP(matcher);
	var isRegExp = util.isRegExp(pattern);
	var protocol;
	if (!isRegExp) {
		protocol = util.getProtocol(pattern);

		if (!isIP) {
			if (pattern.indexOf('/', protocol == null ? 0 : pattern.indexOf('://') + 3) == -1) {
				pattern += '/';
			}
		} else if (!(pattern = util.getHost(pattern))) {
			return;
		}
	} else if (!(pattern = util.toRegExp(pattern))) {
		return;
	}

	(isIP ? hosts : rules).push({
		isRegExp: isRegExp,
		protocol: protocol,
		pattern: pattern,
		matcher: matcher
	});
}

exports.parse = parse;

function resolve(_url, callback) {
	var rule = {};
	var matchedUrl = resolveRule(_url, rule);
	var error, done;
	var matcher = matchedUrl || _url;
	var options = url.parse(matcher);
	var hosts = options.hosts = [];
	options.url = matcher;
	options.rule = rule;
	options.hasMatcher = !!matchedUrl;

	if (matchedUrl) {
		resolveHost(matchedUrl, function(err, ip) {
			hosts[1] = ip;
			error = err;
			execCallback();
		});

		hosts[0] = null;
		execCallback();
	} else {
		resolveHost(_url, function(err, ip) {
			hosts[0] = ip;
			if (!matchedUrl) {
				hosts[1] = ip;
				error = err;
			}
			execCallback();
		});
	}

	function execCallback() {
		if (!done && (error || (typeof hosts[0] != 'undefined' && typeof hosts[1] != 'undefined'))) {
			done = true;
			hosts[1] = hosts[1] || hosts[0];
			hosts[0] = hosts[0] || hosts[1];
			callback(error, options);
		}
	}
}

exports.resolve = resolve;

function resolveHost(_url, callback) {
	var options = _url ? url.parse(util.setProtocol(_url)) : {};
	var protocol = options.protocol;
	if (!util.isWebProtocol(protocol)) {
		callback(null, null);
		return;
	}
	var hostname = options.hostname;
	for (var i = 0, host; host = hosts[i]; i++) {
		if (host.isRegExp ? host.pattern.test(_url) : (hostname == host.pattern && (!host.protocol || host.protocol == protocol))) {
			callback(null, host.matcher);
			return;
		}
	}

	try {
		dns.lookup(hostname, function(err, ip, addressType) {
		      callback(err, err ? null : (ip || (!addressType || addressType === 4 ? '127.0.0.1' : '0:0:0:0:0:0:0:1')));
		  });
	} catch(err) {//如果断网，可能直接抛异常，https代理没有用到error-handler
		callback(err);
	}
}

exports.resolveHost = resolveHost;

function resolveRule(url, data) {
	data = data || {};
	var _url = url.replace(/(?:\?|#).*$/, '');
	for (var i = 0, rule; rule = rules[i]; i++) {
		var pattern = rule.pattern;
		if (rule.isRegExp) {
			if (pattern.test(url)) {
				var regExp = {};
				for (var i = 0; i < 10; i++) {
					regExp['$' + i] = RegExp['$' + i] || '';
				}
				extend(data, rule);
				return rule.matcher.replace(/(^|.)?(\$[1-9])/g,
						function(matched, $1, $2) {
					return $1 == '\\' ? $2 : ($1 || '') + regExp[$2];
				});
			}
		} else {
			pattern = setProtocol(pattern, url);
			if (_url.indexOf(pattern) === 0) {
				var len = pattern.length;
				if (pattern == _url || isPathSeparator(_url[len]) || isPathSeparator(pattern[len - 1])) {
					extend(data, rule);
					return join(setProtocol(rule.matcher, url), url.substring(len));
				}
			}
		}
	}
}

function setProtocol(target, source) {
	if (util.hasProtocol(target)) {
		return target;
	}

	var protocol = util.getProtocol(source);
	if (protocol == null) {
		return target;
	}

	return protocol + '//' + target;
}

exports.resolveRule = resolveRule;

function isPathSeparator(ch) {
	return ch == '/' || ch == '\\';
}

function join(first, last) {
	if (!first || !last) {
		return first + last;
	}

	var len = first.length - 1;
	if (isPathSeparator(first[len])) {
		return isPathSeparator(last[0]) ? first.substring(0, len) + last : first + last;
	}

	return isPathSeparator(last[0]) ? first + last : first + '/' + last;
}

<commit_msg>add filter<commit_after>var util = require('../util/util');
var url = require('url');
var net = require('net');
var dns = require('dns');
var extend = require('util')._extend;

var rules = [];
var hosts = [];
var filters = [];

function parse(text) {
	rules = [];
	hosts = [];
	filters = [];
	if (!text || !(text = text.trim())) {
		return;
	}

	text.split(/\n|\r\n|\r/g).forEach(parseHost);
}

function parseHost(line) {
	line = line.replace(/#.*$/, '').trim().split(/\s+/);
	var pattern = line[0] && line[0].trim();
	var matcher = line[1] && line[1].trim();

	if (!pattern || !matcher) {
		return;
	}

	if (net.isIP(pattern) || util.isRegExp(matcher) || (util.hasProtocol(pattern) && !/^https?:\/\//.test(pattern))) {
		var tmp = pattern;
		pattern = matcher;
		matcher = tmp;
	}

	var isIP = net.isIP(matcher);
	var isRegExp = util.isRegExp(pattern);
	var protocol;
	if (!isRegExp) {
		protocol = util.getProtocol(pattern);

		if (!isIP) {
			if (pattern.indexOf('/', protocol == null ? 0 : pattern.indexOf('://') + 3) == -1) {
				pattern += '/';
			}
		} else if (!(pattern = util.getHost(pattern))) {
			return;
		}
	} else if (!(pattern = util.toRegExp(pattern))) {
		return;
	}

	line = {
			isRegExp: isRegExp,
			protocol: protocol,
			pattern: pattern,
			matcher: matcher
		};

	if (isIP) {
		hosts.push(line);
	} else if (/^filter:\/\//.test(matcher)) {
		filters.push(line);
	} else {
		rules.push(line);
	}
}

exports.parse = parse;

function resolve(_url, callback) {
	var rule = {};
	var matchedUrl = resolveRule(_url, rule);
	var error, done;
	var matcher = matchedUrl || _url;
	var options = url.parse(matcher);
	var hosts = options.hosts = [];
	options.url = matcher;
	options.rule = rule;
	options.hasMatcher = !!matchedUrl;

	if (matchedUrl) {
		resolveHost(matchedUrl, function(err, ip) {
			hosts[1] = ip;
			error = err;
			execCallback();
		});

		hosts[0] = null;
		execCallback();
	} else {
		resolveHost(_url, function(err, ip) {
			hosts[0] = ip;
			if (!matchedUrl) {
				hosts[1] = ip;
				error = err;
			}
			execCallback();
		});
	}

	function execCallback() {
		if (!done && (error || (typeof hosts[0] != 'undefined' && typeof hosts[1] != 'undefined'))) {
			done = true;
			hosts[1] = hosts[1] || hosts[0];
			hosts[0] = hosts[0] || hosts[1];
			callback(error, options);
		}
	}
}

exports.resolve = resolve;

function resolveHost(_url, callback) {
	var options = _url ? url.parse(util.setProtocol(_url)) : {};
	var protocol = options.protocol;
	if (!util.isWebProtocol(protocol)) {
		callback(null, null);
		return;
	}
	var hostname = options.hostname;
	for (var i = 0, host; host = hosts[i]; i++) {
		if (host.isRegExp ? host.pattern.test(_url) : (hostname == host.pattern && (!host.protocol || host.protocol == protocol))) {
			callback(null, host.matcher);
			return;
		}
	}

	try {
		dns.lookup(hostname, function(err, ip, addressType) {
		      callback(err, err ? null : (ip || (!addressType || addressType === 4 ? '127.0.0.1' : '0:0:0:0:0:0:0:1')));
		  });
	} catch(err) {//如果断网，可能直接抛异常，https代理没有用到error-handler
		callback(err);
	}
}

exports.resolveHost = resolveHost;

function resolveRule(url, data) {
	data = data || {};
	var _url = url.replace(/(?:\?|#).*$/, '');
	for (var i = 0, rule; rule = rules[i]; i++) {
		var pattern = rule.pattern;
		if (rule.isRegExp) {
			if (pattern.test(url)) {
				var regExp = {};
				for (var i = 0; i < 10; i++) {
					regExp['$' + i] = RegExp['$' + i] || '';
				}
				extend(data, rule);
				return rule.matcher.replace(/(^|.)?(\$[1-9])/g,
						function(matched, $1, $2) {
					return $1 == '\\' ? $2 : ($1 || '') + regExp[$2];
				});
			}
		} else {
			pattern = setProtocol(pattern, url);
			if (_url.indexOf(pattern) === 0) {
				var len = pattern.length;
				if (pattern == _url || isPathSeparator(_url[len]) || isPathSeparator(pattern[len - 1])) {
					extend(data, rule);
					return join(setProtocol(rule.matcher, url), url.substring(len));
				}
			}
		}
	}
}

function setProtocol(target, source) {
	if (util.hasProtocol(target)) {
		return target;
	}

	var protocol = util.getProtocol(source);
	if (protocol == null) {
		return target;
	}

	return protocol + '//' + target;
}

exports.resolveRule = resolveRule;

function isPathSeparator(ch) {
	return ch == '/' || ch == '\\';
}

function join(first, last) {
	if (!first || !last) {
		return first + last;
	}

	var len = first.length - 1;
	if (isPathSeparator(first[len])) {
		return isPathSeparator(last[0]) ? first.substring(0, len) + last : first + last;
	}

	return isPathSeparator(last[0]) ? first + last : first + '/' + last;
}

<|endoftext|>


<commit_before>// @flow

import * as React from 'react'
import {Checkbox, FormControl, FormGroup, ControlLabel, Tooltip, OverlayTrigger} from 'react-bootstrap'
import Select from 'react-select'
import moment from 'moment'
import DateTimeField from 'react-bootstrap-datetimepicker'
import Dropzone from 'react-dropzone'

import * as activeActions from '../actions/active'
import * as editorActions from '../actions/editor'
import {getEntityName, getTableById} from '../util/gtfs'
import {FIELD_PROPS} from '../util/types'
import {doesNotExist} from '../util/validation'
import TimezoneSelect from '../../common/components/TimezoneSelect'
import LanguageSelect from '../../common/components/LanguageSelect'
import toSentenceCase from '../../common/util/to-sentence-case'
import type {Entity, Feed, GtfsSpecField, GtfsAgency, GtfsStop} from '../../types'
import type {EditorTables} from '../../types/reducers'

import ZoneSelect from './ZoneSelect'
import VirtualizedEntitySelect from './VirtualizedEntitySelect'
import ColorField from './ColorField'

type Props = {
  activeComponent: string,
  activeEntity?: Entity,
  approveGtfsDisabled: boolean,
  currentValue: any,
  feedSource?: Feed, // Optional, but needed for uploadBrandingAsset.
  field: GtfsSpecField,
  isNotValid: boolean,
  onChange?: any => void,
  tableData: EditorTables,
  updateActiveGtfsEntity?: typeof activeActions.updateActiveGtfsEntity,
  uploadBrandingAsset?: typeof editorActions.uploadBrandingAsset,
  zoneOptions: Array<any>
}

const agencyToOption = (agency: GtfsAgency) => ({
  value: agency.agency_id,
  label: agency.agency_name,
  agency
})

const entityToOption = (entity: ?Entity, key: string) => {
  return entity
    ? {
      value: entity[key],
      label: getEntityName(entity),
      entity
    }
    : null
}

const renderRouteTypeOption = ({text, value}: {text: string, value: string}) => (
  <option key={value} value={value}>{text} ({value})</option>
)

export default class EditorInput extends React.Component<Props> {
  _onColorChange = (color: any) => {
    const {onChange, updateActiveGtfsEntity, activeEntity, activeComponent, field} = this.props
    const val = color.hex.split('#')[1]
    onChange && onChange(val)
    updateActiveGtfsEntity && activeEntity && updateActiveGtfsEntity({
      component: activeComponent,
      entity: activeEntity,
      props: {[field.name]: val}
    })
  }

  _onDateChange = (millis: number) => {
    const {onChange, updateActiveGtfsEntity, activeEntity, activeComponent, field} = this.props
    const val = moment(+millis).format('YYYYMMDD')
    onChange && onChange(val)
    updateActiveGtfsEntity && activeEntity && updateActiveGtfsEntity({
      component: activeComponent,
      entity: activeEntity,
      props: {[field.name]: val}
    })
  }

  _onDowChange = (evt: SyntheticInputEvent<HTMLInputElement>) => {
    const {onChange, updateActiveGtfsEntity, activeEntity, activeComponent, field} = this.props
    const val = evt.target.checked ? 1 : 0
    onChange && onChange(val)
    updateActiveGtfsEntity && activeEntity && updateActiveGtfsEntity({
      component: activeComponent,
      entity: activeEntity,
      props: {[field.name]: val}
    })
  }

  _onInputChange = (evt: SyntheticInputEvent<HTMLInputElement>) => {
    const {onChange, updateActiveGtfsEntity, activeEntity, activeComponent, field} = this.props
    const val = evt.target.value
    onChange && onChange(val)
    updateActiveGtfsEntity && activeEntity && updateActiveGtfsEntity({
      component: activeComponent,
      entity: activeEntity,
      props: {[field.name]: val}
    })
  }

  _onSelectChange = (option: any) => {
    const {onChange, updateActiveGtfsEntity, activeEntity, activeComponent, field} = this.props
    const val = option ? option.value : null
    onChange && onChange(val)
    updateActiveGtfsEntity && activeEntity && updateActiveGtfsEntity({
      component: activeComponent,
      entity: activeEntity,
      props: {[field.name]: val}
    })
  }

  _uploadBranding = (files: Array<File>) => {
    const {uploadBrandingAsset, feedSource, activeEntity, activeComponent} = this.props
    if (feedSource && uploadBrandingAsset && activeEntity && activeEntity.id !== null) {
      uploadBrandingAsset(feedSource.id, activeEntity.id, activeComponent, files[0])
    } else {
      throw new Error('EditorInput needs feedSource and uploadBrandingAsset props (and valid entity id) defined in order to use this._uploadBranding private method.')
    }
  }

  _renderRouteTypeOptions = (field: GtfsSpecField): Array<React.Node> => {
    const options = field.options || []
    // The first 10 options (types 0 - 12) are the standard types found in the
    // GTFS specification. All others represent extended route types.
    const routeTypes = [
      {
        label: 'Standard',
        options: options.filter(opt => parseInt(opt.value, 10) < 100).map(renderRouteTypeOption)
      },
      {
        label: 'Extended',
        options: options.filter(opt => parseInt(opt.value, 10) >= 100).map(renderRouteTypeOption)
      }
    ]
    return routeTypes.map(({label, options}) => (
      <optgroup key={label} label={label}>{options}</optgroup>
    ))
  }

  render () {
    const {
      activeEntity,
      activeComponent,
      tableData,
      field,
      currentValue,
      approveGtfsDisabled,
      zoneOptions,
      isNotValid
    } = this.props
    const editorField = field.displayName || field.name
    const formProps = {}
    formProps.controlId = `${editorField}`
    formProps.className = `col-xs-${field.columnWidth}`
    if (isNotValid) {
      formProps.validationState = 'error'
    } else if (field.required) {
      formProps.validationState = 'success'
    }
    const fieldType = FIELD_PROPS.find(f => f.inputType === field.inputType) || {}
    const value = !doesNotExist(currentValue)
      ? currentValue
      : undefined
    const fieldProps = {
      value,
      placeholder: field.placeholder || '',
      onChange: this._onInputChange,
      ...fieldType.props
    }
    const basicLabel = field.helpContent
      ? <OverlayTrigger
        placement='right'
        overlay={<Tooltip id='tooltip'>{field.helpContent}</Tooltip>}>
        <ControlLabel>
          {editorField}{field.required ? ' *' : ''}
        </ControlLabel>
      </OverlayTrigger>
      : <ControlLabel>
        {editorField}{field.required ? ' *' : ''}
      </ControlLabel>
    switch (field.inputType) {
      case 'GTFS_ID':
      case 'TEXT':
      case 'TIME':
      case 'GTFS_TRIP':
      case 'EMAIL':
      case 'GTFS_SHAPE':
      case 'LATITUDE':
      case 'LONGITUDE':
      case 'NUMBER':
      case 'POSITIVE_INT':
      case 'POSITIVE_NUM':
      case 'GTFS_BLOCK':
      case 'GTFS_FARE':
      case 'GTFS_SERVICE': {
        // Ensure that an empty string is passed to value prop, so that on 'undo'
        // the input value will revert back to a blank field.
        const stringValue = typeof fieldProps.value === 'undefined'
          ? ''
          : fieldProps.value
        return (
          <FormGroup {...formProps}>
            {basicLabel}
            <FormControl {...fieldProps} value={stringValue} />
          </FormGroup>
        )
      }
      case 'URL': {
        // Ensure that an empty string is passed to value prop, so that on 'undo'
        // the input value will revert back to a blank field.
        const stringValue = typeof fieldProps.value === 'undefined'
          ? ''
          : fieldProps.value
        const elements = [
          <FormGroup {...formProps} key={`${editorField}-input`}>
            {basicLabel}
            <FormControl {...fieldProps} value={stringValue} />
          </FormGroup>
        ]
        if (field.name.indexOf('_branding_url') > -1) {
          const url: ?string = activeEntity && activeEntity[field.name]
          elements.push(
            <FormGroup
              className='col-xs-12'
              key={`${editorField}-upload`}>
              <ControlLabel>Upload {activeComponent} branding asset</ControlLabel>
              <Dropzone
                accept='image/*'
                multiple={false}
                onDrop={this._uploadBranding}>

Drop {activeComponent} image here, or click to select image to upload.

                {url
                  ?
                  : null
                }
              </Dropzone>
            </FormGroup>
          )
        }
        return {elements}
      }
      case 'GTFS_ZONE':
        return (
          <FormGroup {...formProps}>
            {basicLabel}
            <ZoneSelect
              addCreateOption
              onChange={this._onSelectChange}
              value={currentValue}
              options={zoneOptions} />
          </FormGroup>
        )
      case 'TIMEZONE':
        return (
          <FormGroup {...formProps}>
            {basicLabel}
            <TimezoneSelect
              value={currentValue}
              clearable={!field.required}
              onChange={this._onSelectChange} />
          </FormGroup>
        )
      case 'LANGUAGE':
        return (
          <FormGroup {...formProps}>
            {basicLabel}
            <LanguageSelect
              value={currentValue}
              clearable={false}
              onChange={this._onSelectChange} />
          </FormGroup>
        )
      case 'DATE':
        const defaultValue = /end/.test(editorField)
          ? +moment().startOf('day').add(3, 'months')
          : +moment().startOf('day')
        const dateTimeProps = {}
        dateTimeProps.mode = 'date'
        dateTimeProps.dateTime = currentValue ? +moment(currentValue) : defaultValue
        dateTimeProps.onChange = this._onDateChange
        if (!currentValue) {
          dateTimeProps.defaultText = 'Please select a date'
        }
        return (
          <FormGroup {...formProps}>
            {basicLabel}
            <DateTimeField {...dateTimeProps} />
          </FormGroup>
        )
      case 'COLOR':
        return (
          <ColorField
            field={field}
            formProps={formProps}
            label={basicLabel}
            onChange={this._onColorChange}
            value={value} />
        )
      case 'DAY_OF_WEEK_BOOLEAN':
        return (

              {editorField === 'monday' // insert label for entire category on first checkbox
                ?
<ControlLabel>Days of service</ControlLabel>

                : null
              }

              <Checkbox
                inline
                checked={currentValue === 1}
                onChange={this._onDowChange}>
                {toSentenceCase(editorField.substr(0, 3))}
              </Checkbox>

        )
      case 'DROPDOWN':
        const options = field.options || []
        return (
          <FormGroup
            {...formProps}
            className={field.columnWidth ? `col-xs-${field.columnWidth}` : 'col-xs-12'}>
            {basicLabel}
            <FormControl
              {...fieldProps}
              // set value to '' to allow for selection of disabled option
              value={!doesNotExist(value) ? value : ''}
              disabled={approveGtfsDisabled && field.adminOnly}>
              {/* Add field for empty string value if that is not an allowable option so that user selection triggers onChange */}
              {options.findIndex(option => option.value === '') === -1
                ? <option disabled value=''>
                  {field.required ? '-- select an option --' : '(optional)' }
                </option>
                : null
              }
              {field.name === 'route_type'
                ? this._renderRouteTypeOptions(field)
                : options.map(o => (
                  <option value={o.value} key={o.value}>
                    {o.text || o.value}
                  </option>
                ))
              }
            </FormControl>
          </FormGroup>
        )
      case 'GTFS_ROUTE': {
        const routes = getTableById(tableData, 'route')
        const key = 'route_id'
        const route = routes.find(s => s[key] === currentValue)
        return (
          <VirtualizedEntitySelect
            value={entityToOption(route, key)}
            component={'route'}
            entityKey={key}
            entities={routes}
            onChange={this._onSelectChange} />
        )
      }
      case 'GTFS_AGENCY':
        const agencies = getTableById(tableData, 'agency')
        const agency = agencies.find(a => a.agency_id === currentValue)
        return (
          <FormGroup {...formProps}>
            {basicLabel}
            <Select
              placeholder='Select agency...'
              clearable
              value={agency
                ? agencyToOption(agency)
                : currentValue !== null
                  // Still display agency_id value for route if not null
                  ? {value: currentValue}
                  : null
              }
              onChange={this._onSelectChange}
              options={agencies.map(agencyToOption)} />
          </FormGroup>
        )
      case 'GTFS_STOP': {
        // Create copy of stops table (because of destructive splice operation
        // below).
        const stops: Array<GtfsStop> = [...getTableById(tableData, 'stop')]
        const key = 'stop_id'
        // Remove current entity from list of stops because this is only used
        // for parent_station selection and we can't make the self the parent).
        if (activeEntity) {
          const castedEntity = ((activeEntity: any): GtfsStop)
          const activeStopIndex = stops.findIndex(s => s[key] === castedEntity[key])
          if (activeStopIndex !== -1) {
            stops.splice(activeStopIndex, 1)
          }
        }
        return (
          <FormGroup {...formProps}>
            {basicLabel}
            <VirtualizedEntitySelect
              value={entityToOption(stops.find(s => s[key] === currentValue), key)}
              component={'stop'}
              entityKey={key}
              entities={stops}
              onChange={this._onSelectChange} />
          </FormGroup>
        )
      }
      default:
        return null
    }
  }
}
<commit_msg>refactor(EditorInput): Reorder imports<commit_after>// @flow

import * as React from 'react'
import {Checkbox, FormControl, FormGroup, ControlLabel, Tooltip, OverlayTrigger} from 'react-bootstrap'
import Select from 'react-select'
import moment from 'moment'
import DateTimeField from 'react-bootstrap-datetimepicker'
import Dropzone from 'react-dropzone'

import * as activeActions from '../actions/active'
import * as editorActions from '../actions/editor'
import {getEntityName, getTableById} from '../util/gtfs'
import {FIELD_PROPS} from '../util/types'
import {doesNotExist} from '../util/validation'
import TimezoneSelect from '../../common/components/TimezoneSelect'
import LanguageSelect from '../../common/components/LanguageSelect'
import toSentenceCase from '../../common/util/to-sentence-case'
import type {Entity, Feed, GtfsSpecField, GtfsAgency, GtfsStop} from '../../types'
import type {EditorTables} from '../../types/reducers'

import ColorField from './ColorField'
import VirtualizedEntitySelect from './VirtualizedEntitySelect'
import ZoneSelect from './ZoneSelect'

type Props = {
  activeComponent: string,
  activeEntity?: Entity,
  approveGtfsDisabled: boolean,
  currentValue: any,
  feedSource?: Feed, // Optional, but needed for uploadBrandingAsset.
  field: GtfsSpecField,
  isNotValid: boolean,
  onChange?: any => void,
  tableData: EditorTables,
  updateActiveGtfsEntity?: typeof activeActions.updateActiveGtfsEntity,
  uploadBrandingAsset?: typeof editorActions.uploadBrandingAsset,
  zoneOptions: Array<any>
}

const agencyToOption = (agency: GtfsAgency) => ({
  value: agency.agency_id,
  label: agency.agency_name,
  agency
})

const entityToOption = (entity: ?Entity, key: string) => {
  return entity
    ? {
      value: entity[key],
      label: getEntityName(entity),
      entity
    }
    : null
}

const renderRouteTypeOption = ({text, value}: {text: string, value: string}) => (
  <option key={value} value={value}>{text} ({value})</option>
)

export default class EditorInput extends React.Component<Props> {
  _onColorChange = (color: any) => {
    const {onChange, updateActiveGtfsEntity, activeEntity, activeComponent, field} = this.props
    const val = color.hex.split('#')[1]
    onChange && onChange(val)
    updateActiveGtfsEntity && activeEntity && updateActiveGtfsEntity({
      component: activeComponent,
      entity: activeEntity,
      props: {[field.name]: val}
    })
  }

  _onDateChange = (millis: number) => {
    const {onChange, updateActiveGtfsEntity, activeEntity, activeComponent, field} = this.props
    const val = moment(+millis).format('YYYYMMDD')
    onChange && onChange(val)
    updateActiveGtfsEntity && activeEntity && updateActiveGtfsEntity({
      component: activeComponent,
      entity: activeEntity,
      props: {[field.name]: val}
    })
  }

  _onDowChange = (evt: SyntheticInputEvent<HTMLInputElement>) => {
    const {onChange, updateActiveGtfsEntity, activeEntity, activeComponent, field} = this.props
    const val = evt.target.checked ? 1 : 0
    onChange && onChange(val)
    updateActiveGtfsEntity && activeEntity && updateActiveGtfsEntity({
      component: activeComponent,
      entity: activeEntity,
      props: {[field.name]: val}
    })
  }

  _onInputChange = (evt: SyntheticInputEvent<HTMLInputElement>) => {
    const {onChange, updateActiveGtfsEntity, activeEntity, activeComponent, field} = this.props
    const val = evt.target.value
    onChange && onChange(val)
    updateActiveGtfsEntity && activeEntity && updateActiveGtfsEntity({
      component: activeComponent,
      entity: activeEntity,
      props: {[field.name]: val}
    })
  }

  _onSelectChange = (option: any) => {
    const {onChange, updateActiveGtfsEntity, activeEntity, activeComponent, field} = this.props
    const val = option ? option.value : null
    onChange && onChange(val)
    updateActiveGtfsEntity && activeEntity && updateActiveGtfsEntity({
      component: activeComponent,
      entity: activeEntity,
      props: {[field.name]: val}
    })
  }

  _uploadBranding = (files: Array<File>) => {
    const {uploadBrandingAsset, feedSource, activeEntity, activeComponent} = this.props
    if (feedSource && uploadBrandingAsset && activeEntity && activeEntity.id !== null) {
      uploadBrandingAsset(feedSource.id, activeEntity.id, activeComponent, files[0])
    } else {
      throw new Error('EditorInput needs feedSource and uploadBrandingAsset props (and valid entity id) defined in order to use this._uploadBranding private method.')
    }
  }

  _renderRouteTypeOptions = (field: GtfsSpecField): Array<React.Node> => {
    const options = field.options || []
    // The first 10 options (types 0 - 12) are the standard types found in the
    // GTFS specification. All others represent extended route types.
    const routeTypes = [
      {
        label: 'Standard',
        options: options.filter(opt => parseInt(opt.value, 10) < 100).map(renderRouteTypeOption)
      },
      {
        label: 'Extended',
        options: options.filter(opt => parseInt(opt.value, 10) >= 100).map(renderRouteTypeOption)
      }
    ]
    return routeTypes.map(({label, options}) => (
      <optgroup key={label} label={label}>{options}</optgroup>
    ))
  }

  render () {
    const {
      activeEntity,
      activeComponent,
      tableData,
      field,
      currentValue,
      approveGtfsDisabled,
      zoneOptions,
      isNotValid
    } = this.props
    const editorField = field.displayName || field.name
    const formProps = {}
    formProps.controlId = `${editorField}`
    formProps.className = `col-xs-${field.columnWidth}`
    if (isNotValid) {
      formProps.validationState = 'error'
    } else if (field.required) {
      formProps.validationState = 'success'
    }
    const fieldType = FIELD_PROPS.find(f => f.inputType === field.inputType) || {}
    const value = !doesNotExist(currentValue)
      ? currentValue
      : undefined
    const fieldProps = {
      value,
      placeholder: field.placeholder || '',
      onChange: this._onInputChange,
      ...fieldType.props
    }
    const basicLabel = field.helpContent
      ? <OverlayTrigger
        placement='right'
        overlay={<Tooltip id='tooltip'>{field.helpContent}</Tooltip>}>
        <ControlLabel>
          {editorField}{field.required ? ' *' : ''}
        </ControlLabel>
      </OverlayTrigger>
      : <ControlLabel>
        {editorField}{field.required ? ' *' : ''}
      </ControlLabel>
    switch (field.inputType) {
      case 'GTFS_ID':
      case 'TEXT':
      case 'TIME':
      case 'GTFS_TRIP':
      case 'EMAIL':
      case 'GTFS_SHAPE':
      case 'LATITUDE':
      case 'LONGITUDE':
      case 'NUMBER':
      case 'POSITIVE_INT':
      case 'POSITIVE_NUM':
      case 'GTFS_BLOCK':
      case 'GTFS_FARE':
      case 'GTFS_SERVICE': {
        // Ensure that an empty string is passed to value prop, so that on 'undo'
        // the input value will revert back to a blank field.
        const stringValue = typeof fieldProps.value === 'undefined'
          ? ''
          : fieldProps.value
        return (
          <FormGroup {...formProps}>
            {basicLabel}
            <FormControl {...fieldProps} value={stringValue} />
          </FormGroup>
        )
      }
      case 'URL': {
        // Ensure that an empty string is passed to value prop, so that on 'undo'
        // the input value will revert back to a blank field.
        const stringValue = typeof fieldProps.value === 'undefined'
          ? ''
          : fieldProps.value
        const elements = [
          <FormGroup {...formProps} key={`${editorField}-input`}>
            {basicLabel}
            <FormControl {...fieldProps} value={stringValue} />
          </FormGroup>
        ]
        if (field.name.indexOf('_branding_url') > -1) {
          const url: ?string = activeEntity && activeEntity[field.name]
          elements.push(
            <FormGroup
              className='col-xs-12'
              key={`${editorField}-upload`}>
              <ControlLabel>Upload {activeComponent} branding asset</ControlLabel>
              <Dropzone
                accept='image/*'
                multiple={false}
                onDrop={this._uploadBranding}>

Drop {activeComponent} image here, or click to select image to upload.

                {url
                  ?
                  : null
                }
              </Dropzone>
            </FormGroup>
          )
        }
        return {elements}
      }
      case 'GTFS_ZONE':
        return (
          <FormGroup {...formProps}>
            {basicLabel}
            <ZoneSelect
              addCreateOption
              onChange={this._onSelectChange}
              value={currentValue}
              options={zoneOptions} />
          </FormGroup>
        )
      case 'TIMEZONE':
        return (
          <FormGroup {...formProps}>
            {basicLabel}
            <TimezoneSelect
              value={currentValue}
              clearable={!field.required}
              onChange={this._onSelectChange} />
          </FormGroup>
        )
      case 'LANGUAGE':
        return (
          <FormGroup {...formProps}>
            {basicLabel}
            <LanguageSelect
              value={currentValue}
              clearable={false}
              onChange={this._onSelectChange} />
          </FormGroup>
        )
      case 'DATE':
        const defaultValue = /end/.test(editorField)
          ? +moment().startOf('day').add(3, 'months')
          : +moment().startOf('day')
        const dateTimeProps = {}
        dateTimeProps.mode = 'date'
        dateTimeProps.dateTime = currentValue ? +moment(currentValue) : defaultValue
        dateTimeProps.onChange = this._onDateChange
        if (!currentValue) {
          dateTimeProps.defaultText = 'Please select a date'
        }
        return (
          <FormGroup {...formProps}>
            {basicLabel}
            <DateTimeField {...dateTimeProps} />
          </FormGroup>
        )
      case 'COLOR':
        return (
          <ColorField
            field={field}
            formProps={formProps}
            label={basicLabel}
            onChange={this._onColorChange}
            value={value} />
        )
      case 'DAY_OF_WEEK_BOOLEAN':
        return (

              {editorField === 'monday' // insert label for entire category on first checkbox
                ?
<ControlLabel>Days of service</ControlLabel>

                : null
              }

              <Checkbox
                inline
                checked={currentValue === 1}
                onChange={this._onDowChange}>
                {toSentenceCase(editorField.substr(0, 3))}
              </Checkbox>

        )
      case 'DROPDOWN':
        const options = field.options || []
        return (
          <FormGroup
            {...formProps}
            className={field.columnWidth ? `col-xs-${field.columnWidth}` : 'col-xs-12'}>
            {basicLabel}
            <FormControl
              {...fieldProps}
              // set value to '' to allow for selection of disabled option
              value={!doesNotExist(value) ? value : ''}
              disabled={approveGtfsDisabled && field.adminOnly}>
              {/* Add field for empty string value if that is not an allowable option so that user selection triggers onChange */}
              {options.findIndex(option => option.value === '') === -1
                ? <option disabled value=''>
                  {field.required ? '-- select an option --' : '(optional)' }
                </option>
                : null
              }
              {field.name === 'route_type'
                ? this._renderRouteTypeOptions(field)
                : options.map(o => (
                  <option value={o.value} key={o.value}>
                    {o.text || o.value}
                  </option>
                ))
              }
            </FormControl>
          </FormGroup>
        )
      case 'GTFS_ROUTE': {
        const routes = getTableById(tableData, 'route')
        const key = 'route_id'
        const route = routes.find(s => s[key] === currentValue)
        return (
          <VirtualizedEntitySelect
            value={entityToOption(route, key)}
            component={'route'}
            entityKey={key}
            entities={routes}
            onChange={this._onSelectChange} />
        )
      }
      case 'GTFS_AGENCY':
        const agencies = getTableById(tableData, 'agency')
        const agency = agencies.find(a => a.agency_id === currentValue)
        return (
          <FormGroup {...formProps}>
            {basicLabel}
            <Select
              placeholder='Select agency...'
              clearable
              value={agency
                ? agencyToOption(agency)
                : currentValue !== null
                  // Still display agency_id value for route if not null
                  ? {value: currentValue}
                  : null
              }
              onChange={this._onSelectChange}
              options={agencies.map(agencyToOption)} />
          </FormGroup>
        )
      case 'GTFS_STOP': {
        // Create copy of stops table (because of destructive splice operation
        // below).
        const stops: Array<GtfsStop> = [...getTableById(tableData, 'stop')]
        const key = 'stop_id'
        // Remove current entity from list of stops because this is only used
        // for parent_station selection and we can't make the self the parent).
        if (activeEntity) {
          const castedEntity = ((activeEntity: any): GtfsStop)
          const activeStopIndex = stops.findIndex(s => s[key] === castedEntity[key])
          if (activeStopIndex !== -1) {
            stops.splice(activeStopIndex, 1)
          }
        }
        return (
          <FormGroup {...formProps}>
            {basicLabel}
            <VirtualizedEntitySelect
              value={entityToOption(stops.find(s => s[key] === currentValue), key)}
              component={'stop'}
              entityKey={key}
              entities={stops}
              onChange={this._onSelectChange} />
          </FormGroup>
        )
      }
      default:
        return null
    }
  }
}
<|endoftext|>


<commit_before>var boids = require('boids');
var viewport = require('./viewport');

var flock = null;

module.exports = {
  init: function(width, height) {
    flock = boids({
      boids: 20,              // The amount of boids to use
      speedLimit: 2,          // Max steps to take per tick
      accelerationLimit: 0.2,   // Max acceleration per tick
      separationDistance: 60, // Radius at which boids avoid others
      alignmentDistance: 180, // Radius at which boids align with others
      cohesionDistance: 180,  // Radius at which boids approach others
      separationForce: 0.05,  // Speed to avoid at
      alignmentForce: 0.25,   // Speed to align with other boids
      choesionForce: 0.5,     // Speed to move towards other boids
    });

    flock.boids.forEach(function(boid) {
      boid[0] = Math.random() * width;
      boid[1] = Math.random() * height;
    });
  },

  tick: function() {
    flock.tick();
  },

  boids: function() {
    return flock.boids;
  },

  addAttractor: function(x, y, radius, force) {
    flock.attractors.push([x, y, radius, Math.abs(force)]);
  },

  addRepeller: function(x, y, radius, force) {
    flock.attractors.push([x, y, radius, -Math.abs(force)]);
  },

  reportVisibleFlock: function() {
    var serializedFlockData = {};
    for(var i = 0; i < flock.boids.length; i++) {
      if(!viewport.containsBoid(flock.boids[i])) {
        continue;
      }

      serializedFlockData[i] = flock.boids[i];
    }

    // TODO: Send this over a socket!
  },

  reportEntireFlock: function() {
    // TODO: Send flock.boids over the wire
  },

  receiveVisibleFlockUpdate: function(boidSet) {
    Object.keys(boidSet).forEach(function(index) {
      flock.boids[index] = boidSet[index];
    });
  },
};
<commit_msg>Unneeded methods. We'll use a server to sync everything<commit_after>var boids = require('boids');
var viewport = require('./viewport');

var flock = null;

module.exports = {
  init: function(width, height) {
    flock = boids({
      boids: 20,              // The amount of boids to use
      speedLimit: 2,          // Max steps to take per tick
      accelerationLimit: 0.2,   // Max acceleration per tick
      separationDistance: 60, // Radius at which boids avoid others
      alignmentDistance: 180, // Radius at which boids align with others
      cohesionDistance: 180,  // Radius at which boids approach others
      separationForce: 0.05,  // Speed to avoid at
      alignmentForce: 0.25,   // Speed to align with other boids
      choesionForce: 0.5,     // Speed to move towards other boids
    });

    flock.boids.forEach(function(boid) {
      boid[0] = Math.random() * width;
      boid[1] = Math.random() * height;
    });
  },

  tick: function() {
    flock.tick();
  },

  boids: function() {
    return flock.boids;
  },

  addAttractor: function(x, y, radius, force) {
    flock.attractors.push([x, y, radius, Math.abs(force)]);
  },

  addRepeller: function(x, y, radius, force) {
    flock.attractors.push([x, y, radius, -Math.abs(force)]);
  },

  receiveVisibleFlockUpdate: function(boidSet) {
    Object.keys(boidSet).forEach(function(index) {
      flock.boids[index] = boidSet[index];
    });
  },
};
<|endoftext|>


<commit_before>/*eslint dot-notation: 0*/
import * as types from "../actions/types";
import * as globals from "../util/globals";
import getColorScale from "../util/getColorScale";
import moment from 'moment';
import d3 from "d3";
import { determineColorByGenotypeType } from "../util/urlHelpers";
import { floatDateToMoment } from "../util/dateHelpers";
import maxBy from "lodash";

const checkColorByConfidence = function (attrs, colorBy) {
  return colorBy !== "num_date" && attrs.indexOf(colorBy + "_confidence") > -1;
};

const getMinDateViaRoot = function (rootAttr) {
  const root = floatDateToMoment(rootAttr.num_date);
  root.subtract(1, "days"); /* slider should be earlier than actual day */
  return root;
};

const getMaxDateViaTips = function (tree) {
  const nodes = d3.layout.tree().nodes(tree);
  const latestTip = _.maxBy(nodes, function(node) { return node.attr.num_date; });
  let maxTipDate = floatDateToMoment(latestTip.attr.num_date);
  maxTipDate.add(1, "days"); /* slider should be later than actual day */
  return maxTipDate;
};

/* defaultState is a fn so that we can re-create it
at any time, e.g. if we want to revert things (e.g. on dataset change)
*/
const getDefaultState = function () {
  return {
    showBranchLabels: false,
    selectedLegendItem: null,
    selectedBranch: null,
    selectedNode: null,
    region: null,
    search: null,
    strain: null,
    splitTreeAndMap: true,
    mutType: globals.mutType,
    temporalConfidence: {exists: false, display: false, on: false},
    layout: globals.defaultLayout,
    distanceMeasure: globals.defaultDistanceMeasure,
    dateMin: moment().subtract(globals.defaultDateRange, "years").format("YYYY-MM-DD"),
    dateMax: moment().format("YYYY-MM-DD"),
    absoluteDateMin: moment().subtract(globals.defaultDateRange, "years").format("YYYY-MM-DD"),
    absoluteDateMax: moment().format("YYYY-MM-DD"),
    colorBy: globals.defaultColorBy,
    defaultColorBy: globals.defaultColorBy,
    colorByConfidence: {display: false, on: false},
    colorScale: getColorScale(globals.defaultColorBy, {}, {}, {}, 0),
    analysisSlider: false,
    geoResolution: globals.defaultGeoResolution,
    datasetPathName: "",
    filters: {},
    dateScale: d3.time.scale().domain([new Date(2000, 0, 0), new Date(2100, 0, 0)]).range([2000, 2100]),
    dateFormat: d3.time.format("%Y-%m-%d"),
    quickdraw: false, // if true, components may skip expensive computes.
    mapAnimationDurationInMilliseconds: 30000, // in milliseconds
    mapAnimationStartDate: null, // Null so it can pull the absoluteDateMin as the default
    mapAnimationCumulative: false,
    mapAnimationPlayPauseButton: "Play"
  };
};

const Controls = (state = getDefaultState(), action) => {
  switch (action.type) {
  case types.DATA_INVALID:
    return Object.assign({}, state, {
      datasetPathName: undefined
    });
  case types.NEW_DATASET:
    const base = getDefaultState();
    base["datasetPathName"] = action.datasetPathName;
    const rootDate = getMinDateViaRoot(action.tree.attr);
    base["dateMin"] = rootDate.format("YYYY-MM-DD");
    base["absoluteDateMin"] = rootDate.format("YYYY-MM-DD");
    const maxTipDate = getMaxDateViaTips(action.tree);
    base["dateMax"] = maxTipDate.format("YYYY-MM-DD");
    base["absoluteDateMax"] = maxTipDate.format("YYYY-MM-DD");
    /* overwrite base state with data from the metadata JSON */
    if (action.meta.date_range) {
      if (action.meta.date_range.date_min) {
        base["mapAnimationStartDate"] = action.meta.date_range.date_min;
        if (rootDate.isBefore(moment(action.meta.date_range.date_min, "YYYY-MM-DD"))) {
          base["dateMin"] = action.meta.date_range.date_min;
        }
      }
      if (action.meta.date_range.date_max) {
        /* this may be useful if, e.g., one were to want to display an outbreak
        from 2000-2005 (the default is the present day) */
        base["dateMax"] = action.meta.date_range.date_max;
        base["absoluteDateMax"] = action.meta.date_range.date_max;
      }
    };

    if (action.meta.analysisSlider) {
      base["analysisSlider"] = {key: action.meta.analysisSlider, valid: false};
    }
    if (action.meta.defaults) {
      if (action.meta.defaults.geoResolution) {
        base["geoResolution"] = action.meta.defaults.geoResolution;
      }
      if (action.meta.defaults.colorBy) {
        base["colorBy"] = action.meta.defaults.colorBy;
      }
      if (action.meta.defaults.distanceMeasure) {
        base["distanceMeasure"] = action.meta.defaults.distanceMeasure;
      }
      if (action.meta.defaults.layout) {
        base["layout"] = action.meta.defaults.layout;
      }
      if (action.meta.defaults.mapTriplicate) {
       //convert string to boolean; default is true; turned off with either false (js) or False (python)
       base["mapTriplicate"] = (action.meta.defaults.mapTriplicate == 'false' || action.meta.defaults.mapTriplicate == 'False') ? false : true;
      }
    }
    /* now overwrite state with data from the URL */
    if (action.query.l) {
      base["layout"] = action.query.l;
    }
    if (action.query.m) {
      base["distanceMeasure"] = action.query.m;
    }
    if (action.query.c) {
      base["colorBy"] = action.query.c;
    }
    if (action.query.r) {
      base["geoResolution"] = action.query.r;
    }
    if (action.query.dmin) {
      base["dateMin"] = action.query.dmin;
    }
    if (action.query.dmax) {
      base["dateMax"] = action.query.dmax;
    }
    base["temporalConfidence"] = Object.keys(action.tree.attr).indexOf("num_date_confidence") > -1 ?
      {exists: true, display: true, on: false} : {exists: false, display: false, on: false};
    if (base.temporalConfidence.exists && base.layout !== "rect") {
      base.temporalConfidence.display = false;
    }
    /* basic sanity checking */
    if (Object.keys(action.meta.color_options).indexOf(base["colorBy"]) === -1) {
      /* ideally, somehow, a notification is dispatched, but redux, unlike elm,
      doesn't allow dispatches from the reducer */
      // throw new Error("colorBy (" + base["colorBy"] + ") not available.");
      const available_colorBy = Object.keys(action.meta.color_options);
      /* remove "gt" */
      if (available_colorBy.indexOf("gt") > -1) {
        available_colorBy.splice(available_colorBy.indexOf("gt"), 1);
      }
      base["colorBy"] = available_colorBy[0];
    }
    /* available tree attrs - based upon the root node */
    base["attrs"] = Object.keys(action.tree.attr);
    base["colorByConfidence"] = checkColorByConfidence(base["attrs"], base["colorBy"]);
    base["defaultColorBy"] = base["colorBy"];
    return base;
  case types.TOGGLE_BRANCH_LABELS:
    return Object.assign({}, state, {
      showBranchLabels: !state.showBranchLabels
    });
  case types.LEGEND_ITEM_MOUSEENTER:
    return Object.assign({}, state, {
      selectedLegendItem: action.data
    });
  case types.LEGEND_ITEM_MOUSELEAVE:
    return Object.assign({}, state, {
      selectedLegendItem: null
    });
  case types.BRANCH_MOUSEENTER:
    return Object.assign({}, state, {
      selectedBranch: action.data
    });
  case types.BRANCH_MOUSELEAVE:
    return Object.assign({}, state, {
      selectedBranch: null
    });
  case types.NODE_MOUSEENTER:
    return Object.assign({}, state, {
      selectedNode: action.data
    });
  case types.NODE_MOUSELEAVE:
    return Object.assign({}, state, {
      selectedNode: null
    });
  case types.CHANGE_LAYOUT:
    const layout = action.data;
    /* if temporalConfidence and layout !== rect then disable confidence toggle */
    const temporalConfidence = Object.assign({}, state.temporalConfidence);
    if (temporalConfidence.exists) {
      temporalConfidence.display = layout === "rect";
    }
    return Object.assign({}, state, {
      layout,
      temporalConfidence
    });
  case types.CHANGE_DISTANCE_MEASURE:
    /* while this may change, div currently doesn't have CIs,
    so they shouldn't be displayed. The SVG el's still exist, they're just of
    width zero */
    if (state.temporalConfidence.exists) {
      if (state.temporalConfidence.display && action.data === "div") {
        return Object.assign({}, state, {
          distanceMeasure: action.data,
          temporalConfidence: Object.assign({}, state.temporalConfidence, {display: false})
        });
      } else if (state.layout === "rect" && action.data === "num_date") {
        return Object.assign({}, state, {
          distanceMeasure: action.data,
          temporalConfidence: Object.assign({}, state.temporalConfidence, {display: true})
        });
      }
    }
    return Object.assign({}, state, {
      distanceMeasure: action.data
    });
  case types.CHANGE_DATES_VISIBILITY_THICKNESS:
    return Object.assign({}, state, {
      // quickdraw: action.quickdraw,
      dateMin: action.dateMin ? action.dateMin : state.dateMin,
      dateMax: action.dateMax ? action.dateMax : state.dateMax
    });
  case types.CHANGE_ABSOLUTE_DATE_MIN:
    return Object.assign({}, state, {
      absoluteDateMin: action.data
    });
  case types.CHANGE_ABSOLUTE_DATE_MAX:
    return Object.assign({}, state, {
      absoluteDateMax: action.data
    });
  case types.CHANGE_ANIMATION_TIME:
    return Object.assign({}, state, {
      mapAnimationDurationInMilliseconds: action.data
    });
  case types.CHANGE_ANIMATION_CUMULATIVE:
    return Object.assign({}, state, {
      mapAnimationCumulative: action.data
    });
  case types.MAP_ANIMATION_PLAY_PAUSE_BUTTON:
    return Object.assign({}, state, {
      mapAnimationPlayPauseButton: action.data
    });
  case types.CHANGE_ANIMATION_START:
    return Object.assign({}, state, {
      mapAnimationStartDate: action.data
    });
  case types.NEW_COLORS:
    const newState = Object.assign({}, state, {
      colorBy: action.colorBy,
      colorScale: action.colorScale,
      colorByConfidence: checkColorByConfidence(state.attrs, action.colorBy)
    });
    /* may need to toggle the entropy selector AA <-> NUC */
    if (determineColorByGenotypeType(action.colorBy)) {
      newState.mutType = determineColorByGenotypeType(action.colorBy);
    }
    return newState;
  case types.CHANGE_GEO_RESOLUTION:
    return Object.assign({}, state, {
      geoResolution: action.data
    });
  case types.APPLY_FILTER_QUERY:
    // values arrive as array
    const filters = Object.assign({}, state.filters, {});
    filters[action.fields] = action.values;
    // console.log(filters)
    return Object.assign({}, state, {
      filters
    });
  case types.TOGGLE_MUT_TYPE:
    return Object.assign({}, state, {
      mutType: action.data
    });
  case types.TOGGLE_TEMPORAL_CONF:
    return Object.assign({}, state, {
      temporalConfidence: Object.assign({}, state.temporalConfidence, {
        on: !state.temporalConfidence.on
      })
    });
  case types.ANALYSIS_SLIDER:
    if (action.destroy) {
      return Object.assign({}, state, {
        analysisSlider: false
      });
    }
    return Object.assign({}, state, {
      analysisSlider: {
        key: state.analysisSlider.key,
        // valid: true, // TESTING ONLY
        valid: false, // FIXME --- This is a temporary hack to disable the analysis slider, while keeping color options
        value: action.maxVal,
        absoluteMinVal: action.minVal,
        absoluteMaxVal: action.maxVal
      }
    });
  case types.CHANGE_ANALYSIS_VALUE:
    return Object.assign({}, state, {
      analysisSlider: Object.assign({}, state.analysisSlider, {
        value: action.value
      }
    )});
  default:
    return state;
  }
};

export default Controls;
<commit_msg>enable quickdraw<commit_after>/*eslint dot-notation: 0*/
import * as types from "../actions/types";
import * as globals from "../util/globals";
import getColorScale from "../util/getColorScale";
import moment from 'moment';
import d3 from "d3";
import { determineColorByGenotypeType } from "../util/urlHelpers";
import { floatDateToMoment } from "../util/dateHelpers";
import maxBy from "lodash";

const checkColorByConfidence = function (attrs, colorBy) {
  return colorBy !== "num_date" && attrs.indexOf(colorBy + "_confidence") > -1;
};

const getMinDateViaRoot = function (rootAttr) {
  const root = floatDateToMoment(rootAttr.num_date);
  root.subtract(1, "days"); /* slider should be earlier than actual day */
  return root;
};

const getMaxDateViaTips = function (tree) {
  const nodes = d3.layout.tree().nodes(tree);
  const latestTip = _.maxBy(nodes, function(node) { return node.attr.num_date; });
  let maxTipDate = floatDateToMoment(latestTip.attr.num_date);
  maxTipDate.add(1, "days"); /* slider should be later than actual day */
  return maxTipDate;
};

/* defaultState is a fn so that we can re-create it
at any time, e.g. if we want to revert things (e.g. on dataset change)
*/
const getDefaultState = function () {
  return {
    showBranchLabels: false,
    selectedLegendItem: null,
    selectedBranch: null,
    selectedNode: null,
    region: null,
    search: null,
    strain: null,
    splitTreeAndMap: true,
    mutType: globals.mutType,
    temporalConfidence: {exists: false, display: false, on: false},
    layout: globals.defaultLayout,
    distanceMeasure: globals.defaultDistanceMeasure,
    dateMin: moment().subtract(globals.defaultDateRange, "years").format("YYYY-MM-DD"),
    dateMax: moment().format("YYYY-MM-DD"),
    absoluteDateMin: moment().subtract(globals.defaultDateRange, "years").format("YYYY-MM-DD"),
    absoluteDateMax: moment().format("YYYY-MM-DD"),
    colorBy: globals.defaultColorBy,
    defaultColorBy: globals.defaultColorBy,
    colorByConfidence: {display: false, on: false},
    colorScale: getColorScale(globals.defaultColorBy, {}, {}, {}, 0),
    analysisSlider: false,
    geoResolution: globals.defaultGeoResolution,
    datasetPathName: "",
    filters: {},
    dateScale: d3.time.scale().domain([new Date(2000, 0, 0), new Date(2100, 0, 0)]).range([2000, 2100]),
    dateFormat: d3.time.format("%Y-%m-%d"),
    quickdraw: false, // if true, components may skip expensive computes.
    mapAnimationDurationInMilliseconds: 30000, // in milliseconds
    mapAnimationStartDate: null, // Null so it can pull the absoluteDateMin as the default
    mapAnimationCumulative: false,
    mapAnimationPlayPauseButton: "Play"
  };
};

const Controls = (state = getDefaultState(), action) => {
  switch (action.type) {
  case types.DATA_INVALID:
    return Object.assign({}, state, {
      datasetPathName: undefined
    });
  case types.NEW_DATASET:
    const base = getDefaultState();
    base["datasetPathName"] = action.datasetPathName;
    const rootDate = getMinDateViaRoot(action.tree.attr);
    base["dateMin"] = rootDate.format("YYYY-MM-DD");
    base["absoluteDateMin"] = rootDate.format("YYYY-MM-DD");
    const maxTipDate = getMaxDateViaTips(action.tree);
    base["dateMax"] = maxTipDate.format("YYYY-MM-DD");
    base["absoluteDateMax"] = maxTipDate.format("YYYY-MM-DD");
    /* overwrite base state with data from the metadata JSON */
    if (action.meta.date_range) {
      if (action.meta.date_range.date_min) {
        base["mapAnimationStartDate"] = action.meta.date_range.date_min;
        if (rootDate.isBefore(moment(action.meta.date_range.date_min, "YYYY-MM-DD"))) {
          base["dateMin"] = action.meta.date_range.date_min;
        }
      }
      if (action.meta.date_range.date_max) {
        /* this may be useful if, e.g., one were to want to display an outbreak
        from 2000-2005 (the default is the present day) */
        base["dateMax"] = action.meta.date_range.date_max;
        base["absoluteDateMax"] = action.meta.date_range.date_max;
      }
    };

    if (action.meta.analysisSlider) {
      base["analysisSlider"] = {key: action.meta.analysisSlider, valid: false};
    }
    if (action.meta.defaults) {
      if (action.meta.defaults.geoResolution) {
        base["geoResolution"] = action.meta.defaults.geoResolution;
      }
      if (action.meta.defaults.colorBy) {
        base["colorBy"] = action.meta.defaults.colorBy;
      }
      if (action.meta.defaults.distanceMeasure) {
        base["distanceMeasure"] = action.meta.defaults.distanceMeasure;
      }
      if (action.meta.defaults.layout) {
        base["layout"] = action.meta.defaults.layout;
      }
      if (action.meta.defaults.mapTriplicate) {
       //convert string to boolean; default is true; turned off with either false (js) or False (python)
       base["mapTriplicate"] = (action.meta.defaults.mapTriplicate == 'false' || action.meta.defaults.mapTriplicate == 'False') ? false : true;
      }
    }
    /* now overwrite state with data from the URL */
    if (action.query.l) {
      base["layout"] = action.query.l;
    }
    if (action.query.m) {
      base["distanceMeasure"] = action.query.m;
    }
    if (action.query.c) {
      base["colorBy"] = action.query.c;
    }
    if (action.query.r) {
      base["geoResolution"] = action.query.r;
    }
    if (action.query.dmin) {
      base["dateMin"] = action.query.dmin;
    }
    if (action.query.dmax) {
      base["dateMax"] = action.query.dmax;
    }
    base["temporalConfidence"] = Object.keys(action.tree.attr).indexOf("num_date_confidence") > -1 ?
      {exists: true, display: true, on: false} : {exists: false, display: false, on: false};
    if (base.temporalConfidence.exists && base.layout !== "rect") {
      base.temporalConfidence.display = false;
    }
    /* basic sanity checking */
    if (Object.keys(action.meta.color_options).indexOf(base["colorBy"]) === -1) {
      /* ideally, somehow, a notification is dispatched, but redux, unlike elm,
      doesn't allow dispatches from the reducer */
      // throw new Error("colorBy (" + base["colorBy"] + ") not available.");
      const available_colorBy = Object.keys(action.meta.color_options);
      /* remove "gt" */
      if (available_colorBy.indexOf("gt") > -1) {
        available_colorBy.splice(available_colorBy.indexOf("gt"), 1);
      }
      base["colorBy"] = available_colorBy[0];
    }
    /* available tree attrs - based upon the root node */
    base["attrs"] = Object.keys(action.tree.attr);
    base["colorByConfidence"] = checkColorByConfidence(base["attrs"], base["colorBy"]);
    base["defaultColorBy"] = base["colorBy"];
    return base;
  case types.TOGGLE_BRANCH_LABELS:
    return Object.assign({}, state, {
      showBranchLabels: !state.showBranchLabels
    });
  case types.LEGEND_ITEM_MOUSEENTER:
    return Object.assign({}, state, {
      selectedLegendItem: action.data
    });
  case types.LEGEND_ITEM_MOUSELEAVE:
    return Object.assign({}, state, {
      selectedLegendItem: null
    });
  case types.BRANCH_MOUSEENTER:
    return Object.assign({}, state, {
      selectedBranch: action.data
    });
  case types.BRANCH_MOUSELEAVE:
    return Object.assign({}, state, {
      selectedBranch: null
    });
  case types.NODE_MOUSEENTER:
    return Object.assign({}, state, {
      selectedNode: action.data
    });
  case types.NODE_MOUSELEAVE:
    return Object.assign({}, state, {
      selectedNode: null
    });
  case types.CHANGE_LAYOUT:
    const layout = action.data;
    /* if temporalConfidence and layout !== rect then disable confidence toggle */
    const temporalConfidence = Object.assign({}, state.temporalConfidence);
    if (temporalConfidence.exists) {
      temporalConfidence.display = layout === "rect";
    }
    return Object.assign({}, state, {
      layout,
      temporalConfidence
    });
  case types.CHANGE_DISTANCE_MEASURE:
    /* while this may change, div currently doesn't have CIs,
    so they shouldn't be displayed. The SVG el's still exist, they're just of
    width zero */
    if (state.temporalConfidence.exists) {
      if (state.temporalConfidence.display && action.data === "div") {
        return Object.assign({}, state, {
          distanceMeasure: action.data,
          temporalConfidence: Object.assign({}, state.temporalConfidence, {display: false})
        });
      } else if (state.layout === "rect" && action.data === "num_date") {
        return Object.assign({}, state, {
          distanceMeasure: action.data,
          temporalConfidence: Object.assign({}, state.temporalConfidence, {display: true})
        });
      }
    }
    return Object.assign({}, state, {
      distanceMeasure: action.data
    });
  case types.CHANGE_DATES_VISIBILITY_THICKNESS:
    return Object.assign({}, state, {
      quickdraw: action.quickdraw,
      dateMin: action.dateMin ? action.dateMin : state.dateMin,
      dateMax: action.dateMax ? action.dateMax : state.dateMax
    });
  case types.CHANGE_ABSOLUTE_DATE_MIN:
    return Object.assign({}, state, {
      absoluteDateMin: action.data
    });
  case types.CHANGE_ABSOLUTE_DATE_MAX:
    return Object.assign({}, state, {
      absoluteDateMax: action.data
    });
  case types.CHANGE_ANIMATION_TIME:
    return Object.assign({}, state, {
      mapAnimationDurationInMilliseconds: action.data
    });
  case types.CHANGE_ANIMATION_CUMULATIVE:
    return Object.assign({}, state, {
      mapAnimationCumulative: action.data
    });
  case types.MAP_ANIMATION_PLAY_PAUSE_BUTTON:
    return Object.assign({}, state, {
      mapAnimationPlayPauseButton: action.data
    });
  case types.CHANGE_ANIMATION_START:
    return Object.assign({}, state, {
      mapAnimationStartDate: action.data
    });
  case types.NEW_COLORS:
    const newState = Object.assign({}, state, {
      colorBy: action.colorBy,
      colorScale: action.colorScale,
      colorByConfidence: checkColorByConfidence(state.attrs, action.colorBy)
    });
    /* may need to toggle the entropy selector AA <-> NUC */
    if (determineColorByGenotypeType(action.colorBy)) {
      newState.mutType = determineColorByGenotypeType(action.colorBy);
    }
    return newState;
  case types.CHANGE_GEO_RESOLUTION:
    return Object.assign({}, state, {
      geoResolution: action.data
    });
  case types.APPLY_FILTER_QUERY:
    // values arrive as array
    const filters = Object.assign({}, state.filters, {});
    filters[action.fields] = action.values;
    // console.log(filters)
    return Object.assign({}, state, {
      filters
    });
  case types.TOGGLE_MUT_TYPE:
    return Object.assign({}, state, {
      mutType: action.data
    });
  case types.TOGGLE_TEMPORAL_CONF:
    return Object.assign({}, state, {
      temporalConfidence: Object.assign({}, state.temporalConfidence, {
        on: !state.temporalConfidence.on
      })
    });
  case types.ANALYSIS_SLIDER:
    if (action.destroy) {
      return Object.assign({}, state, {
        analysisSlider: false
      });
    }
    return Object.assign({}, state, {
      analysisSlider: {
        key: state.analysisSlider.key,
        // valid: true, // TESTING ONLY
        valid: false, // FIXME --- This is a temporary hack to disable the analysis slider, while keeping color options
        value: action.maxVal,
        absoluteMinVal: action.minVal,
        absoluteMaxVal: action.maxVal
      }
    });
  case types.CHANGE_ANALYSIS_VALUE:
    return Object.assign({}, state, {
      analysisSlider: Object.assign({}, state.analysisSlider, {
        value: action.value
      }
    )});
  default:
    return state;
  }
};

export default Controls;
<|endoftext|>


<commit_before>import { performance } from 'perf_hooks'

const { assign } = Object

export default class InProcessRunner {
  constructor(functionKey, handlerPath, handlerName, env, timeout) {
    this._env = env
    this._functionKey = functionKey
    this._handlerName = handlerName
    this._handlerPath = handlerPath
    this._timeout = timeout
  }

  // no-op
  // () => void
  cleanup() {}

  async run(event, context) {
    // check if the handler module path exists
    if (!require.resolve(this._handlerPath)) {
      throw new Error(
        `Could not find handler module '${this._handlerPath}' for function '${this._functionKey}'.`,
      )
    }

    // process.env should be available in the handler module scope as well as in the handler function scope
    // NOTE: Don't use Object spread (...) here!
    // otherwise the values of the attached props are not coerced to a string
    // e.g. process.env.foo = 1 should be coerced to '1' (string)
    assign(process.env, this._env)

    // lazy load handler with first usage

    const handlerPath = this._handlerPath
    const { [this._handlerName]: handler } = await import(handlerPath)

    if (typeof handler !== 'function') {
      throw new Error(
        `offline: handler '${this._handlerName}' in ${this._handlerPath} is not a function`,
      )
    }

    let callback

    const callbackCalled = new Promise((resolve, reject) => {
      callback = (err, data) => {
        if (err) {
          reject(err)
        }
        resolve(data)
      }
    })

    const executionTimeout = performance.now() + this._timeout * 1000

    // attach doc-deprecated functions
    // create new immutable object
    const lambdaContext = {
      ...context,
      getRemainingTimeInMillis: () => {
        const timeLeft = executionTimeout - performance.now()

        // just return 0 for now if we are beyond alotted time (timeout)
        return timeLeft > 0 ? timeLeft : 0
      },
      done: (err, data) => callback(err, data),
      fail: (err) => callback(err),
      succeed: (res) => callback(null, res),
    }

    let result

    // execute (run) handler
    try {
      result = handler(event, lambdaContext, callback)
    } catch (err) {
      // this only executes when we have an exception caused by synchronous code
      // TODO logging
      console.log(err)
      throw new Error(`Uncaught error in '${this._functionKey}' handler.`)
    }

    // // not a Promise, which is not supported by aws
    // if (result == null || typeof result.then !== 'function') {
    //   throw new Error(`Synchronous function execution is not supported.`)
    // }

    const callbacks = [callbackCalled]

    // Promise was returned
    if (result != null && typeof result.then === 'function') {
      callbacks.push(result)
    }

    let callbackResult

    try {
      callbackResult = await Promise.race(callbacks)
    } catch (err) {
      // TODO logging
      console.log(err)
      throw err
    }

    return callbackResult
  }
}
<commit_msg>Remove additional variable<commit_after>import { performance } from 'perf_hooks'

const { assign } = Object

export default class InProcessRunner {
  constructor(functionKey, handlerPath, handlerName, env, timeout) {
    this._env = env
    this._functionKey = functionKey
    this._handlerName = handlerName
    this._handlerPath = handlerPath
    this._timeout = timeout
  }

  // no-op
  // () => void
  cleanup() {}

  async run(event, context) {
    // check if the handler module path exists
    if (!require.resolve(this._handlerPath)) {
      throw new Error(
        `Could not find handler module '${this._handlerPath}' for function '${this._functionKey}'.`,
      )
    }

    // process.env should be available in the handler module scope as well as in the handler function scope
    // NOTE: Don't use Object spread (...) here!
    // otherwise the values of the attached props are not coerced to a string
    // e.g. process.env.foo = 1 should be coerced to '1' (string)
    assign(process.env, this._env)

    // lazy load handler with first usage

    const { [this._handlerName]: handler } = await import(this._handlerPath)

    if (typeof handler !== 'function') {
      throw new Error(
        `offline: handler '${this._handlerName}' in ${this._handlerPath} is not a function`,
      )
    }

    let callback

    const callbackCalled = new Promise((resolve, reject) => {
      callback = (err, data) => {
        if (err) {
          reject(err)
        }
        resolve(data)
      }
    })

    const executionTimeout = performance.now() + this._timeout * 1000

    // attach doc-deprecated functions
    // create new immutable object
    const lambdaContext = {
      ...context,
      getRemainingTimeInMillis: () => {
        const timeLeft = executionTimeout - performance.now()

        // just return 0 for now if we are beyond alotted time (timeout)
        return timeLeft > 0 ? timeLeft : 0
      },
      done: (err, data) => callback(err, data),
      fail: (err) => callback(err),
      succeed: (res) => callback(null, res),
    }

    let result

    // execute (run) handler
    try {
      result = handler(event, lambdaContext, callback)
    } catch (err) {
      // this only executes when we have an exception caused by synchronous code
      // TODO logging
      console.log(err)
      throw new Error(`Uncaught error in '${this._functionKey}' handler.`)
    }

    // // not a Promise, which is not supported by aws
    // if (result == null || typeof result.then !== 'function') {
    //   throw new Error(`Synchronous function execution is not supported.`)
    // }

    const callbacks = [callbackCalled]

    // Promise was returned
    if (result != null && typeof result.then === 'function') {
      callbacks.push(result)
    }

    let callbackResult

    try {
      callbackResult = await Promise.race(callbacks)
    } catch (err) {
      // TODO logging
      console.log(err)
      throw err
    }

    return callbackResult
  }
}
<|endoftext|>


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

const log = require('../net2/logger.js')(__filename);
const util = require('util');
const dgram = require('dgram');
const ip = require('ip');
const SysManager = require('../net2/SysManager.js');
const sysManager = new SysManager('info');

const Sensor = require('./Sensor.js').Sensor;

class FirewallaDiscoverSensor extends Sensor {
  constructor() {
    super();
    this.ip = sysManager.myIp();
    this.subnet = sysManager.mySubnet();
    this.cidr = ip.cidrSubnet(this.subnet);
  }

  _getPongResponse() {
    return util.format("pong %s", this.ip);
  }

  run() {
    const socket = dgram.createSocket('udp4');
    const port = this.config.listenPort || 4096;

    socket.on('listening', () => {
      socket.setBroadcast(true);
      setInterval(() => {
        const broadcastAddr = this.cidr.broadcastAddress;
        log.info("Ping " + broadcastAddr);
        socket.send("ping", port, broadcastAddr);
      }, 60 * 1000);
    });

    socket.on('message', (message, info) => {
      if (message.toString() === "ping") {
        log.info(util.format("Received ping request from %s:%d", info.address, info.port));
        if (info.address === this.ip) {
          log.info("Ignore ping request from localhost");
        } else {
          const response = this._getPongResponse();
          socket.send(response, info.port, info.address);
        }
      }
      if (message.toString() === "pong") {
        log.info(util.format("Received pong response from %s:%d", info.address, info.port));
        // Another firewalla box might be found in the same subnet. Further actions can be applied, e.g., generate notification?
      }
    });

    socket.bind(port, "0.0.0.0");
  }
}

module.exports = FirewallaDiscoverSensor;<commit_msg>reduce logs<commit_after>/*    Copyright 2016 Firewalla LLC
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
'use strict';

const log = require('../net2/logger.js')(__filename);
const util = require('util');
const dgram = require('dgram');
const ip = require('ip');
const SysManager = require('../net2/SysManager.js');
const sysManager = new SysManager('info');

const Sensor = require('./Sensor.js').Sensor;

class FirewallaDiscoverSensor extends Sensor {
  constructor() {
    super();
    this.ip = sysManager.myIp();
    this.subnet = sysManager.mySubnet();
    this.cidr = ip.cidrSubnet(this.subnet);
  }

  _getPongResponse() {
    return util.format("pong %s", this.ip);
  }

  run() {
    const socket = dgram.createSocket('udp4');
    const port = this.config.listenPort || 4096;

    socket.on('listening', () => {
      socket.setBroadcast(true);
      setInterval(() => {
        const broadcastAddr = this.cidr.broadcastAddress;
        log.debug("Ping " + broadcastAddr);
        socket.send("ping", port, broadcastAddr);
      }, 60 * 1000);
    });

    socket.on('message', (message, info) => {
      if (message.toString() === "ping") {
        log.debug(util.format("Received ping request from %s:%d", info.address, info.port));
        if (info.address === this.ip) {
          log.debug("Ignore ping request from localhost");
        } else {
          const response = this._getPongResponse();
          socket.send(response, info.port, info.address);
        }
      }
      if (message.toString() === "pong") {
        log.info(util.format("Received pong response from %s:%d", info.address, info.port));
        // Another firewalla box might be found in the same subnet. Further actions can be applied, e.g., generate notification?
      }
    });

    socket.bind(port, "0.0.0.0");
  }
}

module.exports = FirewallaDiscoverSensor;<|endoftext|>


<commit_before>'use strict';

const assertJump = require('./helpers/assertJump');
var StandardTokenMock = artifacts.require('./helpers/StandardTokenMock.sol');

contract('StandardToken', function(accounts) {

  let token;

  beforeEach(async function() {
    token = await StandardTokenMock.new(accounts[0], 100);
  });

  it('should return the correct totalSupply after construction', async function() {
    let totalSupply = await token.totalSupply();

    assert.equal(totalSupply, 100);
  });

  it('should return the correct allowance amount after approval', async function() {
    let token = await StandardTokenMock.new();
    await token.approve(accounts[1], 100);
    let allowance = await token.allowance(accounts[0], accounts[1]);

    assert.equal(allowance, 100);
  });

  it('should return correct balances after transfer', async function() {
    let token = await StandardTokenMock.new(accounts[0], 100);
    await token.transfer(accounts[1], 100);
    let balance0 = await token.balanceOf(accounts[0]);
    assert.equal(balance0, 0);

    let balance1 = await token.balanceOf(accounts[1]);
    assert.equal(balance1, 100);
  });

  it('should throw an error when trying to transfer more than balance', async function() {
    let token = await StandardTokenMock.new(accounts[0], 100);
    try {
      await token.transfer(accounts[1], 101);
      assert.fail('should have thrown before');
    } catch(error) {
      assertJump(error);
    }
  });

  it('should return correct balances after transfering from another account', async function() {
    let token = await StandardTokenMock.new(accounts[0], 100);
    await token.approve(accounts[1], 100);
    await token.transferFrom(accounts[0], accounts[2], 100, {from: accounts[1]});

    let balance0 = await token.balanceOf(accounts[0]);
    assert.equal(balance0, 0);

    let balance1 = await token.balanceOf(accounts[2]);
    assert.equal(balance1, 100);

    let balance2 = await token.balanceOf(accounts[1]);
    assert.equal(balance2, 0);
  });

  it('should throw an error when trying to transfer more than allowed', async function() {
    await token.approve(accounts[1], 99);
    try {
      await token.transferFrom(accounts[0], accounts[2], 100, {from: accounts[1]});
      assert.fail('should have thrown before');
    } catch (error) {
      assertJump(error);
    }
  });

  describe('validating allowance updates to spender', function() {
    let preApproved;

    it('should start with zero', async function() {
      preApproved = await token.allowance(accounts[0], accounts[1]);
      assert.equal(preApproved, 0);
    })

    it('should increase by 50 then decrease by 10', async function() {
      await token.increaseApproval(accounts[1], 50);
      let postIncrease = await token.allowance(accounts[0], accounts[1]);
      preApproved.plus(50).should.be.bignumber.equal(postIncrease);
      await token.decreaseApproval(accounts[1], 10);
      let postDecrease = await token.allowance(accounts[0], accounts[1]);
      postIncrease.minus(10).should.be.bignumber.equal(postDecrease);
    })
  });

  it('should throw an error when trying to transfer to 0x0', async function() {
    let token = await StandardTokenMock.new(accounts[0], 100);
    try {
      let transfer = await token.transfer(0x0, 100);
      assert.fail('should have thrown before');
    } catch(error) {
      assertJump(error);
    }
  });

  it('should throw an error when trying to transferFrom to 0x0', async function() {
    let token = await StandardTokenMock.new(accounts[0], 100);
    await token.approve(accounts[1], 100);
    try {
      let transfer = await token.transferFrom(accounts[0], 0x0, 100, {from: accounts[1]});
      assert.fail('should have thrown before');
    } catch(error) {
      assertJump(error);
    }
  });

});
<commit_msg>Adding some additional tests<commit_after>'use strict';

const assertJump = require('./helpers/assertJump');
const expectThrow = require('./helpers/expectThrow');
var StandardTokenMock = artifacts.require('./helpers/StandardTokenMock.sol');

contract('StandardToken', function(accounts) {

  let token;

  beforeEach(async function() {
    token = await StandardTokenMock.new(accounts[0], 100);
  });

  it('should return the correct totalSupply after construction', async function() {
    let totalSupply = await token.totalSupply();

    assert.equal(totalSupply, 100);
  });

  it('should return the correct allowance amount after approval', async function() {
    let token = await StandardTokenMock.new();
    await token.approve(accounts[1], 100);
    let allowance = await token.allowance(accounts[0], accounts[1]);

    assert.equal(allowance, 100);
  });

  it('should return correct balances after transfer', async function() {
    let token = await StandardTokenMock.new(accounts[0], 100);
    await token.transfer(accounts[1], 100);
    let balance0 = await token.balanceOf(accounts[0]);
    assert.equal(balance0, 0);

    let balance1 = await token.balanceOf(accounts[1]);
    assert.equal(balance1, 100);
  });

  it('should throw an error when trying to transfer more than balance', async function() {
    let token = await StandardTokenMock.new(accounts[0], 100);
    try {
      await token.transfer(accounts[1], 101);
      assert.fail('should have thrown before');
    } catch(error) {
      assertJump(error);
    }
  });

  it('should return correct balances after transfering from another account', async function() {
    let token = await StandardTokenMock.new(accounts[0], 100);
    await token.approve(accounts[1], 100);
    await token.transferFrom(accounts[0], accounts[2], 100, {from: accounts[1]});

    let balance0 = await token.balanceOf(accounts[0]);
    assert.equal(balance0, 0);

    let balance1 = await token.balanceOf(accounts[2]);
    assert.equal(balance1, 100);

    let balance2 = await token.balanceOf(accounts[1]);
    assert.equal(balance2, 0);
  });

  it('should throw an error when trying to transfer more than allowed', async function() {
    await token.approve(accounts[1], 99);
    try {
      await token.transferFrom(accounts[0], accounts[2], 100, {from: accounts[1]});
      assert.fail('should have thrown before');
    } catch (error) {
      assertJump(error);
    }
  });

  it('should throw an error when trying to transferFrom more than _from has', async function() {
    let balance0 = await token.balanceOf(accounts[0]);
    await token.approve(accounts[1], 99);
    try {
      await token.transferFrom(accounts[0], accounts[2], balance0+1, {from: accounts[1]});
      assert.fail('should have thrown before');
    } catch (error) {
      assertJump(error);
    }
  });

  describe('validating allowance updates to spender', function() {
    let preApproved;

    it('should start with zero', async function() {
      preApproved = await token.allowance(accounts[0], accounts[1]);
      assert.equal(preApproved, 0);
    })

    it('should increase by 50 then decrease by 10', async function() {
      await token.increaseApproval(accounts[1], 50);
      let postIncrease = await token.allowance(accounts[0], accounts[1]);
      preApproved.plus(50).should.be.bignumber.equal(postIncrease);
      await token.decreaseApproval(accounts[1], 10);
      let postDecrease = await token.allowance(accounts[0], accounts[1]);
      postIncrease.minus(10).should.be.bignumber.equal(postDecrease);
    })
  });

  it('should increase by 50 then set to 0 when decreasing by more than 50', async function() {
    await token.approve(accounts[1], 50);
    await token.decreaseApproval(accounts[1], 60);
    let postDecrease = await token.allowance(accounts[0], accounts[1]);
    postDecrease.should.be.bignumber.equal(0);
});

  it('should throw an error when trying to transfer to 0x0', async function() {
    let token = await StandardTokenMock.new(accounts[0], 100);
    try {
      let transfer = await token.transfer(0x0, 100);
      assert.fail('should have thrown before');
    } catch(error) {
      assertJump(error);
    }
  });

  it('should throw an error when trying to transferFrom to 0x0', async function() {
    let token = await StandardTokenMock.new(accounts[0], 100);
    await token.approve(accounts[1], 100);
    try {
      let transfer = await token.transferFrom(accounts[0], 0x0, 100, {from: accounts[1]});
      assert.fail('should have thrown before');
    } catch(error) {
      assertJump(error);
    }
  });

});
<|endoftext|>


<commit_before>var JX = require('javelin').JX;
JX.require('AphlictListener', __dirname);

JX.install('AphlictListenerList', {
  construct: function() {
    this._listeners = {};
  },

  members: {
    _listeners: null,
    _nextID: 0,
    _activeListenerCount: 0,
    _totalListenerCount: 0,

    addListener: function(socket) {
      var listener = new JX.AphlictListener(this._generateNextID(), socket);

      this._listeners[listener.getID()] = listener;
      this._activeListenerCount++;
      this._totalListenerCount++;

      return listener;
    },

    removeListener: function(listener) {
      var id = listener.getID();
      if (id in this._listeners) {
        delete this._listeners[id];
        this._activeListenerCount--;
      }
    },

    getListeners: function() {
      var keys = Object.keys(this._listeners);
      var listeners = [];

      for (var i = 0; i < keys.length; i++) {
        listeners.push(this._listeners[keys[i]]);
      }

      return listeners;
    },

    getActiveListenerCount: function() {
      return this._activeListenerCount;
    },

    getTotalListenerCount: function() {
      return this._totalListenerCount;
    },

    _generateNextID: function() {
      do {
        this._nextID = ((this._nextID + 1) % 1000000000000);
      } while (this._nextID in this._listeners);

      return this._nextID;
    }

  }

});
<commit_msg>Don't explicitly keep track of `_activeListenerCount` in the Aphlict server.<commit_after>var JX = require('javelin').JX;
JX.require('AphlictListener', __dirname);

JX.install('AphlictListenerList', {
  construct: function() {
    this._listeners = {};
  },

  members: {
    _listeners: null,
    _nextID: 0,
    _totalListenerCount: 0,

    addListener: function(socket) {
      var listener = new JX.AphlictListener(this._generateNextID(), socket);

      this._listeners[listener.getID()] = listener;
      this._totalListenerCount++;

      return listener;
    },

    removeListener: function(listener) {
      var id = listener.getID();
      if (id in this._listeners) {
        delete this._listeners[id];
      }
    },

    getListeners: function() {
      var keys = Object.keys(this._listeners);
      var listeners = [];

      for (var i = 0; i < keys.length; i++) {
        listeners.push(this._listeners[keys[i]]);
      }

      return listeners;
    },

    getActiveListenerCount: function() {
      return Object.keys(this._listeners).length;
    },

    getTotalListenerCount: function() {
      return this._totalListenerCount;
    },

    _generateNextID: function() {
      do {
        this._nextID = ((this._nextID + 1) % 1000000000000);
      } while (this._nextID in this._listeners);

      return this._nextID;
    }

  }

});
<|endoftext|>


<commit_before>var conn = new Mongo("localhost:27017");
db       = conn.getDB('vusion');

db.getSiblingDB('vusion2');

var userLog = db.getCollection('user_logs').exists();
if (!this.userLog) {
    db.createCollection('user_logs');
}
db.user_logs.ensureIndex({'timestamp': 1});
<commit_msg>renamed the databasename<commit_after>var conn = new Mongo("localhost:27017");
db       = conn.getDB('vusion');

db.getSiblingDB('vusion');

var userLog = db.getCollection('user_logs').exists();
if (!this.userLog) {
    db.createCollection('user_logs');
}
db.user_logs.ensureIndex({'timestamp': 1});
<|endoftext|>