<commit_before>module.exports.main = function () {

	var fileref=document.createElement('script');
	fileref.setAttribute("type","text/javascript");
	fileref.setAttribute("src", "js/threex.domevents.js");
	document.getElementsByTagName("head")[0].appendChild(fileref);

	var fileref=document.createElement('script');
	fileref.setAttribute("type","text/javascript");
	fileref.setAttribute("src", "js/three.js");
	document.getElementsByTagName("head")[0].appendChild(fileref);

	setTimeout(function(){
		var graphId = $('#graphId').val();
		console.info(graphId);
		if (graphId) {
			getData(graphId);
			//timerId = setInterval(function(){getData(graphId)},10000);
		} else {
			console.info('No graphId');
		}
	}, 500);

};

module.exports.buildGraph = function (data) {

	var graph = graph ? graph : require('ngraph.graph')();
	var layout = layout ? layout : require('ngraph.forcelayout3d')(graph, {gravity: 1.2, theta: 0.2, dragCoeff: 0.9, timeStep : 1 } );
	var threeGraphics = threeGraphics ? threeGraphics : require('ngraph.three')(graph,{ interactive: true });
	var THREE = THREE ? THREE : threeGraphics.THREE;
	var camera = camera ? camera : threeGraphics.camera;

	var domEvents = domEvents ? domEvents : new THREEx.DomEvents(camera, threeGraphics.renderer.domElement, THREE);

	 // tell graphics we want custom UI
	threeGraphics.createNodeUI(function (node) {
		var nodeGeometry = node.data.additionalProperties.type == 'vk' ? new THREE.SphereGeometry(node.data.size) : new THREE.BoxGeometry(Math.round(node.data.size),Math.round(node.data.size),Math.round(node.data.size));
		var nodeMaterial = new THREE.MeshBasicMaterial({ color: node.data.color });

		var result = new THREE.Mesh(nodeGeometry, nodeMaterial);
		result['nodeId'] =  node.id;
		node.data['selected'] = false;
		domEvents.addEventListener(result, 'mouseover',onMouseOver);
		domEvents.addEventListener(result, 'mouseout',onMouseOut);
        domEvents.addEventListener(result, 'click',onMouseClick);
		return result;
  }).createLinkUI(function(link) {
		var linkGeometry = new THREE.Geometry();
		// we don't care about position here. linkRenderer will update it
		linkGeometry.vertices.push(new THREE.Vector3(0, 0, 0));
		linkGeometry.vertices.push(new THREE.Vector3(0, 0, 0));

		var linkMaterial = new THREE.LineBasicMaterial({ color: link.data.color });
		return new THREE.Line(linkGeometry, linkMaterial);
  });

	layout.step();

	addEventListeners(graph,threeGraphics, 'transparentLinks' )
	createGraph(graph,data);

	threeGraphics.run();

	function onMouseOver(e) {
		var nodeId = e.target.nodeId;
		/*console.info('nodeId - ' + nodeId + ' nodeIdUI - ' + e.target.id);*/
		var node = graph.getNode(nodeId);
		/*console.info('node name ' + node.data.name);*/

		var links = node.links;

		for (var i=0; i < links.length; i++) {
			var link = threeGraphics.getLinkUI(links[i].id);
			if (link) link.material.color.setStyle('#b14b56');
		}
		if(node.data['selected']  != true)
		{
			showName(node.data.name, e);
		}
	}

	function onMouseClick(e) {
		var nodeId = e.target.nodeId;
		var node = graph.getNode(nodeId);
		if(node.data['selected'] != true)
		{
	        graph.forEachNode(function(nodes){
	        	 if(nodes.data['selected'] == true)
	        	 {
	                 nodes.data['selected'] = false;
	                 var links = nodes.links;
	         		for (var i=0; i < links.length; i++) {
	        			var link = threeGraphics.getLinkUI(links[i].id);
	        			if (link) link.material.color.setStyle(links[i].data.color ? links[i].data.color : 'blue');
	        		}
	         		hideDetailsInfo();
	        	 }

	        });
			node.data['selected'] = true;
	        var links = node.links;
	 		for (var i=0; i < links.length; i++) {
				var link = threeGraphics.getLinkUI(links[i].id);
				if (link) link.material.color.setHex(0xff0000);
			}
	 		hideName();
	 		showDetailsInfo(node,e);

	        console.info('nodeId selected ' + node.id);
		}
		else
		{
            node.data['selected'] = false;
            var links = node.links;
    		for (var i=0; i < links.length; i++)
    		{
    			var link = threeGraphics.getLinkUI(links[i].id);
    			if (link) link.material.color.setStyle(links[i].data.color ? links[i].data.color : 'blue');
    		}
    		hideDetailsInfo();
		}
	}

	function onMouseOut(e) {
		var nodeId = e.target.nodeId;
		var node = graph.getNode(nodeId);
		var links = node.links;

		if(node.data['selected'] != true)
		{

			for (var i=0; i < links.length; i++) {
				var link = threeGraphics.getLinkUI(links[i].id);
				if (link) link.material.color.setStyle(links[i].data.color ? links[i].data.color : 'blue');
			}

		}
		hideName();
	}

};

function showName(name, event) {

	var newDiv = document.createElement('div');
	newDiv.className = 'div-class';
	newDiv.name = 'nameDiv';
	newDiv.innerHTML = name;

	newDiv.style.position = "absolute";
	newDiv.style.left = (event.origDomEvent.clientX + 10)+'px';
	newDiv.style.top = (event.origDomEvent.clientY - 10)+'px';
	newDiv.style.color = 'white';
	newDiv.style.fontWeight="bold";
	newDiv.style.fontSize = '26px';

	document.body.appendChild(newDiv);
}

function showDetailsInfo(node, event) {
	var newDiv = document.createElement('div');
	newDiv.className = 'div-info';
	newDiv.name = 'nameDiv';
	newDiv.innerHTML = name;

	newDiv.style.position = "absolute";
	newDiv.style.right = '0px';
	newDiv.style.top = '0px';
	newDiv.style.fontSize = '24px';
	newDiv.style.color = 'white';
	newDiv.style.backgroundColor = '#101010';
	newDiv.align = 'center';

	newDiv.style.padding = '5px';
	newDiv.style.borderRadius = '10px';

	var divText = document.createElement("p");
	divText.height = '100px';
	divText.textContent = node.data.name;
	divText.align = 'center';
	newDiv.appendChild(divText);

	if(node.data.photos && node.data.photos[0])
	{
		var img = document.createElement("img");
		img.src = node.data.photos[0];
		img.style.width="200";
		img.style.height = '400';
		newDiv.appendChild(img);
	}

	document.body.appendChild(newDiv);
}

function hideDetailsInfo() {
	var elems = document.getElementsByClassName('div-info');

	if(elems)
	{
		for (var i = 0; i < elems.length; i++) {
			document.body.removeChild(elems[i]);
		}
	}
}

function hideName() {
	var elems = document.getElementsByClassName('div-class');

	if(elems)
	{
		for (var i = 0; i < elems.length; i++) {
			document.body.removeChild(elems[i]);
		}
	}
}

function createGraph(graph, data) {

	if (!data.nodes || !data.nodes.length || !data.edges || !data.edges.length) {
		console.info('Graph not created!');
		return;
	}

	graph.beginUpdate();

	for (var i = 0; i < data.nodes.length; i++) {
		//console.info('Node : id - ' + data.nodes[i].id);
		graph.addNode(data.nodes[i].id, data.nodes[i]);
	}

	for (var i = 0; i < data.edges.length; i++) {
		//console.info('Link : from - ' + data.edges[i].from + ' to - ' + data.edges[i].to);
		graph.addLink(data.edges[i].from, data.edges[i].to, data.edges[i]);
	}

	graph.endUpdate();
	console.info('Graph created!');
}

function addEventListeners(graph, threeGraphics, elementId) {
	var element = document.getElementById(elementId);
	if (element) {
		element.addEventListener('click', function(){
			graph.forEachLink(function(link){
				var linkUI = threeGraphics.getLinkUI(link.id);
				if (linkUI)
					linkUI.material.opacity = linkUI.material.opacity > 0 ? 0 : 1;
			});
		});
	}
}

function getData(graphId) {
	jQuery.ajax({
		type : 'GET',
		async : true,
		cashe : false,
		dataType : 'json',
		url : 'js/final.json',
		//url : 'rest/pull?id='+graphId,
		success : function(data) {
			console.info(data);
			if (!data) {
				//clearInterval(timerId);
			} else {
				ngraph.buildGraph(data);
			}
		},
		error : function(jqXHR, textStatus, errorThrown) {
			console.log(textStatus, errorThrown);
			alert('Error occured!');
			//clearInterval(timerId);
		}
	});
}<commit_msg>fix hide/show links<commit_after>module.exports.main = function () {

	var fileref=document.createElement('script');
	fileref.setAttribute("type","text/javascript");
	fileref.setAttribute("src", "js/threex.domevents.js");
	document.getElementsByTagName("head")[0].appendChild(fileref);

	var fileref=document.createElement('script');
	fileref.setAttribute("type","text/javascript");
	fileref.setAttribute("src", "js/three.js");
	document.getElementsByTagName("head")[0].appendChild(fileref);

	setTimeout(function(){
		var graphId = $('#graphId').val();
		console.info(graphId);
		if (graphId) {
			getData(graphId);
			//timerId = setInterval(function(){getData(graphId)},10000);
		} else {
			console.info('No graphId');
		}
	}, 500);

};

