<commit_before>/** MIT License (c) copyright B Cavalier & J Hann */

/**
 * curl css! plugin
 *
 * Licensed under the MIT License at:
 * 		http://www.opensource.org/licenses/mit-license.php
 *
 */

(function (global) {
"use strict";

/*
 * AMD css! plugin
 * This plugin will load and wait for css files.  This could be handy when
 * loading css files as part of a layer or as a way to apply a run-time theme.
 * Some browsers do not support the load event handler of the link element.
 * Therefore, we have to use other means to detect when a css file loads.
 * Some browsers don't support the error event handler, either.
 * The HTML5 spec states that the LINK element should have both load and
 * error events:
 * http://www.w3.org/TR/html5/semantics.html#the-link-element
 *
 * This plugin tries to use the load event and a universal work-around when
 * it is invoked the first time.  If the load event works, it is used on
 * every successive load.  Therefore, browsers that support the load event will
 * just work (i.e. no need for hacks!).  FYI, Feature-detecting the load
 * event is tricky since most browsers have a non-functional onload property.
 *
 * The universal work-around watches a stylesheet until its rules are
 * available (not null or undefined).  There are nuances, of course, between
 * the various browsers.  The isLinkReady function accounts for these.
 *
 * Note: it appears that all browsers load @import'ed stylesheets before
 * fully processing the rest of the importing stylesheet. Therefore, we
 * don't need to find and wait for any @import rules explicitly.
 *
 * Global configuration options:
 *
 * cssDeferLoad: Boolean. You can also instruct this plugin to not wait
 * for any css resources. They'll get loaded asap, but other code won't wait
 * for them. This is just like using the !nowait option on every css file.
 *
 * cssWatchPeriod: if direct load-detection techniques fail, this option
 * determines the msec to wait between brute-force checks for rules. The
 * default is 50 msec.
 *
 * You may specify an alternate file extension:
 *      require('css!myproj/component.less') // --> myproj/component.less
 *      require('css!myproj/component.scss') // --> myproj/component.scss
 *
 * When using alternative file extensions, be sure to serve the files from
 * the server with the correct mime type (text/css) or some browsers won't
 * parse them, causing an error in the plugin.
 *
 * usage:
 *      require(['css!myproj/comp']); // load and wait for myproj/comp.css
 *      define(['css!some/folder/file'], {}); // wait for some/folder/file.css
 *      require(['css!myWidget!nowait']);
 *
 * Tested in:
 *      Firefox 3.6, 4.0, 11
 *      Safari 3.0.4, 3.2.1, 5.0
 *      Chrome 19
 *      Opera 11.62
 *      IE 6, 7, 8, and 9
*/

	var
		// compressibility shortcuts
		createElement = 'createElement',
		// doc will be undefined during a build
		doc = global.document,
		// find the head element and set it to it's standard property if nec.
		head,
		collectSheets,
		failIfBlankSheet,
		collectorSheet = doc && !!doc.createStyleSheet,
		hasEvent = { links: {} };

	if (doc) {
		head = doc.head || (doc.head = doc.getElementsByTagName('head')[0]);
		// 'about:blank' returns a valid stylesheet (blank)
		testLinkEvent('load', 'about:blank');
		// this test doesn't work in FF<=13 (and maybe future versions)
		testLinkEvent('error', 'about:_curl_bogus');
		// FF and Chrome correctly detect on this one, but Safari screams loudly (in Net tab)
		//testLinkEvent('error', 'javascript:');
		// FF and chrome also correctly fail here, but Safari screams loudly (in Net tab)
		//testLinkEvent('error', 'data:text/css;base64,_');
		// FF correctly fails here and Safari doesn't scream, yay:
		testLinkEvent('error', 'data:text/text,');
		// detect IE false positives (fires onload instead of onerror)
		testLinkEvent('load', 'about:_curl_bogus', 'false-load');
	}

	function testLinkEvent (event, page, name) {
		var link;
		name = name || event;
		link = hasEvent.links[name] = createLink(false);
		link['on' + event] = function () { setLoadDetection(event, true, name); };
		link.href = page;
		head.appendChild(link);
		setTimeout(function () { head.removeChild(link); }, 50);
	}

	function setLoadDetection (event, hasNative, name) {
		name = name || event;
		// TODO: cancel in-flight detection routines (how?)
		hasEvent[name] = hasEvent[name] || hasNative;
	}

	// TODO: how about we just move sheets to collector as soon as they're loaded? -> hm. debugging @imports sucks so we should try to keep them as links?
	function createLink (collectSheets) {
		var link;
		// TODO: detect if we need to avoid 31-sheet limit in IE
		if (collectSheets) {
			if (!collectorSheet) {
				collectorSheet = document.createStyleSheet();
			}
			if (doc.styleSheets.length >= 30) {
				moveLinksToCollector();
			}
		}
		link = doc[createElement]('link');
		link.rel = "stylesheet";
		link.type = "text/css";
		if (collectSheets) link['_curl_movable'] = true;
		return link;
	}

	function moveLinksToCollector () {
		// IE 6-8 fail when there are 31 sheets, so we collect them.
		// Note: this hack relies on proper cache headers.
		var link, links, collector, pos = 0;
		collector = collectorSheet;
		collectorSheet = null; // so a new one will be created
		links = document.getElementsByTagName('link');
		while ((link = links[pos])) {
			if (link['_curl_movable']) {
				// move to the collector (note: bad cache directive
				// will cause a re-download)
				collector.addImport(link.href);
				// remove from document
				if (link.parentNode) link.parentNode.removeChild(link);
			}
			else {
				// skip this sheet
				pos++;
			}
		}
	}

	/***** load-detection functions *****/

	function loadHandler (link, cb) {
		link.onload = function () {
			// we know this works now!
			setLoadDetection('load', true);
			if (hasEvent['false-load'] && failIfBlankSheet) {
				// TODO: if this could be a false positive, figure out how to determine this without causing another HTTP fetch
				// how to do this for xdomain? same-domain is easy: look for rules.length > 0
			}
			cb();
		};
	}

	function errorHandler (link, cb) {
		link.onerror = function () {
			// we know this works now!
			setLoadDetection('error', true);
			cb();
		};
	}

	function isLinkReady (link) {
		var ready, sheet, rules;
		// don't bother testing until we've fully initialized the link;
		if (!link.href) return false;

		ready = false;

		try {
			// no need to check for IE's link.styleSheet cuz IE has native onload
			sheet = link.sheet;
			if (sheet) {
				// FF will throw a security exception here when an XD
				// sheet is loaded. webkits (that don't support onload)
				// will return null when an XD sheet is loaded
				rules = sheet.cssRules;
				ready = rules === null;
				// TODO: remove browser sniff cuz it's probably not needed
				if (!ready && 'length' in rules && !window.chrome) {
					// Opera needs to further test for rule manipulation
					sheet.insertRule('-curl-css-test {}', 0);
					sheet.deleteRule(0);
					ready = true;
					setLoadDetection('load', false);
				}
			}
		}
		catch (ex) {
			// a "security" or "access denied" error indicates that an XD
			// stylesheet has been successfully loaded!
			ready = /security|denied/i.test(ex.message);
			setLoadDetection('load', false);
		}

		return ready;
	}

	function finalize (link) {
		// noop serves as a flag that a link event fired
		// note: Opera and IE won't clear handlers if we use a non-function
		link.onload = link.onerror = noop;
	}

	function isFinalized (link) {
		return link.onload == noop;
	}

	function ssWatcher (link, wait, cb) {
		// watches a stylesheet for loading signs.
		if (hasEvent['load']) return; // always check on re-entry
		if (isLinkReady(link)) {
			cb();
		}
		else if (!isFinalized(link)) {
			setTimeout(function () { ssWatcher(link, wait, cb); }, wait);
		}
	}

	function errorWatcher (link, wait, eb) {
		if (hasEvent['error']) return;
		// for browsers that don't call onerror after an http error:
		// we wait (at least) 500 msec before trying again with an image
		// element. the image element's onerror handler
		// will fire when the browser has determined if the href is valid
		// or not (20X or 40X/50X).  however, we can't know if it's a 20X
		// or something else, so we delay just a bit longer to see if
		// the sheet loaded. this will cause another fetch, but we don't
		// have any other options for dumbass browsers.
		setTimeout(function () {
			var img;
			if (hasEvent['error'] || isFinalized(link)) return;
			// Note: can't use `new Image()` in webkit browsers
			// (it doesn't seem to fire events)
			img = document[createElement]('img');
			img.onerror = img.onload = function () {
				setTimeout(function () {
					if (!hasEvent['error'] && !isFinalized(link)) eb();
				}, 10); // a wee bit more time to process sheet
			};
console.log(link.href, 'launched counter strike')
			img.src = link.href;
		}, wait);
	}

	function loadDetector (link, wait, cb) {
		// most browsers now support link.onload, but many older browsers
		// don't. Browsers that don't will launch the ssWatcher to repeatedly
		// test the link for readiness.
		function load () {
			// only executes once (link.onload is acting as a flag)
			if (isFinalized(link)) return;
			finalize(link);
			waitForDocumentComplete(cb);
		}
		// always try standard handler
		loadHandler(link, load);
		// also try the fallback
		ssWatcher(link, wait, load);
	}

	function errorDetector (link, cb) {
		var h;
		// very few browsers (Chrome 19+ and FF9+ as of Apr 2012) have a
		// functional onerror handler (and those only detect 40X/50X http
		// errors, not parsing errors as per the w3c spec).
		// IE6-9 call onload when there's an http error, but I can't seem
		// to find a way to detect the error, yet.
		function error () {
			clearTimeout(h);
			// only executes once (link.onload is acting as a flag)
			if (isFinalized(link)) return;
			finalize(link);
			cb(new Error('HTTP or network error.'));
		}
		// always try standard handler
		errorHandler(link, error);
		// if we are not sure if the native error event works, try the fallback
		errorWatcher(link, 500, error);
	}

	function waitForDocumentComplete (cb) {
		// this isn't exactly the same as domReady (when dom can be
		// manipulated). it's later (when styles are applied).
		// chrome needs this (and opera?)
		function complete () {
			if (!doc.readyState || doc.readyState == 'complete') {
				cb();
			}
			else {
				setTimeout(complete, 10);
			}
		}
		complete();
	}

	function nameWithExt (name, defaultExt) {
		return name.lastIndexOf('.') <= name.lastIndexOf('/') ?
			name + '.' + defaultExt : name;
	}

	function noop () {}

	/***** finally! the actual plugin *****/

	define(/*=='css',==*/ {

		'normalize': function (resourceId, normalize) {
			var resources, normalized;

			if (!resourceId) return resourceId;

			resources = resourceId.split(",");
			normalized = [];

			for (var i = 0, len = resources.length; i < len; i++) {
				normalized.push(normalize(resources[i]));
			}

			return normalized.join(',');
		},

		'load': function (resourceId, require, callback, config) {
			var resources = (resourceId || '').split(","),
				loadingCount = resources.length,
				i;

			// all detector functions must ensure that this function only gets
			// called once per stylesheet!
			function loaded () {
				if (--loadingCount == 0) {
					callback();
				}
			}

			function failed (ex) {
				var eb;
				eb = callback.reject || function (ex) { throw ex; };
				eb(ex);
			}

			// `after` will become truthy once the loop executes a second time
			for (i = 0; i < resources.length; i++) {

				resourceId = resources[i];

				var
					url = require['toUrl'](nameWithExt(resourceId, 'css')),
					link = createLink(),
					nowait = !!config['cssDeferLoad'],
					wait = config['cssWatchPeriod'] || 50;

				if (nowait) {
					callback();
				}
				else {
					// hook up load detector(s)
					loadDetector(link, wait, loaded);
					// hook up error detector(s)
					errorDetector(link, failed);
				}

				// go!
				link.href = url;
console.log(link.href, 'go!');
				head.appendChild(link);
			}

		},

		'plugin-builder': './builder/css',
		'pluginBuilder': './builder/css'

	});

})(this);
<commit_msg>more compressible and removed some gunk<commit_after>/** MIT License (c) copyright B Cavalier & J Hann */

