<commit_before>/*
 * Feedback arrows UX extension.
 * Shows two independent webgl models that should immitate spacenav movement.
 * Object should fade in and fade out on spacenav use.
 */
/*
 * Feedback arrows UX extension.
 * Shows two independent webgl models that should immitate spacenav movement.
 * Object should fade in and fade out on spacenav use.
 */

console.log('Loading Feedback arrows Extension: creating WS socket');

//Let's connect directly to websocket<->ROS bridge
var spacenavROS = new ROSLIB.Ros({
	url : 'ws://master:9090'
});

console.log('Loading Feedback arrows Extension: initializing ROS');

// Define topic object
var feedbackArrowsSpacenavListener = new ROSLIB.Topic({
	ros : spacenavROS,
	name : 'spacenav/twist',
	messageType : 'geometry_msgs/Twist',
	throttle_rate : 50
});

// we'll need a map function
Number.prototype.map = function ( in_min , in_max , out_min , out_max ) {
	  return ( this - in_min ) * ( out_max - out_min ) / ( in_max - in_min ) + out_min;
	}

var ringMultiplier = 0.1;
var arrowMultiplier = 0.1;
var spacenav_min = -350;
var spacenav_max = 350;

var arrows_min = -3;
var arrows_max = 3;

var arrowObjPosition = [ 0, 0, 0, 0, 0, 0 ];
var ringObjPosition = [ 0, 0, 0, 0, 0, 0 ];

// Subscribe to spacenav topic + ROS messages rate limiting
console.log('Loading Feedback arrows Extension: subscribing to spacenav topic');

//Let's normalize values with .map function ( in_min , in_max , out_min , out_max )

feedbackArrowsSpacenavListener.subscribe(function(msg) {
	this.msg = msg;
	if (this.msg.linear.x == 0 && this.msg.linear.y == 0
			&& this.msg.linear.z == 0 && this.msg.angular.x == 0
			&& this.msg.angular.y == 0 && this.msg.angular.z == 0)
		{
		/***
		 * - fade objects out
		 * - return to point 0
		 */
		for (var i = 0; i < arrowObjPosition.length; i++) {
			arrowObjPosition[i] = 0;
			ringObjPosition[i] = 0;
		}
		console.log("Setting opacity to 0");
		this.ring_material.opacity = 0;
		this.arrow_material.opacity = 0;
		return;

	} else {
		/***
		 * - map spacenav values to threejs object coordinates
		 * - fade in
		 * - move objects
		 *
		 *	 ObjPosition =
		 *	 [
		 *	 0 : "go front right",
		 *	 1 : "go up (z)",
		 *	 2 : "go front left",
		 *	 3 : "rotate over y axis",
		 *	 4 : "rotate over center",
		 *	 5 : "rotate over x axis"
		 *	 ]
		 *
		 *	 rostopic echo /spacenav/twist:
		 *
		 *	 [
		 *	 "push then pull" : "linear z -350 => +350",
		 *	 "rotate from left to right" : "angular z: +350 => -350",
		 *	 "move backward then forward" : "linear x -350=>+350",
		 *	 "move left then right" : "linear y +350 => -350",
		 *	 "lean left then lean right" : "angular x -350 => +350",
		 *	 "lean forward then lean backward" : "angular y +350 => -350"
		 *	 ]
		 *
		 ***/

		// needed for arrow
		this.msg.linear.x = this.msg.linear.x.map(spacenav_min, spacenav_max, -1, 1);
		this.msg.linear.y = this.msg.linear.y.map(spacenav_min, spacenav_max, -1, 1);

		// needed for ring
		this.msg.linear.z = this.msg.linear.z.map(spacenav_min, spacenav_max, arrows_min, arrows_max);
		this.msg.angular.x = this.msg.angular.x.map(spacenav_min, spacenav_max, arrows_min, arrows_max);
		this.msg.angular.y = this.msg.angular.y.map(spacenav_min, spacenav_max, arrows_min, arrows_max);
		this.msg.angular.z = this.msg.angular.z.map(spacenav_min, spacenav_max, arrows_min, arrows_max);

		// make object transparency proportional to the values
		this.ring_material.opacity = 1;
		this.arrow_material.opacity = 1;
		console.log("Setting opacity to 1");

		// pull up , push down
		ringObjPosition[1] = this.msg.linear.z;
		// rotate (twist)
		ringObjPosition[4] = this.msg.angular.z * 0.5;
		console.log("this.msg.angular.z =>", this.msg.angular.z);
		// lean forward and backward
		ringObjPosition[5] = this.msg.angular.x * -0.1;
		ringObjPosition[3] = this.msg.angular.y * -0.1;

		// let's rotate and show the direction arrow with little tresholding
		if ((abs(this.msg.linear.y) > 0.2) && (abs(this.msg.linear.x) > 0.2)) {
			this.msg.linear.y = this.msg.linear.y * -1;
			direction = (Math.atan2(this.msg.linear.y, this.msg.linear.x)
					/ Math.PI * 180)
					/ -18;
			console.log("This is direction1:", direction,
					"computed out of (x,y)", this.msg.linear.y, "/",
					this.msg.linear.x);
			arrowObjPosition[4] = direction;
		}
	}

});

// Three.js part
var container, stats;
var camera, scene, renderer;
var mouseX = 0, mouseY = 0;

var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

console.log("Arrows: before init");
init();
console.log("Arrows: after init");
console.log("Arrows: before animate");
animate();
console.log("Arrows: after animate");

function init() {
	container = document.createElement('div');
	container.id = 'feedback_arrows';
	document.body.appendChild(container);

	camera = new THREE.PerspectiveCamera(45, window.innerWidth
			/ window.innerHeight, 1, 2000);
	camera.position.x = 0;
	camera.position.y = 10;
	camera.position.z = 33;

	// scene

	scene = new THREE.Scene();

	var ambient = new THREE.AmbientLight(0x101030);
	scene.add(ambient);

	var directionalLight = new THREE.DirectionalLight(0xffeedd);
	directionalLight.position.set(0, 0, 1);
	scene.add(directionalLight);

	// texture

	var manager = new THREE.LoadingManager();
	manager.onProgress = function(item, loaded, total) {

		console.log(item, loaded, total);

	};

	var texture = new THREE.Texture();
	var imaginator = new Image();
	imaginator.src = "data:image/jpeg;base64,"
			+ "R0lGODlhkAGQAfAAAP///wAAACH5BAAAAAAAIf4Kc2NyaThlLmNvbQAsAAAAAJABkAEAAv6Ej6nL7Q+jnLTai7PevPsPhuJIluaJpurKtu4Lx/JM1/aN5/rO9/4PDAqHxKLxiEwql8ym8wmNSqfUqvWKzWq33K73Cw6Lx+Sy+YxOq9fstvsNj8vn9Lr9js/r9/y+/w8YKDhIWGh4iJiouMjY6PgIGSk5SVlpeYmZqbnJ2en5CRoqOkpaanqKmqq6ytrq+gobKztLW2t7i5uru8vb6/sLHCw8TFxsfIycrLzM3Oz8DB0tPU1dbX2Nna29zd3t/Q0eLj5OXm5+jp6uvs7e7v4OHy8/T19vf4+fr7/P3+//DzCgwIEECxo8iDChwoUMGzp8CDGixIkUK1q8iDGjxv6NHDt6/AgypMiRJEuaPIkypcqVLFu6fAkzpsyZNGvavIkzp86dPHv6/Ak0qNChRIsaPYo0qdKlTJs6fQo1qtSpVKtavYo1q9atXLt6/Qo2rNixZMuaPYs2rdq1bNu6fQs3rty5dOvavYs3r969fPv6/Qs4sODBhAsbPow4seLFjBs7fgw5suTJlCtbvow5s+bNnDt7/gw6tOjRpEubPo06terVrFu7fg07tuzZtGvbvo07t+7dvHv7/g08uPDhxIsbP448ufLlzJs7fw49uvTp1Ktbv449u/bt3Lt7/w4+vPjx5MubP48+vfr17Nu7fw8/vvz59Ovbv48/v/79/E/7+/8PYIACDkhggQYeiGCCCi7IYIMOPghhhBJOSGGFFl6IYYYabshhhx5+CGKIIo5IYokmnohiiiquyGKLLr4IY4wyzkhjjTbeiGOObRQAADs="
	texture.image = imaginator;
	texture.needsUpdate = true;
	// EOFD

	var arrows_loader = new THREE.OBJLoader(manager);
	arrows_loader.load(chrome.extension.getURL('models/arrow.obj'), function(
			arrow_object) {
		this.arrowObj = arrow_object;
		arrow_object.traverse(function(child) {
			if (child instanceof THREE.Mesh) {
				child.material.map = texture;
				this.arrow_material = child.material;
				this.arrow_material.transparent = true;
			}
		});
		scene.add(arrow_object);
	});

	var ring_loader = new THREE.OBJLoader(manager);
	ring_loader.load(chrome.extension.getURL('models/ring.obj'), function(
			ring_object) {
		this.ringObj = ring_object;
		ring_object.traverse(function(child) {
			if (child instanceof THREE.Mesh) {
				child.material.map = texture;
				this.ring_material = child.material;
				this.ring_material.transparent = true;
			}
		});
		scene.add(ring_object);
	});

	//

	// let's make transparent background
	renderer = new THREE.WebGLRenderer({
		alpha : true
	});
	renderer.setSize(window.innerWidth, window.innerHeight);
	container.appendChild(renderer.domElement);
	renderer.setClearColor(0x000000, 0);
	window.addEventListener('resize', onWindowResize, false);

}

// we need this for debug purposes
function onWindowResize() {
	windowHalfX = window.innerWidth / 2;
	windowHalfY = window.innerHeight / 2;
	camera.aspect = window.innerWidth / window.innerHeight;
	camera.updateProjectionMatrix();
	renderer.setSize(window.innerWidth, window.innerHeight);
}

//

function animate() {
	requestAnimationFrame(animate);
	render();
}

function render() {
	if (arrowObj != undefined) {
		arrowObj.position.x = arrowObjPosition[0];
		arrowObj.position.y = arrowObjPosition[1];
		arrowObj.position.z = arrowObjPosition[2];
		arrowObj.rotation.x = arrowObjPosition[3];
		arrowObj.rotation.y = arrowObjPosition[4];
		arrowObj.rotation.z = arrowObjPosition[5];
	}
	if (ringObj != undefined) {
		ringObj.position.x = ringObjPosition[0];
		ringObj.position.y = ringObjPosition[1];
		ringObj.position.z = ringObjPosition[2];
		ringObj.rotation.x = ringObjPosition[3];
		ringObj.rotation.y = ringObjPosition[4];
		ringObj.rotation.z = ringObjPosition[5];
	}
	camera.lookAt(scene.position);
	renderer.render(scene, camera);
}
<commit_msg>More debug<commit_after>/*
 * Feedback arrows UX extension.
 * Shows two independent webgl models that should immitate spacenav movement.
 * Object should fade in and fade out on spacenav use.
 */