module.exports.buildGraph = function (data) {

	var graph = graph ? graph : require('ngraph.graph')();
	var layout = layout ? layout : require('ngraph.forcelayout3d')(graph, {gravity: 1.2, theta: 0.2, dragCoeff: 0.9, timeStep : 1 } );
	var threeGraphics = threeGraphics ? threeGraphics : require('ngraph.three')(graph,{ interactive: true });
	var THREE = THREE ? THREE : threeGraphics.THREE;
	var camera = camera ? camera : threeGraphics.camera;

	var domEvents = domEvents ? domEvents : new THREEx.DomEvents(camera, threeGraphics.renderer.domElement, THREE);

	 // tell graphics we want custom UI
	threeGraphics.createNodeUI(function (node) {
		var nodeGeometry = node.data.additionalProperties.type == 'vk' ? new THREE.SphereGeometry(node.data.size) : new THREE.BoxGeometry(Math.round(node.data.size),Math.round(node.data.size),Math.round(node.data.size));
		var nodeMaterial = new THREE.MeshBasicMaterial({ color: node.data.color });

		var result = new THREE.Mesh(nodeGeometry, nodeMaterial);
		result['nodeId'] =  node.id;
		node.data['selected'] = false;
		domEvents.addEventListener(result, 'mouseover',onMouseOver);
		domEvents.addEventListener(result, 'mouseout',onMouseOut);
        domEvents.addEventListener(result, 'click',onMouseClick);
		return result;
  }).createLinkUI(function(link) {
		var linkGeometry = new THREE.Geometry();
		// we don't care about position here. linkRenderer will update it
		linkGeometry.vertices.push(new THREE.Vector3(0, 0, 0));
		linkGeometry.vertices.push(new THREE.Vector3(0, 0, 0));

		var linkMaterial = new THREE.LineBasicMaterial({ color: link.data.color, transparent: true });
		return new THREE.Line(linkGeometry, linkMaterial);
  });

	layout.step();

	addEventListeners(graph,threeGraphics, 'transparentLinks' )
	createGraph(graph,data);

	threeGraphics.run();

	function onMouseOver(e) {
		var nodeId = e.target.nodeId;
		/*console.info('nodeId - ' + nodeId + ' nodeIdUI - ' + e.target.id);*/
		var node = graph.getNode(nodeId);
		/*console.info('node name ' + node.data.name);*/

		var links = node.links;

		for (var i=0; i < links.length; i++) {
			var link = threeGraphics.getLinkUI(links[i].id);
			if (link) link.material.color.setStyle('#b14b56');
		}
		if(node.data['selected']  != true)
		{
			showName(node.data.name, e);
		}
	}

	function onMouseClick(e) {
		var nodeId = e.target.nodeId;
		var node = graph.getNode(nodeId);
		if(node.data['selected'] != true)
		{
	        graph.forEachNode(function(nodes){
	        	 if(nodes.data['selected'] == true)
	        	 {
	                 nodes.data['selected'] = false;
	                 var links = nodes.links;
	         		for (var i=0; i < links.length; i++) {
	        			var link = threeGraphics.getLinkUI(links[i].id);
	        			if (link) link.material.color.setStyle(links[i].data.color ? links[i].data.color : 'blue');
	        		}
	         		hideDetailsInfo();
	        	 }

	        });
			node.data['selected'] = true;
	        var links = node.links;
	 		for (var i=0; i < links.length; i++) {
				var link = threeGraphics.getLinkUI(links[i].id);
				if (link) link.material.color.setHex(0xff0000);
			}
	 		hideName();
	 		showDetailsInfo(node,e);

	        console.info('nodeId selected ' + node.id);
		}
		else
		{
            node.data['selected'] = false;
            var links = node.links;
    		for (var i=0; i < links.length; i++)
    		{
    			var link = threeGraphics.getLinkUI(links[i].id);
    			if (link) link.material.color.setStyle(links[i].data.color ? links[i].data.color : 'blue');
    		}
    		hideDetailsInfo();
		}
	}

	function onMouseOut(e) {
		var nodeId = e.target.nodeId;
		var node = graph.getNode(nodeId);
		var links = node.links;

		if(node.data['selected'] != true)
		{

			for (var i=0; i < links.length; i++) {
				var link = threeGraphics.getLinkUI(links[i].id);
				if (link) link.material.color.setStyle(links[i].data.color ? links[i].data.color : 'blue');
			}

		}
		hideName();
	}

};

function showName(name, event) {

	var newDiv = document.createElement('div');
	newDiv.className = 'div-class';
	newDiv.name = 'nameDiv';
	newDiv.innerHTML = name;

	newDiv.style.position = "absolute";
	newDiv.style.left = (event.origDomEvent.clientX + 10)+'px';
	newDiv.style.top = (event.origDomEvent.clientY - 10)+'px';
	newDiv.style.color = 'white';
	newDiv.style.fontWeight="bold";
	newDiv.style.fontSize = '26px';

	document.body.appendChild(newDiv);
}

function showDetailsInfo(node, event) {
	var newDiv = document.createElement('div');
	newDiv.className = 'div-info';
	newDiv.name = 'nameDiv';
	newDiv.innerHTML = name;

	newDiv.style.position = "absolute";
	newDiv.style.right = '0px';
	newDiv.style.top = '0px';
	newDiv.style.fontSize = '24px';
	newDiv.style.color = 'white';
	newDiv.style.backgroundColor = '#101010';
	newDiv.align = 'center';

	newDiv.style.padding = '5px';
	newDiv.style.borderRadius = '10px';

	var divText = document.createElement("p");
	divText.height = '100px';
	divText.textContent = node.data.name;
	divText.align = 'center';
	newDiv.appendChild(divText);

	if(node.data.photos && node.data.photos[0])
	{
		var img = document.createElement("img");
		img.src = node.data.photos[0];
		img.style.width="200";
		img.style.height = '400';
		newDiv.appendChild(img);
	}

	document.body.appendChild(newDiv);
}

function hideDetailsInfo() {
	var elems = document.getElementsByClassName('div-info');

	if(elems)
	{
		for (var i = 0; i < elems.length; i++) {
			document.body.removeChild(elems[i]);
		}
	}
}

function hideName() {
	var elems = document.getElementsByClassName('div-class');

	if(elems)
	{
		for (var i = 0; i < elems.length; i++) {
			document.body.removeChild(elems[i]);
		}
	}
}

function createGraph(graph, data) {

	if (!data.nodes || !data.nodes.length || !data.edges || !data.edges.length) {
		console.info('Graph not created!');
		return;
	}

	graph.beginUpdate();

	for (var i = 0; i < data.nodes.length; i++) {
		//console.info('Node : id - ' + data.nodes[i].id);
		graph.addNode(data.nodes[i].id, data.nodes[i]);
	}

	for (var i = 0; i < data.edges.length; i++) {
		//console.info('Link : from - ' + data.edges[i].from + ' to - ' + data.edges[i].to);
		graph.addLink(data.edges[i].from, data.edges[i].to, data.edges[i]);
	}

	graph.endUpdate();
	console.info('Graph created!');
}

function addEventListeners(graph, threeGraphics, elementId) {
	var element = document.getElementById(elementId);
	if (element) {
		element.addEventListener('click', function(){
			graph.forEachLink(function(link){
				var linkUI = threeGraphics.getLinkUI(link.id);
				if (linkUI)
					linkUI.material.opacity = linkUI.material.opacity > 0 ? 0 : 1;
			});
		});
	}
}

function getData(graphId) {
	jQuery.ajax({
		type : 'GET',
		async : true,
		cashe : false,
		dataType : 'json',
		url : 'js/4080446.json',
		//url : 'rest/pull?id='+graphId,
		success : function(data) {
			console.info(data);
			if (!data) {
				//clearInterval(timerId);
			} else {
				ngraph.buildGraph(data);
			}
		},
		error : function(jqXHR, textStatus, errorThrown) {
			console.log(textStatus, errorThrown);
			alert('Error occured!');
			//clearInterval(timerId);
		}
	});
}<|endoftext|>