/**
 * curl css! plugin
 *
 * Licensed under the MIT License at:
 * 		http://www.opensource.org/licenses/mit-license.php
 *
 */

(function (global) {
"use strict";

/*
 * AMD css! plugin
 * This plugin will load and wait for css files.  This could be handy when
 * loading css files as part of a layer or as a way to apply a run-time theme.
 * Some browsers do not support the load event handler of the link element.
 * Therefore, we have to use other means to detect when a css file loads.
 * Some browsers don't support the error event handler, either.
 * The HTML5 spec states that the LINK element should have both load and
 * error events:
 * http://www.w3.org/TR/html5/semantics.html#the-link-element
 *
 * This plugin tries to use the load event and a universal work-around when
 * it is invoked the first time.  If the load event works, it is used on
 * every successive load.  Therefore, browsers that support the load event will
 * just work (i.e. no need for hacks!).  FYI, Feature-detecting the load
 * event is tricky since most browsers have a non-functional onload property.
 *
 * The universal work-around watches a stylesheet until its rules are
 * available (not null or undefined).  There are nuances, of course, between
 * the various browsers.  The isLinkReady function accounts for these.
 *
 * Note: it appears that all browsers load @import'ed stylesheets before
 * fully processing the rest of the importing stylesheet. Therefore, we
 * don't need to find and wait for any @import rules explicitly.
 *
 * Global configuration options:
 *
 * cssDeferLoad: Boolean. You can also instruct this plugin to not wait
 * for any css resources. They'll get loaded asap, but other code won't wait
 * for them. This is just like using the !nowait option on every css file.
 *
 * cssWatchPeriod: if direct load-detection techniques fail, this option
 * determines the msec to wait between brute-force checks for rules. The
 * default is 50 msec.
 *
 * You may specify an alternate file extension:
 *      require('css!myproj/component.less') // --> myproj/component.less
 *      require('css!myproj/component.scss') // --> myproj/component.scss
 *
 * When using alternative file extensions, be sure to serve the files from
 * the server with the correct mime type (text/css) or some browsers won't
 * parse them, causing an error in the plugin.
 *
 * usage:
 *      require(['css!myproj/comp']); // load and wait for myproj/comp.css
 *      define(['css!some/folder/file'], {}); // wait for some/folder/file.css
 *      require(['css!myWidget!nowait']);
 *
 * Tested in:
 *      Firefox 3.6, 4.0, 11
 *      Safari 3.0.4, 3.2.1, 5.0
 *      Chrome 19
 *      Opera 11.62
 *      IE 6, 7, 8, and 9
*/

	var
		// compressibility shortcuts
		createElement = 'createElement',
		createStyleSheet = 'createStyleSheet',
		parentNode = 'parentNode',
		setTimeout = global.setTimeout,
		goodTestSheet = 'about:blank',
		badTestSheet = 'about:_curl_',
		pluginBuilder = './builder/css',
		// doc will be undefined during a build
		doc = global.document,
		// find the head element and set it to it's standard property if nec.
		head,
		collectSheets,
		failIfBlankSheet,
		// serious inference here:
		collectorSheet = doc && !!doc[createStyleSheet],
		hasEvent = { links: {} };

	if (doc) {
		head = doc.head || (doc.head = doc.getElementsByTagName('head')[0]);
		// the following code attempts to pre-determine if the browser supports
		// onload and onerror event handlers. None of these work in Opera.
		// success: Chrome, FF13, IE6-9
		testLinkEvent('load', goodTestSheet);
		// success: Chrome only
		testLinkEvent('error', badTestSheet);
		// FF and Chrome fire onerror on this one, but Safari and Opera scream loudly (in Net tab)
		//testLinkEvent('error', 'javascript:');
		// FF and chrome also fire onerror here, but Safari and Opera scream loudly (in Net tab)
		//testLinkEvent('error', 'data:text/css;base64,_');
		// FF correctly fails here (protocol error) and Safari doesn't scream, yay:
		testLinkEvent('error', 'data:text/text,');
		// detect IE false positives (IE fires onload instead of onerror)
		testLinkEvent('load', badTestSheet, 'false-load');
	}

	function testLinkEvent (event, page, name) {
		var link;
		name = name || event;
		link = hasEvent.links[name] = createLink(false);
		link['on' + event] = function () { setLoadDetection(event, true, name); };
		link.href = page;
		head.appendChild(link);
		setTimeout(function () { head.removeChild(link); }, 50);
	}

	function setLoadDetection (event, hasNative, name) {
		name = name || event;
		hasEvent[name] = hasEvent[name] || hasNative;
	}

	function createLink (collectSheets) {
		var link;
		if (collectSheets) {
			if (!collectorSheet) {
				collectorSheet = doc[createStyleSheet]();
			}
			if (doc.styleSheets.length >= 30) {
				moveLinksToCollector();
			}
		}
		link = doc[createElement]('link');
		link.rel = "stylesheet";
		link.type = "text/css";
		if (collectSheets) link['_curl_movable'] = true;
		return link;
	}

	function moveLinksToCollector () {
		// IE 6-8 fail when there are 31 sheets, so we collect them.
		// Note: this hack relies on proper cache headers.
		var link, links, collector, pos = 0;
		collector = collectorSheet;
		collectorSheet = null; // so a new one will be created
		links = document.getElementsByTagName('link');
		while ((link = links[pos])) {
			if (link['_curl_movable']) {
				// move to the collector (note: bad cache directive
				// will cause a re-download)
				collector.addImport(link.href);
				// remove from document
				if (link[parentNode]) link[parentNode].removeChild(link);
			}
			else {
				// skip this sheet
				pos++;
			}
		}
	}

	/***** load-detection functions *****/

	function loadHandler (link, cb) {
		link.onload = function () {
			// we know this works now!
			setLoadDetection('load', true);
			if (hasEvent['false-load'] && failIfBlankSheet) {
				// TODO: if this could be a false positive, figure out how to determine this without causing another HTTP fetch
				// how to do this for xdomain? same-domain is easy: look for rules.length > 0
			}
			cb();
		};
	}

	function errorHandler (link, cb) {
		link.onerror = function () {
			// we know this works now!
			setLoadDetection('error', true);
			cb();
		};
	}

	function isLinkReady (link) {
		var ready, sheet, rules;
		// don't bother testing until we've fully initialized the link;
		if (!link.href) return false;

		ready = false;

		try {
			// no need to check for IE's link.styleSheet cuz IE has native onload
			sheet = link.sheet;
			if (sheet) {
				// FF will throw a security exception here when an XD
				// sheet is loaded. webkits (that don't support onload)
				// will return null when an XD sheet is loaded
				rules = sheet.cssRules;
				ready = rules === null;
				if (!ready && 'length' in rules) {
					// Opera needs to further test for rule manipulation
					sheet.insertRule('-curl-css-test {}', 0);
					sheet.deleteRule(0);
					ready = true;
					setLoadDetection('load', false);
				}
			}
		}
		catch (ex) {
			// a "security" or "access denied" error indicates that an XD
			// stylesheet has been successfully loaded!
			ready = /security|denied/i.test(ex.message);
			setLoadDetection('load', false);
		}

		return ready;
	}

	function finalize (link) {
		// noop serves as a flag that a link event fired
		// note: Opera and IE won't clear handlers if we use a non-function
		link.onload = link.onerror = noop;
	}

	function isFinalized (link) {
		return link.onload == noop;
	}

	function ssWatcher (link, wait, cb) {
		// watches a stylesheet for loading signs.
		if (hasEvent['load']) return; // always check on re-entry
		if (isLinkReady(link)) {
			cb();
		}
		else if (!isFinalized(link)) {
			setTimeout(function () { ssWatcher(link, wait, cb); }, wait);
		}
	}

	function errorWatcher (link, wait, eb) {
		if (hasEvent['error']) return;
		// for browsers that don't call onerror after an http error:
		// we wait (at least) 500 msec before trying again with an image
		// element. the image element's onerror handler
		// will fire when the browser has determined if the href is valid
		// or not (20X or 40X/50X).  however, we can't know if it's a 20X
		// or something else, so we delay just a bit longer to see if
		// the sheet loaded. this will cause another fetch, but we don't
		// have any other options for dumbass browsers.
		setTimeout(function () {
			var img;
			if (hasEvent['error'] || isFinalized(link)) return;
			// Note: can't use `new Image()` in webkit browsers
			// (it doesn't seem to fire events)
			img = document[createElement]('img');
			img.onerror = img.onload = function () {
				setTimeout(function () {
					if (!hasEvent['error'] && !isFinalized(link)) eb();
				}, 10); // a wee bit more time to process sheet
			};
			img.src = link.href;
		}, wait);
	}

	function loadDetector (link, wait, cb) {
		// most browsers now support link.onload, but many older browsers
		// don't. Browsers that don't will launch the ssWatcher to repeatedly
		// test the link for readiness.
		function load () {
			// only executes once (link.onload is acting as a flag)
			if (isFinalized(link)) return;
			finalize(link);
			waitForDocumentComplete(cb);
		}
		// always try standard handler
		loadHandler(link, load);
		// also try the fallback
		ssWatcher(link, wait, load);
	}

	function errorDetector (link, cb) {
		var h;
		// very few browsers (Chrome 19+ and FF9+ as of Apr 2012) have a
		// functional onerror handler (and those only detect 40X/50X http
		// errors, not parsing errors as per the w3c spec).
		// IE6-9 call onload when there's an http error, but I can't seem
		// to find a way to detect the error, yet.
		function error () {
			clearTimeout(h);
			// only executes once (link.onload is acting as a flag)
			if (isFinalized(link)) return;
			finalize(link);
			cb(new Error('HTTP or network error.'));
		}
		// always try standard handler
		errorHandler(link, error);
		// if we are not sure if the native error event works, try the fallback
		errorWatcher(link, 500, error);
	}

	function waitForDocumentComplete (cb) {
		// this isn't exactly the same as domReady (when dom can be
		// manipulated). it's later (when styles are applied).
		// chrome needs this (and opera?)
		function complete () {
			if (!doc.readyState || doc.readyState == 'complete') {
				cb();
			}
			else {
				setTimeout(complete, 10);
			}
		}
		complete();
	}

	function nameWithExt (name, defaultExt) {
		return name.lastIndexOf('.') <= name.lastIndexOf('/') ?
			name + '.' + defaultExt : name;
	}

	function noop () {}

	/***** finally! the actual plugin *****/

	define(/*=='css',==*/ {

		'normalize': function (resourceId, normalize) {
			var resources, normalized;

			if (!resourceId) return resourceId;

			resources = resourceId.split(",");
			normalized = [];

			for (var i = 0, len = resources.length; i < len; i++) {
				normalized.push(normalize(resources[i]));
			}

			return normalized.join(',');
		},

		'load': function (resourceId, require, callback, config) {
			var resources = (resourceId || '').split(","),
				loadingCount = resources.length,
				i;

			// all detector functions must ensure that this function only gets
			// called once per stylesheet!
			function loaded () {
				if (--loadingCount == 0) {
					callback();
				}
			}

			function failed (ex) {
				var eb;
				eb = callback.reject || function (ex) { throw ex; };
				eb(ex);
			}

			for (i = 0; i < resources.length; i++) {

				resourceId = resources[i];

				var
					url = require['toUrl'](nameWithExt(resourceId, 'css')),
					link = createLink(),
					nowait = !!config['cssDeferLoad'],
					wait = config['cssWatchPeriod'] || 50;

				if (nowait) {
					callback();
				}
				else {
					// hook up load detector(s)
					loadDetector(link, wait, loaded);
					// hook up error detector(s)
					errorDetector(link, failed);
				}

				// go!
				link.href = url;
				head.appendChild(link);
			}

		},

		'plugin-builder': pluginBuilder,
		'pluginBuilder': pluginBuilder

	});

})(this);
<|endoftext|>


