<commit_before>'use strict';

var JSIGSnippet = require('../lib/jsig-snippet.js');

JSIGSnippet.test('allow optional function fields', {
    snippet: function m() {/*
        function Foo() {
            this.x = null;
            this.y = null;
        }

        var f = new Foo();
        f.x = function noop() {};
    */},
    header: function h() {/*
        type Foo : {
            x: null | Function,
            y: null | (String) => String
        }

        Foo : (this: Foo) => void
    */}
}, function t(snippet, assert) {
    var meta = snippet.compile(assert);

    // TODO: fix error
    assert.equal(meta.errors.length, 1);

    assert.end();
});
<commit_msg>improve unit test<commit_after>'use strict';

var JSIGSnippet = require('../lib/jsig-snippet.js');

JSIGSnippet.test('allow optional function fields', {
    snippet: function m() {/*
        function Foo() {
            this.y = null;
        }

        var f = new Foo();
        f.y = function noop() {};
        f.y = noop;

        function noop() {}
    */},
    header: function h() {/*
        type Foo : {
            y: null | (String) => String
        }

        Foo : (this: Foo) => void
    */}
}, function t(snippet, assert) {
    var meta = snippet.compile(assert);

    // TODO: fix error
    assert.equal(meta.errors.length, 3);

    assert.end();
});
<|endoftext|>


<commit_before>/*
 * This file needs to be renamed as app.js when we want to run unit tests
 * in order this to get loaded by the jxcore ready event.
 * This effectively acts as main entry point to the unit test app
 */

'use strict';

if (typeof Mobile === 'undefined') {
  global.Mobile = require('./lib/wifiBasedNativeMock.js')();
}

var testUtils = require('./lib/testUtils');
var ThaliMobile = require('thali/NextGeneration/thaliMobile');
var Promise = require('lie');
var utResult;

Mobile('ExecuteNativeTests').callNative(function (result) {
  utResult = true;
  if (result && result.executed) {
    console.log("Total number of executed tests: ", result.total);
    console.log("Number of passed tests: ", result.passed);
    console.log("Number of failed tests: ", result.failed);
    console.log("Number of ignored tests: ", result.ignored);
    console.log("Total duration: ", result.duration);
    if (result.failed > 0) {
      utResult = false;
    }
  }
});

if (!utResult) {
  console.log("Failed to execute UT.");
  console.log('****TEST_LOGGER:[PROCESS_ON_EXIT_FAILED]****');
  return;
}

// TODO finish testing here (the node part will be omitted)
console.log('****TEST_LOGGER:[PROCESS_ON_EXIT_SUCCESS]****');
return;

ThaliMobile.getNetworkStatus()
.then(function (networkStatus) {
  var promiseList = [];
  if (networkStatus.wifi === 'off') {
    promiseList.push(testUtils.toggleWifi(true));
  }
  if (networkStatus.bluetooth === 'off') {
    promiseList.push(testUtils.toggleBluetooth(true));
  }
  Promise.all(promiseList)
  .then(function () {
    Mobile('GetDeviceName').callNative(function (name) {
      console.log('My device name is: %s', name);
      testUtils.setName(name);
      // The setImmediate is to avoid this issue:
      // https://github.com/thaliproject/Thali_CordovaPlugin/issues/563
      setImmediate(function () {
        require('./runTests.js');
      });
    });
  });
});

console.log('Unit Test app is loaded');
<commit_msg>Added a multiple test run depending from network type<commit_after>/*
 * This file needs to be renamed as app.js when we want to run unit tests
 * in order this to get loaded by the jxcore ready event.
 * This effectively acts as main entry point to the unit test app
 */

'use strict';

if (typeof Mobile === 'undefined') {
  global.Mobile = require('./lib/wifiBasedNativeMock.js')();
}

var testRunner = require('./runTests.js');
var testUtils = require('./lib/testUtils');
var ThaliMobile = require('thali/NextGeneration/thaliMobile');
var Promise = require('lie');
var utResult;

Mobile('ExecuteNativeTests').callNative(function (result) {
  utResult = true;
  if (result && result.executed) {
    console.log("Total number of executed tests: ", result.total);
    console.log("Number of passed tests: ", result.passed);
    console.log("Number of failed tests: ", result.failed);
    console.log("Number of ignored tests: ", result.ignored);
    console.log("Total duration: ", result.duration);
    if (result.failed > 0) {
      utResult = false;
    }
  }
});

if (!utResult) {
  console.log("Failed to execute UT.");
  console.log('****TEST_LOGGER:[PROCESS_ON_EXIT_FAILED]****');
  return;
}

// TODO finish testing here (the node part will be omitted)
console.log('****TEST_LOGGER:[PROCESS_ON_EXIT_SUCCESS]****');
return;

// Issue #914
var networkTypes = [];
if (process.platform === 'android') {
  networkTypes = [
    ThaliMobile.networkTypes.WIFI,
    ThaliMobile.networkTypes.NATIVE,
    ThaliMobile.networkTypes.BOTH
  ];
} else if (process.platform === 'ios') {
  networkTypes = [
    ThaliMobile.networkTypes.NATIVE,
    ThaliMobile.networkTypes.BOTH
  ];
}

ThaliMobile.getNetworkStatus()
.then(function (networkStatus) {
  var promiseList = [];
  if (networkStatus.wifi === 'off') {
    promiseList.push(testUtils.toggleWifi(true));
  }
  if (networkStatus.bluetooth === 'off') {
    promiseList.push(testUtils.toggleBluetooth(true));
  }
  Promise.all(promiseList)
  .then(function () {
    Mobile('GetDeviceName').callNative(function (name) {
      console.log('My device name is: %s', name);
      testUtils.setName(name);

      networkTypes.reduce(function (sequence, networkType) {
        return sequence.
          .then(function () {
            console.log('Running for ' + networkType + ' network type');
            global.NETWORK_TYPE = networkType;
            return testRunner.run();
          });
      }, Promise.resolve());
    });
  });
});

console.log('Unit Test app is loaded');
<|endoftext|>


<commit_before>const MAX_SLIDES = 2
const slideClasses = ['one', 'two', 'three', 'four', 'five', 'six']

// If window orientation changes
const getDevice = () => {
	//	Some large tablets exist, but for all intents and purposes, we’ll treat them as desktops.
	if (Math.max(windowWidth, windowHeight) >= 1025) {
		return 'desktop'
	}
	if (Math.min(windowWidth, windowHeight) >= 641) {
		return 'tablet'
	}
	return 'mobile'
}
const deviceOrientation = windowWidth > windowHeight
	? 'landscape'
	: 'portrait'

// Preload images and randomly rotate
if (window.location.pathname === '/') {
	// Randomly use different hero images from 1 to 4
	let randomSlide = 0
	const hero = document.getElementsByClassName('hero-slide')[0]
	do {
		randomSlide = Math.floor(Math.random() * MAX_SLIDES) + 1
	}
	// Don’t use same slide
	while (randomSlide === 1 && hero.classList.contains(slideClasses[randomSlide - 1]))
	for (let slideClass in slideClasses) {
		hero.classList.remove(slideClass)
	}
	hero.classList.add(slideClasses[randomSlide - 1])
}<commit_msg>Added hero image onload.<commit_after>const MAX_SLIDES = 2
const slideClasses = ['one', 'two', 'three', 'four', 'five', 'six']

// If window orientation changes
const getDevice = () => {
	//	Some large tablets exist, but for all intents and purposes, we’ll treat them as desktops.
	if (Math.max(windowWidth, windowHeight) >= 1025) {
		return 'desktop'
	}
	if (Math.min(windowWidth, windowHeight) >= 641) {
		return 'tablet'
	}
	return 'mobile'
}
const deviceOrientation = windowWidth > windowHeight
	? 'landscape'
	: 'portrait'

// Preload images and randomly rotate
if (window.location.pathname === '/') {
	// Randomly use different hero images from 1 to 4
	let slideNumber = 0
	const hero = document.getElementsByClassName('hero-slide')[0]
	do {
		slideNumber = Math.floor(Math.random() * MAX_SLIDES) + 1
	}
	// Don’t use same slide
	while (slideNumber === 1 && hero.classList.contains(slideClasses[slideNumber - 1]))
	for (let slideClass in slideClasses) {
		hero.classList.remove(slideClass)
	}
	hero.classList.add(slideClasses[slideNumber - 1])
	// Slide in Hero Text
	const heroTitle = document.getElementsByClassName('hero-slide-title')[slideNumber]
	heroTitle.classList.add('fade-slide')
}<|endoftext|>


<commit_before>SERVERIP = '10.24.25.130:8000';