<commit_before>/**
 * The MIT License
 *
 * Copyright (c) 2010 Adam Abrons and Misko Hevery http://getangular.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
(function(window) {

  var filename = /^(.*\/)angular-bootstrap.js(#.*)?$/,
      scripts = document.getElementsByTagName("SCRIPT"),
      serverPath,
      match,
      globalVars = {};

  for(var j = 0; j < scripts.length; j++) {
    match = (scripts[j].src || "").match(filename);
    if (match) {
      serverPath = match[1];
    }
  }

  function key(prop) {
    return "ng-clobber_" + prop;
  }

  window.angularClobberTest = function(file) {
    var varKey, prop,
        clobbered = [];

    for (prop in window) {
      varKey = key(prop);

      if (prop === 'event') { //skip special variables which keep on changing
        continue;
      }
      else if (!globalVars.hasOwnProperty(varKey)) {
        //console.log('new global variable found: ', prop);
        try {
          globalVars[varKey] = window[prop];
        } catch(e) {} //ignore properties that throw exception when accessed (common in FF)
      } else if (globalVars[varKey] !== window[prop] && !isActuallyNaN(window[prop])) {
        clobbered.push(prop);
        console.error("Global variable clobbered by script " + file + "! Variable name: " + prop);
        globalVars[varKey] = window[prop];
      }
    }

    for (varKey in globalVars) {
      prop = varKey.substr(11);
      if (clobbered.indexOf(prop) == -1 &&
          prop != 'event' &&
          !isActuallyNaN(globalVars[varKey]) &&
          globalVars[varKey] !== window[prop]) {

        delete globalVars[varKey];
        console.warn("Global variable unexpectedly deleted in script " + file + "! " +
                     "Variable name: " + prop);
      }
    }

    function isActuallyNaN(val) {
      return isNaN(val) && (typeof val === 'number');
    }
  };

  function addScripts(){
    var prop, i;

    // initialize the window property cache
    for (prop in window) {
      try {
        globalVars[key(prop)] = window[prop];
      } catch(e) {} //ignore properties that throw exception when accessed (common in FF)
    }

    // load the js scripts
    for (i in Array.prototype.slice.call(arguments, 0)) {
      file = arguments[i];
      document.write('<script type="text/javascript" src="' + serverPath + file + '" ' +
                             'onload="angularClobberTest(\'' + file + '\')"></script>');
    }
  }

  function addCss(file) {
    document.write('<link rel="stylesheet" type="text/css" href="' +
                      serverPath + '../css/' + file  + '"/>');
  }

  addCss('angular.css');

  addScripts('Angular.js',
             'JSON.js',
             'Compiler.js',
             'Scope.js',
             'Injector.js',
             'jqLite.js',
             'parser.js',
             'Resource.js',
             'Browser.js',
             'sanitizer.js',
             'AngularPublic.js',

             // Extension points

             'service/cookieStore.js',
             'service/cookies.js',
             'service/defer.js',
             'service/document.js',
             'service/exceptionHandler.js',
             'service/hover.js',
             'service/invalidWidgets.js',
             'service/location.js',
             'service/log.js',
             'service/resource.js',
             'service/route.js',
             'service/updateView.js',
             'service/window.js',
             'service/xhr.bulk.js',
             'service/xhr.cache.js',
             'service/xhr.error.js',
             'service/xhr.js',

             'apis.js',
             'filters.js',
             'formatters.js',
             'validators.js',
             'directives.js',
             'markups.js',
             'widgets.js');

  function onLoadListener(){
    // empty the cache to prevent mem leaks
    globalVars = {};

    //angular-ie-compat.js needs to be pregenerated for development with IE<8
    if (msie<8) addScript('../angular-ie-compat.js');

    angularInit(angularJsConfig(document), document);
  }

  if (window.addEventListener){
    window.addEventListener('load', onLoadListener, false);
  } else if (window.attachEvent){
    window.attachEvent('onload', onLoadListener);
  }

})(window);

<commit_msg>removed jqLite warning<commit_after>/**
 * The MIT License
 *
 * Copyright (c) 2010 Adam Abrons and Misko Hevery http://getangular.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
(function(window) {

  var filename = /^(.*\/)angular-bootstrap.js(#.*)?$/,
      scripts = document.getElementsByTagName("SCRIPT"),
      serverPath,
      match,
      globalVars = {};

  for(var j = 0; j < scripts.length; j++) {
    match = (scripts[j].src || "").match(filename);
    if (match) {
      serverPath = match[1];
    }
  }

  function key(prop) {
    return "ng-clobber_" + prop;
  }

  window.angularClobberTest = function(file) {
    var varKey, prop,
        clobbered = [];

    for (prop in window) {
      varKey = key(prop);

      if (prop === 'event') { //skip special variables which keep on changing
        continue;
      }
      else if (!globalVars.hasOwnProperty(varKey)) {
        //console.log('new global variable found: ', prop);
        try {
          globalVars[varKey] = window[prop];
        } catch(e) {} //ignore properties that throw exception when accessed (common in FF)
      } else if (globalVars[varKey] !== window[prop] && !isActuallyNaN(window[prop]) && prop != 'jqLite') {
        clobbered.push(prop);
        console.error("Global variable clobbered by script " + file + "! Variable name: " + prop);
        globalVars[varKey] = window[prop];
      }
    }
    for (varKey in globalVars) {
      prop = varKey.substr(11);
      if (clobbered.indexOf(prop) == -1 &&
          prop != 'event' &&
          prop != 'jqLite' &&
          !isActuallyNaN(globalVars[varKey]) &&
          globalVars[varKey] !== window[prop]) {

        delete globalVars[varKey];
        console.warn("Global variable unexpectedly deleted in script " + file + "! " +
                     "Variable name: " + prop);
      }
    }

    function isActuallyNaN(val) {
      return isNaN(val) && (typeof val === 'number');
    }
  };

  function addScripts(){
    var prop, i;

    // initialize the window property cache
    for (prop in window) {
      try {
        globalVars[key(prop)] = window[prop];
      } catch(e) {} //ignore properties that throw exception when accessed (common in FF)
    }

    // load the js scripts
    for (i in Array.prototype.slice.call(arguments, 0)) {
      file = arguments[i];
      document.write('<script type="text/javascript" src="' + serverPath + file + '" ' +
                             'onload="angularClobberTest(\'' + file + '\')"></script>');
    }
  }

  function addCss(file) {
    document.write('<link rel="stylesheet" type="text/css" href="' +
                      serverPath + '../css/' + file  + '"/>');
  }

  addCss('angular.css');

  addScripts('Angular.js',
             'JSON.js',
             'Compiler.js',
             'Scope.js',
             'Injector.js',
             'jqLite.js',
             'parser.js',
             'Resource.js',
             'Browser.js',
             'sanitizer.js',
             'AngularPublic.js',

             // Extension points

             'service/cookieStore.js',
             'service/cookies.js',
             'service/defer.js',
             'service/document.js',
             'service/exceptionHandler.js',
             'service/hover.js',
             'service/invalidWidgets.js',
             'service/location.js',
             'service/log.js',
             'service/resource.js',
             'service/route.js',
             'service/updateView.js',
             'service/window.js',
             'service/xhr.bulk.js',
             'service/xhr.cache.js',
             'service/xhr.error.js',
             'service/xhr.js',

             'apis.js',
             'filters.js',
             'formatters.js',
             'validators.js',
             'directives.js',
             'markups.js',
             'widgets.js');

  function onLoadListener(){
    // empty the cache to prevent mem leaks
    globalVars = {};

    //angular-ie-compat.js needs to be pregenerated for development with IE<8
    if (msie<8) addScript('../angular-ie-compat.js');

    angularInit(angularJsConfig(document), document);
  }

  if (window.addEventListener){
    window.addEventListener('load', onLoadListener, false);
  } else if (window.attachEvent){
    window.attachEvent('onload', onLoadListener);
  }

})(window);

<|endoftext|>


<commit_before>import React from 'react'
import { connect } from 'react-redux'
import Form from 'react-jsonschema-form'
import BaseInput from 'react-jsonschema-form/lib/components/widgets/BaseInput'

import RefWidget from './RefWidget'
import UploadWidget from './UploadWidget'
import FlowPickWidget from './FlowPickWidget'

import TextMl from './i18n/Text'
import ArrayMl from './i18n/Array'
import withLanguage from '../Util/withLanguage'

const CustomBaseInput = props => {
  const { type, $subtype } = props.schema
  if (type === 'string') {
    if ($subtype === 'ref') {
      return <RefWidget {...props} />
    } else if ($subtype === 'media') {
      return <UploadWidget {...props} />
    } else if ($subtype === 'flow') {
      return <FlowPickWidget {...props} />
    }
  }
  return <BaseInput {...props} />
}

const widgets = {
  BaseInput: CustomBaseInput
}

const fields = { i18n_field: TextMl, i18n_array: ArrayMl }

class ContentForm extends React.Component {
  state = {}

  updateMultiLangProp = (field, value) => {
    this.setState({ [field]: value })
  }

  handleOnChange = event => {
    this.props.onChange({
      ...event,
      formData: {
        ...event.formData,
        ...this.state
      }
    })
  }

  render() {
    const defaultFormData = this.props.schema.type === 'array' ? [] : {}

    const context = {
      ...this.props.formData,
      updateProp: this.updateMultiLangProp,
      languages: this.props.languages,
      activeLang: this.props.contentLang,
      defaultLang: this.props.defaultLang
    }

    return (
      <Form
        {...this.props}
        formData={this.props.formData || defaultFormData}
        formContext={context}
        safeRenderCompletion={true}
        widgets={widgets}
        fields={fields}
        onChange={this.handleOnChange}
        changeContentLanguage={this.props.changeContentLanguage}
      />
    )
  }
}

export default withLanguage(ContentForm)
<commit_msg>fixed defaultLang mapping<commit_after>import React from 'react'
import { connect } from 'react-redux'
import Form from 'react-jsonschema-form'
import BaseInput from 'react-jsonschema-form/lib/components/widgets/BaseInput'

import RefWidget from './RefWidget'
import UploadWidget from './UploadWidget'
import FlowPickWidget from './FlowPickWidget'

import TextMl from './i18n/Text'
import ArrayMl from './i18n/Array'
import withLanguage from '../Util/withLanguage'

const CustomBaseInput = props => {
  const { type, $subtype } = props.schema
  if (type === 'string') {
    if ($subtype === 'ref') {
      return <RefWidget {...props} />
    } else if ($subtype === 'media') {
      return <UploadWidget {...props} />
    } else if ($subtype === 'flow') {
      return <FlowPickWidget {...props} />
    }
  }
  return <BaseInput {...props} />
}

const widgets = {
  BaseInput: CustomBaseInput
}

const fields = { i18n_field: TextMl, i18n_array: ArrayMl }

class ContentForm extends React.Component {
  state = {}

  updateMultiLangProp = (field, value) => {
    this.setState({ [field]: value })
  }

  handleOnChange = event => {
    this.props.onChange({
      ...event,
      formData: {
        ...event.formData,
        ...this.state
      }
    })
  }

  render() {
    const defaultFormData = this.props.schema.type === 'array' ? [] : {}

    const context = {
      ...this.props.formData,
      updateProp: this.updateMultiLangProp,
      languages: this.props.languages,
      activeLang: this.props.contentLang,
      defaultLang: this.props.defaultLanguage
    }

    return (
      <Form
        {...this.props}
        formData={this.props.formData || defaultFormData}
        formContext={context}
        safeRenderCompletion={true}
        widgets={widgets}
        fields={fields}
        onChange={this.handleOnChange}
        changeContentLanguage={this.props.changeContentLanguage}
      />
    )
  }
}

export default withLanguage(ContentForm)
<|endoftext|>


<commit_before>frappe.ui.form.ControlSelect = frappe.ui.form.ControlData.extend({
	html_element: 'select',
	make_input: function() {
		this._super();

		const is_xs_input = this.df.input_class
			&& this.df.input_class.includes('input-xs');
		this.set_icon(is_xs_input);
		this.df.placeholder && this.set_placeholder(is_xs_input);

		this.$input.addClass('ellipsis')
		this.set_options();
	},
	set_icon: function(is_xs_input) {
		const select_icon_html =
			`

				${frappe.utils.icon('select', is_xs_input ? 'xs' : 'sm')}

`
		if (this.only_input) {
			this.$wrapper.append(select_icon_html);
		} else {
			this.$wrapper.find('.control-input')
				.addClass('flex align-center')
				.append(select_icon_html);
		}
	},
	set_placeholder: function(is_xs_input) {
		this.$wrapper.append(`

				${this.df.placeholder}

`
		);
		this.toggle_placeholder();
	},
	set_formatted_input: function(value) {
		// refresh options first - (new ones??)
		if(value==null) value = '';
		this.set_options(value);

		// set in the input element
		this._super(value);

		// check if the value to be set is selected
		var input_value = '';
		if(this.$input) {
			input_value = this.$input.val();
		}

		if(value && input_value && value !== input_value) {
			// trying to set a non-existant value
			// model value must be same as whatever the input is
			this.set_model_value(input_value);
		}
		this.toggle_placeholder();
	},
	set_options: function(value) {
		// reset options, if something new is set
		var options = this.df.options || [];

		if(typeof this.df.options==="string") {
			options = this.df.options.split("\n");
		}

		// nothing changed
		if (JSON.stringify(options) === this.last_options) {
			return;
		}
		this.last_options = JSON.stringify(options);

		if(this.$input) {
			var selected = this.$input.find(":selected").val();
			this.$input.empty().add_options(options || []);

			if(value===undefined && selected) {
				this.$input.val(selected);
			}
		}
	},
	get_file_attachment_list: function() {
		if(!this.frm) return;
		var fl = frappe.model.docinfo[this.frm.doctype][this.frm.docname];
		if(fl && fl.attachments) {
			this.set_description("");
			var options = [""];
			$.each(fl.attachments, function(i, f) {
				options.push(f.file_url);
			});
			return options;
		} else {
			this.set_description(__("Please attach a file first."));
			return [""];
		}
	},
	toggle_placeholder: function() {
		const input_set = Boolean(this.$input.val());
		this.$wrapper.find('.placeholder').toggle(!input_set);
	}
});

// add <option> list to <select>
(function($) {
	$.fn.add_options = function(options_list) {
		// create options
		for(var i=0, j=options_list.length; i<j; i++) {
			var v = options_list[i];
			var value = null;
			var label = null;
			if (!is_null(v)) {
				var is_value_null = is_null(v.value);
				var is_label_null = is_null(v.label);
				var is_disabled = Boolean(v.disabled);

				if (is_value_null && is_label_null) {
					value = v;
					label = __(v);
				} else {
					value = is_value_null ? "" : v.value;
					label = is_label_null ? __(value) : __(v.label);
				}
			}
			$('<option>').html(cstr(label))
				.attr('value', value)
				.prop('disabled', is_disabled)
				.appendTo(this);
		}
		// select the first option
		this.selectedIndex = 0;
		return $(this);
	};
	$.fn.set_working = function() {
		this.prop('disabled', true);
	};
	$.fn.done_working = function() {
		this.prop('disabled', false);
	};
})(jQuery);
<commit_msg>style: fix formatting<commit_after>frappe.ui.form.ControlSelect = frappe.ui.form.ControlData.extend({
	html_element: 'select',
	make_input: function() {
		this._super();

		const is_xs_input = this.df.input_class
			&& this.df.input_class.includes('input-xs');
		this.set_icon(is_xs_input);
		this.df.placeholder && this.set_placeholder(is_xs_input);

		this.$input.addClass('ellipsis');
		this.set_options();
	},
	set_icon: function(is_xs_input) {
		const select_icon_html =
			`

				${frappe.utils.icon('select', is_xs_input ? 'xs' : 'sm')}

`;
		if (this.only_input) {
			this.$wrapper.append(select_icon_html);
		} else {
			this.$wrapper.find('.control-input')
				.addClass('flex align-center')
				.append(select_icon_html);
		}
	},
	set_placeholder: function(is_xs_input) {
		this.$wrapper.append(`

				${this.df.placeholder}

`
		);
		this.toggle_placeholder();
	},
	set_formatted_input: function(value) {
		// refresh options first - (new ones??)
		if(value==null) value = '';
		this.set_options(value);

		// set in the input element
		this._super(value);

		// check if the value to be set is selected
		var input_value = '';
		if(this.$input) {
			input_value = this.$input.val();
		}

		if(value && input_value && value !== input_value) {
			// trying to set a non-existant value
			// model value must be same as whatever the input is
			this.set_model_value(input_value);
		}
		this.toggle_placeholder();
	},
	set_options: function(value) {
		// reset options, if something new is set
		var options = this.df.options || [];

		if(typeof this.df.options==="string") {
			options = this.df.options.split("\n");
		}

		// nothing changed
		if (JSON.stringify(options) === this.last_options) {
			return;
		}
		this.last_options = JSON.stringify(options);

		if(this.$input) {
			var selected = this.$input.find(":selected").val();
			this.$input.empty().add_options(options || []);

			if(value===undefined && selected) {
				this.$input.val(selected);
			}
		}
	},
	get_file_attachment_list: function() {
		if(!this.frm) return;
		var fl = frappe.model.docinfo[this.frm.doctype][this.frm.docname];
		if(fl && fl.attachments) {
			this.set_description("");
			var options = [""];
			$.each(fl.attachments, function(i, f) {
				options.push(f.file_url);
			});
			return options;
		} else {
			this.set_description(__("Please attach a file first."));
			return [""];
		}
	},
	toggle_placeholder: function() {
		const input_set = Boolean(this.$input.val());
		this.$wrapper.find('.placeholder').toggle(!input_set);
	}
});

// add <option> list to <select>
(function($) {
	$.fn.add_options = function(options_list) {
		// create options
		for(var i=0, j=options_list.length; i<j; i++) {
			var v = options_list[i];
			var value = null;
			var label = null;
			if (!is_null(v)) {
				var is_value_null = is_null(v.value);
				var is_label_null = is_null(v.label);
				var is_disabled = Boolean(v.disabled);

				if (is_value_null && is_label_null) {
					value = v;
					label = __(v);
				} else {
					value = is_value_null ? "" : v.value;
					label = is_label_null ? __(value) : __(v.label);
				}
			}
			$('<option>').html(cstr(label))
				.attr('value', value)
				.prop('disabled', is_disabled)
				.appendTo(this);
		}
		// select the first option
		this.selectedIndex = 0;
		return $(this);
	};
	$.fn.set_working = function() {
		this.prop('disabled', true);
	};
	$.fn.done_working = function() {
		this.prop('disabled', false);
	};
})(jQuery);
<|endoftext|>


<commit_before>var module = angular.module('commafeed.services', [ 'ngResource' ]);

module.factory('SubscriptionService', [ '$resource', '$http',
		function($resource, $http) {

		    var flatten = function(category, parentName, array) {
		    	if(!array) array = [];
				array.push({
					id : category.id,
					name : category.name + (parentName ? (' (in ' + parentName + ')') : '')
				});
				if (category.children) {
					for ( var i = 0; i < category.children.length; i++) {
						flatten(category.children[i], category.name, array);
					}
				}
				return array;
			}
			var actions = {
				get : {
					method : 'GET',
					params : {
						_method : ''
					}
				},
				subscribe : {
					method : 'POST',
					params : {
						_method : 'subscribe'
					}
				},
				unsubscribe : {
					method : 'GET',
					params : {
						_method : 'unsubscribe'
					}
				}
			};
			var s = {};
			s.subscriptions = {};
			s.flatCategories = {};

			var res = $resource('rest/subscriptions/:_method', {}, actions);
			s.init = function(callback) {
				s.subscriptions = res.get(function(data) {
					s.flatCategories = flatten(s.subscriptions);
					callback(data);
				});
			};
			s.subscribe = function(sub, callback) {
				res.subscribe(sub, callback);
				s.init();
			};
			s.unsubscribe = function(id, callback) {
				res.unsubscribe({
					id : id
				}, callback);
				s.init();
			};
			s.init();
			return s;
		} ]);

module.factory('EntryService', [
		'$resource',
		'$http',
		function($resource, $http) {
			var actions = {
				get : {
					method : 'GET',
					params : {
						_method : 'get'
					}
				},
				mark : {
					method : 'GET',
					params : {
						_method : 'mark'
					}
				}
			};
			res = $resource('rest/entries/:_method', {},
					actions);
			return res;
		} ]);

module.service('SettingsService', function($resource) {
	var s = {}
	s.settings = $resource('rest/settings/get').get();
	s.save = function() {
		$resource('rest/settings/save').save(s.settings);
	};
	return s;
});<commit_msg>fix undefined error<commit_after>var module = angular.module('commafeed.services', [ 'ngResource' ]);

module.factory('SubscriptionService', [ '$resource', '$http',
		function($resource, $http) {

		    var flatten = function(category, parentName, array) {
		    	if(!array) array = [];
				array.push({
					id : category.id,
					name : category.name + (parentName ? (' (in ' + parentName + ')') : '')
				});
				if (category.children) {
					for ( var i = 0; i < category.children.length; i++) {
						flatten(category.children[i], category.name, array);
					}
				}
				return array;
			}
			var actions = {
				get : {
					method : 'GET',
					params : {
						_method : ''
					}
				},
				subscribe : {
					method : 'POST',
					params : {
						_method : 'subscribe'
					}
				},
				unsubscribe : {
					method : 'GET',
					params : {
						_method : 'unsubscribe'
					}
				}
			};
			var s = {};
			s.subscriptions = {};
			s.flatCategories = {};

			var res = $resource('rest/subscriptions/:_method', {}, actions);
			s.init = function(callback) {
				s.subscriptions = res.get(function(data) {
					s.flatCategories = flatten(s.subscriptions);
					if(callback)
						callback(data);
				});
			};
			s.subscribe = function(sub, callback) {
				res.subscribe(sub, callback);
				s.init();
			};
			s.unsubscribe = function(id, callback) {
				res.unsubscribe({
					id : id
				}, callback);
				s.init();
			};
			s.init();
			return s;
		} ]);

module.factory('EntryService', [
		'$resource',
		'$http',
		function($resource, $http) {
			var actions = {
				get : {
					method : 'GET',
					params : {
						_method : 'get'
					}
				},
				mark : {
					method : 'GET',
					params : {
						_method : 'mark'
					}
				}
			};
			res = $resource('rest/entries/:_method', {},
					actions);
			return res;
		} ]);

module.service('SettingsService', function($resource) {
	var s = {}
	s.settings = $resource('rest/settings/get').get();
	s.save = function() {
		$resource('rest/settings/save').save(s.settings);
	};
	return s;
});<|endoftext|>


<commit_before>angular.lazyLoad = function(rootModule, baseUrl) {
  var $module = angular.module;
  var $q      = angular.injector(['ng']).get('$q');
  var modules = [];

  var LazyLoadModule = function(name, deps, baseUrl) {
    var proxies   = {
      config:     [],
      constant:   [],
      controller: [],
      run:        [],
      value:      []
    };

    var scripts = [];

    this.name   = name;
    this.deps   = deps;
    this.loaded = false;

    this.bootstrap = function() {
      angular.forEach(scripts, function(script) {
        script();
      });
    };

    this.config = function() {
      proxies.config.push(arguments);

      return this;
    };

    this.constant = function() {
      proxies.constant.push(arguments);

      return this;
    };

    this.controller = function() {
      proxies.controller.push(arguments);

      return this;
    };

    this.run = function() {
      proxies.run.push(arguments);

      return this;
    };

    this.value = function() {
      proxies.value.push(arguments);

      return this;
    };

    this.load = function() {
      var $http     = angular.injector(['ng']).get('$http');
      var resources = [];

      angular.forEach(deps, function(dep) {
        var url = baseUrl + dep.replace(/\./g, '/') + '.js';

        resources.push($http.get(url).success(function(source) {
          var script = new Function(source);
          script.name = url;

          scripts.push(script);

          script();
        }));
      });

      return $q.all(resources).then(angular.bind(this, function() {
        this.loaded = true;
      }));
    };
  };

  var ModuleProxy = function(name, deps) {
    var module = new LazyLoadModule(name, deps || [], baseUrl);

    modules.unshift(module);

    return module;
  };

  angular.element().ready(function BootstrapProxy() {
    var $q = angular.injector(['ng']).get('$q');

    if (rootModule) {
      modules.unshift(new LazyLoadModule('lazyLoad.bootstrap', [rootModule], baseUrl));
    }

    var loadModules = function() {
      for (var i in modules) {
        var module = modules[i];

        if (!module.loaded) {
          return $q.when(module.load()).then(function() {
            return loadModules();
          });
        }
      }
    };

    console.log('dang');

    loadModules().then(function() {
      angular.module = $module;

      modules.forEach(function(module) {
        module.bootstrap();
      });

      angular.resumeBootstrap();
    });
  });

  window.name = window.name + 'NG_DEFER_BOOTSTRAP!';

  if (baseUrl && ('/' !== baseUrl.substr(-1))) {
    baseUrl += '/';
  }

  angular.module = ModuleProxy;

  return this;
};
<commit_msg>Remove comment<commit_after>angular.lazyLoad = function(rootModule, baseUrl) {
  var $module = angular.module;
  var $q      = angular.injector(['ng']).get('$q');
  var modules = [];

  var LazyLoadModule = function(name, deps, baseUrl) {
    var proxies   = {
      config:     [],
      constant:   [],
      controller: [],
      run:        [],
      value:      []
    };

    var scripts = [];

    this.name   = name;
    this.deps   = deps;
    this.loaded = false;

    this.bootstrap = function() {
      angular.forEach(scripts, function(script) {
        script();
      });
    };

    this.config = function() {
      proxies.config.push(arguments);

      return this;
    };

    this.constant = function() {
      proxies.constant.push(arguments);

      return this;
    };

    this.controller = function() {
      proxies.controller.push(arguments);

      return this;
    };

    this.run = function() {
      proxies.run.push(arguments);

      return this;
    };

    this.value = function() {
      proxies.value.push(arguments);

      return this;
    };

    this.load = function() {
      var $http     = angular.injector(['ng']).get('$http');
      var resources = [];

      angular.forEach(deps, function(dep) {
        var url = baseUrl + dep.replace(/\./g, '/') + '.js';

        resources.push($http.get(url).success(function(source) {
          var script = new Function(source);
          script.name = url;

          scripts.push(script);

          script();
        }));
      });

      return $q.all(resources).then(angular.bind(this, function() {
        this.loaded = true;
      }));
    };
  };

  var ModuleProxy = function(name, deps) {
    var module = new LazyLoadModule(name, deps || [], baseUrl);

    modules.unshift(module);

    return module;
  };

  angular.element().ready(function BootstrapProxy() {
    var $q = angular.injector(['ng']).get('$q');

    if (rootModule) {
      modules.unshift(new LazyLoadModule('lazyLoad.bootstrap', [rootModule], baseUrl));
    }

    var loadModules = function() {
      for (var i in modules) {
        var module = modules[i];

        if (!module.loaded) {
          return $q.when(module.load()).then(function() {
            return loadModules();
          });
        }
      }
    };

    loadModules().then(function() {
      angular.module = $module;

      modules.forEach(function(module) {
        module.bootstrap();
      });

      angular.resumeBootstrap();
    });
  });

  window.name = window.name + 'NG_DEFER_BOOTSTRAP!';

  if (baseUrl && ('/' !== baseUrl.substr(-1))) {
    baseUrl += '/';
  }

  angular.module = ModuleProxy;

  return this;
};
<|endoftext|>


<commit_before>const micro = require('micro')
const crypto = require('crypto')
const os = require('os')
const git = require('simple-git')()
const uuid = require('uuid/v4')
const pify = require('pify')
const rimraf = pify(require('rimraf'))
let mergeDirs = require('merge-dirs')
const gitClone = pify(git.clone.bind(git))
const { resolve } = require('path')
const json = micro.json
const send = micro.send
// Fix merge-dirs default export
mergeDirs = mergeDirs.default ? mergeDirs.default : mergeDirs

// Refresh documentation files (pull from Github)
module.exports = async function ({ req, res }, getFiles) {
  const body = await json(req)
  // Only for production
  if (!process.env.GH_HOOK_SECRET || !req.headers['x-hub-signature']) {
    return send(res, 501)
  }
  // Check if X-Hub-Signature matches our secret
  let hmac = crypto.createHmac('sha1', process.env.GH_HOOK_SECRET)
  hmac.update(JSON.stringify(body))
  let signature = 'sha1=' + hmac.digest('hex')
  if (req.headers['x-hub-signature'] !== signature) {
    return send(res, 403)
  }
  // Accept only push hook events
  if (req.headers['x-github-event'] === 'ping') {
    return send(res, 200, 'OK')
  }
  // Only push event authorized
  if (req.headers['x-github-event'] !== 'push') {
    return send(res, 501)
  }
  const clonePath = resolve(os.tmpdir(), uuid())
  await gitClone('https://github.com/nuxt/docs.git', clonePath)
  mergeDirs(clonePath, resolve(__dirname), 'overwrite')
  await getFiles()
  await rimraf(clonePath)
  send(res, 200, 'OK')
}
<commit_msg>Add logs<commit_after>const micro = require('micro')
const crypto = require('crypto')
const os = require('os')
const git = require('simple-git')()
const uuid = require('uuid/v4')
const pify = require('pify')
const rimraf = pify(require('rimraf'))
let mergeDirs = require('merge-dirs')
const gitClone = pify(git.clone.bind(git))
const { resolve } = require('path')
const json = micro.json
const send = micro.send
// Fix merge-dirs default export
mergeDirs = mergeDirs.default ? mergeDirs.default : mergeDirs

// Refresh documentation files (pull from Github)
module.exports = async function ({ req, res }, getFiles) {
  const body = await json(req)
  // Only for production
  if (!process.env.GH_HOOK_SECRET || !req.headers['x-hub-signature']) {
    return send(res, 501)
  }
  console.log('Received GitHub Hook', req.headers['x-gitHub-delivery'])
  // Check if X-Hub-Signature matches our secret
  let hmac = crypto.createHmac('sha1', process.env.GH_HOOK_SECRET)
  hmac.update(JSON.stringify(body))
  let signature = 'sha1=' + hmac.digest('hex')
  if (req.headers['x-hub-signature'] !== signature) {
    return send(res, 403)
  }
  // Accept only push hook events
  if (req.headers['x-github-event'] === 'ping') {
    return send(res, 200, 'OK')
  }
  // Only push event authorized
  if (req.headers['x-github-event'] !== 'push') {
    return send(res, 501)
  }
  const clonePath = resolve(os.tmpdir(), uuid())
  console.log('Clone repository...')
  await gitClone('https://github.com/nuxt/docs.git', clonePath)
  mergeDirs(clonePath, resolve(__dirname), 'overwrite')
  await getFiles()
  await rimraf(clonePath)
  console.log('Docs file updated!')
  send(res, 200, 'OK')
}
<|endoftext|>


<commit_before>var sys = require('sys')
  , eyes = require('eyes')
  , http = require('http')
  , events = require('events')
  ;

function Pool (port, host, https, credentials) {
  this.port = port;
  this.host = host;
  this.https = https;
  this.credentials = credentials;
  this.clients = [];
  this.pending = [];
  this.minClients = 0;
  this.maxClients = 8;
};

sys.inherits(Pool, events.EventEmitter);

Pool.prototype.getClient = function (cb) {
  for (var i=0;i<this.clients.length;i+=1) {
    if (!this.clients[i].busy) {
      // Check if the client closed unexpectedly
      if (this.clients[i].readyState === 'closed') {
        delete this.clients[i];
        this.clients[i] = http.createClient(this.port, this.host, this.https, this.credentials);
        this.clients[i].busy = false;
      }

      if (this.clients.length > this.maxClients) {
        this.clients[i].end();
        this.clients.splice(i, 1);
        i-=1;
      } else {
        return cb(this.clients[i]);
      }
    }
  }
  if (this.clients.length >= this.maxClients) {
    this.pending.push(cb);
  } else {
    var client = http.createClient(this.port, this.host, this.https, this.credentials);
    this.clients.push(client);
    cb(client);
  }
};

Pool.prototype.request = function () {
  // Argument parsing. This gets a little dicey with the
  // differences in defaults
  var method, url, headers, callback, args;
  var self = this;
  args = Array.prototype.slice.call(arguments);

  if (typeof args[args.length - 1] === 'function') {
    callback = args.pop();
  }
  if (args[0]) method = args[0];
  if (args[1]) url = args[1];
  if (args[2]) headers = args[2];

  if (!headers) headers = {};
  if (!headers.Connection) headers.Connection = 'keep-alive';

  self.getClient(function (client) {
    var errorListener = function (error) {
      client.removeListener("error", errorListener);

      // Remove the client from the available clients since it has errored
      self.clients.splice(self.clients.indexOf(client), 1);

      self.emit("error", error);
      request.emit("error", error);
    };

    var request = client.request(method, url, headers);
    client.on("error", errorListener);
    request.on("response", function (response) {
      response.on("end", function () {
        client.removeListener("error", errorListener);
        client.busy = false;
        self.onFree(client);
      })
    })
    client.busy = true;
    callback(request);
  });
};

Pool.prototype.onFree = function (client) {
  if (this.pending.length > 0) this.pending.shift()(client);
};

Pool.prototype.getFree = function () {
  return this.clients.filter(function (client) { return !client.busy }).length;
};

Pool.prototype.getBusy = function () {
  return this.clients.filter(function (client) { return client.busy }).length;
};

Pool.prototype.setMinClients = function (num) {
  this.minClients = num;
  if (this.clients.length < num) {
    for (var i=this.clients.length;i<num;i+=1) {
      var client = http.createClient(this.port, this.host, this.https, this.credentials);
      this.clients.push(client);
      this.emit('free', client);
    }
  }
};

Pool.prototype.setMaxClients = function (num) {
  this.maxClients = num;
};

Pool.prototype.end = function () {
  this.clients.forEach(function (c) {c.end()});
};

function PoolManager () {
  this.pools = {};
  this.pending = [];
  this.minClients = 0;
  this.maxClients = 8;
};

PoolManager.prototype.setMaxClients = function (num) {
  this.maxClients = num;
  for (i in this.pools) {
    this.pools[i].setMaxClients(num);
  }
};

PoolManager.prototype.setMinClients = function (num) {
  this.minClients = num;
  for (i in this.pools) {
    this.pools[i].setMinClients(num);
  }
};

PoolManager.prototype.getPool = function (port, host, https, credentials) {
  var k = (port+host+https+credentials);
  if (!this.pools[k]) {
    this.pools[k] = exports.createPool(port, host, https, credentials);
    this.pools[k].setMinClients(this.minClients);
    this.pools[k].setMaxClients(this.maxClients);
  }
  return this.pools[k];
};

exports.createPool = function (port, host, https, credentials) {
  return new Pool(port, host, https, credentials);
};

exports.createPoolManager = function () {
  return new PoolManager();
};
<commit_msg>[debug] Trying to repair pool busy client growth<commit_after>var sys = require('sys')
  , eyes = require('eyes')
  , http = require('http')
  , events = require('events')
  ;

function Pool (port, host, https, credentials) {
  this.port = port;
  this.host = host;
  this.https = https;
  this.credentials = credentials;
  this.clients = [];
  this.pending = [];
  this.minClients = 0;
  this.maxClients = 8;
};

sys.inherits(Pool, events.EventEmitter);

Pool.prototype.getClient = function (cb) {
  for (var i=0;i<this.clients.length;i+=1) {
    if (!this.clients[i].busy) {
      // Check if the client closed unexpectedly
      if (this.clients[i].readyState === 'closed') {
        delete this.clients[i];
        this.clients[i] = http.createClient(this.port, this.host, this.https, this.credentials);
        this.clients[i].busy = false;
      }

      if (this.clients.length > this.maxClients) {
        this.clients[i].end();
        this.clients.splice(i, 1);
        i-=1;
      } else {
        return cb(this.clients[i]);
      }
    }
  }
  if (this.clients.length >= this.maxClients) {
    this.pending.push(cb);
  } else {
    var client = http.createClient(this.port, this.host, this.https, this.credentials);
    this.clients.push(client);
    cb(client);
  }
};

Pool.prototype.request = function () {
  // Argument parsing. This gets a little dicey with the
  // differences in defaults
  var method, url, headers, callback, args;
  var self = this;
  args = Array.prototype.slice.call(arguments);

  if (typeof args[args.length - 1] === 'function') {
    callback = args.pop();
  }
  if (args[0]) method = args[0];
  if (args[1]) url = args[1];
  if (args[2]) headers = args[2];

  if (!headers) headers = {};
  if (!headers.Connection) headers.Connection = 'close';

  self.getClient(function (client) {
    var errorListener = function (error) {
      client.removeListener("error", errorListener);

      // Remove the client from the available clients since it has errored
      self.clients.splice(self.clients.indexOf(client), 1);

      self.emit("error", error);
      request.emit("error", error);
    };

    var request = client.request(method, url, headers);
    client.on("error", errorListener);
    request.on("response", function (response) {
      response.on("end", function () {
        client.removeListener("error", errorListener);
        client.busy = false;
        self.onFree(client);
      })
    })
    client.busy = true;
    callback(request);
  });
};

Pool.prototype.onFree = function (client) {
  if (this.pending.length > 0) this.pending.shift()(client);
};

Pool.prototype.getFree = function () {
  return this.clients.filter(function (client) { return !client.busy }).length;
};

Pool.prototype.getBusy = function () {
  return this.clients.filter(function (client) { return client.busy }).length;
};

Pool.prototype.setMinClients = function (num) {
  this.minClients = num;
  if (this.clients.length < num) {
    for (var i=this.clients.length;i<num;i+=1) {
      var client = http.createClient(this.port, this.host, this.https, this.credentials);
      this.clients.push(client);
      this.emit('free', client);
    }
  }
};

Pool.prototype.setMaxClients = function (num) {
  this.maxClients = num;
};

Pool.prototype.end = function () {
  this.clients.forEach(function (c) {c.end()});
};

function PoolManager () {
  this.pools = {};
  this.pending = [];
  this.minClients = 0;
  this.maxClients = 8;
};

PoolManager.prototype.setMaxClients = function (num) {
  this.maxClients = num;
  for (i in this.pools) {
    this.pools[i].setMaxClients(num);
  }
};

PoolManager.prototype.setMinClients = function (num) {
  this.minClients = num;
  for (i in this.pools) {
    this.pools[i].setMinClients(num);
  }
};

PoolManager.prototype.getPool = function (port, host, https, credentials) {
  var k = (port+host+https+credentials);
  if (!this.pools[k]) {
    this.pools[k] = exports.createPool(port, host, https, credentials);
    this.pools[k].setMinClients(this.minClients);
    this.pools[k].setMaxClients(this.maxClients);
  }
  return this.pools[k];
};

exports.createPool = function (port, host, https, credentials) {
  return new Pool(port, host, https, credentials);
};

exports.createPoolManager = function () {
  return new PoolManager();
};
<|endoftext|>


<commit_before>var _ = require('underscore');
var cdb = require('cartodb.js');
var Dashboard = require('./dashboard');
var DashboardView = require('../dashboard-view');
var WidgetsCollection = require('../widgets/widgets-collection');
var WidgetsService = require('../widgets-service');

/**
 * Translates a vizJSON v3 datastructure into a working dashboard which will be rendered in given selector.
 *
 * @param {String} selector e.g. "#foobar-id", ".some-class"
 * @param {Object} vizJSON JSON datastructure
 * @param {Object} opts (Optional) flags, see 3rd param for cdb.createVis for available ones. Keys used here:
 *   renderMenu: {Boolean} If true (default), render a top-level menu on the left side.
 * @return {Object} with keys:
 *   dashboardView: root (backbone) view of the dashboard
 *   vis: the instantiated vis map, same result as given from cdb.createVis()
 */