<commit_before>import Transform from '../Transform';
import {inherits} from '../util/Functions';
import {error} from '../util/Errors';
import {id} from '../Tuple';

import {map} from 'd3-collection';

/**
 * Joins a set of data elements against a set of visual items.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): object} params.item - An item generator function.
 * @param {function(object): *} [params.key] - The key field associating data and visual items.
 */
export default function DataJoin(params) {
  Transform.call(this, map(), params);
}

var prototype = inherits(DataJoin, Transform);

prototype.transform = function(_, pulse) {
  var out = pulse.fork(pulse.NO_SOURCE),
      item = _.item,
      key = _.key || id,
      lut = this.value;

  if (_.modified('key') || pulse.modified(key)) {
    // TODO: support re-keying?
    error('DataJoin does not support modified key function or key fields.');
  }

  pulse.visit(pulse.REM, function(t) {
    var k = key(t),
        x = lut.get(k);

    if (x) {
      lut.remove(k);
      out.rem.push(x);
    }
  });

  pulse.visit(pulse.ADD, function(t) {
    var k = key(t),
        x = lut.get(k);

    if (x) {
      out.mod.push(x);
    } else {
      lut.set(k, x = item(t));
      out.add.push(x);
    }
    x.datum = t;
  });

  pulse.visit(pulse.MOD, function(t) {
    var k = key(t),
        x = lut.get(k);

    if (x) {
      out.mod.push(x);
    }
  });
  return out;
};
<commit_msg>Add default item generator for DataJoin.<commit_after>import Transform from '../Transform';
import {inherits} from '../util/Functions';
import {error} from '../util/Errors';
import {id, ingest} from '../Tuple';

import {map} from 'd3-collection';

/**
 * Joins a set of data elements against a set of visual items.
 * @constructor
 * @param {object} params - The parameters for this operator.
 * @param {function(object): object} [params.item] - An item generator function.
 * @param {function(object): *} [params.key] - The key field associating data and visual items.
 */
export default function DataJoin(params) {
  Transform.call(this, map(), params);
}

var prototype = inherits(DataJoin, Transform);

function defaultItemCreate() {
  return ingest({});
}

prototype.transform = function(_, pulse) {
  var out = pulse.fork(pulse.NO_SOURCE),
      item = _.item || defaultItemCreate,
      key = _.key || id,
      lut = this.value;

  if (_.modified('key') || pulse.modified(key)) {
    // TODO: support re-keying?
    error('DataJoin does not support modified key function or key fields.');
  }

  pulse.visit(pulse.REM, function(t) {
    var k = key(t),
        x = lut.get(k);

    if (x) {
      lut.remove(k);
      out.rem.push(x);
    }
  });

  pulse.visit(pulse.ADD, function(t) {
    var k = key(t),
        x = lut.get(k);

    if (x) {
      out.mod.push(x);
    } else {
      lut.set(k, x = item(t));
      out.add.push(x);
    }
    x.datum = t;
  });

  pulse.visit(pulse.MOD, function(t) {
    var k = key(t),
        x = lut.get(k);

    if (x) {
      out.mod.push(x);
    }
  });

  return out;
};
<|endoftext|>


<commit_before>import ItemEditor   from '../../../panels/ItemEditor';
import React        from 'react';

import Workflows    from '../../../workflows';
import client       from '../../../network';

export default React.createClass({

    displayName: 'Simulation/New',

    propTypes: {
        params: React.PropTypes.object,
    },

    contextTypes: {
        router: React.PropTypes.object,
    },

    getInitialState() {
        return {
            project: null,
        };
    },

    componentWillMount() {
        this.updateProject();
    },

    componentWillReceiveProps(nextProps) {
        if (nextProps.params.projectId !== this.props.params.projectId) {
            this.updateProject(nextProps.params.projectId);
        }
    },

    updateProject(id=this.props.params.projectId) {
        client.getProject(id)
            .then(resp => this.setState({project: resp.data, error: false}))
            .catch(err => {
                this.setState({ _error: err.data.message });
                console.log('Error: Sim/New-get', err)
            });
    },

    onAction(action, data, attachements) {
        this[action](data, attachements);
    },

    newSimulation(data, attachements) {
        const { name, description } = data,
            projectId = this.props.params.projectId,
            metadata = {},
            stepsInfo = Workflows[this.state.project.type].steps,
            steps = stepsInfo._initial_state,
            disabled = stepsInfo._disabled || [],
            active = stepsInfo._active || stepsInfo._order[0],
            simulation = { name, description, steps, metadata, projectId, active, disabled };

        client.saveSimulation(simulation)
            .then(resp => {
                var simId = Array.isArray(resp) ? resp[0].data._id : resp.data._id;
                this.context.router.replace('/View/Simulation/' + simId);
            })
            .catch(err => {
                this.setState({ _error: err.data.message });
                console.log('Error: Sim/New-save', err)
            });
    },

    cancel() {
        this.context.router.replace('/View/Project/' + this.props.params.projectId);
    },

    render() {
        if(!this.state.project) {
            return null;
        }

        const type = this.state.project.type;
        const childComponent = type ? Workflows[type].components.NewSimulation : null;
        const workflowAddOn = childComponent ? React.createElement(childComponent, { owner: () => this.refs.container }) : null;
        return (
            <ItemEditor
                breadcrumb={{
                    paths:['/', `/View/Project/${this.state.project._id}`],
                    icons:['fa fa-fw fa-list', 'fa fa-fw fa-folder-open-o'],
                }}
                error={this.state._error}
                ref='container'
                title='New Simulation'
                actions={[
                    {name: 'cancel', label: 'Cancel'},
                    {name: 'newSimulation', label: 'Create simulation'},
                ]}
                onAction={ this.onAction }>

                { workflowAddOn }

            </ItemEditor>);
    },
});
<commit_msg>Fix file upload for simulation<commit_after>import ItemEditor   from '../../../panels/ItemEditor';
import React        from 'react';

import Workflows    from '../../../workflows';
import client       from '../../../network';

export default React.createClass({

    displayName: 'Simulation/New',

    propTypes: {
        params: React.PropTypes.object,
    },

    contextTypes: {
        router: React.PropTypes.object,
    },

    getInitialState() {
        return {
            project: null,
        };
    },

    componentWillMount() {
        this.updateProject();
    },

    componentWillReceiveProps(nextProps) {
        if (nextProps.params.projectId !== this.props.params.projectId) {
            this.updateProject(nextProps.params.projectId);
        }
    },

    updateProject(id=this.props.params.projectId) {
        client.getProject(id)
            .then(resp => this.setState({project: resp.data, error: false}))
            .catch(err => {
                this.setState({ _error: err.data.message });
                console.log('Error: Sim/New-get', err)
            });
    },

    onAction(action, data, attachements) {
        this[action](data, attachements);
    },

    newSimulation(data, attachements) {
        const { name, description } = data,
            projectId = this.props.params.projectId,
            metadata = {},
            stepsInfo = Workflows[this.state.project.type].steps,
            steps = stepsInfo._initial_state,
            disabled = stepsInfo._disabled || [],
            active = stepsInfo._active || stepsInfo._order[0],
            simulation = { name, description, steps, metadata, projectId, active, disabled };

        client.saveSimulation(simulation, attachements)
            .then(resp => {
                var simId = Array.isArray(resp) ? resp[0].data._id : resp.data._id;
                this.context.router.replace('/View/Simulation/' + simId);
            })
            .catch(err => {
                this.setState({ _error: err.data.message });
                console.log('Error: Sim/New-save', err)
            });
    },

    cancel() {
        this.context.router.replace('/View/Project/' + this.props.params.projectId);
    },

    render() {
        if(!this.state.project) {
            return null;
        }

        const type = this.state.project.type;
        const childComponent = type ? Workflows[type].components.NewSimulation : null;
        const workflowAddOn = childComponent ? React.createElement(childComponent, { owner: () => this.refs.container }) : null;
        return (
            <ItemEditor
                breadcrumb={{
                    paths:['/', `/View/Project/${this.state.project._id}`],
                    icons:['fa fa-fw fa-list', 'fa fa-fw fa-folder-open-o'],
                }}
                error={this.state._error}
                ref='container'
                title='New Simulation'
                actions={[
                    {name: 'cancel', label: 'Cancel'},
                    {name: 'newSimulation', label: 'Create simulation'},
                ]}
                onAction={ this.onAction }>

                { workflowAddOn }

            </ItemEditor>);
    },
});
<|endoftext|>


<commit_before>var stream = require('stream');
var schema = require('../models/schema');
var _ = require('lodash');

var DELIMITER = ',';
var IGNORED_FIELDS = ['_id', '__v'];

module.exports = function (dbConn) {
  return function (req, res) {
    var cursor = dbConn.collection('patients').find({}).stream({ transform: JSON.stringify });
    var columns = _.filter(_.keys(schema.patientSchema.paths), function(k) { return !contains(IGNORED_FIELDS, k); });
    var titleRow = buildTitleRow(columns);
    res.write(titleRow);
    // return cursor.pipe(transform(_.identity)).pipe(res);
    return cursor.pipe(transform(jsonToCsv(columns))).pipe(res);
  };
};