/*
 * Feedback arrows UX extension.
 * Shows two independent webgl models that should immitate spacenav movement.
 * Object should fade in and fade out on spacenav use.
 */

console.log('Loading Feedback arrows Extension: creating WS socket');

//Let's connect directly to websocket<->ROS bridge
var spacenavROS = new ROSLIB.Ros({
	url : 'ws://master:9090'
});

console.log('Loading Feedback arrows Extension: initializing ROS');

// Define topic object
var feedbackArrowsSpacenavListener = new ROSLIB.Topic({
	ros : spacenavROS,
	name : 'spacenav/twist',
	messageType : 'geometry_msgs/Twist',
	throttle_rate : 50
});

// we'll need a map function
Number.prototype.map = function ( in_min , in_max , out_min , out_max ) {
	  return ( this - in_min ) * ( out_max - out_min ) / ( in_max - in_min ) + out_min;
	}

var ringMultiplier = 0.1;
var arrowMultiplier = 0.1;
var spacenav_min = -350;
var spacenav_max = 350;

var arrows_min = -3;
var arrows_max = 3;

var arrowObjPosition = [ 0, 0, 0, 0, 0, 0 ];
var ringObjPosition = [ 0, 0, 0, 0, 0, 0 ];

// Subscribe to spacenav topic + ROS messages rate limiting
console.log('Loading Feedback arrows Extension: subscribing to spacenav topic');

//Let's normalize values with .map function ( in_min , in_max , out_min , out_max )

feedbackArrowsSpacenavListener.subscribe(function(msg) {
	this.msg = msg;
	if (this.msg.linear.x == 0 && this.msg.linear.y == 0
			&& this.msg.linear.z == 0 && this.msg.angular.x == 0
			&& this.msg.angular.y == 0 && this.msg.angular.z == 0)
		{
		/***
		 * - fade objects out
		 * - return to point 0
		 */
		for (var i = 0; i < arrowObjPosition.length; i++) {
			arrowObjPosition[i] = 0;
			ringObjPosition[i] = 0;
		}
		console.log("Setting opacity to 0");
		this.ring_material.opacity = 0;
		this.arrow_material.opacity = 0;
		return;

	} else {
		/***
		 * - map spacenav values to threejs object coordinates
		 * - fade in
		 * - move objects
		 *
		 *	 ObjPosition =
		 *	 [
		 *	 0 : "go front right",
		 *	 1 : "go up (z)",
		 *	 2 : "go front left",
		 *	 3 : "rotate over y axis",
		 *	 4 : "rotate over center",
		 *	 5 : "rotate over x axis"
		 *	 ]
		 *
		 *	 rostopic echo /spacenav/twist:
		 *
		 *	 [
		 *	 "push then pull" : "linear z -350 => +350",
		 *	 "rotate from left to right" : "angular z: +350 => -350",
		 *	 "move backward then forward" : "linear x -350=>+350",
		 *	 "move left then right" : "linear y +350 => -350",
		 *	 "lean left then lean right" : "angular x -350 => +350",
		 *	 "lean forward then lean backward" : "angular y +350 => -350"
		 *	 ]
		 *
		 ***/

		// needed for arrow
		this.msg.linear.x = this.msg.linear.x.map(spacenav_min, spacenav_max, -1, 1);
		this.msg.linear.y = this.msg.linear.y.map(spacenav_min, spacenav_max, -1, 1);

		// needed for ring
		this.msg.linear.z = this.msg.linear.z.map(spacenav_min, spacenav_max, arrows_min, arrows_max);
		this.msg.angular.x = this.msg.angular.x.map(spacenav_min, spacenav_max, arrows_min, arrows_max);
		this.msg.angular.y = this.msg.angular.y.map(spacenav_min, spacenav_max, arrows_min, arrows_max);
		this.msg.angular.z = this.msg.angular.z.map(spacenav_min, spacenav_max, arrows_min, arrows_max);

		// make object transparency proportional to the values
		this.ring_material.opacity = 1;
		this.arrow_material.opacity = 1;
		console.log("Setting opacity to 1");

		// pull up , push down
		ringObjPosition[1] = this.msg.linear.z;
		// rotate (twist)
		ringObjPosition[4] = this.msg.angular.z * 0.5;
		console.log("this.msg.angular.z =>", this.msg.angular.z);
		// lean forward and backward
		ringObjPosition[5] = this.msg.angular.x * -0.1;
		ringObjPosition[3] = this.msg.angular.y * -0.1;

		// let's rotate and show the direction arrow with little tresholding
		console.log("(abs(this.msg.linear.y) > 0.2) || (abs(this.msg.linear.x) > 0.2)", (abs(this.msg.linear.y) > 0.2), "/", (abs(this.msg.linear.x) > 0.2))
		if ((abs(this.msg.linear.y) > 0.2) || (abs(this.msg.linear.x) > 0.2)) {
			this.msg.linear.y = this.msg.linear.y * -1;
			direction = (Math.atan2(this.msg.linear.y, this.msg.linear.x)/ Math.PI * 180)/ -18;
			console.log("This is direction1:", direction,
					"computed out of (x,y)", this.msg.linear.y, "/",
					this.msg.linear.x);
			arrowObjPosition[4] = direction;
		}
	}

});

// Three.js part
var container, stats;
var camera, scene, renderer;
var mouseX = 0, mouseY = 0;

var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

console.log("Arrows: before init");
init();
console.log("Arrows: after init");
console.log("Arrows: before animate");
animate();
console.log("Arrows: after animate");

function init() {
	container = document.createElement('div');
	container.id = 'feedback_arrows';
	document.body.appendChild(container);

	camera = new THREE.PerspectiveCamera(45, window.innerWidth
			/ window.innerHeight, 1, 2000);
	camera.position.x = 0;
	camera.position.y = 10;
	camera.position.z = 33;

	// scene

	scene = new THREE.Scene();

	var ambient = new THREE.AmbientLight(0x101030);
	scene.add(ambient);

	var directionalLight = new THREE.DirectionalLight(0xffeedd);
	directionalLight.position.set(0, 0, 1);
	scene.add(directionalLight);

	// texture

	var manager = new THREE.LoadingManager();
	manager.onProgress = function(item, loaded, total) {

		console.log(item, loaded, total);

	};

	var texture = new THREE.Texture();
	var imaginator = new Image();
	imaginator.src = "data:image/jpeg;base64,"
			+ "R0lGODlhkAGQAfAAAP///wAAACH5BAAAAAAAIf4Kc2NyaThlLmNvbQAsAAAAAJABkAEAAv6Ej6nL7Q+jnLTai7PevPsPhuJIluaJpurKtu4Lx/JM1/aN5/rO9/4PDAqHxKLxiEwql8ym8wmNSqfUqvWKzWq33K73Cw6Lx+Sy+YxOq9fstvsNj8vn9Lr9js/r9/y+/w8YKDhIWGh4iJiouMjY6PgIGSk5SVlpeYmZqbnJ2en5CRoqOkpaanqKmqq6ytrq+gobKztLW2t7i5uru8vb6/sLHCw8TFxsfIycrLzM3Oz8DB0tPU1dbX2Nna29zd3t/Q0eLj5OXm5+jp6uvs7e7v4OHy8/T19vf4+fr7/P3+//DzCgwIEECxo8iDChwoUMGzp8CDGixIkUK1q8iDGjxv6NHDt6/AgypMiRJEuaPIkypcqVLFu6fAkzpsyZNGvavIkzp86dPHv6/Ak0qNChRIsaPYo0qdKlTJs6fQo1qtSpVKtavYo1q9atXLt6/Qo2rNixZMuaPYs2rdq1bNu6fQs3rty5dOvavYs3r969fPv6/Qs4sODBhAsbPow4seLFjBs7fgw5suTJlCtbvow5s+bNnDt7/gw6tOjRpEubPo06terVrFu7fg07tuzZtGvbvo07t+7dvHv7/g08uPDhxIsbP448ufLlzJs7fw49uvTp1Ktbv449u/bt3Lt7/w4+vPjx5MubP48+vfr17Nu7fw8/vvz59Ovbv48/v/79/E/7+/8PYIACDkhggQYeiGCCCi7IYIMOPghhhBJOSGGFFl6IYYYabshhhx5+CGKIIo5IYokmnohiiiquyGKLLr4IY4wyzkhjjTbeiGOObRQAADs="
	texture.image = imaginator;
	texture.needsUpdate = true;
	// EOFD

	var arrows_loader = new THREE.OBJLoader(manager);
	arrows_loader.load(chrome.extension.getURL('models/arrow.obj'), function(
			arrow_object) {
		this.arrowObj = arrow_object;
		arrow_object.traverse(function(child) {
			if (child instanceof THREE.Mesh) {
				child.material.map = texture;
				this.arrow_material = child.material;
				this.arrow_material.transparent = true;
			}
		});
		scene.add(arrow_object);
	});

	var ring_loader = new THREE.OBJLoader(manager);
	ring_loader.load(chrome.extension.getURL('models/ring.obj'), function(
			ring_object) {
		this.ringObj = ring_object;
		ring_object.traverse(function(child) {
			if (child instanceof THREE.Mesh) {
				child.material.map = texture;
				this.ring_material = child.material;
				this.ring_material.transparent = true;
			}
		});
		scene.add(ring_object);
	});

	//

	// let's make transparent background
	renderer = new THREE.WebGLRenderer({
		alpha : true
	});
	renderer.setSize(window.innerWidth, window.innerHeight);
	container.appendChild(renderer.domElement);
	renderer.setClearColor(0x000000, 0);
	window.addEventListener('resize', onWindowResize, false);

}

// we need this for debug purposes
function onWindowResize() {
	windowHalfX = window.innerWidth / 2;
	windowHalfY = window.innerHeight / 2;
	camera.aspect = window.innerWidth / window.innerHeight;
	camera.updateProjectionMatrix();
	renderer.setSize(window.innerWidth, window.innerHeight);
}

//

function animate() {
	requestAnimationFrame(animate);
	render();
}

function render() {
	if (arrowObj != undefined) {
		arrowObj.position.x = arrowObjPosition[0];
		arrowObj.position.y = arrowObjPosition[1];
		arrowObj.position.z = arrowObjPosition[2];
		arrowObj.rotation.x = arrowObjPosition[3];
		arrowObj.rotation.y = arrowObjPosition[4];
		arrowObj.rotation.z = arrowObjPosition[5];
	}
	if (ringObj != undefined) {
		ringObj.position.x = ringObjPosition[0];
		ringObj.position.y = ringObjPosition[1];
		ringObj.position.z = ringObjPosition[2];
		ringObj.rotation.x = ringObjPosition[3];
		ringObj.rotation.y = ringObjPosition[4];
		ringObj.rotation.z = ringObjPosition[5];
	}
	camera.lookAt(scene.position);
	renderer.render(scene, camera);
}
<|endoftext|>