var createDashboard = function (selector, vizJSON, opts, callback) {
  var dashboardEl = document.querySelector(selector);
  if (!dashboardEl) throw new Error('no element found with selector ' + selector);

  // Default options
  opts = opts || {};
  opts.renderMenu = _.isBoolean(opts.renderMenu)
    ? opts.renderMenu
    : true;

  var widgets = new WidgetsCollection();

  var model = new cdb.core.Model({
    title: vizJSON.title,
    description: vizJSON.description,
    updatedAt: vizJSON.updated_at,
    userName: vizJSON.user.fullname,
    userAvatarURL: vizJSON.user.avatar_url,
    renderMenu: opts.renderMenu
  });
  var dashboardView = new DashboardView({
    el: dashboardEl,
    widgets: widgets,
    model: model
  });
  var vis = cdb.createVis(dashboardView.$('#map'), vizJSON, _.extend(opts, {
    skipMapInstantiation: true
  }));

  // Create widgets
  var widgetsService = new WidgetsService(widgets, vis.dataviews);
  var widgetModelsMap = {
    list: widgetsService.createListModel.bind(widgetsService),
    formula: widgetsService.createFormulaModel.bind(widgetsService),
    histogram: widgetsService.createHistogramModel.bind(widgetsService),
    'time-series': widgetsService.createTimeSeriesModel.bind(widgetsService),
    category: widgetsService.createCategoryModel.bind(widgetsService)
  };
  vizJSON.widgets.forEach(function (d) {
    // Flatten the data structure given in vizJSON, the widgetsService will use whatever it needs and ignore the rest
    var attrs = _.extend({}, d, d.options);
    var newWidgetModel = widgetModelsMap[d.type];

    if (_.isFunction(newWidgetModel)) {
      // Find the Layer that the Widget should be created for.
      var layer;
      if (d.layer_id) {
        layer = vis.map.layers.get(d.layer_id);
      } else if (Number.isInteger(d.layerIndex)) {
        // TODO Since namedmap doesn't have ids we need to map in another way, here using index
        //   should we solve this in another way?
        layer = vis.map.layers.at(d.layerIndex);
      }

      newWidgetModel(attrs, layer);
    } else {
      cdb.log.error('No widget found for type ' + d.type);
    }
  });

  widgetsService.setWidgetsState();

  dashboardView.render();

  if (widgets.size() > 0) {
    vis.centerMapToOrigin();
  }

  vis.done(function () {
    callback && callback(null, {
      dashboardView: dashboardView,
      widgets: widgetsService,
      vis: vis
    });
  });

  vis.error(function (error) {
    callback && callback(error);
  });

  vis.instantiateMap();
};