function csvEscape(delimiter) {
  return function(value) {
    // If it contains a quote, escape it with a quote
    var escapedValue = value.replace(/"/g, '""');

    // If it contains particular characters, it needs wrapping in quotes
    if (value.indexOf(delimiter) !== -1 || value.indexOf('"') !== -1 || value.indexOf('\n') !== -1) {
      escapedValue = '"' + escapedValue + '"';
    }
    return escapedValue;
  };
}

function buildTitleRow(patientSchemaProperties) {
  return patientSchemaProperties.map(csvEscape(DELIMITER)).join(DELIMITER) + '\n';
}

function jsonToCsv(patientSchemaProperties) {
  return function (rawJson) {
    var json = JSON.parse(rawJson);
    var extractValue = function (property) {
      var value = '';
      if (property.indexOf('.') !== -1) {
        var properties = property.split('.');
        value = json[properties[0]] ? json[properties[0]][properties[1]] : '';
      } else {
        value = json[property];
      }
      return value ? JSON.stringify(value) : '';
    };
    return patientSchemaProperties.map(extractValue).map(csvEscape(DELIMITER)).join(DELIMITER);
  };
}

function transform(transformer) {
  return new stream.Transform({
    transform: function (chunk, encoding, next) {
      // TODO: handles UTF-8 ?
      this.push(transformer(String(chunk)));
      next();
    },
    flush: function (done) {
      done();
    }
  });
}

function contains(iterable, value) {
  return iterable.filter(function(v){ return v === value; }).length > 0;
}
/*
 Andy Duncan
 How about everything except scores in one report.	11:16 AM
 And then only scores in another. Multiple rows per patient who has multiple scores?	11:16 AM
 Then csv is doable.	11:17 AM
 And you can use the scheme to get columns.	11:17 AM
 Maybe flatten, with concatenation of fields like 'admission - blah blah' whatever the fields are (sorry not at my desk)	11:18 AM
 Then you don't need the whole database in memory to get column headers.	11:18 AM
 Schema.	11:18 AM
 What do you think?	11:19 AM

 Jake Howard
 Sounds like a plan. Comorbidities and scores in separate files. Just like RDBMS mapping tables.	11:22 AM
 (On a train) (bad signal)	11:22 AM

 Andy Duncan
 Mmmmm	11:22 AM
 No. Just concatenate comorbidities	11:23 AM
 In the main csv
 */

// This end point does the main chunk of the data
// Call a separate end point to get the other file (look into downloading two files from one call later)
<commit_msg>various:<commit_after>var stream = require('stream');
var schema = require('../models/schema');
var _ = require('lodash');

var DELIMITER = ',';
var IGNORED_FIELDS = ['_id', '__v', 'scores'];

module.exports = function (dbConn) {
  return function (req, res) {
    var cursor = dbConn.collection('patients').find({}).stream({ transform: JSON.stringify });
    var columns = _.filter(_.keys(schema.patientSchema.paths), function (k) {
      return !contains(IGNORED_FIELDS, k);
    });
    var titleRow = buildTitleRow(columns);
    res.write(titleRow);
    // return cursor.pipe(transform(_.identity)).pipe(res);
    return cursor.pipe(transform(jsonToCsv(columns))).pipe(res);
  };
};

function csvEscape(delimiter) {
  return function (value) {
    // If it contains a quote, escape it with a quote
    var escapedValue = String(value).replace(/"/g, '""');

    // If it contains particular characters, it needs wrapping in quotes
    if (escapedValue.indexOf(delimiter) !== -1 || escapedValue.indexOf('"') !== -1 || escapedValue.indexOf('\n') !== -1) {
      escapedValue = '"' + escapedValue + '"';
    }
    return escapedValue;
  };
}

function concatIfArray(value) {
  if (value) console.log(value, value.constructor);
  if (value && value.constructor === Array) {
    var joinDelimiter = DELIMITER === ',' ? ';' : ',';
    return value.join(joinDelimiter);
  }
  return value;
}

function buildTitleRow(patientSchemaProperties) {
  return patientSchemaProperties.map(csvEscape(DELIMITER)).join(DELIMITER) + '\n';
}

function jsonToCsv(patientSchemaProperties) {
  return function (rawJson) {
    var json = JSON.parse(rawJson);
    var extractValue = function (property) {
      var value = '';
      if (property.indexOf('.') !== -1) {
        var properties = property.split('.');
        value = json[properties[0]] ? json[properties[0]][properties[1]] : '';
      } else {
        value = json[property];
      }
      return value ? value : '';
    };
    // TODO: change this to a pipe/flow
    return patientSchemaProperties
      .map(extractValue)
      .map(concatIfArray)
      .map(csvEscape(DELIMITER))
      .join(DELIMITER);
  };
}

function transform(transformer) {
  return new stream.Transform({
    transform: function (chunk, encoding, next) {
      // TODO: handles UTF-8 ?
      this.push(transformer(String(chunk)) + '\n');
      next();
    },
    flush: function (done) {
      done();
    }
  });
}

function contains(iterable, value) {
  return iterable.filter(function (v) {
      return v === value;
    }).length > 0;
}
/*
 Andy Duncan
 How about everything except scores in one report.	11:16 AM
 And then only scores in another. Multiple rows per patient who has multiple scores?	11:16 AM
 Then csv is doable.	11:17 AM
 And you can use the scheme to get columns.	11:17 AM
 Maybe flatten, with concatenation of fields like 'admission - blah blah' whatever the fields are (sorry not at my desk)	11:18 AM
 Then you don't need the whole database in memory to get column headers.	11:18 AM
 Schema.	11:18 AM
 What do you think?	11:19 AM

 Jake Howard
 Sounds like a plan. Comorbidities and scores in separate files. Just like RDBMS mapping tables.	11:22 AM
 (On a train) (bad signal)	11:22 AM

 Andy Duncan
 Mmmmm	11:22 AM
 No. Just concatenate comorbidities	11:23 AM
 In the main csv
 */

// This end point does the main chunk of the data
// Call a separate end point to get the other file (look into downloading two files from one call later)
<|endoftext|>


<commit_before>import treeherder from '../../treeherder';
import thNotificationsBoxTemplate from '../../../partials/main/thNotificationsBox.html';
import { thFavicons } from '../../constants';

// Directive blurThis which removes focus from a specific element
treeherder.directive('blurThis', ['$timeout', function ($timeout) {
    return function (scope, elem, attr) {
        scope.$on('blur-this', function (event, id) {
            if (attr.id === id) {
                $timeout(function () {
                    elem[0].blur();
                }, 0);
            }
        });
    };
}]);

// Directive focusMe which sets a global focus state for elements
// which listen to it via ''focus-me="focusInput'' in angular markup
treeherder.directive('focusMe', [
    '$timeout',
    function ($timeout) {
        return {
            link: function (scope, element, attrs) {
                scope.$watch(attrs.focusMe, function (value) {
                    if (value) {
                        $timeout(function () {
                            element[0].focus();
                        }, 0);
                    } else {
                        $timeout(function () {
                            element[0].blur();
                        }, 0);
                    }
                });
            },
        };
    }]);

// Allow copy to system clipboard during hover
treeherder.directive('copyValue', [
    function () {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                const cont = document.getElementById('clipboard-container');
                const clip = document.getElementById('clipboard');
                element.on('mouseenter', function () {
                    cont.style.display = 'block';
                    clip.value = attrs.copyValue;
                    clip.focus();
                    clip.select();
                });
                element.on('mouseleave', function () {
                    cont.style.display = 'none';
                    clip.value = '';
                });
            },
        };
    },
]);

// Prevent default behavior on left mouse click. Useful
// for html anchor's that need to do in application actions
// on left click but default href type functionality on
// middle or right mouse click.
treeherder.directive('preventDefaultOnLeftClick', [
    function () {
        return {
            restrict: 'A',
            link: function (scope, element) {
                element.on('click', function (event) {
                    if (event.which === 1) {
                        event.preventDefault();
                    }
                    element.blur();
                });
            },
        };
    },
]);

treeherder.directive('stopPropagationOnLeftClick', [
    function () {
        return {
            restrict: 'A',
            link: function (scope, element) {
                element.on('click', function (event) {
                    if (event.which === 1) {
                        event.stopPropagation();
                    }
                });
            },
        };
    },
]);

treeherder.directive('thNotificationBox', [
    'thNotify',
    function (thNotify) {
        return {
            restrict: 'E',
            template: thNotificationsBoxTemplate,
            link: function (scope) {
                scope.notifier = thNotify;
                scope.alert_class_prefix = 'alert-';
            },
        };
    }]);

treeherder.directive('thFaviconLink', [
    '$sce', 'ThRepositoryModel',
    function ($sce, ThRepositoryModel) {
        return {
            restrict: 'E',
            link: function (scope) {
                scope.currentTreeStatus = ThRepositoryModel.getCurrentTreeStatus;
                scope.$watch('currentTreeStatus()', function (newVal) {
                    if (newVal) {
                        scope.favicon = $sce.trustAsResourceUrl(thFavicons[ThRepositoryModel.getCurrentTreeStatus()]);
                    }
                });
            },
            template: '<link id="favicon" type="image/png" rel="shortcut icon" href="{{favicon}}" />',
        };
    }]);

treeherder.directive('bugInput', function () {
    return {
        restrict: 'A',
        link: function (scope, elem) {
            elem.on('invalid', function (event) {
                event.target.setCustomValidity('Please enter a bug number');
            });
            elem.on('input', function (event) {
                event.target.setCustomValidity('');
                event.target.value = event.target.value.trim();
            });
            elem.attr('type', 'text');
            elem.attr('pattern', '\\s*\\d+\\s*');
        },
    };
});
<commit_msg>Bug 1450022 - Remove unused focusMe directive (#3692)<commit_after>import treeherder from '../../treeherder';
import thNotificationsBoxTemplate from '../../../partials/main/thNotificationsBox.html';
import { thFavicons } from '../../constants';

// Directive blurThis which removes focus from a specific element
treeherder.directive('blurThis', ['$timeout', function ($timeout) {
    return function (scope, elem, attr) {
        scope.$on('blur-this', function (event, id) {
            if (attr.id === id) {
                $timeout(function () {
                    elem[0].blur();
                }, 0);
            }
        });
    };
}]);

// Allow copy to system clipboard during hover
treeherder.directive('copyValue', [
    function () {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                const cont = document.getElementById('clipboard-container');
                const clip = document.getElementById('clipboard');
                element.on('mouseenter', function () {
                    cont.style.display = 'block';
                    clip.value = attrs.copyValue;
                    clip.focus();
                    clip.select();
                });
                element.on('mouseleave', function () {
                    cont.style.display = 'none';
                    clip.value = '';
                });
            },
        };
    },
]);

// Prevent default behavior on left mouse click. Useful
// for html anchor's that need to do in application actions
// on left click but default href type functionality on
// middle or right mouse click.
treeherder.directive('preventDefaultOnLeftClick', [
    function () {
        return {
            restrict: 'A',
            link: function (scope, element) {
                element.on('click', function (event) {
                    if (event.which === 1) {
                        event.preventDefault();
                    }
                    element.blur();
                });
            },
        };
    },
]);

treeherder.directive('stopPropagationOnLeftClick', [
    function () {
        return {
            restrict: 'A',
            link: function (scope, element) {
                element.on('click', function (event) {
                    if (event.which === 1) {
                        event.stopPropagation();
                    }
                });
            },
        };
    },
]);