<commit_before>'use strict';

function DebugLogger(name, enabled) {
  this.name = name;
  this.enabled = enabled;
}

DebugLogger.prototype.enable = function() {
  this.enabled = true;
};

DebugLogger.prototype.disable = function() {
  this.enabled = false;
};

DebugLogger.prototype.group = function() {
  if (this.enabled) {
    console.group.apply(console, arguments);
  }
};

DebugLogger.prototype.groupCollapsed = function() {
  if (this.enabled) {
    console.groupCollapsed.apply(console, arguments);
  }
};

DebugLogger.prototype.groupEnd = function() {
  if (this.enabled) {
    console.groupEnd.apply(console, arguments);
  }
};

DebugLogger.prototype.debug = function() {
  if (this.enabled) {
    console.debug.apply(console, arguments);
  }
};

var netConsole = new DebugLogger('net', !config.disableNetLog);
var gomConsole = new DebugLogger('lua', !config.disableGomLog);
var luaConsole = new DebugLogger('lua', !config.disableLuaLog);
var qsdConsole = new DebugLogger('qsd', !config.disableQsdLog);
<commit_msg>Add .warn and .error to DebugLogger<commit_after>'use strict';

function DebugLogger(name, enabled) {
  this.name = name;
  this.enabled = enabled;
}

DebugLogger.prototype.enable = function() {
  this.enabled = true;
};

DebugLogger.prototype.disable = function() {
  this.enabled = false;
};

DebugLogger.prototype.group = function() {
  if (this.enabled) {
    console.group.apply(console, arguments);
  }
};

DebugLogger.prototype.groupCollapsed = function() {
  if (this.enabled) {
    console.groupCollapsed.apply(console, arguments);
  }
};

DebugLogger.prototype.groupEnd = function() {
  if (this.enabled) {
    console.groupEnd.apply(console, arguments);
  }
};

DebugLogger.prototype.debug = function() {
  if (this.enabled) {
    console.debug.apply(console, arguments);
  }
};

DebugLogger.prototype.warn = function() {
  if (this.enabled) {
    console.warn.apply(console, arguments);
  }
};

DebugLogger.prototype.error = function() {
  if (this.enabled) {
    console.error.apply(console, arguments);
  }
};

var netConsole = new DebugLogger('net', !config.disableNetLog);
var gomConsole = new DebugLogger('lua', !config.disableGomLog);
var luaConsole = new DebugLogger('lua', !config.disableLuaLog);
var qsdConsole = new DebugLogger('qsd', !config.disableQsdLog);
<|endoftext|>


<commit_before>/**
* map tab shown in cartodb admin
*/

cdb.admin.MapTab = cdb.core.View.extend({

  events: {
    'click .share a': 'shareMap'
  },

  className: 'map',
  animation_time: 300,

  initialize: function() {
    this.template = this.getTemplate('table/views/maptab');
    this.map = this.model;
    this.map_enabled = false;
    this.featureHovered = null;
    this.infowindowModel = this.options.infowindow;
    this.georeferenced = false;

    //this.add_related_model(this.options.dataLayer);
    this.add_related_model(this.map);
    this.add_related_model(this.options.table);
    this.add_related_model(this.infowindowModel);

    var self = this;

    cdb.god.bind("hidePanel", function(ev) {
      self._moveRightButtons("hide");
    });
    cdb.god.bind("showPanel", function(ev) {
      self._moveRightButtons("show");
    });
    cdb.god.bind("narrowPanel", function(ev) {
      self._moveRightButtons("narrow");
    });

    this.map.bind('change:provider', this.switchMapType, this);
    this.options.table.bind('change:privacy', this._setPrivacy, this);
    this.options.table.bind('change:dataSource', this._hideInfowindow, this);

    this.options.table.bind('change', function() {
      this.checkGeoRef();
    }, this);

    _.bindAll(this, 'showNoGeoRefWarning');
  },

  clearMap: function() {

    this.mapView.clean();
    this.zoom.clean();
    this.infowindow.clean();

    delete this.mapView;
    delete this.zoom;
    delete this.infowindow;

    this.map_enabled = false;
  },

  /**
   *  Hide the infowindow when a query is applied or cleared
   */
  _hideInfowindow: function() {
    if(this.infowindow) {
      this.infowindow.model.set('visibility', false);
    }
  },

  _setPrivacy: function() {
    if (this.options.table.get('privacy').toLowerCase() != "public") {
      this.$el.find('div.share a').addClass('disabled');
    } else {
      this.$el.find('div.share a').removeClass('disabled');
    }
  },

  /**
  * this function is used when the map library is changed. Each map library
  * works in different way and need to recreate all the components again
  */
  switchMapType: function() {

    if (this.map_enabled) {
      this.clearMap();
      this.render();
      this.enableMap();
    }
  },

  /**
  * map can't be loaded from the beggining, it needs the DOM to be loaded
  * so we wait until is actually shown to create the mapview and show it
  */
  enableMap: function() {
    this.$('.tipsy').remove();
    var self = this;

    if (!this.map_enabled) {
      var div = this.$('#map')
      , base_maps = this.$('.base_maps');

      if (!this.baseLayerChooser) {

        this.baseLayerChooser = new cdb.admin.BaseMapChooser({
          model: this.map,
          baseLayers: this.options.baseLayers
        });

      }

      base_maps.append(this.baseLayerChooser.render().el);

      var mapViewClass = cdb.geo.LeafletMapView;
      if(this.map.get('provider') === 'googlemaps') {
        mapViewClass = cdb.geo.GoogleMapsMapView;
      }

      this.mapView = new mapViewClass({
        el: div,
        map: this.map
      });
      this.retrigger('editInfoWindow', this.mapView);

      this.clickTimeout = null;
      this._bindMissingClickEvents();

      this.map_enabled = true;

      this.mapView.bind('newLayerView', self._bindDataLayer, self);

      // bind data layer if it is already added to the map
      var dataLayer = this.map.get('dataLayer');
      if(dataLayer) {
        var dl = this.mapView.getLayerByCid(self.map.get('dataLayer').cid);
        this._bindDataLayer(dl);
      }

      // Zoom control
      var zoomControl = new cdb.geo.ui.Zoom({
        model:    this.map,
        template: cdb.templates.getTemplate("table/views/zoom_control")
      });
      this.$el.append(zoomControl.render().$el);
      this.zoom = zoomControl;

      // Search control
      var searchControl = new cdb.geo.ui.Search({
        model:    this.map,
        template: cdb.templates.getTemplate("table/views/search_control")
      });
      this.$el.append(searchControl.render().$el);
      this.search = searchControl;

      // Tiles loader
      var tilesLoader = this.loader = new cdb.admin.TilesLoader({
        template: cdb.templates.getTemplate("table/views/tiles_loader")
      });
      this.$el.append(tilesLoader.render().$el);

      // Infowindow
      self.infowindow = new cdb.admin.MapInfowindow({
        model: self.infowindowModel,
        //template: cdb.templates.getTemplate('table/views/infowindow'),
        mapView: self.mapView,
        table: self.options.table
      });
      self.mapView.$el.append(self.infowindow.el);
      self.retrigger('editInfoWindow', this.infowindow);

      // Editing geometry
      this.geometryEditor = new cdb.admin.GeometryEditor({
        model: this.options.table
      });
      this.geometryEditor.mapView = this.mapView;
      self.mapView.$el.append(self.geometryEditor.render().el);
      this.geometryEditor.hide();

      this.geometryEditor.bind('editStart', this.hideDataLayer, this);
      this.geometryEditor.bind('editDiscard', this.showDataLayer, this);
      this.geometryEditor.bind('editFinish', this.showDataLayer, this);
      this.geometryEditor.bind('editFinish', this.updateDataLayerView, this);
      self.infowindow.bind('editGeom', this.geometryEditor.editGeom, this.geometryEditor);
      self.infowindow.bind('removeGeom', this.updateDataLayerView, this);

      this.options.table.bind('change:dataSource', function() {
        self.geometryEditor.discard();
      });

      // HACK
      // wait a little bit to give time to the mapview
      // to estabilize
      setTimeout(function() {
        self.mapView.setAutoSaveBounds();
      }, 1000);
    }
  },

  activated: function() {
   this.checkGeoRef();
  },

  checkGeoRef: function() {
    if(!this.options.table.isGeoreferenced()) {
      this.trigger('noGeoRef');
      this.showNoGeoRefWarning();
      this.georeferenced = false;
    } else {
      this.trigger('geoRef');
      if(!this.georeferenced) {
        var dataLayer = this.map.get('dataLayer');
        if(dataLayer) {
          dataLayer.invalidate();
        }
      }
      this.georeferenced = true;
      if(this.noGeoRefDialog) {
        this.noGeoRefDialog.hide();
      }
    }
  },

  /**
  * this function binds click and dblclick events
  * in order to not raise click when user does a dblclick
  *
  * it raises a missingClick when the user clicks on the map
  * but not over a feature or ui component
  */
  _bindMissingClickEvents: function() {
    var self = this;
    this.mapView.bind('click', function(e) {
      if(self.clickTimeout === null) {
        self.clickTimeout = setTimeout(function() {
          self.clickTimeout = null;
          if(!self.featureHovered) {
            self.trigger('missingClick');
          }
        }, 150);
      }
      //google maps does not send an event
      if(!self.featureHovered && e.preventDefault) {
        e.preventDefault();
        e.stopPropagation();
      }
    });

    this.mapView.bind('dblclick', function() {
      if(self.clickTimeout !== null) {
        clearTimeout(self.clickTimeout);
        self.clickTimeout = null;
      }
    });
  },

  /**
  * when the layer view is created this method is called
  * to attach all the click events
  */
  _bindDataLayer: function(layer) {
    var self = this;

    var layerType = layer.model.get('type');

    if (layerType === 'CartoDB') { // unbind previos stuff

      if (self.layerDataView) {
        self.layerDataView.unbind(null, null, this);
      }
      var dataLayer = self.map.get('dataLayer');

      this.options.table.bind('change:schema', function() {
        //dataLayer.invalidate();
      }, this);

      if (dataLayer) {

        var cid = dataLayer.cid;

        self.layerDataView = self.mapView.getLayerByCid(cid);

        if (self.layerDataView) {
          self.layerDataView.bind('featureClick', self.featureClick, self);
          self.layerDataView.bind('featureOut',   self.featureOut,   self);
          self.layerDataView.bind('featureOver',  self.featureOver,  self);
          self.layerDataView.bind('loading',      self.loadingTiles, self);
          self.layerDataView.bind('load',         self.loadTiles,    self);
        }
      }
    }
  },

  loadingTiles: function() {
    this.loader.show()
  },

  loadTiles: function() {
    this.loader.hide()
  },

  featureOver: function(e, latlon, pxPos, data) {
    this.mapView.setCursor('pointer');
    this.featureHovered = data;
  },

  featureOut: function() {
    this.mapView.setCursor('auto');
    this.featureHovered = null;
  },

  featureClick: function(e, latlon, pxPos, data) {
    if(data.cartodb_id) {
      this.infowindow
      .setLatLng(latlon)
      .setFeatureInfo(data.cartodb_id)
      .showInfowindow();
    } else {
      cdb.log.error("can't show infowindow, no cartodb_id on data");
    }
  },

  /**
   *  Move all necessary buttons when panel is openned or closed
   */
  _moveRightButtons: function(type) {
    var right = 0;
    if (type == "show") {
      right = 592;
    } else if (type == "hide") {
      right = 57;
    } else {
      right = 442;
    }

    this.$el.find("div.share")
      .animate({
        right: right
      }, this.animation_time);

    this.$el.find("div.search_box")
      .animate({
        right: right
      }, this.animation_time);
  },

  render: function() {
    this.$el.html('');
    this.$el.append(this.template());
    return this;
  },

  shareMap: function(e) {
    e.preventDefault();

    var privacy = this.options.table.get('privacy').toLowerCase()
      , dlg
      , center = false;

    // If the table is not public, we'll show a warning dialog
    if (privacy != 'public') {
      dlg = new cdb.admin.NoShareMapDialog({
        map: this.model,
        table: this.options.table
      });
    } else {
      dlg = new cdb.admin.ShareMapDialog({
        map: this.model,
        table: this.options.table
      });
      center = true;
    }

    dlg.appendToBody().open({ center: center });

    return false;
  },

  addGeometry: function() {
    // row is saved by geometry editor if it is needed
    this.geometryEditor.createGeom(this.options.table.data().newRow(), 'polygon');
  },

  showDataLayer: function() {
    this.layerDataView.setOpacity(1.0);
  },

  hideDataLayer: function() {
    //this.layerDataView.hide();
    this.layerDataView.setOpacity(0.5);
  },

  /**
  * reload tiles
  */
  updateDataLayerView: function() {
    this.layerDataView.reload();
  },
  /**
  * Paints a dialog with a warning when the user hasn't any georeferenced row
  * @method showNoGeorefWarning
  */
  showNoGeoRefWarning: function() {
    if(!this.noGeoRefDialog) {
      this.noGeoRefDialog = new cdb.admin.NoGeoRefDataDialog();
      this.retrigger('georeference', this.noGeoRefDialog);
      this.retrigger('manual', this.noGeoRefDialog);
      this.noGeoRefDialog.render().$el.appendTo(this.$el);
    }
    // if the dialog already has been shown, we don't show it again

  }

});