module.exports = function (selector, vizJSON, opts, callback) {
  var args = arguments;
  var fn = args[args.length - 1];

  if (_.isFunction(fn)) {
    callback = fn;
  }

  function _load (vizJSON) {
    createDashboard(selector, vizJSON, opts, function (error, dashboard) {
      if (error) {
        throw new Error('Error creating dashboard: ' + error);
      }
      callback && callback(null, new Dashboard(dashboard));
    });
  }

  if (typeof vizJSON === 'string') {
    cdb.core.Loader.get(vizJSON, function (data) {
      if (data) {
        _load(data, opts);
      } else {
        callback && callback(new Error('error fetching viz.json file'));
      }
    });
  } else {
    _load(vizJSON, opts);
  }
};
<commit_msg>gets map state from url on dashboard init<commit_after>var _ = require('underscore');
var cdb = require('cartodb.js');
var Dashboard = require('./dashboard');
var DashboardView = require('../dashboard-view');
var WidgetsCollection = require('../widgets/widgets-collection');
var WidgetsService = require('../widgets-service');
var URLHelper = require('./url-helper');

/**
 * Translates a vizJSON v3 datastructure into a working dashboard which will be rendered in given selector.
 *
 * @param {String} selector e.g. "#foobar-id", ".some-class"
 * @param {Object} vizJSON JSON datastructure
 * @param {Object} opts (Optional) flags, see 3rd param for cdb.createVis for available ones. Keys used here:
 *   renderMenu: {Boolean} If true (default), render a top-level menu on the left side.
 * @return {Object} with keys:
 *   dashboardView: root (backbone) view of the dashboard
 *   vis: the instantiated vis map, same result as given from cdb.createVis()
 */