function getconnection(){
	$.getJSON("http://"+SERVERIP+"/logserver/connection", function(result){
		$("#main").html('
');
		$("#stattxt").text('List of connections received.');
		$.each( result, function( key, val ) {
			username = key.split(" ")[0];
			link = ""+username+ ""
			$("#main").append("
"+link+"
");
		});
		$("#main").append("
");
	});
}
function hashlist(){
	$.getJSON("http://"+SERVERIP+"/logserver/hashlist", function(result){
		$("#stattxt").text('List of hash received.');
		$.each( result, function( key, val ) {
			username = key.split(" ")[0];
			link = ""+username+ ""
			$("#main").append("
"+link+"
");
		});
		$("#main").append("
");
	});
}

getconnection();
hashlist();
setInterval(getconnection,3600000);
setInterval(hashlist,3600000);
<commit_msg>Update main.js<commit_after>SERVERIP = '10.24.25.130:8000';

function getconnection(){
	$.getJSON("http://"+SERVERIP+"/logserver/connection", function(result){
		$("#main").html('
');
		$("#stattxt").text('List of connections received.');
		$.each( result, function( key, val ) {
			username = key.split(" ")[0];
			link = ""+username+ ""
			$("#main").append("
"+link+"
");
		});
		$("#main").append("
");
	});
}
function hashlist(){
	$.getJSON("http://"+SERVERIP+"/logserver/hashlist", function(result){
		$("#stattxt").text('List of hash received.');
		$.each( result, function( key, val ) {
			username = key.split(" ")[0];
			link = ""+username+ ""
			$("#main").append("
"+link+"
");
		});
		$("#main").append("
");
	});
}
function rolluplist(){
	$.getJSON("http://"+SERVERIP+"/logserver/rolluplist", function(result){
		$("#exlist").html("");
		$("#stattxt").text('List of rollups received.');
		$.each( result, function( key, val ) {
			username = key.split(" ")[0];
			link = ""+username+ ""
			$("#exlist").append("
"+link+"
");
		});
		$("#exlist").append("
");
	});
}

getconnection();
hashlist();
rolluplist();
setInterval(getconnection,3600000);
setInterval(hashlist,3600000);
<|endoftext|>


<commit_before>function getRandomID() {
	return String(Math.floor(Math.random() * 98765862));
}

function getSkinsDir() {
	Titanium.Filesystem.getFile(Titanium.Filesystem.getApplicationDataDirectory() + 'skins/').createDirectory();
	return Titanium.Filesystem.getApplicationDataDirectory() + 'skins/';
}

function getBGImage() {
	return '/img/stonebrick.png';
}

function getNavColor() {
	return '#888888';
}

function getHeaderFooterView(text, height) {
	var label = Ti.UI.createLabel({
		text:text,
		color:'white',
		font: {
			fontSize:15,
			fontWeight:'bold'
		},
		shadowColor:'black',
		shadowOffset: {
			x:0,
			y:1
		},
		top:10,
		left:15,
		width:295
	});

	var view = Ti.UI.createView({
		height:height
	});

	view.add(label);
	return view;
}<commit_msg>Reducing top location for header/footer label<commit_after>function getRandomID() {
	return String(Math.floor(Math.random() * 98765862));
}

function getSkinsDir() {
	Titanium.Filesystem.getFile(Titanium.Filesystem.getApplicationDataDirectory() + 'skins/').createDirectory();
	return Titanium.Filesystem.getApplicationDataDirectory() + 'skins/';
}

function getBGImage() {
	return '/img/stonebrick.png';
}

function getNavColor() {
	return '#888888';
}

function getHeaderFooterView(text, height) {
	var label = Ti.UI.createLabel({
		text:text,
		color:'white',
		font: {
			fontSize:15,
			fontWeight:'bold'
		},
		shadowColor:'black',
		shadowOffset: {
			x:0,
			y:1
		},
		top:5,
		left:15,
		width:295
	});

	var view = Ti.UI.createView({
		height:height
	});

	view.add(label);
	return view;
}<|endoftext|>


<commit_before>var db = require('lib/db');

var DEBUG = function(s) {
	if (true) {
		Ti.API.info('DEBUG: ' + s);	// set this to false to turn off debug output
	}
};

var dayOfWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];

var monthName = ['January', 'February', 'March', 'April', 'May', 'June',
				 'July', 'August', 'September', 'October', 'November', 'December'];

function TasksWindow(){
	var self = Ti.UI.createWindow({
		title : L('tasks'),
		backgroundColor : 'white',
		layout : 'vertical'
	});

	var prettyDate = function(date){
		date = new Date(date);
		return dayOfWeek[date.getDay()]+', '+monthName[date.getMonth()]+' '+date.getDate()+', '+date.getFullYear();
	};

	var self_title = Ti.UI.createLabel({
		text : prettyDate(Ti.App.Properties.getObject('focus_date')),
		top : 5,
		//height : 20
	});
	self.add(self_title);

	self.addEventListener('swipe',function(e){
		// TODO: we need to consider when we decrement or increment into another month
		// THIS IS DONE AUTOMATICALLY, HELL YEAH

		// if swipe left then increment the date
		if (e.direction == 'left'){
			var old_focus = new Date(Ti.App.Properties.getObject('focus_date'));
			var new_focus = old_focus.setDate(old_focus.getDate()+1); // increment date
			Ti.App.Properties.setObject('focus_date',new_focus);
			self_title.setText(prettyDate(new_focus));

		} // if swipe right then decrement date
		else if (e.direction == 'right'){
			var old_focus = new Date(Ti.App.Properties.getObject('focus_date'));
			var new_focus = old_focus.setDate(old_focus.getDate()-1); // decrement date
			Ti.App.Properties.setObject('focus_date',new_focus);
			self_title.setText(prettyDate(new_focus));

		}

	});

	// the table view that will hold the tasks
	tasks_list = db.daylist(new Date(Ti.App.Properties.getObject('focus_date')));
	var tasks_table = Ti.UI.createTableView({
		data : tasks_list,
		top : 5
	});

	// add the table to our window
	self.add(tasks_table);

	/*
	 * The set of buttons for the task window toolbar
	 */
	var add = Ti.UI.createButton({
		systemButton : Titanium.UI.iPhone.SystemButton.ADD
	});

	var edit = Ti.UI.createButton({
		systemButton : Titanium.UI.iPhone.SystemButton.EDIT,
		enabled : false
	});

	var del = Ti.UI.createButton({
		systemButton : Titanium.UI.iPhone.SystemButton.TRASH,
		enabled : false
	});

	var done = Ti.UI.createButton({
		systemButton : Titanium.UI.iPhone.SystemButton.DONE,
	});

	// used to evenly distribute items on the toolbar
	var flexSpace = Titanium.UI.createButton({
		systemButton:Titanium.UI.iPhone.SystemButton.FLEXIBLE_SPACE
	});

	// set the toolbar for our window using the above buttons
	self.setToolbar([add,flexSpace,edit,flexSpace,del,flexSpace,done]);

	return self;
}

module.exports = TasksWindow;
<commit_msg>Updated TasksWindow so that on swipe the table of tasks is updated for the new 'focus' date<commit_after>var db = require('lib/db');

var DEBUG = function(s) {
	if (true) {
		Ti.API.info('DEBUG: ' + s);	// set this to false to turn off debug output
	}
};

var dayOfWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];

var monthName = ['January', 'February', 'March', 'April', 'May', 'June',
				 'July', 'August', 'September', 'October', 'November', 'December'];

function TasksWindow(){
	var self = Ti.UI.createWindow({
		title : L('tasks'),
		backgroundColor : 'white',
		layout : 'vertical'
	});

	var prettyDate = function(date){
		date = new Date(date);
		return dayOfWeek[date.getDay()]+', '+monthName[date.getMonth()]+' '+date.getDate()+', '+date.getFullYear();
	};

	var self_title = Ti.UI.createLabel({
		text : prettyDate(Ti.App.Properties.getObject('focus_date')),
		top : 5,
		//height : 20
	});
	self.add(self_title);

	self.addEventListener('swipe',function(e){
		// TODO: we need to consider when we decrement or increment into another month
		// THIS IS DONE AUTOMATICALLY, HELL YEAH

		// if swipe left then increment the date
		if (e.direction == 'left'){
			var old_focus = new Date(Ti.App.Properties.getObject('focus_date'));
			var new_focus = old_focus.setDate(old_focus.getDate()+1); // increment date
			Ti.App.Properties.setObject('focus_date',new_focus);

		} // if swipe right then decrement date
		else if (e.direction == 'right'){
			var old_focus = new Date(Ti.App.Properties.getObject('focus_date'));
			var new_focus = old_focus.setDate(old_focus.getDate()-1); // decrement date
			Ti.App.Properties.setObject('focus_date',new_focus);

		}

		/*
		 * Update information, this will do nothing if the swipe wasn't left or right
		 */
		up_date = new Date(Ti.App.Properties.getObject('focus_date')); // get it?
		self_title.setText(prettyDate(up_date));
		tasks_table.setData(db.daylist(up_date));
	});

	// the table view that will hold the tasks
	tasks_list = db.daylist(new Date(Ti.App.Properties.getObject('focus_date')));
	var tasks_table = Ti.UI.createTableView({
		data : tasks_list,
		top : 5
	});

	// add the table to our window
	self.add(tasks_table);

	/*
	 * The set of buttons for the task window toolbar
	 */
	var add = Ti.UI.createButton({
		systemButton : Titanium.UI.iPhone.SystemButton.ADD
	});

	var edit = Ti.UI.createButton({
		systemButton : Titanium.UI.iPhone.SystemButton.EDIT,
		enabled : false
	});

	var del = Ti.UI.createButton({
		systemButton : Titanium.UI.iPhone.SystemButton.TRASH,
		enabled : false
	});

	var done = Ti.UI.createButton({
		systemButton : Titanium.UI.iPhone.SystemButton.DONE,
	});

	// used to evenly distribute items on the toolbar
	var flexSpace = Titanium.UI.createButton({
		systemButton:Titanium.UI.iPhone.SystemButton.FLEXIBLE_SPACE
	});

	// set the toolbar for our window using the above buttons
	self.setToolbar([add,flexSpace,edit,flexSpace,del,flexSpace,done]);

	return self;
}

module.exports = TasksWindow;
<|endoftext|>


<commit_before>//Load modules
var System = require('systemjs');
var ASQ = require('asynquence');

function report (msg) {
	console.log(msg)
};

function repErr (err) {
	console.error(err)
}

var app, http, io, emic;
ASQ()
.then(function () {app = require('express')()})
.then(function () {http = require('http').Server(app)})
.then(function () {io = require('socket.io')(http)})
.then(function () {emic = require('./emic2.js')})
.then(function () {report("Modules loaded successfully")})
.or(repErr("Module load error"));
/*
var pApp = Promise.resolve(require('express')())
	.then(global var )
var app = require('express')()
var http = require('http').Server(app);
var io = require('socket.io')(http);
var EMIC = require('./emic2.js');
*/

//var fs = require('fs');
report(emic);
emic.init();

app.get('/', function(req, res){
    //var html = fs.readFileSync("index3.html", "utf8");
    //res.send(html);
    res.sendFile(__dirname + '/main.html');
});
console.log('connection achieved')

io.on('connection', function(socket){

	console.log('a user connected');
	//console.log('hello connection');
	socket.on('disconnect', function() {
		console.log('a user disconnected');
	});
	socket.on('user message', function(msg){
		//console.log('hi all');
		console.log('sendmessage');
		EMIC.speak(msg);
		console.log('usermessage: ' + msg);
		io.emit('user message', msg);
	});
});

http.listen(3001, function(){
    console.log('listening on *:3001');
});
<commit_msg>update<commit_after>//Load modules
var System = require('systemjs');
var ASQ = require('asynquence');

function report (msg) {
	console.log(msg)
};

function repErr (err) {
	console.error(err)
}

var app, http, io, emic;
ASQ()
.then(function () {app = require('express')()})
.then(function () {http = require('http').Server(app)})
.then(function () {io = require('socket.io')(http)})
.then(function () {emic = require('./emic2.js')})
.then(function () {report("Modules loaded successfully")})
.or(repErr("Module load error"))
.then(emic.init())
.then(app.get('/', function(req, res){
    //var html = fs.readFileSync("index3.html", "utf8");
    //res.send(html);
    res.sendFile(__dirname + '/main.html');
});
)
.then(report('connection achieved'))
.then(

io.on('connection', function(socket){

	console.log('a user connected');
	//console.log('hello connection');
	socket.on('disconnect', function() {
		console.log('a user disconnected');
	});
	socket.on('user message', function(msg){
		//console.log('hi all');
		console.log('sendmessage');
		EMIC.speak(msg);
		console.log('usermessage: ' + msg);
		io.emit('user message', msg);
	});
});

http.listen(3001, function(){
    console.log('listening on *:3001');
});
)
<|endoftext|>


<commit_before>/** @jsx jsx */
import { jsx } from "theme-ui"
import React from "react"
import GoFold from "react-icons/lib/go/fold"
import GoUnfold from "react-icons/lib/go/unfold"

const iconStyles = {
  display: `inline-block`,
  mr: 2,
}

const ExpandAllButton = ({ onClick, expandAll }) => (
  <button
    onClick={onClick}
    sx={{
      alignItems: `center`,
      bg: `transparent`,
      border: `none`,
      borderRadius: 1,
      color: `textMuted`,
      cursor: `pointer`,
      display: `flex`,
      flexGrow: 0,
      fontSize: 0,
      lineHeight: `solid`,
      py: 2,
      textAlign: `left`,
      transition: t => `all ${t.transition.speed.fast}`,
      "&:hover": {
        bg: `purple.10`,
        color: `gatsby`,
      },
    }}
  >
    {expandAll ? (
      <React.Fragment>

          <GoFold />

        Collapse All
      </React.Fragment>
    ) : (
      <React.Fragment>

          <GoUnfold />

        Expand All
      </React.Fragment>
    )}
  </button>
)

export default ExpandAllButton
<commit_msg>fix(www): support dark mode in 'Collapse all' btn on hover (#19062)<commit_after>/** @jsx jsx */
import { jsx } from "theme-ui"
import React from "react"
import GoFold from "react-icons/lib/go/fold"
import GoUnfold from "react-icons/lib/go/unfold"

const iconStyles = {
  display: `inline-block`,
  mr: 2,
}

const ExpandAllButton = ({ onClick, expandAll }) => (
  <button
    onClick={onClick}
    sx={{
      alignItems: `center`,
      bg: `transparent`,
      border: `none`,
      borderRadius: 1,
      color: `textMuted`,
      cursor: `pointer`,
      display: `flex`,
      flexGrow: 0,
      fontSize: 0,
      lineHeight: `solid`,
      py: 2,
      textAlign: `left`,
      transition: t => `all ${t.transition.speed.fast}`,
      "&:hover": {
        bg: `sidebar.itemHoverBackground`,
        color: `navigation.linkHover`,
      },
    }}
  >
    {expandAll ? (
      <React.Fragment>

          <GoFold />

        Collapse All
      </React.Fragment>
    ) : (
      <React.Fragment>

          <GoUnfold />

        Expand All
      </React.Fragment>
    )}
  </button>
)

export default ExpandAllButton
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { connect } from 'react-redux';
import Dimensions from 'react-dimensions'

import * as d3 from 'd3';
import { map, groupBy, reduce, forEach, difference, find, uniq, remove, each, includes, assign } from 'lodash';
import moment from 'moment';

import { selectNodes, selectNode } from '../../modules/data/index';
import { phone, fieldLocator } from '../../helpers/index';

class Graph extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            nodes: [],
            links: [],
            highlight_nodes: [],
            edges: [],
            clusters: {},
            start: new Date(),
            time: 0,
            n: {
                id: 'test',
            },
            ticks: 0
        };

        const { containerHeight, containerWidth } = props;

        this.network = {
            graph: {
                nodes: [],
                links: [],
                highlight_nodes: [],
                selection: null,
                selectedNodes: [],
                tooltip: null,
                transform: d3.zoomIdentity,
                queries: []
            },
            height: containerHeight,
            width: containerWidth,
            simulation: {},
            lines: {
                stroke: {
                    color: "#ccc",
                    thickness: 1
                }
            },
            nodes: {
                fill: {
                    color: "#333"
                },
                stroke: {
                    color: "#fff",
                    thickness: 3
                },
                sizeRange: [12, 30]
            },
            zoomed: function () {
                this.graph.transform = d3.event.transform;
            },
            setup: function (el) {
                this.render = this.render.bind(this);
                this.drawNode = this.drawNode.bind(this);
                this.drawLink = this.drawLink.bind(this);

                this.canvas = el;
                this.context = this.canvas.getContext('2d');
                var canvas = d3.select(this.canvas)

                canvas.on("mousedown", this.mousedown.bind(this))
                    .on("mousemove", this.mousemove.bind(this))
                    .on("mouseup", this.mouseup.bind(this))
                    .call(d3.drag()
                        .filter(() => {
                            return d3.event.altKey;
                        })
                        .subject(this.dragsubject.bind(this))
                        .on("start", this.dragstarted.bind(this))
                        .on("drag", this.dragged.bind(this))
                        .on("end", this.dragended.bind(this))
                    )
                    .call(d3.zoom()
                        .filter(() => {
                            return d3.event.altKey;
                        })
                        .scaleExtent([1 / 2, 8])
                        .on("zoom", this.zoomed.bind(this))
                    );

                this.simulation = d3.forceSimulation()
                    .stop()
                    .force("link", d3.forceLink().id(function (d) {
                        return d.id;
                    }))
                    .force("charge", d3.forceManyBody().strength(-100).distanceMax(300))
                    .force("center", d3.forceCenter(this.width / 2, this.height / 2))
                    .force("vertical", d3.forceY().strength(0.018))
                    .force("horizontal", d3.forceX().strength(0.006));

                this.render();
            },
            forceScale: function (node) {
                var scale = d3.scaleLog().domain(this.nodes.sizeRange).range(this.nodes.sizeRange.slice().reverse());
                return node.r + scale(node.r);
            },
            select: function (nodes) {
                this.graph.selectedNodes = nodes;
            },
            highlight: function (nodes) {
                this.graph.highlight_nodes = nodes;
            },
            addNodes: function (graph) {
                var countExtent = d3.extent(graph.nodes, function (d) {
                        return d.connections;
                    }),
                    radiusScale = d3.scalePow().exponent(2).domain(countExtent).range(this.nodes.sizeRange);

                var newNodes = false;

                var that = this;
                each(graph.nodes, function (node) {
                    var n = find(that.graph.nodes, {id: node.id});
                    if (n) {
                        n.connections++;

                        n.r = radiusScale(n.connections);
                        n.force = that.forceScale(n);

                        n.query.push(node.query);
                        n.query = uniq(n.query);

                        n.color.push(node.color);
                        n.color = uniq(n.color);

                        return;
                    }

                    node.color = [node.color];
                    node.query = [node.query];
                    node.force = that.forceScale(node);
                    node.r = radiusScale(node.connections);
                    node.icon = "\uF047";

                    that.graph.nodes.push(node);

                    newNodes = true;
                });

                this.graph.links = this.graph.links.concat(graph.links);

                if (!newNodes)
                    return;

                this.simulation
                    .nodes(this.graph.nodes);

                this.simulation.force("link")
                    .links(this.graph.links);

                this.simulation.alpha(0.3).restart();
            },
            removeNodes: function (removed) {
                // remove nodes
                this.graph.nodes = remove(this.graph.nodes, (n) => {
                    return find(removed, {id: n});
                });

                // find links
                this.graph.links = remove(this.graph.links, (n) => {
                    return find(removed, {id: n.source.id}) || find(removed, {id: n.target.id});
                });
            },
            render: function () {
                if (!this.graph) {
                    return false;
                }

                this.context.save();
                this.context.clearRect(0, 0, this.width, this.height);

                this.context.translate((0) + this.graph.transform.x, (0) + this.graph.transform.y);

                this.context.scale(this.graph.transform.k, this.graph.transform.k);

                this.context.beginPath();

                this.graph.links.forEach((d)=> {
                    this.drawLink(d);
                });

                this.context.strokeStyle = this.lines.stroke.color;
                this.context.lineWidth = this.lines.stroke.thickness;
                this.context.stroke();

                this.graph.nodes.forEach((d)=> {
                    this.drawNode(d);
                });

                if (this.graph.selection) {
                    this.context.beginPath();
                    this.context.strokeStyle = '#c0c0c0';
                    this.context.fillStyle = "rgba(224, 224, 224, 0.6)";
                    //this.context.fillStyle = '#eee';
                    this.context.lineWidth = 1;
                    // this.context.setLineDash([6]);

                    this.context.rect(this.graph.selection.x1, this.graph.selection.y1, this.graph.selection.x2 - this.graph.selection.x1, this.graph.selection.y2 - this.graph.selection.y1);
                    this.context.fill();
                    this.context.stroke();
                }

                if (this.graph.tooltip) {
                    this.context.fillStyle = '#000'; //d.color[0];
                    this.context.font = "14px Arial";
                    this.context.fillText(this.graph.tooltip.node.id, this.graph.tooltip.x + 5, this.graph.tooltip.y - 5);
                }

                this.context.restore();

                requestAnimationFrame(this.render);
            },
            drawLink: function (d) {
                this.context.moveTo(d.source.x, d.source.y);
                this.context.lineTo(d.target.x, d.target.y);
            },
            drawNode: function (d) {
                // this.context.moveTo(d.x + d.r, d.y);
                // for each different query, show a part. This will show that the edge
                //  has been found in multiple queries.
                for (var i = 0; i < d.query.length; i++) {
                    // find color

                    this.context.beginPath();
                    this.context.arc(d.x, d.y, d.r, 2 * Math.PI * (i / d.color.length), 2 * Math.PI * ( (i + 1) / d.color.length));

                    var color = '#000'; // d.searches[i];

                    for (var j = 0; j < this.graph.queries.length; j++) {
                        if (this.graph.queries[j].q === d.query[i])
                            color = this.graph.queries[j].color;
                    }

                    this.context.fillStyle = color;
                    this.context.fill();

                    if (includes(this.graph.selectedNodes, d)) {
                        this.context.strokeStyle = '#993833';
                        this.context.lineWidth = this.nodes.stroke.thickness;
                        this.context.stroke();
                    }
                }

                // this.context.font="14px FontAwesome";
                // this.context.fillStyle = '#fff';
                // this.context.fillText(d.icon, d.x - ( d.r) + 1, d.y + 5);
            },
            mousedown: function () {
                const { dispatch, graph } = this;

                if (d3.event.altKeys) {
                    return;
                }

                var x = graph.transform.invertX(d3.event.layerX),
                    y = graph.transform.invertY(d3.event.layerY);

                var subject = this.simulation.find(x, y, 20);
                if (!subject) {
                    graph.selection = {x1: x, y1: y, x2: x, y2: y};
                    dispatch(selectNodes({nodes: []}));
                    return;
                } else {
                    if (!includes(graph.selectedNodes, subject)) {
                        graph.selectedNodes.push(subject);
                    } else {
                        remove(graph.selectedNodes, subject);
                    }

                    dispatch(selectNodes({nodes: graph.selectedNodes}));
                }
            },
            mouseup: function () {
                const { graph } = this;

                if (d3.event.altKeys) {
                    return;
                }

                var x = graph.transform.invertX(d3.event.layerX),
                    y = graph.transform.invertY(d3.event.layerY);

                // find all nodes within selection and highliht
                graph.selection = null;
            },
            mousemove: function (n) {
                const { dispatch, graph } = this;

                if (d3.event.altKeys) {
                    return;
                }

                var x = graph.transform.invertX(d3.event.layerX),
                    y = graph.transform.invertY(d3.event.layerY);

                if (graph.selection) {
                    console.debug("BLA", "mousemove");
                    graph.selection = assign(graph.selection, {x2: x, y2: y});

                    graph.nodes.forEach((d)=> {
                        if ((d.x > graph.selection.x1 && d.x < graph.selection.x2) &&
                            (d.y > graph.selection.y1 && d.y < graph.selection.y2)) {
                            if (!includes(graph.selectedNodes, d)) {
                                graph.selectedNodes.push(d);
                            }
                        }

                        if ((d.x > graph.selection.x2 && d.x < graph.selection.x1) &&
                            (d.y > graph.selection.y2 && d.y < graph.selection.y1)) {
                            if (!includes(graph.selectedNodes, d)) {
                                graph.selectedNodes.push(d);
                            }
                        }
                    });

                    dispatch(selectNodes({nodes: graph.selectedNodes}));
                    return;
                }

                var subject = this.simulation.find(x, y, 20);
                if (subject === undefined) {
                    graph.tooltip = null;
                } else {
                    graph.tooltip = {node: subject, x: x, y: y};
                    this.onmousemove(subject);
                }
            },
            dragstarted: function () {
                this.graph.selection = null;
                this.graph.tooltip = null;

                var x = d3.event.x,
                    y = d3.event.y;

                if (!d3.event.active) this.simulation.alphaTarget(0.3).restart();
                d3.event.subject.fx = x;
                d3.event.subject.fy = y;
            },
            dragged: function () {
                var x = d3.event.x,
                    y = d3.event.y;

                d3.event.subject.fx = (x);
                d3.event.subject.fy = (y);
            },
            dragended: function () {
                if (!d3.event.active) this.simulation.alphaTarget(0);
                d3.event.subject.fx = null;
                d3.event.subject.fy = null;
            },
            dragsubject: function () {
                const x = this.graph.transform.invertX(d3.event.x),
                    y = this.graph.transform.invertY(d3.event.y);

                return this.simulation.find(x, y, 20);
            },
            mousemoved: function () {
            }
        };
    }

    componentDidMount() {
        const { network } = this;
        const { dispatch } = this.props;

        network.dispatch = dispatch;
        network.onmouseclick = this.onMouseClick.bind(this);
        network.onmousemove = this.onMouseMove.bind(this);

        network.setup(this.refs["canvas"]);
    }

    onMouseClick(node) {
        const { dispatch } = this.props;
        dispatch(selectNode({node: node}));
    }

    onMouseMove(node) {
        //const { dispatch } = this.props;
        //dispatch(selectNode({node: node}));
    }

    onMouseOver(node) {
        //const { dispatch } = this.props;
        //dispatch(selectNode({node: node}));
    }

    componentWillReceiveProps(nextProps) {
    }

    componentDidUpdate(prevProps, prevState) {
        const { network } = this;
        const { queries } = this.props;

        network.graph.queries = queries;

        var { fields } = this.props;

        var nodes = [];
        var links = [];

        var removed = difference(prevProps.items, this.props.items);
        if (removed.length > 0) {
            var removed2 = [];
            forEach(removed, (d, i) => {
                forEach(fields, (field) => {
                    const value = fieldLocator(d.fields, field);

                    if (value) {
                        removed2.push(value);
                    }

                });
            });

            // this should be node id not packet
            network.removeNodes({
                nodes: removed2,
            });
        }

        if (this.props.items.length > 0) {
            forEach(this.props.items, (d, i) => {
                forEach(fields, (field) => {
                    const value = fieldLocator(d.fields, field);
                    if (!value) return;

                    nodes.push({
                        id: phone(value),
                        query: d.q,
                        name: value,
                        color: d.color,
                        connections: 1
                    });
                });

                forEach(fields, (source) => {
                    const sourceValue = fieldLocator(d.fields, source);
                    if (!sourceValue) return;

                    forEach(fields, (target) => {
                        const targetValue = fieldLocator(d.fields, target);
                        if (!targetValue) return;

                        links.push({
                            source: phone(sourceValue),
                            target: phone(targetValue),
                        });
                    });
                });
            });

            network.addNodes({
                nodes: nodes,
                links: links,
            });
        }
        network.select(this.props.node);
        network.highlight(this.props.highlight_nodes);
    }

    shouldComponentUpdate(){
        return true;
    }

    render() {
        const { containerHeight, containerWidth } = this.props;

        return (
            <canvas
                style={{fontFamily: 'fontAwesome'}}
                width={containerWidth}
                height={containerHeight}
                ref="canvas">
                histogram
            </canvas>
        );
    }
}

const select = (state, ownProps) => {
    return {
        ...ownProps,
        node: state.entries.node,
        queries: state.entries.searches,
        fields: state.entries.fields,
        items: state.entries.items,
        highlight_nodes: state.entries.highlight_nodes,
    }
}

export default connect(select)(Dimensions()(Graph));<commit_msg>removed debug message<commit_after>import React, { Component } from 'react';
import { connect } from 'react-redux';
import Dimensions from 'react-dimensions'

import * as d3 from 'd3';
import { map, groupBy, reduce, forEach, difference, find, uniq, remove, each, includes, assign } from 'lodash';
import moment from 'moment';

import { selectNodes, selectNode } from '../../modules/data/index';
import { phone, fieldLocator } from '../../helpers/index';

class Graph extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            nodes: [],
            links: [],
            highlight_nodes: [],
            edges: [],
            clusters: {},
            start: new Date(),
            time: 0,
            n: {
                id: 'test',
            },
            ticks: 0
        };

        const { containerHeight, containerWidth } = props;

        this.network = {
            graph: {
                nodes: [],
                links: [],
                highlight_nodes: [],
                selection: null,
                selectedNodes: [],
                tooltip: null,
                transform: d3.zoomIdentity,
                queries: []
            },
            height: containerHeight,
            width: containerWidth,
            simulation: {},
            lines: {
                stroke: {
                    color: "#ccc",
                    thickness: 1
                }
            },
            nodes: {
                fill: {
                    color: "#333"
                },
                stroke: {
                    color: "#fff",
                    thickness: 3
                },
                sizeRange: [12, 30]
            },
            zoomed: function () {
                this.graph.transform = d3.event.transform;
            },
            setup: function (el) {
                this.render = this.render.bind(this);
                this.drawNode = this.drawNode.bind(this);
                this.drawLink = this.drawLink.bind(this);

                this.canvas = el;
                this.context = this.canvas.getContext('2d');
                var canvas = d3.select(this.canvas)

                canvas.on("mousedown", this.mousedown.bind(this))
                    .on("mousemove", this.mousemove.bind(this))
                    .on("mouseup", this.mouseup.bind(this))
                    .call(d3.drag()
                        .filter(() => {
                            return d3.event.altKey;
                        })
                        .subject(this.dragsubject.bind(this))
                        .on("start", this.dragstarted.bind(this))
                        .on("drag", this.dragged.bind(this))
                        .on("end", this.dragended.bind(this))
                    )
                    .call(d3.zoom()
                        .filter(() => {
                            return d3.event.altKey;
                        })
                        .scaleExtent([1 / 2, 8])
                        .on("zoom", this.zoomed.bind(this))
                    );

                this.simulation = d3.forceSimulation()
                    .stop()
                    .force("link", d3.forceLink().id(function (d) {
                        return d.id;
                    }))
                    .force("charge", d3.forceManyBody().strength(-100).distanceMax(300))
                    .force("center", d3.forceCenter(this.width / 2, this.height / 2))
                    .force("vertical", d3.forceY().strength(0.018))
                    .force("horizontal", d3.forceX().strength(0.006));

                this.render();
            },
            forceScale: function (node) {
                var scale = d3.scaleLog().domain(this.nodes.sizeRange).range(this.nodes.sizeRange.slice().reverse());
                return node.r + scale(node.r);
            },
            select: function (nodes) {
                this.graph.selectedNodes = nodes;
            },
            highlight: function (nodes) {
                this.graph.highlight_nodes = nodes;
            },
            addNodes: function (graph) {
                var countExtent = d3.extent(graph.nodes, function (d) {
                        return d.connections;
                    }),
                    radiusScale = d3.scalePow().exponent(2).domain(countExtent).range(this.nodes.sizeRange);

                var newNodes = false;

                var that = this;
                each(graph.nodes, function (node) {
                    var n = find(that.graph.nodes, {id: node.id});
                    if (n) {
                        n.connections++;

                        n.r = radiusScale(n.connections);
                        n.force = that.forceScale(n);

                        n.query.push(node.query);
                        n.query = uniq(n.query);

                        n.color.push(node.color);
                        n.color = uniq(n.color);

                        return;
                    }

                    node.color = [node.color];
                    node.query = [node.query];
                    node.force = that.forceScale(node);
                    node.r = radiusScale(node.connections);
                    node.icon = "\uF047";

                    that.graph.nodes.push(node);

                    newNodes = true;
                });

                this.graph.links = this.graph.links.concat(graph.links);

                if (!newNodes)
                    return;

                this.simulation
                    .nodes(this.graph.nodes);

                this.simulation.force("link")
                    .links(this.graph.links);

                this.simulation.alpha(0.3).restart();
            },
            removeNodes: function (removed) {
                // remove nodes
                this.graph.nodes = remove(this.graph.nodes, (n) => {
                    return find(removed, {id: n});
                });

                // find links
                this.graph.links = remove(this.graph.links, (n) => {
                    return find(removed, {id: n.source.id}) || find(removed, {id: n.target.id});
                });
            },
            render: function () {
                if (!this.graph) {
                    return false;
                }

                this.context.save();
                this.context.clearRect(0, 0, this.width, this.height);

                this.context.translate((0) + this.graph.transform.x, (0) + this.graph.transform.y);

                this.context.scale(this.graph.transform.k, this.graph.transform.k);

                this.context.beginPath();

                this.graph.links.forEach((d)=> {
                    this.drawLink(d);
                });

                this.context.strokeStyle = this.lines.stroke.color;
                this.context.lineWidth = this.lines.stroke.thickness;
                this.context.stroke();

                this.graph.nodes.forEach((d)=> {
                    this.drawNode(d);
                });

                if (this.graph.selection) {
                    this.context.beginPath();
                    this.context.strokeStyle = '#c0c0c0';
                    this.context.fillStyle = "rgba(224, 224, 224, 0.6)";
                    //this.context.fillStyle = '#eee';
                    this.context.lineWidth = 1;
                    // this.context.setLineDash([6]);

                    this.context.rect(this.graph.selection.x1, this.graph.selection.y1, this.graph.selection.x2 - this.graph.selection.x1, this.graph.selection.y2 - this.graph.selection.y1);
                    this.context.fill();
                    this.context.stroke();
                }

                if (this.graph.tooltip) {
                    this.context.fillStyle = '#000'; //d.color[0];
                    this.context.font = "14px Arial";
                    this.context.fillText(this.graph.tooltip.node.id, this.graph.tooltip.x + 5, this.graph.tooltip.y - 5);
                }

                this.context.restore();

                requestAnimationFrame(this.render);
            },
            drawLink: function (d) {
                this.context.moveTo(d.source.x, d.source.y);
                this.context.lineTo(d.target.x, d.target.y);
            },
            drawNode: function (d) {
                // this.context.moveTo(d.x + d.r, d.y);
                // for each different query, show a part. This will show that the edge
                //  has been found in multiple queries.
                for (var i = 0; i < d.query.length; i++) {
                    // find color

                    this.context.beginPath();
                    this.context.arc(d.x, d.y, d.r, 2 * Math.PI * (i / d.color.length), 2 * Math.PI * ( (i + 1) / d.color.length));

                    var color = '#000'; // d.searches[i];

                    for (var j = 0; j < this.graph.queries.length; j++) {
                        if (this.graph.queries[j].q === d.query[i])
                            color = this.graph.queries[j].color;
                    }

                    this.context.fillStyle = color;
                    this.context.fill();

                    if (includes(this.graph.selectedNodes, d)) {
                        this.context.strokeStyle = '#993833';
                        this.context.lineWidth = this.nodes.stroke.thickness;
                        this.context.stroke();
                    }
                }

                // this.context.font="14px FontAwesome";
                // this.context.fillStyle = '#fff';
                // this.context.fillText(d.icon, d.x - ( d.r) + 1, d.y + 5);
            },
            mousedown: function () {
                const { dispatch, graph } = this;

                if (d3.event.altKeys) {
                    return;
                }

                var x = graph.transform.invertX(d3.event.layerX),
                    y = graph.transform.invertY(d3.event.layerY);

                var subject = this.simulation.find(x, y, 20);
                if (!subject) {
                    graph.selection = {x1: x, y1: y, x2: x, y2: y};
                    dispatch(selectNodes({nodes: []}));
                    return;
                } else {
                    if (!includes(graph.selectedNodes, subject)) {
                        graph.selectedNodes.push(subject);
                    } else {
                        remove(graph.selectedNodes, subject);
                    }

                    dispatch(selectNodes({nodes: graph.selectedNodes}));
                }
            },
            mouseup: function () {
                const { graph } = this;

                if (d3.event.altKeys) {
                    return;
                }

                var x = graph.transform.invertX(d3.event.layerX),
                    y = graph.transform.invertY(d3.event.layerY);

                // find all nodes within selection and highliht
                graph.selection = null;
            },
            mousemove: function (n) {
                const { dispatch, graph } = this;

                if (d3.event.altKeys) {
                    return;
                }

                var x = graph.transform.invertX(d3.event.layerX),
                    y = graph.transform.invertY(d3.event.layerY);

                if (graph.selection) {
                    graph.selection = assign(graph.selection, {x2: x, y2: y});

                    graph.nodes.forEach((d)=> {
                        if ((d.x > graph.selection.x1 && d.x < graph.selection.x2) &&
                            (d.y > graph.selection.y1 && d.y < graph.selection.y2)) {
                            if (!includes(graph.selectedNodes, d)) {
                                graph.selectedNodes.push(d);
                            }
                        }

                        if ((d.x > graph.selection.x2 && d.x < graph.selection.x1) &&
                            (d.y > graph.selection.y2 && d.y < graph.selection.y1)) {
                            if (!includes(graph.selectedNodes, d)) {
                                graph.selectedNodes.push(d);
                            }
                        }
                    });

                    dispatch(selectNodes({nodes: graph.selectedNodes}));
                    return;
                }

                var subject = this.simulation.find(x, y, 20);
                if (subject === undefined) {
                    graph.tooltip = null;
                } else {
                    graph.tooltip = {node: subject, x: x, y: y};
                    this.onmousemove(subject);
                }
            },
            dragstarted: function () {
                this.graph.selection = null;
                this.graph.tooltip = null;

                var x = d3.event.x,
                    y = d3.event.y;

                if (!d3.event.active) this.simulation.alphaTarget(0.3).restart();
                d3.event.subject.fx = x;
                d3.event.subject.fy = y;
            },
            dragged: function () {
                var x = d3.event.x,
                    y = d3.event.y;

                d3.event.subject.fx = (x);
                d3.event.subject.fy = (y);
            },
            dragended: function () {
                if (!d3.event.active) this.simulation.alphaTarget(0);
                d3.event.subject.fx = null;
                d3.event.subject.fy = null;
            },
            dragsubject: function () {
                const x = this.graph.transform.invertX(d3.event.x),
                    y = this.graph.transform.invertY(d3.event.y);

                return this.simulation.find(x, y, 20);
            },
            mousemoved: function () {
            }
        };
    }

    componentDidMount() {
        const { network } = this;
        const { dispatch } = this.props;

        network.dispatch = dispatch;
        network.onmouseclick = this.onMouseClick.bind(this);
        network.onmousemove = this.onMouseMove.bind(this);

        network.setup(this.refs["canvas"]);
    }

    onMouseClick(node) {
        const { dispatch } = this.props;
        dispatch(selectNode({node: node}));
    }

    onMouseMove(node) {
        //const { dispatch } = this.props;
        //dispatch(selectNode({node: node}));
    }

    onMouseOver(node) {
        //const { dispatch } = this.props;
        //dispatch(selectNode({node: node}));
    }

    componentWillReceiveProps(nextProps) {
    }

    componentDidUpdate(prevProps, prevState) {
        const { network } = this;
        const { queries } = this.props;

        network.graph.queries = queries;

        var { fields } = this.props;

        var nodes = [];
        var links = [];

        var removed = difference(prevProps.items, this.props.items);
        if (removed.length > 0) {
            var removed2 = [];
            forEach(removed, (d, i) => {
                forEach(fields, (field) => {
                    const value = fieldLocator(d.fields, field);

                    if (value) {
                        removed2.push(value);
                    }

                });
            });

            // this should be node id not packet
            network.removeNodes({
                nodes: removed2,
            });
        }

        if (this.props.items.length > 0) {
            forEach(this.props.items, (d, i) => {
                forEach(fields, (field) => {
                    const value = fieldLocator(d.fields, field);
                    if (!value) return;

                    nodes.push({
                        id: phone(value),
                        query: d.q,
                        name: value,
                        color: d.color,
                        connections: 1
                    });
                });

                forEach(fields, (source) => {
                    const sourceValue = fieldLocator(d.fields, source);
                    if (!sourceValue) return;

                    forEach(fields, (target) => {
                        const targetValue = fieldLocator(d.fields, target);
                        if (!targetValue) return;

                        links.push({
                            source: phone(sourceValue),
                            target: phone(targetValue),
                        });
                    });
                });
            });

            network.addNodes({
                nodes: nodes,
                links: links,
            });
        }
        network.select(this.props.node);
        network.highlight(this.props.highlight_nodes);
    }

    shouldComponentUpdate(){
        return true;
    }

    render() {
        const { containerHeight, containerWidth } = this.props;

        return (
            <canvas
                style={{fontFamily: 'fontAwesome'}}
                width={containerWidth}
                height={containerHeight}
                ref="canvas">
                histogram
            </canvas>
        );
    }
}

const select = (state, ownProps) => {
    return {
        ...ownProps,
        node: state.entries.node,
        queries: state.entries.searches,
        fields: state.entries.fields,
        items: state.entries.items,
        highlight_nodes: state.entries.highlight_nodes,
    }
}

export default connect(select)(Dimensions()(Graph));<|endoftext|>


<commit_before>Array.prototype.each = function( callback ) {
    var context = this;
    for( var i = 0; i < context.length; i++ ) {
        callback( context[ i ] );
    }
}
Array.prototype.map = function( filter ) {
    var context = this,
        retVal  = [];
    for( var i = 0; i < context.length; i++ ) {
        var element   = context[ i ],
            filtered  = filter( element );
        retVal.push( filtered );
    }
    return retVal;
}
Array.prototype.sort = function() {
    var context = this;
    var swap = function( items, firstIndex, secondIndex ){
        var temp = items[ firstIndex ];
        items[ firstIndex ] = items[ secondIndex ];
        items[ secondIndex ] = temp;
    }
    var partition = function( items, left, right ) {
        var pivot   = items[ Math.floor( ( right + left ) / 2 ) ],
            i       = left,
            j       = right;
        while ( i <= j ) {
            while ( items[ i ] < pivot ) {
                i++;
            }
            while ( items[ j ] > pivot ) {
                j--;
            }
            if ( i <= j ) {
                swap( items, i, j );
                i++;
                j--;
            }
        }
        return i;
    }
    var quickSort = function( items, left, right ) {
        var index;
        if (items.length > 1) {
            left = typeof left != "number" ? 0 : left;
            right = typeof right != "number" ? items.length - 1 : right;
            index = partition( items, left, right );
            if ( left < index - 1 ) {
                quickSort( items, left, index - 1 );
            }
            if ( index < right ) {
                quickSort( items, index, right );
            }
        }
        return items;
    }
    return quickSort( context );
}
Array.prototype.indexOf = function( item, isSorted ) {
    var binarySearch = function( array, item ) {
        var left  = 0,
    		right = array.length - 1,
    		mid,
    		element;
    	while( left <= right ) {
    		mid = Math.floor( ( left + right ) / 2, 10 );
    		element = array[ mid ];
    		if ( element < item  ) {
    			left = mid + 1;
    		} else if (element > item ) {
    			right = mid - 1;
    		} else {
    			return mid;
    		}
    	}
    	return -1;
    }
    return ( isSorted ) ? binarySearch( this, item ) : binarySearch( Array.prototype.sort.call( this ), item );
}
Array.prototype.first = function( numberOfElements ) {
    if ( !numberOfElements ){
        return this[ 0 ];
    } else {
        var count = ( numberOfElements == this.length ) ? numberOfElements - 1 : numberOfElements,
            ret   = [];
        for( var i = 0; i < count; i++) {
            ret.push( this[ i ] );
        }
        return ret;
    }
}
Array.prototype.last = function( numberOfElements ) {
    if ( !numberOfElements ){
        return this[ this.length - 1 ];
    } else {
        var count = ( numberOfElements == this.length ) ? numberOfElements - 1 : numberOfElements,
            ret   = [];
        for( var i = this.length - numberOfElements; i < this.length; i++) {
            ret.push( this[ i ] );
        }
        return ret;
    }
}
Array.prototype.flatten = function() {
    var ret = [],
        isArray = function( element ) {
            return Object.prototype.toString.call( element ) === '[object Array]';
        },
        flat = function( element ) {
            for( var i = 0; i < element.length; i++ ) {
                var currentElement = element[ i ];
                if ( isArray( currentElement ) ) {
                    flat( currentElement );
                } else {
                    ret.push( currentElement );
                }
            }
        };
    for( var i = 0; i < this.length; i++ ) {
        var currentElement = this[ i ];
        if ( isArray( currentElement ) ) {
            flat( currentElement );
        } else {
            ret.push( currentElement );
        }
    }
    return ret;
}
Array.prototype.clean = function() {
    var ret = [];
    for( var i = 0; i < this.length; i++ ) {
        var current = this[ i ];
        if ( current === false ||
             current === 0 ||
             current === "" ||
             current === null ||
             current === undefined ||
             isNaN( current ) ) {
             continue;
         } else { ret.push( current ); }
    }
    return ret;
}
Array.prototype.exists = function( element ) {
    return Array.prototype.indexOf.call( this, element ) > -1;
}
Array.prototype.union = function( secondArray ) {
    var ret     = this;
    for( var i = 0; i < secondArray.length; i++ ) {
        var current = secondArray[ i ];
        if( !ret.exists( current ) ){ ret.push( current ); }
    }
    return ret;
}
Array.prototype.intersect = function( secondArray ) {
    var ret = [];
    for( var i = 0; i < this.length; i++ ) {
         var current = this[ i ];
         for( var j = 0; j < secondArray.length; j++ ) {
             var c = secondArray[ j ];
             if ( c === current ) {
                 ret.push( c );
             }
         }
    }
    return ret;
}
Array.prototype.atRandom = function( length ) {
    var getRandom = function( start, end ) {
        return ( Math.floor( Math.random() * ( start - end + 1 ) + end ) );
    }
    if ( !length ) {
        return this[ getRandom( 0, this.length - 1 ) ];
    } else {
        var ret = [];
        for( var i = 0; i < length; i++ ) {
            ret.push( this[ getRandom( 0, this.length - 1 ) ] );
        }
        return ret;
    }
}

var Extendere = {
        goBack: function() {
        this.goBackToDepth( -1 );
    },
        goBackToDepth: function( depth ) {
        if ( !( history || false ) ) {
            console.log( "Extendere.js ERROR: The current browser does not support the 'history' object." );
            return;
        }
        history.back( depth );
    },
        onDomReady: function( callback ) {
        document.addEventListener('DOMContentLoaded', function() {
            callback();
        });
    }
}

var ExtendereMath = {
    E: 2.718281828459045,
    LN2: 0.6931471805599453,
    LN10: 2.302585092994046,
    LOG2E: 1.4426950408889634,
    LOG10E: 0.4342944819032518,
    PI: 3.141592653589793,
    SQRT1_2: 0.7071067811865476,
    SQRT2: 1.4142135623730951,
    abs: function( num ) {
        return ( num < 0 ) ? -num : num;
    },
    staticObject: window.Math || Math,
    exposeMath: function() {
        this.staticObject = window.Math || Math;
        window.math = math = ExtendereMath;
    },
    round: function( val, figures ) {
        figures = ( !figures ) ? 2 : figures;
        return Number( Math.round( val + 'e' + figures ) + 'e-' + figures );
    },
    toRadians: function( degrees, round ) {
        return this.round( ( Math.PI / 180 ) * degrees, round ) ;
    },
    toDegrees: function( radians, round ) {
        return this.round( ( 180 / Math.PI ) * radians, round ) ;
    }
};
ExtendereMath.exposeMath();

Object.prototype.allKeys = function() {
    return Object.keys( this );
}
Object.prototype.allValues = function() {
    var keys = Object.prototype.allKeys.call( this ),
        ret  = [];
    for( var i = 0; i < keys.length; i++ ) {
        ret.push( this[ keys[ i ] ] );
    }
    return ret;
}
Object.prototype.mapObject = function( filter ) {
    var keys   = Object.prototype.allKeys.call( this ),
        values = Object.prototype.allValues.call( this ),
        ret    = "";
    for( var i = 0; i < values.length; i++ ) {
        var key = keys[ i ],
            val = filter( key, values[ i ] ),
            escape = ( !( typeof val === "number" ) ) ? "\"" : "";
        ret += "\"" + key + "\"" + ":" + escape + val + escape + ",";
    }
    ret = ret.substring( 0, ret.length - 1 );
    ret = eval ( "({" + ret + "})" );
    return ret;
}
Object.prototype.extract = function() {
    var ret    = [],
        keys   = Object.prototype.allKeys.call( this ),
        values = Object.prototype.allValues.call( this );
    for( var i = 0; i < keys.length; i++ ) {
        var key = keys[ i ],
            val = values[ i ];
        var arr = [];
        arr.push( key );
        arr.push( val );
        ret.push( arr );
    }
    return ret;
}
Object.prototype.invert = function() {
    var keys   = Object.prototype.allKeys.call( this ),
        values = Object.prototype.allValues.call( this ),
        ret    = "";
    for( var i = 0; i < values.length; i++ ) {
        var key = keys[ i ],
            val = values[ i ];
        ret +=  val + ":\"" + key  + "\",";
    }
    ret = ret.substring( 0, ret.length - 1 );
    ret = eval ( "({" + ret + "})" );
    return ret;
}
Object.prototype.merge = function( secondObject ) {
    var keysOne   = Object.prototype.allKeys.call( this ),
        valuesOne = Object.prototype.allValues.call( this ),
        keysTwo   = Object.prototype.allKeys.call( secondObject ),
        valuesTwo = Object.prototype.allValues.call( secondObject ),
        ret       = "";
    for( var i = 0; i < valuesOne.length; i++ ) {
        var key = keysOne[ i ],
            val = valuesOne[ i ];
        if( keysTwo.exists( key ) ) { continue; }
        ret +=  val + ":\"" + key  + "\",";
    }
    for( var i = 0; i < valuesTwo.length; i++ ) {
        var key = keysTwo[ i ],
            val = valuesTwo[ i ];
        ret +=  val + ":\"" + key + "\",";
    }
    ret = ret.substring( 0, ret.length - 1 );
    ret = eval ( "({" + ret + "})" );
    return ret;
}
<commit_msg>fixed the jamup<commit_after>Array.prototype.each = function( callback ) {
    var context = this;
    for( var i = 0; i < context.length; i++ ) {
        callback( context[ i ] );
    }
}
Array.prototype.map = function( filter ) {
    var context = this,
        retVal  = [];
    for( var i = 0; i < context.length; i++ ) {
        var element   = context[ i ],
            filtered  = filter( element );
        retVal.push( filtered );
    }
    return retVal;
}
Array.prototype.sortWith = function( algorithm ) {
    var context = this;
    algorithm = ( algorithm ) || "quicksort";
    switch( algorithm.toLowerCase() ) {
        default:
        case "quicksort":
            var swap = function( items, firstIndex, secondIndex ){
                var temp = items[ firstIndex ];
                items[ firstIndex ] = items[ secondIndex ];
                items[ secondIndex ] = temp;
            }
            var partition = function( items, left, right ) {
                var pivot   = items[ Math.floor( ( right + left ) / 2 ) ],
                    i       = left,
                    j       = right;
                while ( i <= j ) {
                    while ( items[ i ] < pivot ) {
                        i++;
                    }
                    while ( items[ j ] > pivot ) {
                        j--;
                    }
                    if ( i <= j ) {
                        swap( items, i, j );
                        i++;
                        j--;
                    }
                }
                return i;
            }
            var quickSort = function( items, left, right ) {
                var index;
                if (items.length > 1) {
                    left = typeof left != "number" ? 0 : left;
                    right = typeof right != "number" ? items.length - 1 : right;
                    index = partition( items, left, right );
                    if ( left < index - 1 ) {
                        quickSort( items, left, index - 1 );
                    }
                    if ( index < right ) {
                        quickSort( items, index, right );
                    }
                }
                return items;
            }
            return quickSort( context );
            break;
        case "bubblesort":
            var temp,
                arr = context;
            for( var i = 0; i < context.length; i++ ) {
                for( var j = i; j > 0; j-- ) {
                    if( arr[ j ] < arr[ j - 1 ] ) {
                        temp = arr[ j ];
                        arr[ j ] = arr[ j - 1 ];
                        arr[ j - 1 ] = temp;
                    }
                }
            }
            return arr;
            break;
    }
}
Array.prototype.sort = function() {
    return ( Array.prototype.sortWith.call( this ) );
}
Array.prototype.indexOf = function( item, isSorted ) {
    var binarySearch = function( array, item ) {
        var left  = 0,
    		right = array.length - 1,
    		mid,
    		element;
    	while( left <= right ) {
    		mid = Math.floor( ( left + right ) / 2, 10 );
    		element = array[ mid ];
    		if ( element < item  ) {
    			left = mid + 1;
    		} else if (element > item ) {
    			right = mid - 1;
    		} else {
    			return mid;
    		}
    	}
    	return -1;
    }
    return ( isSorted ) ? binarySearch( this, item ) : binarySearch( Array.prototype.sort.call( this ), item );
}
Array.prototype.first = function( numberOfElements ) {
    if ( !numberOfElements ){
        return this[ 0 ];
    } else {
        var count = ( numberOfElements == this.length ) ? numberOfElements - 1 : numberOfElements,
            ret   = [];
        for( var i = 0; i < count; i++) {
            ret.push( this[ i ] );
        }
        return ret;
    }
}
Array.prototype.last = function( numberOfElements ) {
    if ( !numberOfElements ){
        return this[ this.length - 1 ];
    } else {
        var count = ( numberOfElements == this.length ) ? numberOfElements - 1 : numberOfElements,
            ret   = [];
        for( var i = this.length - numberOfElements; i < this.length; i++) {
            ret.push( this[ i ] );
        }
        return ret;
    }
}
Array.prototype.flatten = function() {
    var ret = [],
        flat = function( element ) {
            for( var i = 0; i < element.length; i++ ) {
                var currentElement = element[ i ];
                if ( Array.prototype.isArray.call( this, currentElement ) ) {
                    flat( currentElement );
                } else {
                    ret.push( currentElement );
                }
            }
        };
    for( var i = 0; i < this.length; i++ ) {
        var currentElement = this[ i ];
        if ( Array.prototype.isArray.call( this, currentElement ) ) {
            flat( currentElement );
        } else {
            ret.push( currentElement );
        }
    }
    return ret;
}
Array.prototype.clean = function() {
    var ret = [];
    for( var i = 0; i < this.length; i++ ) {
        var current = this[ i ];
        if ( current === false ||
             current === 0 ||
             current === "" ||
             current === null ||
             current === undefined ||
             isNaN( current ) ) {
             continue;
         } else { ret.push( current ); }
    }
    return ret;
}
Array.prototype.exists = function( element ) {
    return Array.prototype.indexOf.call( this, element ) > -1;
}
Array.prototype.union = function( secondArray ) {
    var ret     = this;
    for( var j = 0; j < arguments.length; j++ ) {
        var arr = arguments[ j ];
        for( var i = 0; i < arr.length; i++ ) {
            var current = arr[ i ];
            if( !ret.exists( current ) ){ ret.push( current ); }
        }
    }
    return ret;
}
Array.prototype.intersect = function( secondArray ) {
    var ret = [],
        arr = [];
    for( var i = 0; i < arguments.length; i++ ) {
        var current = arguments[ i ];
        if( Array.prototype.isArray.call( this, current ) ) {
            arr.push( current );
        }
    }
    var arx = arr.flatten().removeDuplicates();
    for( var i = 0; i < this.length; i++ ) {
        var current = this[ i ];
        if( Array.prototype.exists.call( arx, this[ i ] ) ) { ret.push( current ); }
    }
    return ret;
}
Array.prototype.removeDuplicates = function() {
    var ret = [];
outer:  for( var i = 0; i < this.length; i++ ) {
        for( var j = ( i + 1 ); j < this.length; j++ ) {
            if ( ( this[ i ] === this[ j ] ) ) { continue outer; }
        }
        ret.push( this[ i ] );
    }
    return ret;
}
Array.prototype.atRandom = function( length ) {
    var getRandom = function( start, end ) {
        return ( Math.floor( Math.random() * ( start - end + 1 ) + end ) );
    }
    if ( !length ) {
        return this[ getRandom( 0, this.length - 1 ) ];
    } else {
        var ret = [];
        for( var i = 0; i < length; i++ ) {
            ret.push( this[ getRandom( 0, this.length - 1 ) ] );
        }
        return ret;
    }
}
Array.prototype.isArray = function( arr ) {
    return( Object.prototype.toString.call( arr ) === '[object Array]' );
}

var ExtendereMath = {
    E: 2.718281828459045,
    LN2: 0.6931471805599453,
    LN10: 2.302585092994046,
    LOG2E: 1.4426950408889634,
    LOG10E: 0.4342944819032518,
    PI: 3.141592653589793,
    SQRT1_2: 0.7071067811865476,
    SQRT2: 1.4142135623730951,
    abs: function( num ) {
        return ( num < 0 ) ? -num : num;
    },
    staticObject: window.Math || Math,
    exposeMath: function() {
        this.staticObject = window.Math || Math;
        window.math = math = ExtendereMath;
    },
    round: function( val, figures ) {
        figures = ( !figures ) ? 2 : figures;
        return Number( Math.round( val + 'e' + figures ) + 'e-' + figures );
    },
    toRadians: function( degrees, round ) {
        return this.round( ( Math.PI / 180 ) * degrees, round ) ;
    },
    toDegrees: function( radians, round ) {
        return this.round( ( 180 / Math.PI ) * radians, round ) ;
    }
};
ExtendereMath.exposeMath();

Object.prototype.allKeys = function() {
    return Object.keys( this );
}
Object.prototype.allValues = function() {
    var keys = Object.prototype.allKeys.call( this ),
        ret  = [];
    for( var i = 0; i < keys.length; i++ ) {
        ret.push( this[ keys[ i ] ] );
    }
    return ret;
}
Object.prototype.mapObject = function( filter ) {
    var keys   = Object.prototype.allKeys.call( this ),
        values = Object.prototype.allValues.call( this ),
        ret    = "";
    for( var i = 0; i < values.length; i++ ) {
        var key = keys[ i ],
            val = filter( key, values[ i ] ),
            escape = ( !( typeof val === "number" ) ) ? "\"" : "";
        ret += "\"" + key + "\"" + ":" + escape + val + escape + ",";
    }
    ret = ret.substring( 0, ret.length - 1 );
    ret = eval ( "({" + ret + "})" );
    return ret;
}
Object.prototype.extract = function() {
    var ret    = [],
        keys   = Object.prototype.allKeys.call( this ),
        values = Object.prototype.allValues.call( this );
    for( var i = 0; i < keys.length; i++ ) {
        var key = keys[ i ],
            val = values[ i ];
        var arr = [];
        arr.push( key );
        arr.push( val );
        ret.push( arr );
    }
    return ret;
}
Object.prototype.invert = function() {
    var keys   = Object.prototype.allKeys.call( this ),
        values = Object.prototype.allValues.call( this ),
        ret    = "";
    for( var i = 0; i < values.length; i++ ) {
        var key = keys[ i ],
            val = values[ i ];
        ret +=  val + ":\"" + key  + "\",";
    }
    ret = ret.substring( 0, ret.length - 1 );
    ret = eval ( "({" + ret + "})" );
    return ret;
}
Object.prototype.merge = function( secondObject ) {
    var keysOne   = Object.prototype.allKeys.call( this ),
        valuesOne = Object.prototype.allValues.call( this ),
        keysTwo   = Object.prototype.allKeys.call( secondObject ),
        valuesTwo = Object.prototype.allValues.call( secondObject ),
        ret       = "";
    for( var i = 0; i < valuesOne.length; i++ ) {
        var key = keysOne[ i ],
            val = valuesOne[ i ];
        if( keysTwo.exists( key ) ) { continue; }
        ret +=  val + ":\"" + key  + "\",";
    }
    for( var i = 0; i < valuesTwo.length; i++ ) {
        var key = keysTwo[ i ],
            val = valuesTwo[ i ];
        ret +=  val + ":\"" + key + "\",";
    }
    ret = ret.substring( 0, ret.length - 1 );
    ret = eval ( "({" + ret + "})" );
    return ret;
}

window.goBack = function() {
    this.goBackToDepth( -1 );
}
window.goBackToDepth = function( depth ) {
    if ( !( history || false ) ) {
        console.log( "Extendere.js ERROR: The current browser does not support the 'history' object." );
        return;
    }
    history.back( depth );
}
window.onDomReady = function( callback ) {
    document.addEventListener('DOMContentLoaded', function() {
        callback();
    });
}
window.getReferrer = function() {
    return ( document.referrer );
}
window.wasReferredFrom = function( referredFrom ) {
    return ( document.referrer === referredFrom );
}
window.isValidUri = function( uri ) {
    return /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test( uri );
}
<|endoftext|>


<commit_before>((window, document, $, Promise, toastr, Chart, randomColor, Color, moment, _, App) => {
  /* Charts */
  let cfdChart;

  /* Elements */
  let reportForm;
  let projectSelect;
  let columnsSelect;
  let fromDate;
  let toDate;
  let loadButton;
  let cfdCanvas;
  let leadTimeCanvas;
  let wipCanvas;

  const disableControls = () => {
    projectSelect.attr('disabled', 'disabled');
    columnsSelect.attr('disabled', 'disabled');
    fromDate.attr('disabled', 'disabled');
    toDate.attr('disabled', 'disabled');
    loadButton.attr('disabled', 'disabled');
  };

  const enableControls = () => {
    projectSelect.removeAttr('disabled');
    columnsSelect.removeAttr('disabled');
    fromDate.removeAttr('disabled');
    toDate.removeAttr('disabled');
    loadButton.removeAttr('disabled');
  };

  const populateProjects = (projects) => {
    projectSelect.empty();
    projects.forEach((project) => {
      projectSelect.append($('<option>', {
        text: project.name,
        value: project.id,
      }));
    });
  };

  const populateProjectColumns = (columns) => {
    columnsSelect.empty();
    columns.forEach((column) => {
      columnsSelect.append($('<option>', {
        text: column.name,
        value: column.id,
      }));
    });
  };

  const loadProjectColumns = () => {
    disableControls();

    const project_id = projectSelect.find(':selected').val();

    $.ajax({
      url: App.getBaseUrl(`/api/v1/project/${project_id}/columns`),
      dataType: 'json',
      success: populateProjects,
      complete: enableControls,
    });
  };

  const loadProjects = () => {
    disableControls();

    $.ajax({
      url: App.getBaseUrl('/api/v1/project/'),
      dataType: 'json',
      success: populateProjects,
      complete: enableControls,
    });
  };

  const loadCfd = async (e) => {
    e.preventDefault();

    const query = reportForm.serialize();

    projectSelect.attr('disabled', 'disabled');
    fromDate.attr('disabled', 'disabled');
    toDate.attr('disabled', 'disabled');
    loadButton.attr('disabled', 'disabled');

    try {
      const summaries = await getCfdData(query);

      _.each(summaries, (summary) => {
        _.each(summary.board_moves, (move) => {
          const date = moment.utc(move.when);
          move.day = date.date();
          move.month = date.month() + 1;
          move.year = date.year();
          move.dayOfYear = date.dayOfYear();
          move.millis = date.valueOf();
          move.formatedDate = date.format('DD/MM/YYYY');
          move.column = move.to_column.name;

          delete move.from_column;
          delete move.to_column;
        });

        return _.groupBy(summary.board_moves, 'dayOfYear');
      });

      const labels = _(summaries)
        .map('board_moves')
        .flatten()
        .sortBy('millis')
        .map('formatedDate')
        .uniq()
        .value();

      const datasets = _(summaries)
        .map((summ) => {
          summ.board_moves.forEach((move) => {
            move.issue = summ.issue.number;
          });
          return summ.board_moves;
        })
        .flatten()
        .sortBy('millis')
        .groupBy('column')
        .map((column, key) => {
          column = _.uniqBy(column, column => column.issue + column.formatedDate);
          const color = randomColor();

          let total = 0;
          const data = _.map(labels, (date) => {
            total += _.filter(column, ['formatedDate', date]).length;
            return total;
          });

          return {
            data,
            label: key,
            borderColor: color,
            backgroundColor: Color(color).alpha(0.3).rgbString(),
          }
        })
        .value();

      cfdChart.data = {
        labels,
        datasets,
      };
      cfdChart.update();
    } catch (err) {
      console.error(err);
      toastr.error('An error has occurred');
    } finally {
      projectSelect.removeAttr('disabled');
      fromDate.removeAttr('disabled');
      toDate.removeAttr('disabled');
      loadButton.removeAttr('disabled');
    }
  };

  const getCfdData = (query) => new Promise((resolve, reject) => {
    $.ajax({
      method: 'GET',
      url: App.getBaseUrl(`/api/v1/report/summary?${query}`),
      dataType: 'json',
      success: resolve,
      error: reject,
    });
  });

  const initElements = () => {
    reportForm = $('form#report_form');
    projectSelect = $('select#project_id');
    columnsSelect = $('select#project_columns');
    fromDate = $('input#from_date');
    toDate = $('input#to_date');
    loadButton = $('button#load_report');
    cfdCanvas = $('canvas#cfd');
    leadTimeCanvas = $('canvas#lead_time');
    wipCanvas = $('canvas#wip');
  };

  const initEventHandlers = () => {
    projectSelect.on('change', loadProjectColumns);
    loadButton.on('click', loadCfd);
  };

  const initCharts = () => {
    cfdChart = new Chart(cfdCanvas[0], {
      type: 'line',
      responsive: true,
      scales: {
        xAxes: [{
          scaleLabel: {
            display: true,
            labelString: 'Days',
          },
        }],
        yAxes: [{
          stacked: true,
          scaleLabel: {
            display: true,
            labelString: 'Issues',
          },
        }],
      },
    });
  };

  const init = () => {
    initElements();
    initEventHandlers();
    initCharts();
    loadProjects();
  };

  $(document).ready(init);
})(window, document, jQuery, Promise, toastr, Chart, randomColor, Color, moment, _, App);
<commit_msg>Charts<commit_after>((window, document, $, Promise, toastr, Chart, randomColor, Color, moment, _, App) => {
  /* Charts */
  let cfdChart;

  /* Elements */
  let reportForm;
  let projectSelect;
  let columnsSelect;
  let fromDate;
  let toDate;
  let loadButton;
  let cfdCanvas;
  let leadTimeCanvas;
  let wipCanvas;

  const disableControls = () => {
    projectSelect.attr('disabled', 'disabled');
    columnsSelect.attr('disabled', 'disabled');
    fromDate.attr('disabled', 'disabled');
    toDate.attr('disabled', 'disabled');
    loadButton.attr('disabled', 'disabled');
  };

  const enableControls = () => {
    projectSelect.removeAttr('disabled');
    columnsSelect.removeAttr('disabled');
    fromDate.removeAttr('disabled');
    toDate.removeAttr('disabled');
    loadButton.removeAttr('disabled');
  };

  const populateProjects = (projects) => {
    projectSelect.empty();
    projects.forEach((project) => {
      projectSelect.append($('<option>', {
        text: project.name,
        value: project.id,
      }));
    });
  };

  const populateProjectColumns = (columns) => {
    columnsSelect.empty();
    columns.forEach((column) => {
      columnsSelect.append($('<option>', {
        text: column.name,
        value: column.id,
      }));
    });
  };

  const loadProjectColumns = () => {
    disableControls();

    const project_id = projectSelect.find(':selected').val();

    $.ajax({
      url: App.getBaseUrl(`/api/v1/project/${project_id}/columns`),
      dataType: 'json',
      success: populateProjects,
      complete: enableControls,
    });
  };

  const loadProjects = () => {
    disableControls();

    $.ajax({
      url: App.getBaseUrl('/api/v1/project/'),
      dataType: 'json',
      success: populateProjects,
      complete: enableControls,
    });
  };

  const loadCfd = async (e) => {
    e.preventDefault();

    const query = reportForm.serialize();

    disableControls();

    try {
      const summaries = await getCfdData(query);

      _.each(summaries, (summary) => {
        _.each(summary.board_moves, (move) => {
          const date = moment.utc(move.when);
          move.day = date.date();
          move.month = date.month() + 1;
          move.year = date.year();
          move.dayOfYear = date.dayOfYear();
          move.millis = date.valueOf();
          move.formatedDate = date.format('DD/MM/YYYY');
          move.column = move.to_column.name;

          delete move.from_column;
          delete move.to_column;
        });

        return _.groupBy(summary.board_moves, 'dayOfYear');
      });

      const labels = _(summaries)
        .map('board_moves')
        .flatten()
        .sortBy('millis')
        .map('formatedDate')
        .uniq()
        .value();

      const datasets = _(summaries)
        .map((summ) => {
          summ.board_moves.forEach((move) => {
            move.issue = summ.issue.number;
          });
          return summ.board_moves;
        })
        .flatten()
        .sortBy('millis')
        .groupBy('column')
        .map((column, key) => {
          column = _.uniqBy(column, column => column.issue + column.formatedDate);
          const color = randomColor();

          let total = 0;
          const data = _.map(labels, (date) => {
            total += _.filter(column, ['formatedDate', date]).length;
            return total;
          });

          return {
            data,
            label: key,
            borderColor: color,
            backgroundColor: Color(color).alpha(0.3).rgbString(),
          }
        })
        .value();

      cfdChart.data = {
        labels,
        datasets,
      };
      cfdChart.update();
    } catch (err) {
      console.error(err);
      toastr.error('An error has occurred');
    } finally {
      enableControls();
    }
  };

  const getCfdData = (query) => new Promise((resolve, reject) => {
    $.ajax({
      method: 'GET',
      url: App.getBaseUrl(`/api/v1/report/summary?${query}`),
      dataType: 'json',
      success: resolve,
      error: reject,
    });
  });

  const initElements = () => {
    reportForm = $('form#report_form');
    projectSelect = $('select#project_id');
    columnsSelect = $('select#project_columns');
    fromDate = $('input#from_date');
    toDate = $('input#to_date');
    loadButton = $('button#load_report');
    cfdCanvas = $('canvas#cfd');
    leadTimeCanvas = $('canvas#lead_time');
    wipCanvas = $('canvas#wip');
  };

  const initEventHandlers = () => {
    projectSelect.on('change', loadProjectColumns);
    loadButton.on('click', loadCfd);
  };

  const initCharts = () => {
    cfdChart = new Chart(cfdCanvas[0], {
      type: 'line',
      responsive: true,
      scales: {
        xAxes: [{
          scaleLabel: {
            display: true,
            labelString: 'Days',
          },
        }],
        yAxes: [{
          stacked: true,
          scaleLabel: {
            display: true,
            labelString: 'Issues',
          },
        }],
      },
    });
  };

  const init = () => {
    initElements();
    initEventHandlers();
    initCharts();
    loadProjects();
  };

  $(document).ready(init);
})(window, document, jQuery, Promise, toastr, Chart, randomColor, Color, moment, _, App);
<|endoftext|>