<commit_msg>safety checks<commit_after>/**
* map tab shown in cartodb admin
*/

cdb.admin.MapTab = cdb.core.View.extend({

  events: {
    'click .share a': 'shareMap'
  },

  className: 'map',
  animation_time: 300,

  initialize: function() {
    this.template = this.getTemplate('table/views/maptab');
    this.map = this.model;
    this.map_enabled = false;
    this.featureHovered = null;
    this.infowindowModel = this.options.infowindow;
    this.georeferenced = false;

    //this.add_related_model(this.options.dataLayer);
    this.add_related_model(this.map);
    this.add_related_model(this.options.table);
    this.add_related_model(this.infowindowModel);

    var self = this;

    cdb.god.bind("hidePanel", function(ev) {
      self._moveRightButtons("hide");
    });
    cdb.god.bind("showPanel", function(ev) {
      self._moveRightButtons("show");
    });
    cdb.god.bind("narrowPanel", function(ev) {
      self._moveRightButtons("narrow");
    });

    this.map.bind('change:provider', this.switchMapType, this);
    this.options.table.bind('change:privacy', this._setPrivacy, this);
    this.options.table.bind('change:dataSource', this._hideInfowindow, this);

    this.options.table.bind('change', function() {
      this.checkGeoRef();
    }, this);

    _.bindAll(this, 'showNoGeoRefWarning');
  },

  clearMap: function() {

    this.mapView.clean();
    this.zoom.clean();
    this.infowindow.clean();

    delete this.mapView;
    delete this.zoom;
    delete this.infowindow;

    this.map_enabled = false;
  },

  /**
   *  Hide the infowindow when a query is applied or cleared
   */
  _hideInfowindow: function() {
    if(this.infowindow) {
      this.infowindow.model.set('visibility', false);
    }
  },

  _setPrivacy: function() {
    if (this.options.table.get('privacy').toLowerCase() != "public") {
      this.$el.find('div.share a').addClass('disabled');
    } else {
      this.$el.find('div.share a').removeClass('disabled');
    }
  },

  /**
  * this function is used when the map library is changed. Each map library
  * works in different way and need to recreate all the components again
  */
  switchMapType: function() {

    if (this.map_enabled) {
      this.clearMap();
      this.render();
      this.enableMap();
    }
  },

  /**
  * map can't be loaded from the beggining, it needs the DOM to be loaded
  * so we wait until is actually shown to create the mapview and show it
  */
  enableMap: function() {
    this.$('.tipsy').remove();
    var self = this;

    if (!this.map_enabled) {
      var div = this.$('#map')
      , base_maps = this.$('.base_maps');

      if (!this.baseLayerChooser) {

        this.baseLayerChooser = new cdb.admin.BaseMapChooser({
          model: this.map,
          baseLayers: this.options.baseLayers
        });

      }

      base_maps.append(this.baseLayerChooser.render().el);

      var mapViewClass = cdb.geo.LeafletMapView;
      if(this.map.get('provider') === 'googlemaps') {
        mapViewClass = cdb.geo.GoogleMapsMapView;
      }

      this.mapView = new mapViewClass({
        el: div,
        map: this.map
      });
      this.retrigger('editInfoWindow', this.mapView);

      this.clickTimeout = null;
      this._bindMissingClickEvents();

      this.map_enabled = true;

      this.mapView.bind('newLayerView', self._bindDataLayer, self);

      // bind data layer if it is already added to the map
      var dataLayer = this.map.get('dataLayer');
      if(dataLayer) {
        var dl = this.mapView.getLayerByCid(self.map.get('dataLayer').cid);
        this._bindDataLayer(dl);
      }

      // Zoom control
      var zoomControl = new cdb.geo.ui.Zoom({
        model:    this.map,
        template: cdb.templates.getTemplate("table/views/zoom_control")
      });
      this.$el.append(zoomControl.render().$el);
      this.zoom = zoomControl;

      // Search control
      var searchControl = new cdb.geo.ui.Search({
        model:    this.map,
        template: cdb.templates.getTemplate("table/views/search_control")
      });
      this.$el.append(searchControl.render().$el);
      this.search = searchControl;

      // Tiles loader
      var tilesLoader = this.loader = new cdb.admin.TilesLoader({
        template: cdb.templates.getTemplate("table/views/tiles_loader")
      });
      this.$el.append(tilesLoader.render().$el);

      // Infowindow
      self.infowindow = new cdb.admin.MapInfowindow({
        model: self.infowindowModel,
        //template: cdb.templates.getTemplate('table/views/infowindow'),
        mapView: self.mapView,
        table: self.options.table
      });
      self.mapView.$el.append(self.infowindow.el);
      self.retrigger('editInfoWindow', this.infowindow);

      // Editing geometry
      this.geometryEditor = new cdb.admin.GeometryEditor({
        model: this.options.table
      });
      this.geometryEditor.mapView = this.mapView;
      self.mapView.$el.append(self.geometryEditor.render().el);
      this.geometryEditor.hide();

      this.geometryEditor.bind('editStart', this.hideDataLayer, this);
      this.geometryEditor.bind('editDiscard', this.showDataLayer, this);
      this.geometryEditor.bind('editFinish', this.showDataLayer, this);
      this.geometryEditor.bind('editFinish', this.updateDataLayerView, this);
      self.infowindow.bind('editGeom', this.geometryEditor.editGeom, this.geometryEditor);
      self.infowindow.bind('removeGeom', this.updateDataLayerView, this);

      this.options.table.bind('change:dataSource', function() {
        self.geometryEditor.discard();
      });

      // HACK
      // wait a little bit to give time to the mapview
      // to estabilize
      setTimeout(function() {
        self.mapView.setAutoSaveBounds();
      }, 1000);
    }
  },

  activated: function() {
   this.checkGeoRef();
  },

  checkGeoRef: function() {
    if(this.options && this.options.table) {
      if(!this.options.table.isGeoreferenced()) {
        this.trigger('noGeoRef');
        this.showNoGeoRefWarning();
        this.georeferenced = false;
      } else {
        this.trigger('geoRef');
        if(!this.georeferenced) {
          var dataLayer = this.map.get('dataLayer');
          if(dataLayer) {
            dataLayer.invalidate();
          }
        }
        this.georeferenced = true;
        if(this.noGeoRefDialog) {
          this.noGeoRefDialog.hide();
        }
      }
    }
  },

  /**
  * this function binds click and dblclick events
  * in order to not raise click when user does a dblclick
  *
  * it raises a missingClick when the user clicks on the map
  * but not over a feature or ui component
  */
  _bindMissingClickEvents: function() {
    var self = this;
    this.mapView.bind('click', function(e) {
      if(self.clickTimeout === null) {
        self.clickTimeout = setTimeout(function() {
          self.clickTimeout = null;
          if(!self.featureHovered) {
            self.trigger('missingClick');
          }
        }, 150);
      }
      //google maps does not send an event
      if(!self.featureHovered && e.preventDefault) {
        e.preventDefault();
        e.stopPropagation();
      }
    });

    this.mapView.bind('dblclick', function() {
      if(self.clickTimeout !== null) {
        clearTimeout(self.clickTimeout);
        self.clickTimeout = null;
      }
    });
  },

  /**
  * when the layer view is created this method is called
  * to attach all the click events
  */
  _bindDataLayer: function(layer) {
    var self = this;

    var layerType = layer.model.get('type');

    if (layerType === 'CartoDB') { // unbind previos stuff

      if (self.layerDataView) {
        self.layerDataView.unbind(null, null, this);
      }
      var dataLayer = self.map.get('dataLayer');

      this.options.table.bind('change:schema', function() {
        //dataLayer.invalidate();
      }, this);

      if (dataLayer) {

        var cid = dataLayer.cid;

        self.layerDataView = self.mapView.getLayerByCid(cid);

        if (self.layerDataView) {
          self.layerDataView.bind('featureClick', self.featureClick, self);
          self.layerDataView.bind('featureOut',   self.featureOut,   self);
          self.layerDataView.bind('featureOver',  self.featureOver,  self);
          self.layerDataView.bind('loading',      self.loadingTiles, self);
          self.layerDataView.bind('load',         self.loadTiles,    self);
        }
      }
    }
  },

  loadingTiles: function() {
    this.loader.show()
  },

  loadTiles: function() {
    this.loader.hide()
  },

  featureOver: function(e, latlon, pxPos, data) {
    this.mapView.setCursor('pointer');
    this.featureHovered = data;
  },

  featureOut: function() {
    this.mapView.setCursor('auto');
    this.featureHovered = null;
  },

  featureClick: function(e, latlon, pxPos, data) {
    if(data.cartodb_id) {
      this.infowindow
      .setLatLng(latlon)
      .setFeatureInfo(data.cartodb_id)
      .showInfowindow();
    } else {
      cdb.log.error("can't show infowindow, no cartodb_id on data");
    }
  },

  /**
   *  Move all necessary buttons when panel is openned or closed
   */
  _moveRightButtons: function(type) {
    var right = 0;
    if (type == "show") {
      right = 592;
    } else if (type == "hide") {
      right = 57;
    } else {
      right = 442;
    }

    this.$el.find("div.share")
      .animate({
        right: right
      }, this.animation_time);

    this.$el.find("div.search_box")
      .animate({
        right: right
      }, this.animation_time);
  },

  render: function() {
    this.$el.html('');
    this.$el.append(this.template());
    return this;
  },

  shareMap: function(e) {
    e.preventDefault();

    var privacy = this.options.table.get('privacy').toLowerCase()
      , dlg
      , center = false;

    // If the table is not public, we'll show a warning dialog
    if (privacy != 'public') {
      dlg = new cdb.admin.NoShareMapDialog({
        map: this.model,
        table: this.options.table
      });
    } else {
      dlg = new cdb.admin.ShareMapDialog({
        map: this.model,
        table: this.options.table
      });
      center = true;
    }

    dlg.appendToBody().open({ center: center });

    return false;
  },

  addGeometry: function() {
    // row is saved by geometry editor if it is needed
    this.geometryEditor.createGeom(this.options.table.data().newRow(), 'polygon');
  },

  showDataLayer: function() {
    this.layerDataView.setOpacity(1.0);
  },

  hideDataLayer: function() {
    //this.layerDataView.hide();
    this.layerDataView.setOpacity(0.5);
  },

  /**
  * reload tiles
  */
  updateDataLayerView: function() {
    this.layerDataView.reload();
  },
  /**
  * Paints a dialog with a warning when the user hasn't any georeferenced row
  * @method showNoGeorefWarning
  */
  showNoGeoRefWarning: function() {
    if(!this.noGeoRefDialog) {
      this.noGeoRefDialog = new cdb.admin.NoGeoRefDataDialog();
      this.retrigger('georeference', this.noGeoRefDialog);
      this.retrigger('manual', this.noGeoRefDialog);
      this.noGeoRefDialog.render().$el.appendTo(this.$el);
    }
    // if the dialog already has been shown, we don't show it again

  }

});