var createDashboard = function (selector, vizJSON, opts, callback) {
  var dashboardEl = document.querySelector(selector);
  if (!dashboardEl) throw new Error('no element found with selector ' + selector);

  // Default options
  opts = opts || {};
  opts.renderMenu = _.isBoolean(opts.renderMenu)
    ? opts.renderMenu
    : true;

  var widgets = new WidgetsCollection();
  var coords = JSON.parse(vizJSON.center);

  var model = new cdb.core.Model({
    title: vizJSON.title,
    description: vizJSON.description,
    updatedAt: vizJSON.updated_at,
    userName: vizJSON.user.fullname,
    userAvatarURL: vizJSON.user.avatar_url,
    renderMenu: opts.renderMenu,
    initialPosition: {
      center: coords,
      zoom: vizJSON.zoom
    }
  });
  var dashboardView = new DashboardView({
    el: dashboardEl,
    widgets: widgets,
    model: model
  });
  var vis = cdb.createVis(dashboardView.$('#map'), vizJSON, _.extend(opts, {
    skipMapInstantiation: true
  }));

  // Create widgets
  var widgetsService = new WidgetsService(widgets, vis.dataviews);
  var widgetModelsMap = {
    list: widgetsService.createListModel.bind(widgetsService),
    formula: widgetsService.createFormulaModel.bind(widgetsService),
    histogram: widgetsService.createHistogramModel.bind(widgetsService),
    'time-series': widgetsService.createTimeSeriesModel.bind(widgetsService),
    category: widgetsService.createCategoryModel.bind(widgetsService)
  };
  vizJSON.widgets.forEach(function (d) {
    // Flatten the data structure given in vizJSON, the widgetsService will use whatever it needs and ignore the rest
    var attrs = _.extend({}, d, d.options);
    var newWidgetModel = widgetModelsMap[d.type];

    if (_.isFunction(newWidgetModel)) {
      // Find the Layer that the Widget should be created for.
      var layer;
      if (d.layer_id) {
        layer = vis.map.layers.get(d.layer_id);
      } else if (Number.isInteger(d.layerIndex)) {
        // TODO Since namedmap doesn't have ids we need to map in another way, here using index
        //   should we solve this in another way?
        layer = vis.map.layers.at(d.layerIndex);
      }

      newWidgetModel(attrs, layer);
    } else {
      cdb.log.error('No widget found for type ' + d.type);
    }
  });

  var stateFromURL = URLHelper.getStateFromCurrentURL();
  if (!_.isEmpty(stateFromURL.widgets)) {
    widgetsService.setWidgetsState(stateFromURL.widgets);
  }
  if (!_.isEmpty(stateFromURL.map)) {
    vis.map.setView(stateFromURL.map.center, stateFromURL.map.zoom);
  }

  dashboardView.render();

  if (widgets.size() > 0) {
    vis.centerMapToOrigin();
  }

  vis.done(function () {
    callback && callback(null, {
      dashboardView: dashboardView,
      widgets: widgetsService,
      vis: vis
    });
  });

  vis.error(function (error) {
    callback && callback(error);
  });

  vis.instantiateMap();
};

module.exports = function (selector, vizJSON, opts, callback) {
  var args = arguments;
  var fn = args[args.length - 1];

  if (_.isFunction(fn)) {
    callback = fn;
  }

  function _load (vizJSON) {
    createDashboard(selector, vizJSON, opts, function (error, dashboard) {
      if (error) {
        throw new Error('Error creating dashboard: ' + error);
      }
      callback && callback(null, new Dashboard(dashboard));
    });
  }

  if (typeof vizJSON === 'string') {
    cdb.core.Loader.get(vizJSON, function (data) {
      if (data) {
        _load(data, opts);
      } else {
        callback && callback(new Error('error fetching viz.json file'));
      }
    });
  } else {
    _load(vizJSON, opts);
  }
};
<|endoftext|>