treeherder.directive('thNotificationBox', [
    'thNotify',
    function (thNotify) {
        return {
            restrict: 'E',
            template: thNotificationsBoxTemplate,
            link: function (scope) {
                scope.notifier = thNotify;
                scope.alert_class_prefix = 'alert-';
            },
        };
    }]);

treeherder.directive('thFaviconLink', [
    '$sce', 'ThRepositoryModel',
    function ($sce, ThRepositoryModel) {
        return {
            restrict: 'E',
            link: function (scope) {
                scope.currentTreeStatus = ThRepositoryModel.getCurrentTreeStatus;
                scope.$watch('currentTreeStatus()', function (newVal) {
                    if (newVal) {
                        scope.favicon = $sce.trustAsResourceUrl(thFavicons[ThRepositoryModel.getCurrentTreeStatus()]);
                    }
                });
            },
            template: '<link id="favicon" type="image/png" rel="shortcut icon" href="{{favicon}}" />',
        };
    }]);

treeherder.directive('bugInput', function () {
    return {
        restrict: 'A',
        link: function (scope, elem) {
            elem.on('invalid', function (event) {
                event.target.setCustomValidity('Please enter a bug number');
            });
            elem.on('input', function (event) {
                event.target.setCustomValidity('');
                event.target.value = event.target.value.trim();
            });
            elem.attr('type', 'text');
            elem.attr('pattern', '\\s*\\d+\\s*');
        },
    };
});
<|endoftext|>


<commit_before>import React, { PropTypes, Component } from 'react';
import classNames from 'classnames';
import Tag from './Tag';

import autoBind from '../utils/autoBind';

export default class SearchBox extends Component {
  constructor (props) {
    super(props);

    autoBind([
      'handleQueryChange',
      'removeLastTag'
    ], this);
  }

  getTags () {
    return this.props.multiSelected.map((val, i) => (
      <Tag
        id={i}
        onRemove={this.props.onTagRemove}
        showRemove={this.props.showTagRemove}
        text={val[this.props.valueKey]}
      />
    ));
  }

  getTagContainer () {
    const { multiSelect, multiSelected } = this.props;
    if (multiSelect && multiSelected && multiSelected.length) {
      return (

             {this.getTags()}

      );
    }
    return null;
  }

  handleQueryChange () {
    this.props.onQueryChange(this.refs.autocomplete.value);
  }

  removeLastTag (e) {
    const { onTagRemove, multiSelected } = this.props;
    const keyCode = e.which || e.keyCode;
    if (keyCode === 8 && multiSelected && multiSelected.length) {
      e.preventDefault();
      e.stopPropagation();
      onTagRemove({
        id: multiSelected.length - 1
      });
    }
  }

  render () {
    const {
      onFocus,
      onBlur,
      disabled,
      placeholder,
      value,
      Reset,
      onReset,
      multiSelect
    } = this.props;

    const mainClass = classNames('ac-searchbox', {
      tags: multiSelect
    });

    return (

        {this.getTagContainer()}

        <input
          className='ac-searchbox-input'
          disabled={disabled}
          onBlur={onBlur}
          onChange={this.handleQueryChange}
          onFocus={onFocus}
          onKeyDown={this.removeLastTag}
          placeholder={placeholder}
          ref='autocomplete'
          type='text'
          value={value}
        />

          {value.length > 0 && <Reset />}

    );
  }
}

function noop () {

}

SearchBox.propTypes = {
  Reset: PropTypes.element.isRequired,
  disabled: PropTypes.bool,
  multiSelect: PropTypes.bool,
  multiSelected: PropTypes.array,
  onBlur: PropTypes.func,
  onFocus: PropTypes.func,
  onQueryChange: PropTypes.func.isRequired,
  onReset: PropTypes.func,
  onTagRemove: PropTypes.func,
  placeholder: PropTypes.string,
  showTagRemove: PropTypes.bool,
  value: PropTypes.string.isRequired,
  valueKey: PropTypes.string
};

function ResetContent () {
  return ;
}