<|endoftext|>


<commit_before>/*
 * prompt-test.js: Tests for the prompt prompt.
 *
 * (C) 2010, Nodejitsu Inc.
 *
 */

var assert = require('assert'),
    vows = require('vows'),
    prompt = require('../lib/prompt'),
    helpers = require('./helpers');

vows.describe('prompt').addBatch({
  "When using prompt": {
    topic: function () {
      prompt.start({
        stdin: helpers.stdin,
        stdout: helpers.stdout
      });

      return null;
    },
    "the readLine() method": {
      topic: function () {
        prompt.readLine(this.callback);
        helpers.stdin.write('testing\n');
      },
      "should respond with data from the stdin stream": function (err, input) {
        assert.isNull(err);
        assert.equal(input, 'testing');
      }
    },
    "the readLineHidden() method": {
      topic: function () {
        prompt.readLineHidden(this.callback);
        helpers.stdin.write('testing');
        helpers.stdin.write('\r\n');
      },
      "should respond with data from the stdin stream": function (err, input) {
        assert.isNull(err);
        assert.equal(input, 'testing');
      }
    },
    "the getInput() method": {
      "with a simple string prompt": {
        topic: function () {
          var that = this;
          helpers.stdout.once('data', function (msg) {
            that.msg = msg;
          })

          prompt.getInput('test input', this.callback);
          helpers.stdin.write('test value\n');
        },
        "should prompt to stdout and respond with data": function (err, input) {
          assert.isNull(err);
          assert.equal(input, 'test value');
          assert.isTrue(this.msg.indexOf('test input') !== -1);
        }
      },
      "with a complex property prompt": {
        "and a valid input": {
          topic: function () {
            var that = this;
            helpers.stdout.once('data', function (msg) {
              that.msg = msg;
            });

            prompt.getInput(helpers.properties.username, this.callback);
            helpers.stdin.write('some-user\n');
          },
          "should prompt to stdout and respond with data": function (err, input) {
            assert.isNull(err);
            assert.equal(input, 'some-user');
            assert.isTrue(this.msg.indexOf('username') !== -1);
          }
        },
        "and an invalid input": {
          topic: function () {
            var that = this;
            helpers.stdout.once('data', function (msg) {
              that.msg = msg;
            });

            helpers.stderr.once('data', function (msg) {
              that.errmsg = msg;
            })

            prompt.getInput(helpers.properties.username, this.callback);

            prompt.once('invalid', function () {
              prompt.once('prompt', function () {
                process.nextTick(function () {
                  helpers.stdin.write('some-user\n');
                })
              })
            });

            helpers.stdin.write('some -user\n');
          },
          "should prompt with an error before completing the operation": function (err, input) {
            assert.isNull(err);
            assert.equal(input, 'some-user');
            assert.isTrue(this.errmsg.indexOf('Invalid input') !== -1);
            assert.isTrue(this.msg.indexOf('username') !== -1);
          }
        }
      }
    },
    "the get() method": {
      "with a simple string prompt": {
        "that is not a property in prompt.properties": {
          topic: function () {
            var that = this;
            helpers.stdout.once('data', function (msg) {
              that.msg = msg;
            })

            prompt.get('test input', this.callback);
            helpers.stdin.write('test value\n');
          },
          "should prompt to stdout and respond with the value": function (err, result) {
            assert.isNull(err);
            assert.include(result, 'test input');
            assert.equal(result['test input'], 'test value');
            assert.isTrue(this.msg.indexOf('test input') !== -1);
          }
        },
        "that is a property name in prompt.properties": {
          "with a default value": {
            topic: function () {
              var that = this;

              helpers.stdout.once('data', function (msg) {
                that.msg = msg;
              });

              prompt.properties['riffwabbles'] = helpers.properties['riffwabbles'];
              prompt.get('riffwabbles', this.callback);
              helpers.stdin.write('\n');
            },
            "should prompt to stdout and respond with the default value": function (err, result) {
              assert.isNull(err);
              assert.isTrue(this.msg.indexOf('riffwabbles') !== -1);
              assert.isTrue(this.msg.indexOf('(foobizzles)') !== -1);
              assert.include(result, 'riffwabbles');
              assert.equal(result['riffwabbles'], helpers.properties['riffwabbles'].default);
            }
          }
        }
      }
    },
    "the addProperties() method": {
      topic: function () {
        prompt.addProperties({}, ['foo', 'bar'], this.callback);
        helpers.stdin.write('foo\n');
        helpers.stdin.write('bar\n');
      },
      "should add the properties to the object": function (err, obj) {
        assert.isNull(err);
        assert.isObject(obj);
        assert.equal(obj.foo, 'foo');
        assert.equal(obj.bar, 'bar');
      }
    }
  }
}).export(module);<commit_msg>[minor] Small update to tests<commit_after>/*
 * prompt-test.js: Tests for node-prompt.
 *
 * (C) 2010, Nodejitsu Inc.
 *
 */

var assert = require('assert'),
    vows = require('vows'),
    prompt = require('../lib/prompt'),
    helpers = require('./helpers');

vows.describe('prompt').addBatch({
  "When using prompt": {
    topic: function () {
      prompt.start({
        stdin: helpers.stdin,
        stdout: helpers.stdout
      });

      return null;
    },
    "the readLine() method": {
      topic: function () {
        prompt.readLine(this.callback);
        helpers.stdin.write('testing\n');
      },
      "should respond with data from the stdin stream": function (err, input) {
        assert.isNull(err);
        assert.equal(input, 'testing');
      }
    },
    "the readLineHidden() method": {
      topic: function () {
        prompt.readLineHidden(this.callback);
        helpers.stdin.write('testing');
        helpers.stdin.write('\r\n');
      },
      "should respond with data from the stdin stream": function (err, input) {
        assert.isNull(err);
        assert.equal(input, 'testing');
      }
    },
    "the getInput() method": {
      "with a simple string prompt": {
        topic: function () {
          var that = this;
          helpers.stdout.once('data', function (msg) {
            that.msg = msg;
          })

          prompt.getInput('test input', this.callback);
          helpers.stdin.write('test value\n');
        },
        "should prompt to stdout and respond with data": function (err, input) {
          assert.isNull(err);
          assert.equal(input, 'test value');
          assert.isTrue(this.msg.indexOf('test input') !== -1);
        }
      },
      "with a complex property prompt": {
        "and a valid input": {
          topic: function () {
            var that = this;
            helpers.stdout.once('data', function (msg) {
              that.msg = msg;
            });

            prompt.getInput(helpers.properties.username, this.callback);
            helpers.stdin.write('some-user\n');
          },
          "should prompt to stdout and respond with data": function (err, input) {
            assert.isNull(err);
            assert.equal(input, 'some-user');
            assert.isTrue(this.msg.indexOf('username') !== -1);
          }
        },
        "and an invalid input": {
          topic: function () {
            var that = this;
            helpers.stdout.once('data', function (msg) {
              that.msg = msg;
            });

            helpers.stderr.once('data', function (msg) {
              that.errmsg = msg;
            })

            prompt.getInput(helpers.properties.username, this.callback);

            prompt.once('invalid', function () {
              prompt.once('prompt', function () {
                process.nextTick(function () {
                  helpers.stdin.write('some-user\n');
                })
              })
            });

            helpers.stdin.write('some -user\n');
          },
          "should prompt with an error before completing the operation": function (err, input) {
            assert.isNull(err);
            assert.equal(input, 'some-user');
            assert.isTrue(this.errmsg.indexOf('Invalid input') !== -1);
            assert.isTrue(this.msg.indexOf('username') !== -1);
          }
        }
      }
    },
    "the get() method": {
      "with a simple string prompt": {
        "that is not a property in prompt.properties": {
          topic: function () {
            var that = this;
            helpers.stdout.once('data', function (msg) {
              that.msg = msg;
            })

            prompt.get('test input', this.callback);
            helpers.stdin.write('test value\n');
          },
          "should prompt to stdout and respond with the value": function (err, result) {
            assert.isNull(err);
            assert.include(result, 'test input');
            assert.equal(result['test input'], 'test value');
            assert.isTrue(this.msg.indexOf('test input') !== -1);
          }
        },
        "that is a property name in prompt.properties": {
          "with a default value": {
            topic: function () {
              var that = this;

              helpers.stdout.once('data', function (msg) {
                that.msg = msg;
              });

              prompt.properties['riffwabbles'] = helpers.properties['riffwabbles'];
              prompt.get('riffwabbles', this.callback);
              helpers.stdin.write('\n');
            },
            "should prompt to stdout and respond with the default value": function (err, result) {
              assert.isNull(err);
              assert.isTrue(this.msg.indexOf('riffwabbles') !== -1);
              assert.isTrue(this.msg.indexOf('(foobizzles)') !== -1);
              assert.include(result, 'riffwabbles');
              assert.equal(result['riffwabbles'], helpers.properties['riffwabbles'].default);
            }
          }
        }
      }
    },
    "the addProperties() method": {
      topic: function () {
        prompt.addProperties({}, ['foo', 'bar'], this.callback);
        helpers.stdin.write('foo\n');
        helpers.stdin.write('bar\n');
      },
      "should add the properties to the object": function (err, obj) {
        assert.isNull(err);
        assert.isObject(obj);
        assert.equal(obj.foo, 'foo');
        assert.equal(obj.bar, 'bar');
      }
    }
  }
}).export(module);<|endoftext|>