<commit_before>import React, { useEffect, useRef, useState } from 'react';
import { useSearch } from 'helpers/hooks';
import PropTypes from 'prop-types';
import Textarea from 'components/Texts/Textarea';
import Modal from 'components/Modal';
import Button from 'components/Button';
import Loading from 'components/Loading';
import {
  exceedsCharLimit,
  stringIsEmpty,
  addEmoji,
  finalizeEmoji,
  renderCharLimit
} from 'helpers/stringHelpers';
import SortableThumb from 'components/SortableThumb';
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-touch-backend';
import SelectUploadsForm from 'components/Forms/SelectUploadsForm';
import Input from 'components/Texts/Input';
import SearchInput from 'components/Texts/SearchInput';
import {
  loadUploads,
  searchContent,
  uploadPlaylist
} from 'helpers/requestHelpers';
import { objectify } from 'helpers';
import { css } from 'emotion';
import { connect } from 'react-redux';

AddPlaylistModal.propTypes = {
  dispatch: PropTypes.func,
  existingVideoIds: PropTypes.array,
  focusPlaylistPanelAfterUpload: PropTypes.func,
  onHide: PropTypes.func,
  postPlaylist: PropTypes.func,
  title: PropTypes.string
};

function AddPlaylistModal({
  dispatch,
  existingVideoIds = [],
  focusPlaylistPanelAfterUpload,
  onHide,
  postPlaylist,
  title: initialTitle = ''
}) {
  const [loaded, setLoaded] = useState(false);
  const [isUploading, setIsUploading] = useState(false);
  const [section, setSection] = useState(0);
  const [title, setTitle] = useState(
    initialTitle?.charAt(0).toUpperCase() + initialTitle?.slice(1)
  );
  const [description, setDescription] = useState('');
  const [allVideos, setAllVideos] = useState([]);
  const [searchedVideos, setSearchedVideos] = useState([]);
  const [selectedVideos, setSelectedVideos] = useState([]);
  const [loadingMore, setLoadingMore] = useState(false);
  const [loadMoreButton, setLoadMoreButton] = useState(false);
  const [searchLoadMoreButton, setSearchLoadMoreButton] = useState(false);
  const { handleSearch, searching, searchText } = useSearch({
    onSearch: searchVideo,
    onClear: () => setSearchedVideos([])
  });
  const playlistVideoObjects = useRef({});
  const mounted = useRef(true);

  useEffect(() => {
    mounted.current = true;
    loadVideos();
    async function loadVideos() {
      const { results: loadedVideos, loadMoreButton } = await loadUploads({
        type: 'video',
        limit: 18,
        excludeContentIds: existingVideoIds
      });
      if (mounted.current) {
        playlistVideoObjects.current = objectify(loadedVideos);
        setAllVideos(loadedVideos.map(video => video.id));
        setLoadMoreButton(loadMoreButton);
        setLoaded(true);
      }
    }
    return function cleanUp() {
      mounted.current = false;
    };
  }, []);
  const titleExceedsCharLimit = exceedsCharLimit({
    contentType: 'playlist',
    inputType: 'title',
    text: title
  });
  const descriptionExceedsCharLimit = exceedsCharLimit({
    contentType: 'playlist',
    inputType: 'description',
    text: description
  });

  return (
    <Modal onHide={onHide} large={section > 0}>
      {renderTitle()}

        {!loaded && <Loading />}
        {loaded && (
          <>
            {section === 0 && (
              <form
                className={css`
                  width: 100%;
                `}
                onSubmit={event => event.preventDefault()}
              >

                  <Input
                    autoFocus
                    placeholder="Enter Playlist Title"
                    value={title}
                    onChange={text => setTitle(text)}
                    onKeyUp={event => {
                      if (event.key === ' ') {
                        setTitle(addEmoji(event.target.value));
                      }
                    }}
                    style={titleExceedsCharLimit}
                  />
                  {titleExceedsCharLimit && (

                      {renderCharLimit({
                        contentType: 'playlist',
                        inputType: 'title',
                        text: title
                      })}

                  )}

                  <Textarea
                    name="description"
                    placeholder="Enter Description (Optional)"
                    minRows={4}
                    value={description}
                    onChange={event => setDescription(event.target.value)}
                    onKeyUp={event => {
                      if (event.key === ' ') {
                        setDescription(addEmoji(event.target.value));
                      }
                    }}
                    style={descriptionExceedsCharLimit}
                  />
                  {descriptionExceedsCharLimit && (

                      {renderCharLimit({
                        contentType: 'playlist',
                        inputType: 'description',
                        text: description
                      })}

                  )}

              </form>
            )}
            {section === 1 && (

                <SearchInput
                  placeholder="Search videos..."
                  autoFocus
                  style={{
                    marginBottom: '2em',
                    width: '50%'
                  }}
                  value={searchText}
                  onChange={handleSearch}
                />
                {searching ? (
                  <Loading />
                ) : (
                  <SelectUploadsForm
                    contentObjs={playlistVideoObjects.current}
                    uploads={
                      !stringIsEmpty(searchText) ? searchedVideos : allVideos
                    }
                    selectedUploads={selectedVideos}
                    loadingMore={loadingMore}
                    loadMoreButton={
                      !stringIsEmpty(searchText)
                        ? searchLoadMoreButton
                        : loadMoreButton
                    }
                    onSelect={selectedVideoId =>
                      setSelectedVideos(selectedVideos =>
                        selectedVideos.concat(selectedVideoId)
                      )
                    }
                    onDeselect={deselectedVideoId =>
                      setSelectedVideos(
                        selectedVideos.filter(
                          videoId => videoId !== deselectedVideoId
                        )
                      )
                    }
                    loadMoreUploads={loadMoreVideos}
                  />
                )}

            )}
            {section === 2 && (

                {selectedVideos.map(videoId => (
                  <SortableThumb
                    key={videoId}
                    video={playlistVideoObjects.current[videoId]}
                    onMove={({ sourceId, targetId }) => {
                      let selected = [...selectedVideos];
                      const sourceIndex = selected.indexOf(sourceId);
                      const targetIndex = selected.indexOf(targetId);
                      selected.splice(sourceIndex, 1);
                      selected.splice(targetIndex, 0, sourceId);
                      setSelectedVideos(selected);
                    }}
                  />
                ))}

            )}
          </>
        )}

        {section === 0 ? (
          <Button
            style={{ marginRight: '0.7rem' }}
            transparent
            onClick={onHide}
          >
            Cancel
          </Button>
        ) : (
          <Button
            style={{ marginRight: '0.7rem' }}
            transparent
            onClick={handlePrev}
          >
            Prev
          </Button>
        )}
        {section === 2 ? (
          <Button primary disabled={isUploading} onClick={handleFinish}>
            Finish
          </Button>
        ) : (
          <Button
            primary
            type="submit"
            disabled={
              (section === 0 &&
                (stringIsEmpty(title) ||
                  titleExceedsCharLimit ||
                  descriptionExceedsCharLimit)) ||
              (section === 1 && selectedVideos.length === 0)
            }
            onClick={handleNext}
          >
            Next
          </Button>
        )}

    </Modal>
  );

  function renderTitle() {
    switch (section) {
      case 0:
        return 'Add Playlist';
      case 1:
        return 'Add videos to your playlist';
      case 2:
        return 'Click and drag videos into the order that you would like them to appear';
      default:
        return 'Error';
    }
  }

  function handlePrev() {
    const prevSection = Math.max(section - 1, 0);
    setSection(prevSection);
  }

  function handleNext() {
    const nextSection = Math.min(section + 1, 2);
    setSection(nextSection);
  }

  async function handleFinish() {
    setIsUploading(true);
    try {
      const data = await uploadPlaylist({
        dispatch,
        title: finalizeEmoji(title),
        description: finalizeEmoji(description),
        selectedVideos
      });
      await postPlaylist(data);
      focusPlaylistPanelAfterUpload?.();
      onHide();
    } catch (error) {
      console.error(error);
    }
  }

  async function loadMoreVideos() {
    setLoadingMore(true);
    if (!stringIsEmpty(searchText)) {
      const { results: loadedVideos, loadMoreButton } = await searchContent({
        filter: 'video',
        searchText,
        shownResults: searchedVideos.map(
          videoId => playlistVideoObjects.current[videoId]
        )
      });
      playlistVideoObjects.current = {
        ...playlistVideoObjects.current,
        ...objectify(loadedVideos)
      };
      setSearchedVideos(
        searchedVideos.concat(loadedVideos.map(video => video.id))
      );
      setLoadingMore(false);
      setSearchLoadMoreButton(loadMoreButton);
    } else {
      const { results: loadedVideos, loadMoreButton } = await loadUploads({
        type: 'video',
        limit: 18,
        contentId: allVideos[allVideos.length - 1]
      });
      playlistVideoObjects.current = {
        ...playlistVideoObjects.current,
        ...objectify(loadedVideos)
      };
      setAllVideos(allVideos.concat(loadedVideos.map(video => video.id)));
      setLoadingMore(false);
      setLoadMoreButton(loadMoreButton);
    }
  }

  async function searchVideo(text) {
    const { results: searchResults, loadMoreButton } = await searchContent({
      filter: 'video',
      searchText: text
    });
    playlistVideoObjects.current = {
      ...playlistVideoObjects.current,
      ...objectify(searchResults)
    };
    setSearchedVideos(searchResults.map(video => video.id));
    setSearchLoadMoreButton(loadMoreButton);
  }
}

export default connect(
  null,
  dispatch => ({ dispatch })
)(DragDropContext(HTML5Backend)(AddPlaylistModal));
<commit_msg>minor fix<commit_after>import React, { useEffect, useRef, useState } from 'react';
import { useSearch } from 'helpers/hooks';
import PropTypes from 'prop-types';
import Textarea from 'components/Texts/Textarea';
import Modal from 'components/Modal';
import Button from 'components/Button';
import Loading from 'components/Loading';
import {
  exceedsCharLimit,
  stringIsEmpty,
  addEmoji,
  finalizeEmoji,
  renderCharLimit
} from 'helpers/stringHelpers';
import SortableThumb from 'components/SortableThumb';
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-touch-backend';
import SelectUploadsForm from 'components/Forms/SelectUploadsForm';
import Input from 'components/Texts/Input';
import SearchInput from 'components/Texts/SearchInput';
import {
  loadUploads,
  searchContent,
  uploadPlaylist
} from 'helpers/requestHelpers';
import { objectify } from 'helpers';
import { css } from 'emotion';
import { connect } from 'react-redux';

AddPlaylistModal.propTypes = {
  dispatch: PropTypes.func,
  existingVideoIds: PropTypes.array,
  focusPlaylistPanelAfterUpload: PropTypes.func,
  onHide: PropTypes.func,
  postPlaylist: PropTypes.func,
  title: PropTypes.string
};