SearchBox.defaultProps = {
  Reset: ResetContent,
  onBlur: noop,
  onFocus: noop,
  placeholder: 'Search'
};
<commit_msg>fix(AutoComplete): backspace deletes text before tags (#27)<commit_after>import React, { PropTypes, Component } from 'react';
import classNames from 'classnames';
import Tag from './Tag';

import autoBind from '../utils/autoBind';

export default class SearchBox extends Component {
  constructor (props) {
    super(props);

    autoBind([
      'handleQueryChange',
      'removeLastTag'
    ], this);
  }

  getTags () {
    return this.props.multiSelected.map((val, i) => (
      <Tag
        id={i}
        onRemove={this.props.onTagRemove}
        showRemove={this.props.showTagRemove}
        text={val[this.props.valueKey]}
      />
    ));
  }

  getTagContainer () {
    const { multiSelect, multiSelected } = this.props;
    if (multiSelect && multiSelected && multiSelected.length) {
      return (

             {this.getTags()}

      );
    }
    return null;
  }

  handleQueryChange () {
    this.props.onQueryChange(this.refs.autocomplete.value);
  }

  removeLastTag (e) {
    const { onTagRemove, multiSelected } = this.props;
    const keyCode = e.which || e.keyCode;
    if (keyCode === 8 && multiSelected && multiSelected.length && !this.props.value.length) {
      e.preventDefault();
      e.stopPropagation();
      onTagRemove({
        id: multiSelected.length - 1
      });
    }
  }

  render () {
    const {
      onFocus,
      onBlur,
      disabled,
      placeholder,
      value,
      Reset,
      onReset,
      multiSelect
    } = this.props;

    const mainClass = classNames('ac-searchbox', {
      tags: multiSelect
    });

    return (

        {this.getTagContainer()}

        <input
          className='ac-searchbox-input'
          disabled={disabled}
          onBlur={onBlur}
          onChange={this.handleQueryChange}
          onFocus={onFocus}
          onKeyDown={this.removeLastTag}
          placeholder={placeholder}
          ref='autocomplete'
          type='text'
          value={value}
        />

          {value.length > 0 && <Reset />}

    );
  }
}

function noop () {

}

SearchBox.propTypes = {
  Reset: PropTypes.element.isRequired,
  disabled: PropTypes.bool,
  multiSelect: PropTypes.bool,
  multiSelected: PropTypes.array,
  onBlur: PropTypes.func,
  onFocus: PropTypes.func,
  onQueryChange: PropTypes.func.isRequired,
  onReset: PropTypes.func,
  onTagRemove: PropTypes.func,
  placeholder: PropTypes.string,
  showTagRemove: PropTypes.bool,
  value: PropTypes.string.isRequired,
  valueKey: PropTypes.string
};

function ResetContent () {
  return ;
}

SearchBox.defaultProps = {
  Reset: ResetContent,
  onBlur: noop,
  onFocus: noop,
  placeholder: 'Search'
};
<|endoftext|>


<commit_before>export default class DragHandler extends Set {
  constructor({
    elements = [],
    exceptions = [],
  } = {}) {
    super();

    this.exceptions = exceptions;

    this.selected = new Set();

    this._onPointerDownBinded = this._onPointerDown.bind(this);
    this._onPointerMoveBinded = this._onPointerMove.bind(this);
    this._onPointerUpBinded = this._onPointerUp.bind(this);
    this._updateBinded = this._update.bind(this);

    this._previousClientX = 0;
    this._previousClientY = 0;

    this._clientX = 0;
    this._clientY = 0;

    this._dragStartX = 0;
    this._dragStartY = 0;

    this._preventDrag = false;

    this._animationFrameID = -1;

    this._elementTransformMatrices = new Map();

    this._resizeObserver = new ResizeObserver((entries) => {
      this._preventDrag = true;
    });

    for (const element of elements) {
      this.add(element);
    }
  }

  _onPointerDown(event) {
    const nodes = event.composedPath();
    for (const exception of this.exceptions) {
      if (exception(nodes)) {
        return;
      }
    }
    this._preventDrag = false;
    this._previousClientX = event.clientX;
    this._previousClientY = event.clientY;
    this._clientX = event.clientX;
    this._clientY = event.clientY;
    this._dragStartX = event.clientX;
    this._dragStartY = event.clientY;
    this.selected.add(event.currentTarget);
    for (const element of this.selected) {
      this._elementTransformMatrices.set(element, new DOMMatrix(element.style.transform));
    }
    window.addEventListener('pointermove', this._onPointerMoveBinded, { passive: false });
    window.addEventListener('pointerup', this._onPointerUpBinded, { passive: false });
    this._update();
  }

  _onPointerMove(event) {
    for (const element of this.selected) {
      element.style.pointerEvents = 'none';
    }
    this._clientX = event.clientX;
    this._clientY = event.clientY;
  }

  _onPointerUp() {
    cancelAnimationFrame(this._animationFrameID);
    window.removeEventListener('pointermove', this._onPointerMoveBinded);
    window.removeEventListener('pointerup', this._onPointerUpBinded);
    for (const element of this.selected) {
      element.style.pointerEvents = '';
    }
    this._preventDrag = false;
    this.selected.clear();
  }

  _update() {
    if (this._preventDrag) {
      this._onPointerUp();
      return;
    }
    this._animationFrameID = requestAnimationFrame(this._updateBinded);
    if (Math.abs(this._clientX - this._dragStartX) < 2 || Math.abs(this._clientY - this._dragStartY) < 2) {
      return;
    }
    for (const element of this.selected) {
      const domMatrix = this._elementTransformMatrices.get(element);
      domMatrix.translateSelf(this._clientX - this._previousClientX, this._clientY - this._previousClientY);
      element.style.transform = domMatrix.toString();
    }
    this._previousClientX = this._clientX;
    this._previousClientY = this._clientY;
  }

  add(element) {
    element.addEventListener('pointerdown', this._onPointerDownBinded, { passive: false });
    this._resizeObserver.observe(element);
    return super.add(element);
  }

  clear() {
    for (const element of this) {
      this.delete(element);
    }
  }

  delete(element) {
    element.removeEventListener('pointerdown', this._onPointerDownBinded);
    this._resizeObserver.unobserve(element);
    return super.delete(element);
  }
}
<commit_msg>fix DragHandler dragging distance test<commit_after>export default class DragHandler extends Set {
  constructor({
    elements = [],
    exceptions = [],
  } = {}) {
    super();

    this.exceptions = exceptions;

    this.selected = new Set();

    this._onPointerDownBinded = this._onPointerDown.bind(this);
    this._onPointerMoveBinded = this._onPointerMove.bind(this);
    this._onPointerUpBinded = this._onPointerUp.bind(this);
    this._updateBinded = this._update.bind(this);

    this._previousClientX = 0;
    this._previousClientY = 0;

    this._clientX = 0;
    this._clientY = 0;

    this._dragStartX = 0;
    this._dragStartY = 0;

    this._preventDrag = false;

    this._animationFrameID = -1;

    this._elementTransformMatrices = new Map();

    this._resizeObserver = new ResizeObserver((entries) => {
      this._preventDrag = true;
    });

    for (const element of elements) {
      this.add(element);
    }
  }

  _onPointerDown(event) {
    const nodes = event.composedPath();
    for (const exception of this.exceptions) {
      if (exception(nodes)) {
        return;
      }
    }
    this._preventDrag = false;
    this._previousClientX = event.clientX;
    this._previousClientY = event.clientY;
    this._clientX = event.clientX;
    this._clientY = event.clientY;
    this._dragStartX = event.clientX;
    this._dragStartY = event.clientY;
    this.selected.add(event.currentTarget);
    for (const element of this.selected) {
      this._elementTransformMatrices.set(element, new DOMMatrix(element.style.transform));
    }
    window.addEventListener('pointermove', this._onPointerMoveBinded, { passive: false });
    window.addEventListener('pointerup', this._onPointerUpBinded, { passive: false });
    this._update();
  }

  _onPointerMove(event) {
    for (const element of this.selected) {
      element.style.pointerEvents = 'none';
    }
    this._clientX = event.clientX;
    this._clientY = event.clientY;
  }

  _onPointerUp() {
    cancelAnimationFrame(this._animationFrameID);
    window.removeEventListener('pointermove', this._onPointerMoveBinded);
    window.removeEventListener('pointerup', this._onPointerUpBinded);
    for (const element of this.selected) {
      element.style.pointerEvents = '';
    }
    this._preventDrag = false;
    this.selected.clear();
  }

  _update() {
    if (this._preventDrag) {
      this._onPointerUp();
      return;
    }
    this._animationFrameID = requestAnimationFrame(this._updateBinded);
    if (Math.abs(this._clientX - this._dragStartX) < 2 && Math.abs(this._clientY - this._dragStartY) < 2) {
      return;
    }
    for (const element of this.selected) {
      const domMatrix = this._elementTransformMatrices.get(element);
      domMatrix.translateSelf(this._clientX - this._previousClientX, this._clientY - this._previousClientY);
      element.style.transform = domMatrix.toString();
    }
    this._previousClientX = this._clientX;
    this._previousClientY = this._clientY;
  }

  add(element) {
    element.addEventListener('pointerdown', this._onPointerDownBinded, { passive: false });
    this._resizeObserver.observe(element);
    return super.add(element);
  }

  clear() {
    for (const element of this) {
      this.delete(element);
    }
  }

  delete(element) {
    element.removeEventListener('pointerdown', this._onPointerDownBinded);
    this._resizeObserver.unobserve(element);
    return super.delete(element);
  }
}
<|endoftext|>


<commit_before>import {applyMiddleware} from 'redux'

import {Action} from '../client'

export default applyMiddleware(
  ({getState, dispatch}) => (next) => (action) => {
    const prevState = getState()
    next(action)
    const state = getState()
    switch (action.type) {
      case Action.Channel.members.type: {
        const prevMembers = prevState.channel.members
        const nicknames = []
        if (prevMembers.length) {
          state.channel.members.forEach(member1 => {
            if (!prevMembers.find(member2 => member1.id == member2.id)) {
              nicknames.push(member1.nickname)
            }
          })
        } else {
          nicknames.push(state.user.profile.nickname)
        }
        if (nicknames.length) {
          say(`欢迎${nicknames.join('和')}进入悟空`)
        }
        break
      }
    }
  }
)

function say(text) {
  if (window.speechSynthesis) {
    const utterance = new SpeechSynthesisUtterance()
    utterance.text = text
    utterance.lang = 'zh-CN'
    speechSynthesis.speak(utterance)
  }
}
<commit_msg>update speech text<commit_after>import {applyMiddleware} from 'redux'

import {Action} from '../client'

export default applyMiddleware(
  ({getState, dispatch}) => (next) => (action) => {
    const prevState = getState()
    next(action)
    const state = getState()
    switch (action.type) {
      case Action.Channel.members.type: {
        const {user: {profile}, channel: {name, members}} = state
        const {members: prevMembers} = prevState.channel
        if (prevMembers.length) {
          if (members.length >= prevMembers.length) {
            const nicknames = members.filter(member =>
              !prevMembers.find(prevMember => member.id == prevMember.id)
            ).map(member => member.nickname)
            if (nicknames.length) {
              say(`欢迎我们的老伙计，${nicknames.join('和')}来到悟空${name}房间。`)
            }
          } else {
            const nicknames = prevMembers.filter(prevMember =>
              !members.find(member => member.id == prevMember.id)
            ).map(member => member.nickname)
            if (nicknames.length) {
              say(`噢，${nicknames.join('和')}离开了悟空，我向上帝保证，这简直是糟透了。`)
            }
          }
        } else {
          say(`嘿，${profile.nickname}，见到你真是太令人高兴了。`)
        }
        break
      }
    }
  }
)

function say(text) {
  if (window.speechSynthesis) {
    const utterance = new SpeechSynthesisUtterance()
    utterance.text = text
    utterance.lang = 'zh-CN'
    speechSynthesis.speak(utterance)
  }
}
<|endoftext|>


<commit_before>'use strict';

let credentials = {
    key: null,
    cert: null
};

let fs = require('fs');
let execSync = require('child_process').execSync;

class SecurityHelper {
    /**
     * Loads private key and certificate
     *
     * @param {String} siteName
     *
     * @returns {Promise} Result
     */
    static loadCredentials(siteName = 'localhost') {
        if(!fs.existsSync(appRoot + '/ssl')) {
            fs.mkdirSync(appRoot + '/ssl');
        }

        execSync('openssl genrsa -out ' + appRoot + '/ssl/server.key');
        execSync('openssl req -new -key ' + appRoot + '/ssl/server.key -out ' + appRoot + '/ssl/server.csr -subj "/C=DK/ST=Copenhagen/L=Copenhagen/O=Putaitu Productions/OU=Development/CN=' + siteName + '"');
        execSync('openssl x509 -req -in ' + appRoot + '/ssl/server.csr -signkey ' + appRoot + '/ssl/server.key -out ' + appRoot + '/ssl/server.crt');

        credentials.key = fs.readFileSync(appRoot + '/ssl/server.key', 'UTF-8');
        credentials.cert = fs.readFileSync(appRoot + '/ssl/server.crt', 'UTF-8');
    }

    /**
     * Gets the private key and certificate
     *
     * @returns {Object} Key and cert
     */
    static getCredentials() {
        if(!credentials.key || !credentials.cert) {
            this.loadCredentials();
        }

        return credentials;
    }

    /**
     * Starts the letsencrypt handler
     *
     * @returns {Object} Let's encrypt handler
     */
    static startLetsEncrypt() {
        let sslConfigPath = appRoot + '/config/mail.cfg';

        if(!fs.existsSync(sslConfigPath)) { return null; }

        let config = JSON.parse(fs.readFileSync(sslConfigPath));

        // Config sanity check
        if(!config.domain) {
            throw new Error('Variable "domain" not set in /config/ssl.cfg');
        }

        if(!config.email) {
            throw new Error('Variable "email" not set in /config/ssl.cfg');
        }

        // Storage backend
        let leStore = require('le-store-certbot').create({
            configDir: appRoot + '/certs',
            debug: false
        });

        // ACME challenge handler
        let leChallenge = require('le-challenge-fs').create({
            webrootPath: appRoot,
            debug: false
        });

        // Agreement handler
        let leAgree = (opts, agreeCb) => {
            agreeCb(null, opts.tosUrl);
        };

        // Let's Encrypt instance
        let LE = require('greenlock');
        let le = LE.create({
            server: LE.stagingServerUrl,
            store: leStore,
            challenges: { 'http-01': leChallenge },
            challengeType: 'http-01',
            agreeToTerms: leAgree,
            debug: false
        });

        // Check in-memory cache of certificates for the named domain
        le.check({
            domains: [config.domain]
        }).then((results) => {
            // We already  have certificates
            if(results) { return; }

            le.register({
                domains: [config.domain],
                email: config.email,
                agreeTos: true,
                rsaKeySize: 2048,
                challengeType: 'http-01'
            })
            .then(
                (certs) => {
                    console.log(certs);
                },
                (err) => {
                    throw err;
                }
            );
        });

        return le;
    }
}

module.exports = SecurityHelper;
<commit_msg>Implementing SSL<commit_after>'use strict';

let credentials = {
    key: null,
    cert: null
};

let fs = require('fs');
let execSync = require('child_process').execSync;

class SecurityHelper {
    /**
     * Loads private key and certificate
     *
     * @param {String} siteName
     *
     * @returns {Promise} Result
     */
    static loadCredentials(siteName = 'localhost') {
        if(!fs.existsSync(appRoot + '/ssl')) {
            fs.mkdirSync(appRoot + '/ssl');
        }

        execSync('openssl genrsa -out ' + appRoot + '/ssl/server.key');
        execSync('openssl req -new -key ' + appRoot + '/ssl/server.key -out ' + appRoot + '/ssl/server.csr -subj "/C=DK/ST=Copenhagen/L=Copenhagen/O=Putaitu Productions/OU=Development/CN=' + siteName + '"');
        execSync('openssl x509 -req -in ' + appRoot + '/ssl/server.csr -signkey ' + appRoot + '/ssl/server.key -out ' + appRoot + '/ssl/server.crt');

        credentials.key = fs.readFileSync(appRoot + '/ssl/server.key', 'UTF-8');
        credentials.cert = fs.readFileSync(appRoot + '/ssl/server.crt', 'UTF-8');
    }

    /**
     * Gets the private key and certificate
     *
     * @returns {Object} Key and cert
     */
    static getCredentials() {
        if(!credentials.key || !credentials.cert) {
            this.loadCredentials();
        }

        return credentials;
    }

    /**
     * Starts the letsencrypt handler
     *
     * @returns {Object} Let's encrypt handler
     */
    static startLetsEncrypt() {
        let sslConfigPath = appRoot + '/config/ssl.cfg';

        if(!fs.existsSync(sslConfigPath)) { return null; }

        let config = JSON.parse(fs.readFileSync(sslConfigPath));

        // Config sanity check
        if(!config.domain) {
            throw new Error('Variable "domain" not set in /config/ssl.cfg');
        }

        if(!config.email) {
            throw new Error('Variable "email" not set in /config/ssl.cfg');
        }

        // Storage backend
        let leStore = require('le-store-certbot').create({
            configDir: appRoot + '/certs',
            debug: false
        });

        // ACME challenge handler
        let leChallenge = require('le-challenge-fs').create({
            webrootPath: appRoot,
            debug: false
        });

        // Agreement handler
        let leAgree = (opts, agreeCb) => {
            agreeCb(null, opts.tosUrl);
        };

        // Let's Encrypt instance
        let LE = require('greenlock');
        let le = LE.create({
            server: LE.stagingServerUrl,
            store: leStore,
            challenges: { 'http-01': leChallenge },
            challengeType: 'http-01',
            agreeToTerms: leAgree,
            debug: false
        });

        // Check in-memory cache of certificates for the named domain
        le.check({
            domains: [config.domain]
        }).then((results) => {
            // We already  have certificates
            if(results) { return; }

            le.register({
                domains: [config.domain],
                email: config.email,
                agreeTos: true,
                rsaKeySize: 2048,
                challengeType: 'http-01'
            })
            .then(
                (certs) => {
                    console.log(certs);
                },
                (err) => {
                    throw err;
                }
            );
        });

        return le;
    }
}

module.exports = SecurityHelper;
<|endoftext|>


<commit_before>'use strict';

const Stats = require('fast-stats').Stats,
  urlParser = require('url'),
  log = require('intel').getLogger('sitespeedio.plugin.domains'),
  statsHelpers = require('../../support/statsHelpers'),
  isEmpty = require('lodash.isempty'),
  reduce = require('lodash.reduce');

const timingNames = [
  'blocked',
  'dns',
  'connect',
  'ssl',
  'send',
  'wait',
  'receive'
];

function parseDomainName(url) {
  return urlParser.parse(url).hostname;
}

function getDomain(domainName) {
  return {
    domainName,
    requestCount: 0,
    totalTime: new Stats(),
    blocked: new Stats(),
    dns: new Stats(),
    connect: new Stats(),
    ssl: new Stats(),
    send: new Stats(),
    wait: new Stats(),
    receive: new Stats()
  };
}

function calc(domains) {
  return reduce(
    domains,
    (summary, domainStats, domainName) => {
      const domainSummary = {
        requestCount: domainStats.requestCount,
        domainName
      };

      const stats = statsHelpers.summarizeStats(domainStats.totalTime);
      if (!isEmpty(stats)) {
        domainSummary.totalTime = stats;
      }
      timingNames.forEach(name => {
        const stats = statsHelpers.summarizeStats(domainStats[name]);
        if (!isEmpty(stats)) {
          domainSummary[name] = stats;
        }
      });

      summary[domainName] = domainSummary;
      return summary;
    },
    {}
  );
}

function isValidTiming(timing) {
  // The HAR format uses -1 to indicate invalid/missing timings
  return typeof timing === 'number' && timing !== -1;
}

module.exports = {
  groups: {},
  domains: {},
  addToAggregate(har, url) {
    const mainDomain = parseDomainName(url);
    if (this.groups[mainDomain] === undefined) {
      this.groups[mainDomain] = {};
    }
    const firstPageId = har.log.pages[0].id;

    har.log.entries.forEach(entry => {
      if (entry.pageref !== firstPageId) {
        // Only pick the first request out of multiple runs.
        return;
      }

      const domainName = parseDomainName(entry.request.url),
        domain = this.domains[domainName] || getDomain(domainName),
        groupDomain =
          this.groups[mainDomain][domainName] || getDomain(domainName),
        totalTime = entry.time;

      domain.requestCount++;
      groupDomain.requestCount++;

      if (isValidTiming(totalTime)) {
        domain.totalTime.push(totalTime);
        groupDomain.totalTime.push(totalTime);
      } else {
        log.debug('Missing time from har entry for url: ' + entry.request.url);
      }

      timingNames.forEach(name => {
        const timing = entry.timings[name];

        if (isValidTiming(timing)) {
          domain[name].push(timing);
          groupDomain[name].push(timing);
        }
      });
      this.domains[domainName] = domain;
      this.groups[mainDomain][domainName] = groupDomain;
    });
  },
  summarize() {
    const summary = {
      groups: {
        total: calc(this.domains)
      }
    };

    for (let group of Object.keys(this.groups)) {
      summary.groups[group] = calc(this.groups[group]);
    }

    return summary;
  }
};
<commit_msg>Timings from the HAR file in Chrome seems to be faulty #2159 (#2160)<commit_after>'use strict';

const Stats = require('fast-stats').Stats,
  urlParser = require('url'),
  log = require('intel').getLogger('sitespeedio.plugin.domains'),
  statsHelpers = require('../../support/statsHelpers'),
  isEmpty = require('lodash.isempty'),
  reduce = require('lodash.reduce');

const timingNames = [
  'blocked',
  'dns',
  'connect',
  'ssl',
  'send',
  'wait',
  'receive'
];

function parseDomainName(url) {
  return urlParser.parse(url).hostname;
}

function getDomain(domainName) {
  return {
    domainName,
    requestCount: 0,
    totalTime: new Stats(),
    blocked: new Stats(),
    dns: new Stats(),
    connect: new Stats(),
    ssl: new Stats(),
    send: new Stats(),
    wait: new Stats(),
    receive: new Stats()
  };
}

function calc(domains) {
  return reduce(
    domains,
    (summary, domainStats, domainName) => {
      const domainSummary = {
        requestCount: domainStats.requestCount,
        domainName
      };

      const stats = statsHelpers.summarizeStats(domainStats.totalTime);
      if (!isEmpty(stats)) {
        domainSummary.totalTime = stats;
      }
      timingNames.forEach(name => {
        const stats = statsHelpers.summarizeStats(domainStats[name]);
        if (!isEmpty(stats)) {
          domainSummary[name] = stats;
        }
      });

      summary[domainName] = domainSummary;
      return summary;
    },
    {}
  );
}

function isValidTiming(timing) {
  // The HAR format uses -1 to indicate invalid/missing timings
  // isNan see https://github.com/sitespeedio/sitespeed.io/issues/2159
  return typeof timing === 'number' && timing !== -1 && !isNaN(timing);
}

module.exports = {
  groups: {},
  domains: {},
  addToAggregate(har, url) {
    const mainDomain = parseDomainName(url);
    if (this.groups[mainDomain] === undefined) {
      this.groups[mainDomain] = {};
    }
    const firstPageId = har.log.pages[0].id;

    har.log.entries.forEach(entry => {
      if (entry.pageref !== firstPageId) {
        // Only pick the first request out of multiple runs.
        return;
      }

      const domainName = parseDomainName(entry.request.url),
        domain = this.domains[domainName] || getDomain(domainName),
        groupDomain =
          this.groups[mainDomain][domainName] || getDomain(domainName),
        totalTime = entry.time;

      domain.requestCount++;
      groupDomain.requestCount++;

      if (isValidTiming(totalTime)) {
        domain.totalTime.push(totalTime);
        groupDomain.totalTime.push(totalTime);
      } else {
        log.debug('Missing time from har entry for url: ' + entry.request.url);
      }

      timingNames.forEach(name => {
        const timing = entry.timings[name];

        if (isValidTiming(timing)) {
          domain[name].push(timing);
          groupDomain[name].push(timing);
        }
      });
      this.domains[domainName] = domain;
      this.groups[mainDomain][domainName] = groupDomain;
    });
  },
  summarize() {
    const summary = {
      groups: {
        total: calc(this.domains)
      }
    };

    for (let group of Object.keys(this.groups)) {
      summary.groups[group] = calc(this.groups[group]);
    }

    return summary;
  }
};
<|endoftext|>


<commit_before>var passport = require('passport');
var SamlStrategy = require('passport-saml').Strategy;
var SAML = require('passport-saml').SAML;
var fs = require('fs');
var logger = require("../utils/logger");
var path = require('path');

var setCredentials = function () {
    var entitiesJSON = global.saml_config;
    for (key in entitiesJSON) {

        logger.log2('verbose', 'Generating metadata for SAML provider "%s"', key)
        var objectJSON = entitiesJSON[key];
        var strategyConfigOptions = {};
        strategyConfigOptions.callbackUrl = global.applicationHost.concat("/passport/auth/saml/" + key + "/callback");
        if (objectJSON.hasOwnProperty('entryPoint')) {
            strategyConfigOptions.entryPoint = objectJSON['entryPoint'];
        }
        if (objectJSON.hasOwnProperty('issuer')) {
            strategyConfigOptions.issuer = objectJSON['issuer'];
        }
        if (objectJSON.hasOwnProperty('identifierFormat')) {
            strategyConfigOptions.identifierFormat = objectJSON['identifierFormat'];
        }
        if (objectJSON.hasOwnProperty('cert')) {
            strategyConfigOptions.cert = objectJSON['cert'];
        } else {
            logger.log2('warn', '"cert" property is not present. Provider "%s" will not work', key)
            return
        }
        if (objectJSON.hasOwnProperty('skipRequestCompression')) {
            strategyConfigOptions.skipRequestCompression = objectJSON['skipRequestCompression'];
        }
        if (objectJSON.hasOwnProperty('authnRequestBinding')) {
            strategyConfigOptions.authnRequestBinding = objectJSON['authnRequestBinding'];
        }
        if (objectJSON.hasOwnProperty('additionalAuthorizeParams')) {
            strategyConfigOptions.additionalAuthorizeParams = objectJSON['additionalAuthorizeParams'];
        }
        if(objectJSON.hasOwnProperty('forceAuthn')){
            strategyConfigOptions.forceAuthn = objectJSON['forceAuthn'];
        }
        if(objectJSON.hasOwnProperty('providerName')){
            strategyConfigOptions.providerName = objectJSON['providerName'];
        }
        if(objectJSON.hasOwnProperty('signatureAlgorithm')){
            strategyConfigOptions.signatureAlgorithm = objectJSON['signatureAlgorithm'];
        }
        if(objectJSON.hasOwnProperty('requestIdExpirationPeriodMs')){
            strategyConfigOptions.requestIdExpirationPeriodMs = objectJSON['requestIdExpirationPeriodMs'];
        }
        else {
            strategyConfigOptions.requestIdExpirationPeriodMs = 3600000;
        }

        strategyConfigOptions.decryptionPvk = fs.readFileSync('/etc/certs/passport-sp.key', 'utf-8');
        strategyConfigOptions.passReqToCallback = true;
        strategyConfigOptions.validateInResponseTo = true;

        var strategy = new SamlStrategy(strategyConfigOptions,
            function (req, profile, done) {
                logger.log2('verbose', 'Initial profile: %s', JSON.stringify(profile))
                var idp = req.originalUrl.replace("/passport/auth/saml/","").replace("/callback","").replace("/inbound","");
                var mapping = global.saml_config[idp].reverseMapping;
                logger.log2('debug', 'SAML reponse in body:\n%s', req.body.SAMLResponse)

                var userProfile = {
                    id: profile[mapping["id"]] || '',
                    memberOf: profile[mapping["memberOf"]] || '',
                    name: profile[mapping["name"]] || '',
                    username: profile[mapping["username"]] || '',
                    email: profile[mapping["email"]],
                    givenName: profile[mapping["givenName"]] || '',
                    familyName: profile[mapping["familyName"]] || '',
                    provider: profile[mapping["provider"]] || '',
                    providerKey: key
                };
                logger.log2('verbose', 'Profile after mapping: %s', JSON.stringify(userProfile))

                return done(null, userProfile);
            });

        passport.use(key, strategy);

        var idpMetaPath = path.join(__dirname, '..', 'idp-metadata');
        if (!fs.existsSync(idpMetaPath)) {
            fs.mkdirSync(idpMetaPath);
        }

        fs.truncate(path.join(idpMetaPath, key + '.xml'), 0, function (err) { });
        var decryptionCert = fs.readFileSync('/etc/certs/passport-sp.crt', 'utf-8');

        var metaData = strategy.generateServiceProviderMetadata(decryptionCert);
        logger.log2('debug', 'Metadata is:\n%s', metaData)

        fs.writeFile(path.join(idpMetaPath, key + '.xml'), metaData, function (err) {
            if (err) {
                logger.log2('error', 'Failed saving %s', path.join(idpMetaPath, key + '.xml'))
                logger.log2('error', err)
            } else {
                logger.log2('info', '%s saved successfully', path.join(idpMetaPath, key + '.xml'))
            }
        })
    }
};

module.exports = {
    passport: passport,
    setCredentials: setCredentials
};
<commit_msg>Use right callbackUrl URL for inbound flow<commit_after>var passport = require('passport');
var SamlStrategy = require('passport-saml').Strategy;
var SAML = require('passport-saml').SAML;
var fs = require('fs');
var logger = require("../utils/logger");
var path = require('path');

var setCredentials = function () {
    var entitiesJSON = global.saml_config;
    var inboundEntitiesJSON = global.saml_idp_init_config;
    for (key in entitiesJSON) {

        logger.log2('verbose', 'Generating metadata for SAML provider "%s"', key)
        var objectJSON = entitiesJSON[key];
        var inboundJSON = inboundEntitiesJSON[key];
        var strategyConfigOptions = {};
        strategyConfigOptions.callbackUrl = global.applicationHost.concat("/passport/auth/saml/" + key + "/callback");
        if (inboundJSON) {
            strategyConfigOptions.callbackUrl = strategyConfigOptions.callbackUrl + "/inbound"
        }

        if (objectJSON.hasOwnProperty('entryPoint')) {
            strategyConfigOptions.entryPoint = objectJSON['entryPoint'];
        }
        if (objectJSON.hasOwnProperty('issuer')) {
            strategyConfigOptions.issuer = objectJSON['issuer'];
        }
        if (objectJSON.hasOwnProperty('identifierFormat')) {
            strategyConfigOptions.identifierFormat = objectJSON['identifierFormat'];
        }
        if (objectJSON.hasOwnProperty('cert')) {
            strategyConfigOptions.cert = objectJSON['cert'];
        } else {
            logger.log2('warn', '"cert" property is not present. Provider "%s" will not work', key)
            return
        }
        if (objectJSON.hasOwnProperty('skipRequestCompression')) {
            strategyConfigOptions.skipRequestCompression = objectJSON['skipRequestCompression'];
        }
        if (objectJSON.hasOwnProperty('authnRequestBinding')) {
            strategyConfigOptions.authnRequestBinding = objectJSON['authnRequestBinding'];
        }
        if (objectJSON.hasOwnProperty('additionalAuthorizeParams')) {
            strategyConfigOptions.additionalAuthorizeParams = objectJSON['additionalAuthorizeParams'];
        }
        if(objectJSON.hasOwnProperty('forceAuthn')){
            strategyConfigOptions.forceAuthn = objectJSON['forceAuthn'];
        }
        if(objectJSON.hasOwnProperty('providerName')){
            strategyConfigOptions.providerName = objectJSON['providerName'];
        }
        if(objectJSON.hasOwnProperty('signatureAlgorithm')){
            strategyConfigOptions.signatureAlgorithm = objectJSON['signatureAlgorithm'];
        }
        if(objectJSON.hasOwnProperty('requestIdExpirationPeriodMs')){
            strategyConfigOptions.requestIdExpirationPeriodMs = objectJSON['requestIdExpirationPeriodMs'];
        }
        else {
            strategyConfigOptions.requestIdExpirationPeriodMs = 3600000;
        }

        strategyConfigOptions.decryptionPvk = fs.readFileSync('/etc/certs/passport-sp.key', 'utf-8');
        strategyConfigOptions.passReqToCallback = true;
        strategyConfigOptions.validateInResponseTo = true;

        var strategy = new SamlStrategy(strategyConfigOptions,
            function (req, profile, done) {
                logger.log2('verbose', 'Initial profile: %s', JSON.stringify(profile))
                var idp = req.originalUrl.replace("/passport/auth/saml/","").replace("/callback","").replace("/inbound","");
                var mapping = global.saml_config[idp].reverseMapping;
                logger.log2('debug', 'SAML reponse in body:\n%s', req.body.SAMLResponse)

                var userProfile = {
                    id: profile[mapping["id"]] || '',
                    memberOf: profile[mapping["memberOf"]] || '',
                    name: profile[mapping["name"]] || '',
                    username: profile[mapping["username"]] || '',
                    email: profile[mapping["email"]],
                    givenName: profile[mapping["givenName"]] || '',
                    familyName: profile[mapping["familyName"]] || '',
                    provider: profile[mapping["provider"]] || '',
                    providerKey: key
                };
                logger.log2('verbose', 'Profile after mapping: %s', JSON.stringify(userProfile))

                return done(null, userProfile);
            });

        passport.use(key, strategy);

        var idpMetaPath = path.join(__dirname, '..', 'idp-metadata');
        if (!fs.existsSync(idpMetaPath)) {
            fs.mkdirSync(idpMetaPath);
        }

        fs.truncate(path.join(idpMetaPath, key + '.xml'), 0, function (err) { });
        var decryptionCert = fs.readFileSync('/etc/certs/passport-sp.crt', 'utf-8');

        var metaData = strategy.generateServiceProviderMetadata(decryptionCert);
        logger.log2('debug', 'Metadata is:\n%s', metaData)

        fs.writeFile(path.join(idpMetaPath, key + '.xml'), metaData, function (err) {
            if (err) {
                logger.log2('error', 'Failed saving %s', path.join(idpMetaPath, key + '.xml'))
                logger.log2('error', err)
            } else {
                logger.log2('info', '%s saved successfully', path.join(idpMetaPath, key + '.xml'))
            }
        })
    }
};

module.exports = {
    passport: passport,
    setCredentials: setCredentials
};
<|endoftext|>


<commit_before>const { join } = require('path');
const { createWriteStream } = require('fs');
const { create: createArchive } = require('archiver');
const { version } = require('../package.json');
const is_windows = process.platform === 'win32';

main().catch(err => {
  console.error(err);
  process.exit(1);
});

async function main() {
  if (!is_windows) return;

  const dist = join(__dirname, '../dist');
  const unpacked = join(dist, 'unpacked');
  const file = join(dist, `vba-blocks-v${version}.zip`);

  return new Promise((resolve, reject) => {
    try {
      const output = createWriteStream(file);
      const archive = createArchive('zip');

      output.on('close', () => {
        console.log(`Done - ${file}`);
        resolve();
      });
      output.on('error', reject);

      archive.pipe(output);
      archive.on('error', reject);

      archive.directory(unpacked, '/.vba-blocks');
      archive.finalize();
    } catch (err) {
      reject(err);
    }
  });
}
<commit_msg>Flatten zip file<commit_after>const { join } = require('path');
const { createWriteStream } = require('fs');
const { create: createArchive } = require('archiver');
const { version } = require('../package.json');
const is_windows = process.platform === 'win32';

main().catch(err => {
  console.error(err);
  process.exit(1);
});

async function main() {
  if (!is_windows) return;

  const dist = join(__dirname, '../dist');
  const unpacked = join(dist, 'unpacked');
  const file = join(dist, `vba-blocks-v${version}.zip`);

  return new Promise((resolve, reject) => {
    try {
      const output = createWriteStream(file);
      const archive = createArchive('zip');

      output.on('close', () => {
        console.log(`Done - ${file}`);
        resolve();
      });
      output.on('error', reject);

      archive.pipe(output);
      archive.on('error', reject);

      archive.directory(unpacked, '/');
      archive.finalize();
    } catch (err) {
      reject(err);
    }
  });
}
<|endoftext|>


<commit_before>/**
 * CG Tecnico Invaders
 * CG45179 16'17
 *
 * @author: Rui Ventura ( ist181045 )
 * @author: Diogo Freitas ( ist181586 )
 * @author: Sara Azinhal ( ist181700 )
 */

import { Vector3 }  from '../lib/threejs/math/Vector3';

import Collidable from '../Collidable';

class Entity extends Collidable {

	constructor ( x, y, z ) {

		super( x, y, z );

		this.type = 'Entity';

		this.MAX_VELOCITY = 300;

		this.updateBoundingBox = true;

		this.moving       = false;
		this.direction    = new Vector3();
		this.velocity     = new Vector3();
		this.acceleration = 150;
		this.friction     = 130;

	}

	setDirection ( x, y, z ) {

		this.direction.set( x, y, z ).normalize();

	}

	update ( dt ) {

		super.update();

		let updatePos = false;

		let v   = this.velocity.length();
		let dvf = this.friction * dt;

		if ( this.moving ) {

			updatePos = true;

			if ( v !== this.MAX_VELOCITY ) {

				let dv = this.acceleration * dt;

				if ( v + dv > this.MAX_VELOCITY ) {

					this.velocity.setLength( this.MAX_VELOCITY );

				} else {

					this.velocity.addScaledVector( this.direction, dv );

				}

			}

		} else if ( v > dvf ) {

			updatePos = true;
			this.velocity.addScaledVector( this.direction, -dvf );

		} else {

			this.velocity.setLength( 0 );

		}

		if ( updatePos ) {

			let ds = new Vector3().addScaledVector( this.velocity, dt );

			this.position.add( ds );
			this.boundingBox.translate( ds );
			this.boundingSphere.translate( ds );

		}

	}

}

export default Entity;
<commit_msg>Fix update, check if direction and velocity point the same way<commit_after>/**
 * CG Tecnico Invaders
 * CG45179 16'17
 *
 * @author: Rui Ventura ( ist181045 )
 * @author: Diogo Freitas ( ist181586 )
 * @author: Sara Azinhal ( ist181700 )
 */

import { Vector3 }  from '../lib/threejs/math/Vector3';

import Collidable from '../Collidable';

class Entity extends Collidable {

	constructor ( x, y, z ) {

		super( x, y, z );

		this.type = 'Entity';

		this.MAX_VELOCITY = 300;

		this.updateBoundingBox = true;

		this.moving       = false;
		this.direction    = new Vector3();
		this.velocity     = new Vector3();
		this.acceleration = 150;
		this.friction     = 130;

	}

	setDirection ( x, y, z ) {

		this.direction.set( x, y, z ).normalize();

	}

	update ( dt ) {

		super.update();

		let updatePos = false;

		let v   = this.velocity.length();
		let dvf = this.friction * dt;

		if ( this.moving ) {

			updatePos = true;

			if ( v !== this.MAX_VELOCITY ) {

				let dv = this.acceleration * dt;

				if ( v + dv > this.MAX_VELOCITY ) {

					this.velocity.setLength( this.MAX_VELOCITY );

				} else {

					this.velocity.addScaledVector( this.direction, dv );

				}

			}

		} else if ( v > dvf ) {

			updatePos = true;

			if ( v !== this.direction.dot( this.velocity ) ) {

				this.direction.copy( this.velocity ).normalize();

			}

			this.velocity.addScaledVector( this.direction, -dvf );

		} else {

			this.velocity.setLength( 0 );

		}

		if ( updatePos ) {

			let ds = new Vector3().addScaledVector( this.velocity, dt );

			this.position.add( ds );
			this.boundingBox.translate( ds );
			this.boundingSphere.translate( ds );

		}

	}

}

export default Entity;
<|endoftext|>