<commit_before>var scheduler_status = null;

function scheduler_get(success, error) {
    $.ajax({
	url: $SCRIPT_ROOT+'/progressivis/scheduler/',
	dataType: 'json'
    })
	.done(success)
	.fail(error);
};

function scheduler_start(success, error) {
    $.ajax({
	url: $SCRIPT_ROOT+'/progressivis/scheduler/start',
	dataType: 'json'
    })
	.done(success)
	.fail(error);
};

function scheduler_stop(success, error) {
    $.ajax({
	url: $SCRIPT_ROOT+'/progressivis/scheduler/stop',
	dataType: 'json'
    })
	.done(success)
	.fail(error);
};

function cmp_order(mod1, mod2) {
  if (mod1.order == mod2.order) return 0;
  if (mod1.order == undefined) return -1;
  return 1;
}

function scheduler_update(data) {
    var module, i;

    console.log('scheduler update');

    scheduler_status = data;
    if (data.is_running) {
	$('#start').addClass('disabled');
	$('#stop').removeClass('disabled');
    }
    else if (data.is_terminated) {
	$('#start').removeClass('disabled');
	$('#stop').removeClass('disabled');
    }
    else {
	$('#start').removeClass('disabled');
	$('#stop').addClass('disabled');
    }
    var columns = ['id', 'classname', 'state', 'last_update', 'order'];
    var tr = d3
	    .select("tbody")
	    .selectAll("tr")
	    .data(data.modules, function(d) { return d.id; });
    var rows = tr.enter()
	    .append("tr");

    var cells = rows.selectAll("td")
	    .data(function(row) {
		return columns.map(function(column) {
		    return {column: column, value: row[column]};
		});
	    })
	    .enter()
	    .append("td")
	    .text(function(d) { return d.value; });

    tr.selectAll("td")
	.data(function(row) {
	    return columns.map(function(column) {
		return {column: column, value: row[column]};
	    });
	})
	.text(function(d) { return d.value; });

    tr.exit().remove();

    $('#module-tabs-contents .dynamic').remove();
    for (i = 0; i <  data.modules.length; i++) {
	module = data.modules[i];

    }

}

function scheduler_error(ev) {
  contents = '
Error
';
  $('#scheduler').html(contents);
}

function scheduler_refresh() {
  scheduler_get(scheduler_update, scheduler_error);
}

function scheduler_add_tab(name) {
    console.log('add tab '+name);
}

function scheduler_remove_tab(name) {
    console.log('remove tab '+name);
}

function scheduler_ready() {
    $('#start').click(function() { scheduler_start(scheduler_refresh, scheduler_error); });
    $('#stop').click(function() { scheduler_stop(scheduler_refresh, scheduler_error); });
    scheduler_refresh();
    $('#modules-tab a').click(function (e) {
	e.preventDefault();
	$(this).tab('show');
    });
}
<commit_msg>continue to improve<commit_after>var scheduler_status = null;

function scheduler_get(success, error) {
    $.ajax({
	url: $SCRIPT_ROOT+'/progressivis/scheduler/',
	dataType: 'json'
    })
	.done(success)
	.fail(error);
};

function scheduler_start(success, error) {
    $.ajax({
	url: $SCRIPT_ROOT+'/progressivis/scheduler/start',
	dataType: 'json'
    })
	.done(success)
	.fail(error);
};

function scheduler_stop(success, error) {
    $.ajax({
	url: $SCRIPT_ROOT+'/progressivis/scheduler/stop',
	dataType: 'json'
    })
	.done(success)
	.fail(error);
};

function cmp_order(mod1, mod2) {
  if (mod1.order == mod2.order) return 0;
  if (mod1.order == undefined) return -1;
  return 1;
}

function scheduler_update(data) {
    var module, i;

    //console.log('scheduler update');

    scheduler_status = data;
    if (data.is_running) {
	$('#start').addClass('disabled');
	$('#stop').removeClass('disabled');
    }
    else if (data.is_terminated) {
	$('#start').removeClass('disabled');
	$('#stop').removeClass('disabled');
    }
    else {
	$('#start').removeClass('disabled');
	$('#stop').addClass('disabled');
    }
    scheduler_update_table(data);
    scheduler_update_tabs(data);

    $('#module-tabs-contents .dynamic').remove();
    for (i = 0; i <  data.modules.length; i++) {
	module = data.modules[i];

    }
}

function scheduler_update_tabs(data) {
    var modules = data.modules;
    var tabs = d3
	    .select("#module-tabs")
	    .selectAll("div[role='presentation']")
	    .data(modules, function(d) { return d.id; });

    tabs.enter()
	.append("li")
	.attr("role", "presentation")
	.append("a")
	.attr("role", "tab")
	.attr("data-toggle", "tab")
	.attr("href", function(d) { return "#"+d.id; })
	.attr("aria-controls", function(d) { return d.id; })
	.text(function(d) { return d.id;});

    tabs.exit().remove();

    var panel = d3.select("#module-tabs-contents")
	    .selectAll("div[role='tabpanel']")
	    .data(modules, function(d) { return d ? d.id : 'Scheduler'; });
    var tab_content = panel.enter()
	.append("div")
	.attr("role", "tabpanel")
	.attr("class", "tab-pane")
	.attr("id", function(d) { return d.id; });
    tab_content
	.append("h2").text(function(d) { return "Module "+d.id; });

    tab_content
	.append("div")
	.attr("id", function(d) { return "tab-contents-"+d.id; });
}

function scheduler_update_table(data) {
    var columns = ['id', 'classname', 'state', 'last_update', 'order'];
    var tr = d3
	    .select("tbody")
	    .selectAll("tr")
	    .data(data.modules, function(d) { return d.id; });

    // Enter function
    var rows = tr.enter()
	    .append("tr");

    var cells = rows.selectAll("td")
	    .data(function(row) {
		return columns.map(function(column) {
		    return {column: column, value: row[column]};
		});
	    })
	    .enter()
	    .append("td")
	    .text(function(d) { return d.value; });

    // Update function
    tr.selectAll("td")
	.data(function(row) {
	    return columns.map(function(column) {
		return {column: column, value: row[column]};
	    });
	})
	.text(function(d) { return d.value; });

    // Exit function
    tr.exit().remove();
}

function scheduler_error(ev) {
  contents = '
Error
';
  $('#scheduler').html(contents);
}

function scheduler_refresh() {
  scheduler_get(scheduler_update, scheduler_error);
}

function scheduler_add_tab(name) {
    console.log('add tab '+name);
}

function scheduler_remove_tab(name) {
    console.log('remove tab '+name);
}

function scheduler_ready() {
    $('#start').click(function() { scheduler_start(scheduler_refresh, scheduler_error); });
    $('#stop').click(function() { scheduler_stop(scheduler_refresh, scheduler_error); });
    scheduler_refresh();
    $('#modules-tab a').click(function (e) {
	e.preventDefault();
	$(this).tab('show');
    });
}
<|endoftext|>


<commit_before>'use strict'

const { Router } = require('express')
const { ServerError, ClientError, NotFoundError } = require('./errors')
const { identity, set, map, compose } = require('lodash/fp')
const bodyParser = require('body-parser')
const es = require('./elasticsearch')

const restHandler = exports.restHandler = fn => (req, res, next) => {
	Promise.resolve().then(() => fn(req, res))
	.then(data => res.send(data))
	.catch(err => {
		if (!err.status) {
			err.status = 500
		}
		next(err)
	})
}

const saveDocument = (format = identity) => doc => doc.save()
	.then(format)
	.catch(e => {
		let err = new ClientError({ title: 'Validation error' })
		if (e.name === 'ValidationError') {
			err.errors = Object.keys(e.errors).reduce(
				(errors, error) => set(error, e.errors[error].message, errors),
				{}
			)
		}
		return Promise.reject(err)
	})

exports.restRouter = (Model, format = identity, esIndex = null) => {
	const save = saveDocument(format)
	const router = Router()

	router.use(bodyParser.json())

	if (esIndex) {
		router.get('/search', restHandler(searchModel(esIndex, map(compose(format, Model)))))
	}

	router.get('/', restHandler(listModel(Model, map(format))))
	router.get('/:id', restHandler(getModel(Model, format)))
	router.put('/:id', restHandler(updateModel(Model, save)))
	router.post('/', restHandler(createModel(Model, save)))
	router.delete('/:id', restHandler(deleteModel(Model)))

	return router
}

const listModel = (Model, formatAll) => () =>
	Model.find().then(formatAll)

const getModel = (Model, format) => req =>
	Model.findById(req.params.id)
	.then(found => found || Promise.reject(NotFoundError({ title: Model.modelName })))
	.then(format)

const updateModel = (Model, save) => {
	const get = getModel(Model, identity)
	return req => get(req).then(doc => {
		Object.keys(req.body).forEach(field => {
			doc[field] = req.body[field]
		})
		return save(doc)
	})
}

const createModel = (Model, save) => (req, res) => {
	let o
	try {
		o = new Model(req.body)
	} catch (e) {
		if (e.name === 'StrictModeError') {
			// Extra fields
			return Promise.reject(ClientError({ title: e.message }))
		} else {
			return Promise.reject(ServerError({ title: e.message }))
		}
	}
	return save(o).then(saved => {
		res.status(201)
		return saved
	})
}