function AddPlaylistModal({
  dispatch,
  existingVideoIds = [],
  focusPlaylistPanelAfterUpload,
  onHide,
  postPlaylist,
  title: initialTitle = ''
}) {
  const [loaded, setLoaded] = useState(false);
  const [isUploading, setIsUploading] = useState(false);
  const [section, setSection] = useState(0);
  const [title, setTitle] = useState(
    initialTitle?.charAt(0).toUpperCase() + initialTitle?.slice(1)
  );
  const [description, setDescription] = useState('');
  const [allVideos, setAllVideos] = useState([]);
  const [searchedVideos, setSearchedVideos] = useState([]);
  const [selectedVideos, setSelectedVideos] = useState([]);
  const [loadingMore, setLoadingMore] = useState(false);
  const [loadMoreButton, setLoadMoreButton] = useState(false);
  const [searchLoadMoreButton, setSearchLoadMoreButton] = useState(false);
  const { handleSearch, searching, searchText } = useSearch({
    onSearch: searchVideo,
    onClear: () => setSearchedVideos([])
  });
  const playlistVideoObjects = useRef({});
  const mounted = useRef(true);

  useEffect(() => {
    mounted.current = true;
    loadVideos();
    async function loadVideos() {
      const { results: loadedVideos, loadMoreButton } = await loadUploads({
        type: 'video',
        limit: 18,
        excludeContentIds: existingVideoIds
      });
      if (mounted.current) {
        playlistVideoObjects.current = objectify(loadedVideos);
        setAllVideos(loadedVideos.map(video => video.id));
        setLoadMoreButton(loadMoreButton);
        setLoaded(true);
      }
    }
    return function cleanUp() {
      mounted.current = false;
    };
  }, []);
  const titleExceedsCharLimit = exceedsCharLimit({
    contentType: 'playlist',
    inputType: 'title',
    text: title
  });
  const descriptionExceedsCharLimit = exceedsCharLimit({
    contentType: 'playlist',
    inputType: 'description',
    text: description
  });

  return (
    <Modal onHide={onHide} large={section > 0}>
      {renderTitle()}

        {section === 0 && (
          <form
            className={css`
              width: 100%;
            `}
            onSubmit={event => event.preventDefault()}
          >

              <Input
                autoFocus
                placeholder="Enter Playlist Title"
                value={title}
                onChange={text => setTitle(text)}
                onKeyUp={event => {
                  if (event.key === ' ') {
                    setTitle(addEmoji(event.target.value));
                  }
                }}
                style={titleExceedsCharLimit}
              />
              {titleExceedsCharLimit && (

                  {renderCharLimit({
                    contentType: 'playlist',
                    inputType: 'title',
                    text: title
                  })}

              )}

              <Textarea
                name="description"
                placeholder="Enter Description (Optional)"
                minRows={4}
                value={description}
                onChange={event => setDescription(event.target.value)}
                onKeyUp={event => {
                  if (event.key === ' ') {
                    setDescription(addEmoji(event.target.value));
                  }
                }}
                style={descriptionExceedsCharLimit}
              />
              {descriptionExceedsCharLimit && (

                  {renderCharLimit({
                    contentType: 'playlist',
                    inputType: 'description',
                    text: description
                  })}

              )}

          </form>
        )}
        {section === 1 && (

            <SearchInput
              placeholder="Search videos..."
              autoFocus
              style={{
                marginBottom: '2em',
                width: '50%'
              }}
              value={searchText}
              onChange={handleSearch}
            />
            {searching ? (
              <Loading />
            ) : (
              <SelectUploadsForm
                contentObjs={playlistVideoObjects.current}
                uploads={
                  !stringIsEmpty(searchText) ? searchedVideos : allVideos
                }
                selectedUploads={selectedVideos}
                loaded={loaded}
                loadingMore={loadingMore}
                loadMoreButton={
                  !stringIsEmpty(searchText)
                    ? searchLoadMoreButton
                    : loadMoreButton
                }
                onSelect={selectedVideoId =>
                  setSelectedVideos(selectedVideos =>
                    selectedVideos.concat(selectedVideoId)
                  )
                }
                onDeselect={deselectedVideoId =>
                  setSelectedVideos(
                    selectedVideos.filter(
                      videoId => videoId !== deselectedVideoId
                    )
                  )
                }
                loadMoreUploads={loadMoreVideos}
              />
            )}

        )}
        {section === 2 && (

            {selectedVideos.map(videoId => (
              <SortableThumb
                key={videoId}
                video={playlistVideoObjects.current[videoId]}
                onMove={({ sourceId, targetId }) => {
                  let selected = [...selectedVideos];
                  const sourceIndex = selected.indexOf(sourceId);
                  const targetIndex = selected.indexOf(targetId);
                  selected.splice(sourceIndex, 1);
                  selected.splice(targetIndex, 0, sourceId);
                  setSelectedVideos(selected);
                }}
              />
            ))}

        )}
        )

        {section === 0 ? (
          <Button
            style={{ marginRight: '0.7rem' }}
            transparent
            onClick={onHide}
          >
            Cancel
          </Button>
        ) : (
          <Button
            style={{ marginRight: '0.7rem' }}
            transparent
            onClick={handlePrev}
          >
            Prev
          </Button>
        )}
        {section === 2 ? (
          <Button primary disabled={isUploading} onClick={handleFinish}>
            Finish
          </Button>
        ) : (
          <Button
            primary
            type="submit"
            disabled={
              (section === 0 &&
                (stringIsEmpty(title) ||
                  titleExceedsCharLimit ||
                  descriptionExceedsCharLimit)) ||
              (section === 1 && selectedVideos.length === 0)
            }
            onClick={handleNext}
          >
            Next
          </Button>
        )}

    </Modal>
  );

  function renderTitle() {
    switch (section) {
      case 0:
        return 'Add Playlist';
      case 1:
        return 'Add videos to your playlist';
      case 2:
        return 'Click and drag videos into the order that you would like them to appear';
      default:
        return 'Error';
    }
  }

  function handlePrev() {
    const prevSection = Math.max(section - 1, 0);
    setSection(prevSection);
  }

  function handleNext() {
    const nextSection = Math.min(section + 1, 2);
    setSection(nextSection);
  }

  async function handleFinish() {
    setIsUploading(true);
    try {
      const data = await uploadPlaylist({
        dispatch,
        title: finalizeEmoji(title),
        description: finalizeEmoji(description),
        selectedVideos
      });
      await postPlaylist(data);
      focusPlaylistPanelAfterUpload?.();
      onHide();
    } catch (error) {
      console.error(error);
    }
  }

  async function loadMoreVideos() {
    setLoadingMore(true);
    if (!stringIsEmpty(searchText)) {
      const { results: loadedVideos, loadMoreButton } = await searchContent({
        filter: 'video',
        searchText,
        shownResults: searchedVideos.map(
          videoId => playlistVideoObjects.current[videoId]
        )
      });
      playlistVideoObjects.current = {
        ...playlistVideoObjects.current,
        ...objectify(loadedVideos)
      };
      setSearchedVideos(
        searchedVideos.concat(loadedVideos.map(video => video.id))
      );
      setLoadingMore(false);
      setSearchLoadMoreButton(loadMoreButton);
    } else {
      const { results: loadedVideos, loadMoreButton } = await loadUploads({
        type: 'video',
        limit: 18,
        contentId: allVideos[allVideos.length - 1]
      });
      playlistVideoObjects.current = {
        ...playlistVideoObjects.current,
        ...objectify(loadedVideos)
      };
      setAllVideos(allVideos.concat(loadedVideos.map(video => video.id)));
      setLoadingMore(false);
      setLoadMoreButton(loadMoreButton);
    }
  }

  async function searchVideo(text) {
    const { results: searchResults, loadMoreButton } = await searchContent({
      filter: 'video',
      searchText: text
    });
    playlistVideoObjects.current = {
      ...playlistVideoObjects.current,
      ...objectify(searchResults)
    };
    setSearchedVideos(searchResults.map(video => video.id));
    setSearchLoadMoreButton(loadMoreButton);
  }
}

export default connect(
  null,
  dispatch => ({ dispatch })
)(DragDropContext(HTML5Backend)(AddPlaylistModal));
<|endoftext|>


<commit_before>'use strict';
var Q = require('q');
var _ = require('lodash');
var restler = require('restler');

var httpVerbs = ['request', 'get', 'post', 'put', 'del', 'head', 'patch'];
var jsonMethods =['json', 'postJson', 'putJson'];

// Function that generate the restler wrapper for all the basic http verbs to return promise
_.forEach(httpVerbs, function(verb){
  exports[verb] = function(url, options){
    var d = Q.defer();
    restler[verb](url, options).on('complete', function(result, response){
      if (result instanceof Error) {
        d.reject(result)
      } else {
        d.resolve({'data': result, 'response':response});
      }
    }).on('error', function(err, response){
      d.reject({'error': err, 'response': response });
    }).on('timeout', function(ms){
      d.reject({'name': 'timeout', 'message':'Timeout after '+ms+'ms'});
    });
    return d.promise;
  };
});

// Function that generate the restler wrapper for all the json methods to return promise
_.forEach(jsonMethods, function(verb){
  exports[verb] = function(url, data, options){
    var d = Q.defer();
    restler[verb](url, data, options).on('complete', function(result, response){
      if (result instanceof Error) {
        d.reject(result)
      } else {
        d.resolve({'data': result, 'response':response});
      }
    }).on('error', function(err, response){
      d.reject({'error': err, 'response': response });
    }).on('timeout', function(ms){
      d.reject({'name': 'timeout', 'message':'Timeout after '+ms+'ms'});
    });
    return d.promise;
  };
});
<commit_msg>fixing return on error<commit_after>'use strict';
var Q = require('q');
var _ = require('lodash');
var restler = require('restler');

var httpVerbs = ['request', 'get', 'post', 'put', 'del', 'head', 'patch'];
var jsonMethods =['json', 'postJson', 'putJson'];

// Function that generate the restler wrapper for all the basic http verbs to return promise
_.forEach(httpVerbs, function(verb){
  exports[verb] = function(url, options){
    var d = Q.defer();
    restler[verb](url, options).on('complete', function(result, response){
      if (result instanceof Error) {
        d.reject(result)
      } else {
        d.resolve({'data': result, 'response':response});
      }
    }).on('error', function(error){
      d.reject(error);
    }).on('timeout', function(ms){
      d.reject({'name': 'timeout', 'message':'Timeout after '+ms+'ms'});
    });
    return d.promise;
  };
});

// Function that generate the restler wrapper for all the json methods to return promise
_.forEach(jsonMethods, function(verb){
  exports[verb] = function(url, data, options){
    var d = Q.defer();
    restler[verb](url, data, options).on('complete', function(result, response){
      if (result instanceof Error) {
        d.reject(result)
      } else {
        d.resolve({'data': result, 'response':response});
      }
    }).on('error', function(error){
      d.reject(error);
    }).on('timeout', function(ms){
      d.reject({'name': 'timeout', 'message':'Timeout after '+ms+'ms'});
    });
    return d.promise;
  };
});
<|endoftext|>