const deleteModel = Model => (req, res) =>
	Model.remove({ _id: req.params.id })
	.then(({ result }) => result.n > 0)
	.then(deleted => deleted || Promise.reject(NotFoundError({ title: Model.modelName })))
	.then(() => {
		res.status(204)
		return null
	})

const searchModel = (esIndex, formatAll) => req => {
	const query = req.query.q
	const fields = req.query.fields ? req.query.fields.split(',') : undefined

	if (!query) {
		throw new ClientError({ title: 'Missing query string (field "q")' })
	}

	return es.q(esIndex, { query, fields }).then(formatAll)
}
<commit_msg>fix(server): use Document#remove instead of Model.remove to trigger hooks<commit_after>'use strict'

const { Router } = require('express')
const { ServerError, ClientError, NotFoundError } = require('./errors')
const { identity, set, map, compose } = require('lodash/fp')
const bodyParser = require('body-parser')
const es = require('./elasticsearch')

const restHandler = exports.restHandler = fn => (req, res, next) => {
	Promise.resolve().then(() => fn(req, res))
	.then(data => res.send(data))
	.catch(err => {
		if (!err.status) {
			err.status = 500
		}
		next(err)
	})
}

const saveDocument = (format = identity) => doc => doc.save()
	.then(format)
	.catch(e => {
		let err = new ClientError({ title: 'Validation error' })
		if (e.name === 'ValidationError') {
			err.errors = Object.keys(e.errors).reduce(
				(errors, error) => set(error, e.errors[error].message, errors),
				{}
			)
		}
		return Promise.reject(err)
	})

exports.restRouter = (Model, format = identity, esIndex = null) => {
	const save = saveDocument(format)
	const router = Router()

	router.use(bodyParser.json())

	if (esIndex) {
		router.get('/search', restHandler(searchModel(esIndex, map(compose(format, Model)))))
	}

	router.get('/', restHandler(listModel(Model, map(format))))
	router.get('/:id', restHandler(getModel(Model, format)))
	router.put('/:id', restHandler(updateModel(Model, save)))
	router.post('/', restHandler(createModel(Model, save)))
	router.delete('/:id', restHandler(deleteModel(Model)))

	return router
}

const listModel = (Model, formatAll) => () =>
	Model.find().then(formatAll)

const getModel = (Model, format) => req =>
	Model.findById(req.params.id)
	.then(found => found || Promise.reject(NotFoundError({ title: Model.modelName })))
	.then(format)

const updateModel = (Model, save) => {
	const get = getModel(Model, identity)
	return req => get(req).then(doc => {
		Object.keys(req.body).forEach(field => {
			doc[field] = req.body[field]
		})
		return save(doc)
	})
}

const createModel = (Model, save) => (req, res) => {
	let o
	try {
		o = new Model(req.body)
	} catch (e) {
		if (e.name === 'StrictModeError') {
			// Extra fields
			return Promise.reject(ClientError({ title: e.message }))
		} else {
			return Promise.reject(ServerError({ title: e.message }))
		}
	}
	return save(o).then(saved => {
		res.status(201)
		return saved
	})
}

const deleteModel = Model => (req, res) =>
	Model.findById(req.params.id)
	.then(found => found || Promise.reject(NotFoundError({ title: Model.modelName })))
	.then(doc => doc.remove())
	.then(() => {
		res.status(204)
		return null
	})

const searchModel = (esIndex, formatAll) => req => {
	const query = req.query.q
	const fields = req.query.fields ? req.query.fields.split(',') : undefined

	if (!query) {
		throw new ClientError({ title: 'Missing query string (field "q")' })
	}

	return es.q(esIndex, { query, fields }).then(formatAll)
}
<|endoftext|>


<commit_before>var axios = require('axios');

//import helper functions
//  to check ajax (AXIOS) responses - error handling
import { CheckReponse } from './responses';

//  general functions and  helpers.  reuse functions
import { getNextLevel } from '../utils/helpers';

//import ACTION constants
import { AGO_URL, DATA_FEATUREID, ENCODED_COMMAS } from '../constants/actionConstants';
import { START_POSITION, CATALOGING_UNIT_FROM_HUC12_END_POISTION } from '../constants/appConstants';

//set consts for this module
const CHART_DATA_OUT_FIELDS_LIST = [
  'ID',
  'OBJECTID',
  'chart_description',
  'chart_id',
  'chart_label',
  'chart_level',
  'chart_level_label',
  'chart_matchid',
  'chart_type',
  'chart_value',
  'geography_label',
  'geography_level',
  'geography_match_id'
];
const CHART_DATA_OUT_FIELDS = CHART_DATA_OUT_FIELDS_LIST.join(ENCODED_COMMAS);
const CHART_DATA_ORDER_BY_FIELDS = 'chart_level' + ENCODED_COMMAS + 'chart_matchid';

//set base URL for axios
axios.defaults.baseURL = AGO_URL;

//get chart data for all hucs of the next lower level in the huc heirachy (huc6,huc8,huc12) for huc id
//   requires an id of huc6,huc8, or huc12....
//            geogLevel which is the current geography level,
//            need this so we can limit the
//  the huc heirachy is huc 6 (river basins), huc 8 (Cataloging units), huc 12 (huc 12) for now will be adding
//      TRA's and catchments
function AGO_AllChartData_byID(hucid,current_geography_level){

   //set default id
   var id = hucid;

   //get the lower level in the huc heirachy
   var next_level = getNextLevel(current_geography_level);

   //if current huc hierachy is set to huc12 we do not have a lower level in the heirachy
   //  but we want to show all the hucs in the current huc12's Cataloging unit
   //  so we need to get the first 8 characters, which is the Cataloging Unit
   if(current_geography_level === 'HUC12'){
     id = hucid.substring(START_POSITION, CATALOGING_UNIT_FROM_HUC12_END_POISTION);
   }

   //build the query to arcgis online api for getting the raw chart data
   const query_URL = '/RDRBP/FeatureServer/' + DATA_FEATUREID + '/query' +
                   '?where=ID+like+%27' + id + '%25%27+and+geography_level%3D'+ next_level +
                   '&objectIds=' +
                   '&time=' +
                   '&resultType=none' +
                   '&outFields=' + CHART_DATA_OUT_FIELDS +
                   '&returnIdsOnly=false' +
                   '&returnCountOnly=false' +
                   '&returnDistinctValues=true' +
                   '&orderByFields=' + CHART_DATA_ORDER_BY_FIELDS +
                   '&groupByFieldsForStatistics=' +
                   '&outStatistics=' +
                   '&resultOffset=' +
                   '&resultRecordCount=' +
                   '&f=pgeojson&token=';

  //send the ajax request via axios
  return axios.get(query_URL);

}

//get chart data for a single huc id
//   requires the id to search
function AGO_ChartData_byID(id){
   const query_URL = '/RDRBP/FeatureServer/' + DATA_FEATUREID + '/query' +
                     '?where=id%3D%27' + id + '%27' +
                     '&objectIds=' +
                     '&time=' +
                     '&resultType=none' +
                     '&outFields=' + CHART_DATA_OUT_FIELDS +
                     '&returnIdsOnly=false' +
                     '&returnCountOnly=false' +
                     '&returnDistinctValues=true' +
                     '&orderByFields=' +  CHART_DATA_ORDER_BY_FIELDS +
                     '&groupByFieldsForStatistics=' +
                     '&outStatistics=' +
                     '&resultOffset=' +
                     '&resultRecordCount=' +
                     '&f=pgeojson' +
                     '&token=';

  //send the ajax request via axios
  return axios.get(query_URL);

}
//
export function get_ChartData(id,level){
    return (dispatch,getState) => {
      axios.all([AGO_ChartData_byID(id), AGO_AllChartData_byID(id,level)])
      .then(axios.spread(function (chartbyid, chartbylevel) {

        const state = getState()

        let visibility = false;

        visibility = ( state.chartData.chart_visibility === undefined ? false : state.chartData.chart_visibility);

        let chartData_Level = {};
        let chartData_ID = {};

        //only check responses if limiting data (ID ir LEVEL) was passed id
        //   this would cause an error but we still want data to flow in for initializing the charts state object.
        if(id){
          //check for errors in responses
          chartData_Level = CheckReponse(chartbylevel,'AGO_API_ERROR');
          chartData_ID = CheckReponse(chartbyid,'AGO_API_ERROR');
        }
        //send the chart data on
        dispatch(ChartData('GET_CHART_DATA', chartData_ID, chartData_Level, visibility))

      })
    )
    .catch(error => { console.log('request failed', error); });
  }
}

export function update_ChartVisiblity (visibility){
    return (dispatch, getState) => {
      const state = getState()

      //ensure that the chart data exists create blank if not.
      let chartData_Level = ( state.chartData.chart_data.level_json ? state.chartData.chart_data.level_json : {});
      let chartData_ID = ( state.chartData.chart_data.id_json ? state.chartData.chart_data.id_json : {});

      //change visibility
      let isVisible = (state.chartData.chart_visibility ? false : true);

      //send visibility setting on
      dispatch(ChartData('SET_CHART_VISIBILITY',chartData_ID,chartData_Level,isVisible))

    }
}
//function to handle sending to reducer and store
function ChartData(type,id_json,level_json,visibility) {
  return {
    type: type,
    chart_data: {id_json,level_json},
    chart_visibility: visibility,
    receivedAt: Date.now()
  }
}
<commit_msg>update from dev fix adding of uplift data<commit_after>var axios = require('axios');

//import helper functions
//  to check ajax (AXIOS) responses - error handling
import { CheckReponse } from './responses';

//  general functions and  helpers.  reuse functions
import { getNextLevel } from '../utils/helpers';

//import ACTION constants
import { AGO_URL, DATA_FEATUREID, ENCODED_COMMAS } from '../constants/actionConstants';
import { START_POSITION, CATALOGING_UNIT_FROM_HUC12_END_POISTION } from '../constants/appConstants';

//set consts for this module
const CHART_DATA_OUT_FIELDS_LIST = [
  'ID',
  'OBJECTID',
  'chart_description',
  'chart_id',
  'chart_label',
  'chart_level',
  'chart_level_label',
  'chart_matchid',
  'chart_type',
  'chart_value',
  'geography_label',
  'geography_level',
  'geography_match_id'
];
const CHART_DATA_OUT_FIELDS = CHART_DATA_OUT_FIELDS_LIST.join(ENCODED_COMMAS);
const CHART_DATA_ORDER_BY_FIELDS = 'chart_level' + ENCODED_COMMAS + 'chart_matchid';

const CHART_TYPE = 'BASELINE';

//set base URL for axios
axios.defaults.baseURL = AGO_URL;

//get chart data for all hucs of the next lower level in the huc heirachy (huc6,huc8,huc12) for huc id
//   requires an id of huc6,huc8, or huc12....
//            geogLevel which is the current geography level,
//            need this so we can limit the
//  the huc heirachy is huc 6 (river basins), huc 8 (Cataloging units), huc 12 (huc 12) for now will be adding
//      TRA's and catchments
function AGO_AllChartData_byID(hucid,current_geography_level){

   //set default id
   var id = hucid;

   //get the lower level in the huc heirachy
   var next_level = getNextLevel(current_geography_level);

   //if current huc hierachy is set to huc12 we do not have a lower level in the heirachy
   //  but we want to show all the hucs in the current huc12's Cataloging unit
   //  so we need to get the first 8 characters, which is the Cataloging Unit
   if(current_geography_level === 'HUC12'){
     id = hucid.substring(START_POSITION, CATALOGING_UNIT_FROM_HUC12_END_POISTION);
   }

   //build the query to arcgis online api for getting the raw chart data
   const query_URL = '/RDRBP/FeatureServer/' + DATA_FEATUREID + '/query' +
                   '?where=ID+like+%27' + id + '%25%27+and+geography_level%3D'+ next_level + '+and+chart_type%3D%27' + CHART_TYPE + '%27' +
                   '&objectIds=' +
                   '&time=' +
                   '&resultType=none' +
                   '&outFields=' + CHART_DATA_OUT_FIELDS +
                   '&returnIdsOnly=false' +
                   '&returnCountOnly=false' +
                   '&returnDistinctValues=true' +
                   '&orderByFields=' + CHART_DATA_ORDER_BY_FIELDS +
                   '&groupByFieldsForStatistics=' +
                   '&outStatistics=' +
                   '&resultOffset=' +
                   '&resultRecordCount=' +
                   '&f=pgeojson&token=';
  //send the ajax request via axios
  return axios.get(query_URL);

}

//get chart data for a single huc id
//   requires the id to search
function AGO_ChartData_byID(id){
   const query_URL = '/RDRBP/FeatureServer/' + DATA_FEATUREID + '/query' +
                     '?where=id%3D%27' + id + '%27' + ' +and+chart_type%3D%27' + CHART_TYPE + '%27' +
                     '&objectIds=' +
                     '&time=' +
                     '&resultType=none' +
                     '&outFields=' + CHART_DATA_OUT_FIELDS +
                     '&returnIdsOnly=false' +
                     '&returnCountOnly=false' +
                     '&returnDistinctValues=true' +
                     '&orderByFields=' +  CHART_DATA_ORDER_BY_FIELDS +
                     '&groupByFieldsForStatistics=' +
                     '&outStatistics=' +
                     '&resultOffset=' +
                     '&resultRecordCount=' +
                     '&f=pgeojson' +
                     '&token=';

  //send the ajax request via axios
  return axios.get(query_URL);

}
//
export function get_ChartData(id,level){
    return (dispatch,getState) => {
      axios.all([AGO_ChartData_byID(id), AGO_AllChartData_byID(id,level)])
      .then(axios.spread(function (chartbyid, chartbylevel) {

        const state = getState()

        let visibility = false;

        visibility = ( state.chartData.chart_visibility === undefined ? false : state.chartData.chart_visibility);

        let chartData_Level = {};
        let chartData_ID = {};

        //only check responses if limiting data (ID ir LEVEL) was passed id
        //   this would cause an error but we still want data to flow in for initializing the charts state object.
        if(id){
          //check for errors in responses
          chartData_Level = CheckReponse(chartbylevel,'AGO_API_ERROR');
          chartData_ID = CheckReponse(chartbyid,'AGO_API_ERROR');
        }
        //send the chart data on
        dispatch(ChartData('GET_CHART_DATA', chartData_ID, chartData_Level, visibility))

      })
    )
    .catch(error => { console.log('request failed', error); });
  }
}

export function update_ChartVisiblity (visibility){
    return (dispatch, getState) => {
      const state = getState()

      //ensure that the chart data exists create blank if not.
      let chartData_Level = ( state.chartData.chart_data.level_json ? state.chartData.chart_data.level_json : {});
      let chartData_ID = ( state.chartData.chart_data.id_json ? state.chartData.chart_data.id_json : {});

      //change visibility
      let isVisible = (state.chartData.chart_visibility ? false : true);

      //send visibility setting on
      dispatch(ChartData('SET_CHART_VISIBILITY',chartData_ID,chartData_Level,isVisible))

    }
}
//function to handle sending to reducer and store
function ChartData(type,id_json,level_json,visibility) {
  return {
    type: type,
    chart_data: {id_json,level_json},
    chart_visibility: visibility,
    receivedAt: Date.now()
  }
}
<|endoftext|>


<commit_before>import { includes, keys, sortBy, uniq, values } from 'lodash'

import $           from 'cheerio'
import express     from 'express'
import path        from 'path'
import utils       from 'fs-utils'

import grep        from '../helpers/grep'
import Config      from '../services/Config'
import Links       from '../services/Links'

const { folders } = Config

export default express()
.get('/:search_term', async (request, response) => {
  let search_term = encode(request.params.search_term).toLowerCase();

  const resultSets = [
    ...getTitleMatches(search_term),
    ...await getContentMatches(search_term),
  ]

  let indexed = {}
  resultSets.forEach(result => {
    const current = indexed[result.file] || {}
    indexed[result.file] = {
      ...current, ...result,
      aliases: uniq([...(current.aliases || []), result.alias]),
      type: uniq([...(current.type || []), result.type]),
    }
  })

  const results = values(indexed)
  .filter(result => !!result)
  .map(entry => {
    const $html = $(utils.readFileSync(entry.file))
    const link = Links.get(entry.slug)

    return {
      file:    entry.slug,
      image:   $html.find('img').first().attr('src'),
      aliases: entry.aliases.filter(alias => !!alias),
      results: entry.results,
      title:   link.title,
      type:    entry.type
    }
  })

  const sorted = sortBy(results, result => {
    const order = includes(result.type, 'article:title')
      ? 0 : 1

    return `${order}-${result.title}`
  })
  response.status(200).send(JSON.stringify(sorted))
})

function getTitleMatches(search_term) {
  const pattern = new RegExp(search_term, 'gi')
  return keys(Links.links)
    .filter(slug => {
      const title = Links.get(slug).title || ''
      return slug.match(pattern) // Slug directly matches
          || title.match(pattern)
    })
    .map(matched_slug => {
      const slug = Links.resolve(matched_slug)
      return {
        slug,
        alias: matched_slug,
        file: path.join(folders.articles, `${slug}.html`),
        type: 'article:title',
      }
    })
  ;
}

async function getContentMatches(search_term) {
  return grep(search_term, folders.articles, { ext: 'html' })
    .then(list =>
      list.map(hit => {
        const filename = hit.file.split('/').pop(),
              slug = filename.split('.').reverse().pop()

        return {
          slug,
          file: hit.file,
          results: hit.results.map(result => {
            const text = $(result.text).text();
            if (!text.match(new RegExp(search_term, 'gi')))
              return null;

            return { ...result, text }
          }).filter(result => !!result), // Only truthy results
          type: 'article:content',
        }
      }).filter(hit => hit.results.length)
    )
  ;
}

const html_codes = {
  '&': '&',
  "'": ''',
  '"': '"',
  '<': '<',
  '>': '>'
}
function encode(input) {
  let output = input

  Object.keys(html_codes).forEach(key => {
    const regex = new RegExp(`[${key}]`, 'g')
    output = output.replace(regex, html_codes[key])
  })

  return output
}
<commit_msg>Exact, case-insensitive matches for title, slug or alias are now the first results.<commit_after>import { includes, keys, sortBy, uniq, values } from 'lodash'

import $           from 'cheerio'
import express     from 'express'
import path        from 'path'
import utils       from 'fs-utils'

import grep        from '../helpers/grep'
import Config      from '../services/Config'
import Links       from '../services/Links'

const { folders } = Config

export default express()
.get('/:search_term', async (request, response) => {
  let search_term = encode(request.params.search_term).toLowerCase();

  const resultSets = [
    ...getTitleMatches(search_term),
    ...await getContentMatches(search_term),
  ]

  let indexed = {}
  resultSets.forEach(result => {
    const current = indexed[result.file] || {}
    indexed[result.file] = {
      ...current, ...result,
      aliases: uniq([...(current.aliases || []), result.alias]),
      type: uniq([...(current.type || []), result.type]),
    }
  })

  const results = values(indexed)
  .filter(result => !!result)
  .map(entry => {
    const $html = $(utils.readFileSync(entry.file))
    const link = Links.get(entry.slug)

    return {
      file:    entry.slug,
      image:   $html.find('img').first().attr('src'),
      aliases: entry.aliases.filter(alias => !!alias),
      results: entry.results,
      title:   link.title,
      type:    entry.type
    }
  })

  const sorted = sortBy(results, result => {
    let order = ''
    if (result.title.toLowerCase() === search_term
      || includes(result.aliases, search_term))
      order = 0
    else if (includes(result.type, 'article:title'))
      order = 1
    else
      order = 2

    return `${order}-${result.title}`
  })
  response.status(200).send(JSON.stringify(sorted))
})

function getTitleMatches(search_term) {
  const pattern = new RegExp(search_term, 'gi')
  return keys(Links.links)
    .filter(slug => {
      const title = Links.get(slug).title || ''
      return slug.match(pattern) // Slug directly matches
          || title.match(pattern)
    })
    .map(matched_slug => {
      const slug = Links.resolve(matched_slug)
      return {
        slug,
        alias: matched_slug,
        file: path.join(folders.articles, `${slug}.html`),
        type: 'article:title',
      }
    })
  ;
}

async function getContentMatches(search_term) {
  return grep(search_term, folders.articles, { ext: 'html' })
    .then(list =>
      list.map(hit => {
        const filename = hit.file.split('/').pop(),
              slug = filename.split('.').reverse().pop()

        return {
          slug,
          file: hit.file,
          results: hit.results.map(result => {
            const text = $(result.text).text();
            if (!text.match(new RegExp(search_term, 'gi')))
              return null;

            return { ...result, text }
          }).filter(result => !!result), // Only truthy results
          type: 'article:content',
        }
      }).filter(hit => hit.results.length)
    )
  ;
}

const html_codes = {
  '&': '&',
  "'": ''',
  '"': '"',
  '<': '<',
  '>': '>'
}
function encode(input) {
  let output = input

  Object.keys(html_codes).forEach(key => {
    const regex = new RegExp(`[${key}]`, 'g')
    output = output.replace(regex, html_codes[key])
  })

  return output
}
<|endoftext|>


<commit_before>frappe.listview_settings['Supplier'] = {
	add_fields: ["supplier_name", "supplier_type"],
};
<commit_msg>display image in supplier's list view (#9500)<commit_after>frappe.listview_settings['Supplier'] = {
	add_fields: ["supplier_name", "supplier_type", "image"],
};
<|endoftext|>