<commit_before>// ==UserScript==
// @name        GitHub Files Filter
// @version     1.1.7
// @description A userscript that adds filters that toggle the view of repo files by extension
// @license     MIT
// @author      Rob Garrison
// @namespace   https://github.com/Mottie
// @include     https://github.com/*
// @run-at      document-idle
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_addStyle
// @require     https://greasyfork.org/scripts/28721-mutations/code/mutations.js?version=666427
// @icon        https://github.githubassets.com/pinned-octocat.svg
// @updateURL   https://raw.githubusercontent.com/Mottie/GitHub-userscripts/master/github-files-filter.user.js
// @downloadURL https://raw.githubusercontent.com/Mottie/GitHub-userscripts/master/github-files-filter.user.js
// ==/UserScript==
(() => {
	"use strict";

	// Emphasize selected buttons, disable hover when all selected and remove
	// animation delay; See #46
	GM_addStyle(`
		.gff-filter .btn.selected { font-variant: small-caps; }
		.gff-filter .btn:not(.selected):not(:first-child) {
			text-decoration: line-through;
		}
		.gff-filter .gff-all:not(.selected):focus,
		.gff-filter .gff-all:not(.selected) ~ .btn:focus,
		.gff-filter .gff-all:not(.selected) ~ .btn.selected:focus,
		.gff-filter .gff-all:not(.selected):hover,
		.gff-filter .gff-all:not(.selected) ~ .btn:hover,
		.gff-filter .gff-all:not(.selected) ~ .btn.selected:hover {
			border-color: #777 !important;
		}
		.gff-filter .btn:before, .gff-filter .btn:after {
			animation-delay: unset !important;
			filter: invert(10%);
		}
	`);

	let settings,
		list = {};
	const types = {
			// including ":" in key since it isn't allowed in a file name
			":all": {
				// return false to prevent adding files under this type
				is: () => false,
				text: "\u00ABall\u00BB"
			},
			":noExt": {
				is: name => !/\./.test(name),
				text: "\u00ABno-ext\u00BB"
			},
			":dot": {
				// this will include ".travis.yml"... should we add to "yml" instead?
				is: name => /^\./.test(name),
				text: "\u00ABdot-files\u00BB"
			},
			":min": {
				is: name => /\.min\./.test(name),
				text: "\u00ABmin\u00BB"
			}
		},
		// TODO: add toggle for submodule and dot-folders
		folderIconClasses = [
			".octicon-file-directory",
			".octicon-file-symlink-directory",
			".octicon-file-submodule"
		].join(",");

	// default to all file types visible; remember settings between sessions
	list[":all"] = true; // list gets cleared in buildList function
	settings = GM_getValue("gff-filter-settings", list);

	function updateFilter(event) {
		event.preventDefault();
		event.stopPropagation();
		const el = event.target;
		toggleBlocks(
			el.getAttribute("data-ext"),
			el.classList.contains("selected") ? "hide" : "show"
		);
	}

	function updateSettings(name, mode) {
		settings[name] = mode === "show";
		GM_setValue("gff-filter-settings", settings);
	}

	function updateAllButton() {
		if ($(".gff-filter")) {
			const buttons = $(".file-wrap .gff-filter"),
				filters = $$(".btn:not(.gff-all)", buttons),
				selected = $$(".btn:not(.gff-all).selected", buttons);
			// set "all" button
			$(".gff-all", buttons).classList.toggle(
				"selected",
				filters.length === selected.length
			);
		}
	}

	function toggleImagePreview(ext, mode) {
		if ($(".ghip-image-previews")) {
			let selector = "a",
				hasType = types[ext];
			if (!hasType) {
				selector += `[href$="${ext}"]`;
			}
			$$(`.ghip-image-previews ${selector}`).forEach(el => {
				if (!$(".ghip-folder, .ghip-up-tree", el)) {
					if (hasType && ext !== ":all") {
						// image preview includes the filename
						let elm = $(".ghip-file-name", el);
						if (elm && !hasType.is(elm.textContent)) {
							return;
						}
					}
					el.style.display = mode === "show" ? "" : "none";
				}
			});
		}
	}

	function toggleRow(el, mode) {
		const row = el.closest("tr.js-navigation-item");
		// don't toggle folders
		if (row && !$(folderIconClasses, row)) {
			row.style.display = mode === "show" ? "" : "none";
		}
	}

	function toggleAll(mode) {
		const files = $(".file-wrap");
		// Toggle "all" blocks
		$$("td.content .js-navigation-open", files).forEach(el => {
			toggleRow(el, mode);
		});
		// update filter buttons
		$$(".gff-filter .btn", files).forEach(el => {
			el.classList.toggle("selected", mode === "show");
		});
		updateSettings(":all", mode);
	}

	function toggleFilter(filter, mode) {
		const files = $(".file-wrap"),
			elm = $(`.gff-filter .btn[data-ext="${filter}"]`, files);
		/* list[filter] contains an array of file names */
		list[filter].forEach(name => {
			const el = $(`a[title="${name}"]`, files);
			if (el) {
				toggleRow(el, mode);
			}
		});
		if (elm) {
			elm.classList.toggle("selected", mode === "show");
		}
		updateSettings(filter, mode);
	}

	function toggleBlocks(filter, mode) {
		if (filter === ":all") {
			toggleAll(mode);
		} else if (list[filter]) {
			toggleFilter(filter, mode);
		}
		// update view for github-image-preview.user.js
		toggleImagePreview(filter, mode);
		updateAllButton();
	}

	function addExt(ext, txt) {
		if (ext) {
			if (!list[ext]) {
				list[ext] = [];
			}
			list[ext].push(txt);
		}
	}

	function buildList() {
		list = {};
		Object.keys(types).forEach(item => {
			if (item !== ":all") {
				list[item] = [];
			}
		});
		// get all files
		$$("table.files tr.js-navigation-item").forEach(file => {
			if ($("td.icon .octicon-file", file)) {
				let ext, parts, sub,
					link = $("td.content .js-navigation-open", file),
					txt = (link.title || link.textContent || "").trim(),
					name = txt.split("/").slice(-1)[0];
				// test extension types; fallback to regex extraction
				ext = Object.keys(types).find(item => {
					return types[item].is(name);
				}) || /[^./\\]*$/.exec(name)[0];
				parts = name.split(".");
				if (!ext.startsWith(":") && parts.length > 2 && parts[0] !== "") {
					sub = parts.slice(0, -1).join(".");
					// Prevent version numbers & "vs. " from adding a filter button
					// See https://github.com/tpn/pdfs
					if (!/[()]/.test(sub) && !/[\b\w]\.[\b\d]/.test(sub)) {
						addExt(ext, txt);
						ext = parts.slice(-2).join(".");
					}
				}
				addExt(ext, txt);
			}
		});
	}

	function sortList() {
		return Object.keys(list).sort((a, b) => {
			// move ":" filters to the beginning, then sort the rest of the
			// extensions; test on https://github.com/rbsec/sslscan, where
			// the ".1" extension *was* appearing between ":" filters
			if (a[0] === ":") {
				return -1;
			}
			if (b[0] === ":") {
				return 1;
			}
			return a > b;
		});
	}

	function makeFilter() {
		let filters = 0;
		// get length, but don't count empty arrays
		Object.keys(list).forEach(ext => {
			filters += list[ext].length > 0 ? 1 : 0;
		});
		// Don't bother if only one extension is found
		const files = $(".file-wrap");
		if (files && filters > 1) {
			filters = $(".gff-filter-wrapper");
			if (!filters) {
				filters = document.createElement("div");
				// "commitinfo" allows GitHub-Dark styling
				filters.className = "gff-filter-wrapper commitinfo";
				filters.style = "padding:3px 5px 2px;border-bottom:1px solid #eaecef";
				files.insertBefore(filters, files.firstChild);
				filters.addEventListener("click", updateFilter);
			}
			fixWidth();
			buildHTML();
			applyInitSettings();
		}
	}

	function buildButton(name, label, ext, text) {
		return `<button type="button" ` +
			`class="btn btn-sm selected BtnGroup-item tooltipped tooltipped-n` +
			(name ? name : "") + `" ` +
			`data-ext="${ext}" aria-label="${label}">${text}</button>`;
	}

	function buildHTML() {
		let len,
			html = `<div class="BtnGroup gff-filter">` +
				// add a filter "all" button to the beginning
				buildButton(" gff-all", "Toggle all files", ":all", types[":all"].text);
		sortList().forEach(ext => {
			len = list[ext].length;
			if (len) {
				html += buildButton("", len, ext, types[ext] && types[ext].text || ext);
			}
		});
		// prepend filter buttons
		$(".gff-filter-wrapper").innerHTML = html + "
";
	}

	function getWidth(el) {
		return parseFloat(window.getComputedStyle(el).width);
	}

	// lock-in the table cell widths, or the navigation up link jumps when you
	// hide all files... using percentages in case someone is using GitHub wide
	function fixWidth() {
		let group, width,
			html = "",
			table = $("table.files"),
			tableWidth = getWidth(table),
			cells = $$("tbody:last-child tr:last-child td", table);
		if (table && cells.length > 1 && !$("colgroup", table)) {
			group = document.createElement("colgroup");
			table.insertBefore(group, table.childNodes[0]);
			cells.forEach(el => {
				// keep two decimal point accuracy
				width = parseInt(getWidth(el) / tableWidth * 1e4, 10) / 100;
				html += `<col style="width:${width}%">`;
			});
			group.innerHTML = html;
		}
	}

	function applyInitSettings() {
		// list doesn't include type.all entry
		if (settings[":all"] === false) {
			toggleBlocks(":all", "hide");
		} else {
			Object.keys(list).forEach(name => {
				if (settings[name] === false) {
					toggleBlocks(name, "hide");
				}
			});
		}
	}

	function init() {
		if ($("table.files")) {
			buildList();
			makeFilter();
		}
	}

	function $(str, el) {
		return (el || document).querySelector(str);
	}

	function $$(str, el) {
		return Array.from((el || document).querySelectorAll(str));
	}

	document.addEventListener("ghmo:container", () => {
		// init after a short delay to allow rendering of file list
		setTimeout(() => {
			init();
		}, 200);
	});
	init();

})();
<commit_msg>Files-filter: Filters work after using go back. Fixes #77<commit_after>// ==UserScript==
// @name        GitHub Files Filter
// @version     1.1.8
// @description A userscript that adds filters that toggle the view of repo files by extension
// @license     MIT
// @author      Rob Garrison
// @namespace   https://github.com/Mottie
// @include     https://github.com/*
// @run-at      document-idle
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_addStyle
// @require     https://greasyfork.org/scripts/28721-mutations/code/mutations.js?version=666427
// @icon        https://github.githubassets.com/pinned-octocat.svg
// @updateURL   https://raw.githubusercontent.com/Mottie/GitHub-userscripts/master/github-files-filter.user.js
// @downloadURL https://raw.githubusercontent.com/Mottie/GitHub-userscripts/master/github-files-filter.user.js
// ==/UserScript==
(() => {
	"use strict";

	// Emphasize selected buttons, disable hover when all selected and remove
	// animation delay; See #46
	GM_addStyle(`
		.gff-filter .btn.selected { font-variant: small-caps; }
		.gff-filter .btn:not(.selected):not(:first-child) {
			text-decoration: line-through;
		}
		.gff-filter .gff-all:not(.selected):focus,
		.gff-filter .gff-all:not(.selected) ~ .btn:focus,
		.gff-filter .gff-all:not(.selected) ~ .btn.selected:focus,
		.gff-filter .gff-all:not(.selected):hover,
		.gff-filter .gff-all:not(.selected) ~ .btn:hover,
		.gff-filter .gff-all:not(.selected) ~ .btn.selected:hover {
			border-color: #777 !important;
		}
		.gff-filter .btn:before, .gff-filter .btn:after {
			animation-delay: unset !important;
			filter: invert(10%);
		}
	`);

	let settings,
		list = {};
	const types = {
			// including ":" in key since it isn't allowed in a file name
			":all": {
				// return false to prevent adding files under this type
				is: () => false,
				text: "\u00ABall\u00BB"
			},
			":noExt": {
				is: name => !/\./.test(name),
				text: "\u00ABno-ext\u00BB"
			},
			":dot": {
				// this will include ".travis.yml"... should we add to "yml" instead?
				is: name => /^\./.test(name),
				text: "\u00ABdot-files\u00BB"
			},
			":min": {
				is: name => /\.min\./.test(name),
				text: "\u00ABmin\u00BB"
			}
		},
		// TODO: add toggle for submodule and dot-folders
		folderIconClasses = [
			".octicon-file-directory",
			".octicon-file-symlink-directory",
			".octicon-file-submodule"
		].join(",");

	// default to all file types visible; remember settings between sessions
	list[":all"] = true; // list gets cleared in buildList function
	settings = GM_getValue("gff-filter-settings", list);

	function updateFilter(event) {
		event.preventDefault();
		event.stopPropagation();
		const el = event.target;
		toggleBlocks(
			el.getAttribute("data-ext"),
			el.classList.contains("selected") ? "hide" : "show"
		);
	}

	function updateSettings(name, mode) {
		settings[name] = mode === "show";
		GM_setValue("gff-filter-settings", settings);
	}

	function updateAllButton() {
		if ($(".gff-filter")) {
			const buttons = $(".file-wrap .gff-filter"),
				filters = $$(".btn:not(.gff-all)", buttons),
				selected = $$(".btn:not(.gff-all).selected", buttons);
			// set "all" button
			$(".gff-all", buttons).classList.toggle(
				"selected",
				filters.length === selected.length
			);
		}
	}

	function toggleImagePreview(ext, mode) {
		if ($(".ghip-image-previews")) {
			let selector = "a",
				hasType = types[ext];
			if (!hasType) {
				selector += `[href$="${ext}"]`;
			}
			$$(`.ghip-image-previews ${selector}`).forEach(el => {
				if (!$(".ghip-folder, .ghip-up-tree", el)) {
					if (hasType && ext !== ":all") {
						// image preview includes the filename
						let elm = $(".ghip-file-name", el);
						if (elm && !hasType.is(elm.textContent)) {
							return;
						}
					}
					el.style.display = mode === "show" ? "" : "none";
				}
			});
		}
	}

	function toggleRow(el, mode) {
		const row = el.closest("tr.js-navigation-item");
		// don't toggle folders
		if (row && !$(folderIconClasses, row)) {
			row.style.display = mode === "show" ? "" : "none";
		}
	}

	function toggleAll(mode) {
		const files = $(".file-wrap");
		// Toggle "all" blocks
		$$("td.content .js-navigation-open", files).forEach(el => {
			toggleRow(el, mode);
		});
		// update filter buttons
		$$(".gff-filter .btn", files).forEach(el => {
			el.classList.toggle("selected", mode === "show");
		});
		updateSettings(":all", mode);
	}

	function toggleFilter(filter, mode) {
		const files = $(".file-wrap"),
			elm = $(`.gff-filter .btn[data-ext="${filter}"]`, files);
		/* list[filter] contains an array of file names */
		list[filter].forEach(name => {
			const el = $(`a[title="${name}"]`, files);
			if (el) {
				toggleRow(el, mode);
			}
		});
		if (elm) {
			elm.classList.toggle("selected", mode === "show");
		}
		updateSettings(filter, mode);
	}

	function toggleBlocks(filter, mode) {
		if (filter === ":all") {
			toggleAll(mode);
		} else if (list[filter]) {
			toggleFilter(filter, mode);
		}
		// update view for github-image-preview.user.js
		toggleImagePreview(filter, mode);
		updateAllButton();
	}

	function addExt(ext, txt) {
		if (ext) {
			if (!list[ext]) {
				list[ext] = [];
			}
			list[ext].push(txt);
		}
	}

	function buildList() {
		list = {};
		Object.keys(types).forEach(item => {
			if (item !== ":all") {
				list[item] = [];
			}
		});
		// get all files
		$$("table.files tr.js-navigation-item").forEach(file => {
			if ($("td.icon .octicon-file", file)) {
				let ext, parts, sub,
					link = $("td.content .js-navigation-open", file),
					txt = (link.title || link.textContent || "").trim(),
					name = txt.split("/").slice(-1)[0];
				// test extension types; fallback to regex extraction
				ext = Object.keys(types).find(item => {
					return types[item].is(name);
				}) || /[^./\\]*$/.exec(name)[0];
				parts = name.split(".");
				if (!ext.startsWith(":") && parts.length > 2 && parts[0] !== "") {
					sub = parts.slice(0, -1).join(".");
					// Prevent version numbers & "vs. " from adding a filter button
					// See https://github.com/tpn/pdfs
					if (!/[()]/.test(sub) && !/[\b\w]\.[\b\d]/.test(sub)) {
						addExt(ext, txt);
						ext = parts.slice(-2).join(".");
					}
				}
				addExt(ext, txt);
			}
		});
	}

	function sortList() {
		return Object.keys(list).sort((a, b) => {
			// move ":" filters to the beginning, then sort the rest of the
			// extensions; test on https://github.com/rbsec/sslscan, where
			// the ".1" extension *was* appearing between ":" filters
			if (a[0] === ":") {
				return -1;
			}
			if (b[0] === ":") {
				return 1;
			}
			return a > b;
		});
	}

	function makeFilter() {
		let filters = 0;
		// get length, but don't count empty arrays
		Object.keys(list).forEach(ext => {
			filters += list[ext].length > 0 ? 1 : 0;
		});
		// Don't bother if only one extension is found
		const files = $(".file-wrap");
		if (files && filters > 1) {
			filters = $(".gff-filter-wrapper");
			if (!filters) {
				filters = document.createElement("div");
				// "commitinfo" allows GitHub-Dark styling
				filters.className = "gff-filter-wrapper commitinfo";
				filters.style = "padding:3px 5px 2px;border-bottom:1px solid #eaecef";
				files.insertBefore(filters, files.firstChild);
			}
			fixWidth();
			buildHTML();
			applyInitSettings();
		}
	}

	function buildButton(name, label, ext, text) {
		return `<button type="button" ` +
			`class="btn btn-sm selected BtnGroup-item tooltipped tooltipped-n` +
			(name ? name : "") + ` gff-btn" ` +
			`data-ext="${ext}" aria-label="${label}">${text}</button>`;
	}

	function buildHTML() {
		let len,
			html = `<div class="BtnGroup gff-filter">` +
				// add a filter "all" button to the beginning
				buildButton(" gff-all", "Toggle all files", ":all", types[":all"].text);
		sortList().forEach(ext => {
			len = list[ext].length;
			if (len) {
				html += buildButton("", len, ext, types[ext] && types[ext].text || ext);
			}
		});
		// prepend filter buttons
		$(".gff-filter-wrapper").innerHTML = html + "
";
	}

	function getWidth(el) {
		return parseFloat(window.getComputedStyle(el).width);
	}

	// lock-in the table cell widths, or the navigation up link jumps when you
	// hide all files... using percentages in case someone is using GitHub wide
	function fixWidth() {
		let group, width,
			html = "",
			table = $("table.files"),
			tableWidth = getWidth(table),
			cells = $$("tbody:last-child tr:last-child td", table);
		if (table && cells.length > 1 && !$("colgroup", table)) {
			group = document.createElement("colgroup");
			table.insertBefore(group, table.childNodes[0]);
			cells.forEach(el => {
				// keep two decimal point accuracy
				width = parseInt(getWidth(el) / tableWidth * 1e4, 10) / 100;
				html += `<col style="width:${width}%">`;
			});
			group.innerHTML = html;
		}
	}

	function applyInitSettings() {
		// list doesn't include type.all entry
		if (settings[":all"] === false) {
			toggleBlocks(":all", "hide");
		} else {
			Object.keys(list).forEach(name => {
				if (settings[name] === false) {
					toggleBlocks(name, "hide");
				}
			});
		}
	}

	function init() {
		if ($("table.files")) {
			buildList();
			makeFilter();
		}
	}

	function $(str, el) {
		return (el || document).querySelector(str);
	}

	function $$(str, el) {
		return Array.from((el || document).querySelectorAll(str));
	}

	document.addEventListener("click", e => {
		if (e.target.classList.contains("gff-btn")) {
			updateFilter(e);
		}
	});

	document.addEventListener("ghmo:container", () => {
		// init after a short delay to allow rendering of file list
		setTimeout(() => {
			init();
		}, 200);
	});
	init();

})();
<|endoftext|>


<commit_before>ngDefine('cockpit.plugin.statistics-plugin.directives', function(module) {
	module.directive('startEndControlElement', function(){
		 return {
		      restrict: 'E',
		      template:
		    	 '<form class="form-horizontal">'+
		    	 	'
Show:
'+
		    	 	'
starting time or ending time
'+
		    	 	'
'+
		    	 		'<select ng-model="currentXValue" ng-options="currentXValue.xValue for currentXValue in xValueSpecifiers" ng-change="getDataAndDrawGraph()">'+
		    	 		'</select>'+
		    	 	'
'+
		    	 	'
{{currentXValue.xValue}} on a weekly or dayly basis
'+
		    	 	'
'+
		    	 		'<select ng-model="currentFrame" ng-options="currentFrame.frame for currentFrame in timeFrames" ng-change="getDataAndDrawGraph()">'+
		    	 		'</select>'+
		    	 	'
'+
		    	 	'
of process instances or user tasks
'+
		    	 	'
'+
	    	 			'<select ng-model="currentLevel" ng-options="currentLevel.level for currentLevel in levelSpecifiers" ng-change="getDataAndDrawGraph()">'+
	    	 			'</select>'+
	    	 		'
'+
	    	 		'
of a specific process or all
'+
	    	 		'
'+
    	 				'<select ng-disabled="!currentLevel.moreOptions" ng-model="processInstance" ng-options="processInstance.processDefKey for processInstance in processInstances" ng-change="getDataAndDrawGraph()">'+
    	 				'</select>'+
    	 			'
'+
		    	 	'
adjust width
'+
		    	 	'<input type="number" name="points" min="0" step="10" value="1000" ng-model = "width" ng-change="getDataAndDrawGraph()">'+
//		    	 	'
adjust cluster threshold
'+
//		    	 	'<input type="number" name="cluster" min="0" step="10" value="10" ng-model = "clusterThreshold" ng-change="getDataAndDrawGraph()">'+
		    	 	'
'+
		    	 	'
kmeans
'+
		    	 	'<input type="number" name="kmeans" min="1" step="1" value="5" ng-model = "kMeans" ng-change="getDataAndDrawGraph()">'+
		    	 	'
'+
		    	 '</form>'
		    };
	});
});
<commit_msg>fix: correct label for activity/processinstance dropdown in timing tab<commit_after>ngDefine('cockpit.plugin.statistics-plugin.directives', function(module) {
	module.directive('startEndControlElement', function(){
		 return {
		      restrict: 'E',
		      template:
		    	 '<form class="form-horizontal">'+
		    	 	'
Show:
'+
		    	 	'
starting time or ending time
'+
		    	 	'
'+
		    	 		'<select ng-model="currentXValue" ng-options="currentXValue.xValue for currentXValue in xValueSpecifiers" ng-change="getDataAndDrawGraph()">'+
		    	 		'</select>'+
		    	 	'
'+
		    	 	'
{{currentXValue.xValue}} on a weekly or dayly basis
'+
		    	 	'
'+
		    	 		'<select ng-model="currentFrame" ng-options="currentFrame.frame for currentFrame in timeFrames" ng-change="getDataAndDrawGraph()">'+
		    	 		'</select>'+
		    	 	'
'+
		    	 	'
of process instances or activities
'+
		    	 	'
'+
	    	 			'<select ng-model="currentLevel" ng-options="currentLevel.level for currentLevel in levelSpecifiers" ng-change="getDataAndDrawGraph()">'+
	    	 			'</select>'+
	    	 		'
'+
	    	 		'
of a specific process or all
'+
	    	 		'
'+
    	 				'<select ng-disabled="!currentLevel.moreOptions" ng-model="processInstance" ng-options="processInstance.processDefKey for processInstance in processInstances" ng-change="getDataAndDrawGraph()">'+
    	 				'</select>'+
    	 			'
'+
		    	 	'
adjust width
'+
		    	 	'<input type="number" name="points" min="0" step="10" value="1000" ng-model = "width" ng-change="getDataAndDrawGraph()">'+
//		    	 	'
adjust cluster threshold
'+
//		    	 	'<input type="number" name="cluster" min="0" step="10" value="10" ng-model = "clusterThreshold" ng-change="getDataAndDrawGraph()">'+
		    	 	'
'+
		    	 	'
kmeans
'+
		    	 	'<input type="number" name="kmeans" min="1" step="1" value="5" ng-model = "kMeans" ng-change="getDataAndDrawGraph()">'+
		    	 	'
'+
		    	 '</form>'
		    };
	});
});
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import classnames from 'classnames';
import Card, { CardHeader, CardMedia, CardContent, CardActions } from 'material-ui/Card';
import Collapse from 'material-ui/transitions/Collapse';
import Avatar from 'material-ui/Avatar';
import IconButton from 'material-ui/IconButton';
import Typography from 'material-ui/Typography';
import red from 'material-ui/colors/red';
import FavoriteIcon from 'material-ui-icons/Favorite';
import ShareIcon from 'material-ui-icons/Share';
import ExpandMoreIcon from 'material-ui-icons/ExpandMore';
import MoreVertIcon from 'material-ui-icons/MoreVert';

const styles = theme => ({
  card: {
    maxWidth: 400,
  },
  media: {
    height: 194,
  },
  expand: {
    transform: 'rotate(0deg)',
    transition: theme.transitions.create('transform', {
      duration: theme.transitions.duration.shortest,
    }),
  },
  expandOpen: {
    transform: 'rotate(180deg)',
  },
  avatar: {
    backgroundColor: red[500],
  },
  flexGrow: {
    flex: '1 1 auto',
  },
});

class RecipeReviewCard extends React.Component {
  state = { expanded: false };

  handleExpandClick = () => {
    this.setState({ expanded: !this.state.expanded });
  };

  render() {
    const { classes } = this.props;

    return (

        <Card className={classes.card}>
          <CardHeader
            avatar={
              <Avatar aria-label="Recipe" className={classes.avatar}>
                R
              </Avatar>
            }
            action={
              <IconButton>
                <MoreVertIcon />
              </IconButton>
            }
            title="Shrimp and Chorizo Paella"
            subheader="September 14, 2016"
          />
          <CardMedia
            className={classes.media}
            image="/static/images/cards/paella.jpg"
            title="Contemplative Reptile"
          />
          <CardContent>
            <Typography component="p">
              This impressive paella is a perfect party dish and a fun meal to cook together with
              your guests. Add 1 cup of frozen peas along with the mussels, if you like.
            </Typography>
          </CardContent>
          <CardActions disableActionSpacing>
            <IconButton aria-label="Add to favorites">
              <FavoriteIcon />
            </IconButton>
            <IconButton aria-label="Share">
              <ShareIcon />
            </IconButton>

            <IconButton
              className={classnames(classes.expand, {
                [classes.expandOpen]: this.state.expanded,
              })}
              onClick={this.handleExpandClick}
              aria-expanded={this.state.expanded}
              aria-label="Show more"
            >
              <ExpandMoreIcon />
            </IconButton>
          </CardActions>
          <Collapse in={this.state.expanded} timeout="auto" unmountOnExit>
            <CardContent>
              <Typography paragraph type="body2">
                Method:
              </Typography>
              <Typography paragraph>
                Heat 1/2 cup of the broth in a pot until simmering, add saffron and set aside for 10
                minutes.
              </Typography>
              <Typography paragraph>
                Heat oil in a (14- to 16-inch) paella pan or a large, deep skillet over medium-high
                heat. Add chicken, shrimp and chorizo, and cook, stirring occasionally until lightly
                browned, 6 to 8 minutes. Transfer shrimp to a large plate and set aside, leaving
                chicken and chorizo in the pan. Add pimentón, bay leaves, garlic, tomatoes, onion,
                salt and pepper, and cook, stirring often until thickened and fragrant, about 10
                minutes. Add saffron broth and remaining 4 1/2 cups chicken broth; bring to a boil.
              </Typography>
              <Typography paragraph>
                Add rice and stir very gently to distribute. Top with artichokes and peppers, and
                cook without stirring, until most of the liquid is absorbed, 15 to 18 minutes.
                Reduce heat to medium-low, add reserved shrimp and mussels, tucking them down into
                the rice, and cook again without stirring, until mussels have opened and rice is
                just tender, 5 to 7 minutes more. (Discard any mussels that don’t open.)
              </Typography>
              <Typography>
                Set aside off of the heat to let rest for 10 minutes, and then serve.
              </Typography>
            </CardContent>
          </Collapse>
        </Card>

    );
  }
}

RecipeReviewCard.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(RecipeReviewCard);
<commit_msg>[docs] Remove one DOM element in the Card actions (#9952)<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import classnames from 'classnames';
import Card, { CardHeader, CardMedia, CardContent, CardActions } from 'material-ui/Card';
import Collapse from 'material-ui/transitions/Collapse';
import Avatar from 'material-ui/Avatar';
import IconButton from 'material-ui/IconButton';
import Typography from 'material-ui/Typography';
import red from 'material-ui/colors/red';
import FavoriteIcon from 'material-ui-icons/Favorite';
import ShareIcon from 'material-ui-icons/Share';
import ExpandMoreIcon from 'material-ui-icons/ExpandMore';
import MoreVertIcon from 'material-ui-icons/MoreVert';

const styles = theme => ({
  card: {
    maxWidth: 400,
  },
  media: {
    height: 194,
  },
  actions: {
    display: 'flex',
  },
  expand: {
    transform: 'rotate(0deg)',
    transition: theme.transitions.create('transform', {
      duration: theme.transitions.duration.shortest,
    }),
    marginLeft: 'auto',
  },
  expandOpen: {
    transform: 'rotate(180deg)',
  },
  avatar: {
    backgroundColor: red[500],
  },
});

class RecipeReviewCard extends React.Component {
  state = { expanded: false };

  handleExpandClick = () => {
    this.setState({ expanded: !this.state.expanded });
  };

  render() {
    const { classes } = this.props;

    return (

        <Card className={classes.card}>
          <CardHeader
            avatar={
              <Avatar aria-label="Recipe" className={classes.avatar}>
                R
              </Avatar>
            }
            action={
              <IconButton>
                <MoreVertIcon />
              </IconButton>
            }
            title="Shrimp and Chorizo Paella"
            subheader="September 14, 2016"
          />
          <CardMedia
            className={classes.media}
            image="/static/images/cards/paella.jpg"
            title="Contemplative Reptile"
          />
          <CardContent>
            <Typography component="p">
              This impressive paella is a perfect party dish and a fun meal to cook together with
              your guests. Add 1 cup of frozen peas along with the mussels, if you like.
            </Typography>
          </CardContent>
          <CardActions className={classes.actions} disableActionSpacing>
            <IconButton aria-label="Add to favorites">
              <FavoriteIcon />
            </IconButton>
            <IconButton aria-label="Share">
              <ShareIcon />
            </IconButton>
            <IconButton
              className={classnames(classes.expand, {
                [classes.expandOpen]: this.state.expanded,
              })}
              onClick={this.handleExpandClick}
              aria-expanded={this.state.expanded}
              aria-label="Show more"
            >
              <ExpandMoreIcon />
            </IconButton>
          </CardActions>
          <Collapse in={this.state.expanded} timeout="auto" unmountOnExit>
            <CardContent>
              <Typography paragraph type="body2">
                Method:
              </Typography>
              <Typography paragraph>
                Heat 1/2 cup of the broth in a pot until simmering, add saffron and set aside for 10
                minutes.
              </Typography>
              <Typography paragraph>
                Heat oil in a (14- to 16-inch) paella pan or a large, deep skillet over medium-high
                heat. Add chicken, shrimp and chorizo, and cook, stirring occasionally until lightly
                browned, 6 to 8 minutes. Transfer shrimp to a large plate and set aside, leaving
                chicken and chorizo in the pan. Add pimentón, bay leaves, garlic, tomatoes, onion,
                salt and pepper, and cook, stirring often until thickened and fragrant, about 10
                minutes. Add saffron broth and remaining 4 1/2 cups chicken broth; bring to a boil.
              </Typography>
              <Typography paragraph>
                Add rice and stir very gently to distribute. Top with artichokes and peppers, and
                cook without stirring, until most of the liquid is absorbed, 15 to 18 minutes.
                Reduce heat to medium-low, add reserved shrimp and mussels, tucking them down into
                the rice, and cook again without stirring, until mussels have opened and rice is
                just tender, 5 to 7 minutes more. (Discard any mussels that don’t open.)
              </Typography>
              <Typography>
                Set aside off of the heat to let rest for 10 minutes, and then serve.
              </Typography>
            </CardContent>
          </Collapse>
        </Card>

    );
  }
}

RecipeReviewCard.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(RecipeReviewCard);
<|endoftext|>


<commit_before>import EmberObject, { computed } from '@ember/object';
import Evented from '@ember/object/evented';
import { inject as service } from "@ember/service";

import HammerInteraction from '../hammer-interaction';
import HoverHandler from './hover-handler';
import Raycaster from '../raycaster';

export default EmberObject.extend(Evented, {

  canvas: null,
  camera: null,
  renderer: null,
  raycaster: null,
  rotationObject: null,
  hammerHandler: null,
  hoverHandler: null,

  highlighter: service('visualization/application/highlighter'),
  renderingService: service(),

  raycastObjects: computed('rotationObject', function() {
    return this.get('rotationObject.children');
  }),

  setupInteraction(canvas, camera, renderer, parentObject) {
    this.set('canvas', canvas);
    this.set('camera', camera);
    this.set('renderer', renderer);
    this.set('rotationObject', parentObject);

    const self = this;

    // mouseout handler for disabling notifications
    canvas.addEventListener('mouseout', registerMouseOut, false);

    function registerMouseOut(evt) {
      self.onMouseOut(evt);
    }

    // mouseenter handler for disabling notifications
    canvas.addEventListener('mouseenter', registerMouseEnter, false);

    function registerMouseEnter(evt) {
      self.onMouseEnter(evt);
    }

    // zoom handler
    canvas.addEventListener('mousewheel', registerMouseWheel, false);

    function registerMouseWheel(evt) {
      self.onMouseWheelStart(evt);
    }

    // init Hammer
    if (!this.get('hammerHandler')) {
      this.set('hammerHandler', HammerInteraction.create());
      this.get('hammerHandler').setupHammer(canvas);
    }

    if (!this.get('raycaster')) {
      this.set('raycaster', Raycaster.create());
      this.set('raycaster.objectCatalog', 'applicationObjects');
    }

    // init HoverHandler
    if (!this.get('hoverHandler')) {
      this.set('hoverHandler', HoverHandler.create());
    }

    // hover handler
    self.registerHoverHandler();

    this.setupHammerListener();

  },

  onMouseWheelStart(evt) {

    // Hide (old) tooltip
    this.get('hoverHandler').hideTooltip();

    var delta = Math.max(-1, Math.min(1, (evt.wheelDelta || -evt.detail)));

    // zoom in
    if (delta > 0) {
      this.get('camera').position.z -= delta * 3.5;
    }
    // zoom out
    else {
      this.get('camera').position.z -= delta * 3.5;
    }
  },

  onMouseOut() {
    this.set('hoverHandler.enableTooltips', false);
    this.get('hoverHandler').hideTooltip();
  },

  onMouseEnter() {
    this.set('hoverHandler.enableTooltips', true);
  },

  setupHammerListener() {

    const self = this;

    this.get('hammerHandler').on('doubleClick', function(mouse) {
      self.handleDoubleClick(mouse);
    });

    this.get('hammerHandler').on('panning', function(delta, event) {
      self.handlePanning(delta, event);
    });

    this.get('hammerHandler').on('singleClick', function(mouse) {
      self.handleSingleClick(mouse);
    });

  },

  registerHoverHandler() {

    const self = this;

    // custom event for mousemovement end
    (function (delay) {
        var timeout;
        self.get('canvas').addEventListener('mousemove', function (evt) {
            clearTimeout(timeout);
            timeout = setTimeout(function () {
              var event = new CustomEvent("mousestop", {
                  detail: {
                      clientX: evt.clientX,
                      clientY: evt.clientY
                  },
                  bubbles: true,
                  cancelable: true
              });
              evt.target.dispatchEvent(event);
            }, delay);

            // When moving, hide (old) tooltip
            self.get('hoverHandler').hideTooltip();
        });
    })(300);

    this.get('canvas').addEventListener('mousestop', registerHoverHandler, false);

    function registerHoverHandler(evt) {
      self.handleHover(evt);
    }
  },

  updateEntities(app) {
    this.set('rotationObject', app);
    //this.set('highlighter.application', app.userData.model);
  },

  removeHandlers() {
    this.get('hammerHandler.hammerManager').off();
    this.get('canvas').removeEventListener('mousewheel', this.onMouseWheelStart);
    this.get('canvas').removeEventListener('mousestop', this.handleHover);
  },

  applyHighlighting() {
    this.get('highlighter').applyHighlighting();
  },

  // Handler

  handleDoubleClick(mouse) {

    const origin = {};

    origin.x = ((mouse.x - (this.get('renderer').domElement.offsetLeft+0.66)) /
      this.get('renderer').domElement.clientWidth) * 2 - 1;

    origin.y = -((mouse.y - (this.get('renderer').domElement.offsetTop+0.665)) /
      this.get('renderer').domElement.clientHeight) * 2 + 1;

    const intersectedViewObj = this.get('raycaster').raycasting(null, origin,
      this.get('camera'), this.get('raycastObjects'));

    if(intersectedViewObj) {

      // Hide (old) tooltip
      this.get('hoverHandler').hideTooltip();

      const emberModel = intersectedViewObj.object.userData.model;
      const emberModelName = emberModel.constructor.modelName;

      if(emberModelName === "component"){
        emberModel.setOpenedStatus(!emberModel.get('opened'));

        const highlighted = this.get('highlighter.highlightedEntity');

        if(emberModel === highlighted || emberModel.contains(highlighted)) {
          this.get('highlighter').unhighlightAll();
        }

        this.get('renderingService').redrawScene();
      }

    }

  },

  handleSingleClick(mouse) {

    const origin = {};

    origin.x = ((mouse.x - (this.get('renderer').domElement.offsetLeft+0.66)) /
      this.get('renderer').domElement.clientWidth) * 2 - 1;

    origin.y = -((mouse.y - (this.get('renderer').domElement.offsetTop+0.665)) /
      this.get('renderer').domElement.clientHeight) * 2 + 1;

    const intersectedViewObj = this.get('raycaster').raycasting(null, origin,
      this.get('camera'), this.get('raycastObjects'));

    if(intersectedViewObj) {

      // Hide (old) tooltip
      this.get('hoverHandler').hideTooltip();

      const emberModel = intersectedViewObj.object.userData.model;
      const emberModelName = emberModel.constructor.modelName;

      if(emberModelName === "component" && !emberModel.get('opened')){

        this.get('highlighter').highlight(emberModel);
      }
      else if(emberModelName === "clazz") {
        this.get('highlighter').highlight(emberModel);
      }

      this.get('renderingService').redrawScene();

    }
    else {
      if(this.get('highlighter.highlightedEntity')) {
        // clicked in white space and entity is highlighted
        this.get('highlighter').unhighlightAll();
        this.get('renderingService').redrawScene();
      }

    }

  },

  handlePanning(delta, event) {

    if(event.button === 3) {
      // rotate object
      this.get('rotationObject').rotation.x += delta.y / 100;
      this.get('rotationObject').rotation.y += delta.x / 100;
    }

    else if(event.button === 1){
      // translate camera
      var distanceXInPercent = (delta.x /
      parseFloat(this.get('renderer').domElement.clientWidth)) * 100.0;

      var distanceYInPercent = (delta.y /
        parseFloat(this.get('renderer').domElement.clientHeight)) * 100.0;

      var xVal = this.get('camera').position.x + distanceXInPercent * 6.0 * 0.015 * -(Math.abs(this.get('camera').position.z) / 4.0);

      var yVal = this.get('camera').position.y + distanceYInPercent * 4.0 * 0.01 * (Math.abs(this.get('camera').position.z) / 4.0);

      this.get('camera').position.x = xVal;
      this.get('camera').position.y = yVal;
    }

  },

  handleHover(evt) {

    const mouse = {
      x: evt.detail.clientX,
      y: evt.detail.clientY
    };

    const origin = {};

    origin.x = ((mouse.x - (this.get('renderer').domElement.offsetLeft+0.66)) /
      this.get('renderer').domElement.clientWidth) * 2 - 1;

    origin.y = -((mouse.y - (this.get('renderer').domElement.offsetTop+0.665)) /
      this.get('renderer').domElement.clientHeight) * 2 + 1;

    const intersectedViewObj = this.get('raycaster').raycasting(null, origin,
      this.get('camera'), this.get('raycastObjects'));

    if(intersectedViewObj) {

      const emberModel = intersectedViewObj.object.userData.model;

      this.get('hoverHandler').showTooltip(mouse, emberModel);

    }

  }

});<commit_msg>wip: renaming hover to popup, since we want to use hover for the real hovering effect, as shown in the VR mode<commit_after>import EmberObject, { computed } from '@ember/object';
import Evented from '@ember/object/evented';
import { inject as service } from "@ember/service";

import HammerInteraction from '../hammer-interaction';
import PopUpHandler from './hover-handler';
import Raycaster from '../raycaster';

export default EmberObject.extend(Evented, {

  canvas: null,
  camera: null,
  renderer: null,
  raycaster: null,
  rotationObject: null,
  hammerHandler: null,
  popUpHandler: null,

  highlighter: service('visualization/application/highlighter'),
  renderingService: service(),

  raycastObjects: computed('rotationObject', function() {
    return this.get('rotationObject.children');
  }),

  setupInteraction(canvas, camera, renderer, parentObject) {
    this.set('canvas', canvas);
    this.set('camera', camera);
    this.set('renderer', renderer);
    this.set('rotationObject', parentObject);

    const self = this;

    // mouseout handler for disabling notifications
    canvas.addEventListener('mouseout', registerMouseOut, false);

    function registerMouseOut(evt) {
      self.onMouseOut(evt);
    }

    // mouseenter handler for disabling notifications
    canvas.addEventListener('mouseenter', registerMouseEnter, false);

    function registerMouseEnter(evt) {
      self.onMouseEnter(evt);
    }

    // zoom handler
    canvas.addEventListener('mousewheel', registerMouseWheel, false);

    function registerMouseWheel(evt) {
      self.onMouseWheelStart(evt);
    }

    // init Hammer
    if (!this.get('hammerHandler')) {
      this.set('hammerHandler', HammerInteraction.create());
      this.get('hammerHandler').setupHammer(canvas);
    }

    if (!this.get('raycaster')) {
      this.set('raycaster', Raycaster.create());
      this.set('raycaster.objectCatalog', 'applicationObjects');
    }

    // init PopUpHandler
    if (!this.get('popUpHandler')) {
      this.set('popUpHandler', PopUpHandler.create());
    }

    self.registerPopUpHandler();

    this.setupHammerListener();

  },

  onMouseWheelStart(evt) {

    // Hide (old) tooltip
    this.get('popUpHandler').hideTooltip();

    var delta = Math.max(-1, Math.min(1, (evt.wheelDelta || -evt.detail)));

    // zoom in
    if (delta > 0) {
      this.get('camera').position.z -= delta * 3.5;
    }
    // zoom out
    else {
      this.get('camera').position.z -= delta * 3.5;
    }
  },

  onMouseOut() {
    this.set('popUpHandler.enableTooltips', false);
    this.get('popUpHandler').hideTooltip();
  },

  onMouseEnter() {
    this.set('popUpHandler.enableTooltips', true);
  },

  setupHammerListener() {

    const self = this;

    this.get('hammerHandler').on('doubleClick', function(mouse) {
      self.handleDoubleClick(mouse);
    });

    this.get('hammerHandler').on('panning', function(delta, event) {
      self.handlePanning(delta, event);
    });

    this.get('hammerHandler').on('singleClick', function(mouse) {
      self.handleSingleClick(mouse);
    });

  },

  registerPopUpHandler() {

    const self = this;

    // custom event for mousemovement end
    (function (delay) {
        var timeout;
        self.get('canvas').addEventListener('mousemove', function (evt) {
            clearTimeout(timeout);
            timeout = setTimeout(function () {
              var event = new CustomEvent("mousestop", {
                  detail: {
                      clientX: evt.clientX,
                      clientY: evt.clientY
                  },
                  bubbles: true,
                  cancelable: true
              });
              evt.target.dispatchEvent(event);
            }, delay);

            // When moving, hide (old) tooltip
            self.get('popUpHandler').hideTooltip();
        });
    })(300);

    this.get('canvas').addEventListener('mousestop', registerPopUpHandler, false);

    function registerPopUpHandler(evt) {
      self.handlePopUp(evt);
    }
  },

  updateEntities(app) {
    this.set('rotationObject', app);
    //this.set('highlighter.application', app.userData.model);
  },

  removeHandlers() {
    this.get('hammerHandler.hammerManager').off();
    this.get('canvas').removeEventListener('mousewheel', this.onMouseWheelStart);
    this.get('canvas').removeEventListener('mousestop', this.handlePopUp);
  },

  applyHighlighting() {
    this.get('highlighter').applyHighlighting();
  },

  // Handler

  handleDoubleClick(mouse) {

    const origin = {};

    origin.x = ((mouse.x - (this.get('renderer').domElement.offsetLeft+0.66)) /
      this.get('renderer').domElement.clientWidth) * 2 - 1;

    origin.y = -((mouse.y - (this.get('renderer').domElement.offsetTop+0.665)) /
      this.get('renderer').domElement.clientHeight) * 2 + 1;

    const intersectedViewObj = this.get('raycaster').raycasting(null, origin,
      this.get('camera'), this.get('raycastObjects'));

    if(intersectedViewObj) {

      // Hide (old) tooltip
      this.get('popUpHandler').hideTooltip();

      const emberModel = intersectedViewObj.object.userData.model;
      const emberModelName = emberModel.constructor.modelName;

      if(emberModelName === "component"){
        emberModel.setOpenedStatus(!emberModel.get('opened'));

        const highlighted = this.get('highlighter.highlightedEntity');

        if(emberModel === highlighted || emberModel.contains(highlighted)) {
          this.get('highlighter').unhighlightAll();
        }

        this.get('renderingService').redrawScene();
      }

    }

  },

  handleSingleClick(mouse) {

    const origin = {};

    origin.x = ((mouse.x - (this.get('renderer').domElement.offsetLeft+0.66)) /
      this.get('renderer').domElement.clientWidth) * 2 - 1;

    origin.y = -((mouse.y - (this.get('renderer').domElement.offsetTop+0.665)) /
      this.get('renderer').domElement.clientHeight) * 2 + 1;

    const intersectedViewObj = this.get('raycaster').raycasting(null, origin,
      this.get('camera'), this.get('raycastObjects'));

    if(intersectedViewObj) {

      // Hide (old) tooltip
      this.get('popUpHandler').hideTooltip();

      const emberModel = intersectedViewObj.object.userData.model;
      const emberModelName = emberModel.constructor.modelName;

      if(emberModelName === "component" && !emberModel.get('opened')){

        this.get('highlighter').highlight(emberModel);
      }
      else if(emberModelName === "clazz") {
        this.get('highlighter').highlight(emberModel);
      }

      this.get('renderingService').redrawScene();

    }
    else {
      if(this.get('highlighter.highlightedEntity')) {
        // clicked in white space and entity is highlighted
        this.get('highlighter').unhighlightAll();
        this.get('renderingService').redrawScene();
      }

    }

  },

  handlePanning(delta, event) {

    if(event.button === 3) {
      // rotate object
      this.get('rotationObject').rotation.x += delta.y / 100;
      this.get('rotationObject').rotation.y += delta.x / 100;
    }

    else if(event.button === 1){
      // translate camera
      var distanceXInPercent = (delta.x /
      parseFloat(this.get('renderer').domElement.clientWidth)) * 100.0;

      var distanceYInPercent = (delta.y /
        parseFloat(this.get('renderer').domElement.clientHeight)) * 100.0;

      var xVal = this.get('camera').position.x + distanceXInPercent * 6.0 * 0.015 * -(Math.abs(this.get('camera').position.z) / 4.0);

      var yVal = this.get('camera').position.y + distanceYInPercent * 4.0 * 0.01 * (Math.abs(this.get('camera').position.z) / 4.0);

      this.get('camera').position.x = xVal;
      this.get('camera').position.y = yVal;
    }

  },

  handlePopUp(evt) {

    const mouse = {
      x: evt.detail.clientX,
      y: evt.detail.clientY
    };

    const origin = {};

    origin.x = ((mouse.x - (this.get('renderer').domElement.offsetLeft+0.66)) /
      this.get('renderer').domElement.clientWidth) * 2 - 1;

    origin.y = -((mouse.y - (this.get('renderer').domElement.offsetTop+0.665)) /
      this.get('renderer').domElement.clientHeight) * 2 + 1;

    const intersectedViewObj = this.get('raycaster').raycasting(null, origin,
      this.get('camera'), this.get('raycastObjects'));

    if(intersectedViewObj) {

      const emberModel = intersectedViewObj.object.userData.model;

      this.get('popUpHandler').showTooltip(mouse, emberModel);

    }

  }

});<|endoftext|>


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

var srv = http.createServer(function (req, res) {
  res.writeHead(200), {'Content-Type': 'text/plain'});
  res.write('Hello World.');
  res.end();
});

srv.listen(3000);

<commit_msg>removed typos<commit_after>var http = require('http');

var srv = http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.write('Hello, World.');
  res.end();
});

srv.listen(3000);

<|endoftext|>


<commit_before>//https://medium.com/@jeffandersen/building-a-node-js-rest-api-with-express-46b0901f29b6
var express = require('express');
var mysql = require("mysql");
var app = express();
var pool = mysql.createPool({
    connectionLimit : 100,
    host : 'localhost',
    user: 'root',
    password : '',
    database : 'delivery',
    debug : false
});

app.use(function(res, req, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    next();
});
var categoryRouter = express.Router();

categoryRouter.get('/', categoryList, function(req, res) {});
//categoryRouter.get('/:id', function(req, res) {});
//categoryRouter.post('/', function(req, res) {});
app.use('/categories', categoryRouter);

function categoryList(req, res, next) {
    pool.getConnection(function(err, connection) {
        if(err) {
            res.json({
                "code" : 100,
                "status" : "Error in connection database"
            });
            //return;
        }
        console.log("Connected as id " + connection.threadId);
        connection.query("SELECT * from categories", function(err, rows) {
            connection.release();
            if(!err) {
                res.json(rows);
            }
        });
        connection.on('error', function(err) {
            res.json({
                "code" : 100,
                "status" : "Error in connection database"
            });
        });
    });

}

module.exports = app;

app.listen(3000);<commit_msg>server2 post<commit_after>//https://medium.com/@jeffandersen/building-a-node-js-rest-api-with-express-46b0901f29b6
var express = require('express');
var mysql = require("mysql");
var app = express();
var pool = mysql.createPool({
    connectionLimit : 100,
    host : 'localhost',
    user: 'root',
    password : '',
    database : 'delivery',
    debug : false
});

app.use(function(res, req, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    next();
});
var categoryRouter = express.Router();

categoryRouter.get('/', categoryList, function(req, res) {});
categoryRouter.post('/', categoryCreate, function(req, res) {});
//categoryRouter.get('/:id', function(req, res) {});

app.use('/categories', categoryRouter);

function categoryList(req, res, next) {
    pool.getConnection(function(err, connection) {
        if(err) {
            res.json({
                "code" : 100,
                "status" : "Error in connection database"
            });
            //return;
        }
        console.log("Connected as id " + connection.threadId);
        connection.query("SELECT * from categories", function(err, rows) {
            connection.release();
            if(!err) {
                res.json(rows);
            }
        });
        connection.on('error', function(err) {
            res.json({
                "code" : 100,
                "status" : "Error in connection database"
            });
        });
    });
}

function categoryCreate(req, res, next) {
    pool.getConnection(function(err, connection) {
        var body='';
        req.on('data', function (data) {
            body +=data;
        });

        if(err) {
            res.json({
                "code" : 100,
                "status" : "Error in connection database"
            });
            //return;
        }
        connection.on('error', function(err) {
            res.json({
                "code" : 100,
                "status" : "Error in connection database"
            });
        });

        req.on('end', function () {
            console.log("Connected as id " + connection.threadId);
            connection.query("INSERT INTO categories ( name, shortDescription, description, lockField, created, edited ) VALUES ( " + body.name + "," + body.shortDescription + "," + body.description + "," + body.lockField + "," + body.created + "," + body.edited + ")", function (err, rows) {
                connection.release();
                if (!err) {
                    res.json(rows);
                }
            });
        });
    });
}

module.exports = app;

app.listen(3000);<|endoftext|>


<commit_before>
var assert       = require('assert');
var norma        = require('norma');
var debug        = require('debug')('waif:service');
var _            = require('lodash');
var EventEmitter = require('events').EventEmitter;
var request      = require('request');
var express      = require('express');
var util         = require('util');

var Uri          = require('./state/uri');
var Status       = require('./state/status');

/**
* Service constructor.
*
* Instances will contain a map to all of the
* services that have been mounted onto the
* system.
*/
function Service(name) {
  debug('new service: %s', name);
  assert(name, "service not supplied with name");

  this.name       = name;
  this.middleware = [];
  this.uri        = new Uri();
  this.status     = new Status();

  this.initialize();

  return this;
}
util.inherits(Service, EventEmitter);

Service.prototype.setWaif = function(waif) {
  this.waif = waif;
  return this;
};

Service.prototype.initialize = function() {};

Service.prototype.start = function () {
  debug('start listening on service: %s', this.name);

  // new express server
  this.server = express();

  // mount middleware
  _(this.middleware).each(this.mount, this);

  // listen on whatever url we need to
  var listenArgs = this.uri.listenUrl();
  listenArgs.push(listenFn.bind(this));
  this.server.listen.apply(this.server, listenArgs);

  return this;

  //// helpers
  function listenFn(err) {
    debug('%s: start listening on %o', this.name, this.uri.get());
    this.emit('start');
    this.status.state().go('Running');
  }

};

Service.prototype.stop = function() {
  debug('%s: stop forwarding to %s', this.name, this.uri.get());
  this.emit('stop');
  this.status.state().go('start');
};

Service.prototype.mount = function mount(mw) {
  var _args = [];

  mw.path && _args.push(mw.path);
  _args.push(_initHandler.call(this, mw));

  this.server.use.apply(this.server, _args);

  function _initHandler(mw) {
    if (!mw.options) { return mw.handler; }
    var context = {
      waif: this.waif,
      service: this
    };
    return mw.handler.apply(context, mw.options);
  }
};

Service.prototype.use = function() {
  var args = norma('{path:s?, handler:f, options:.*}', arguments);
  this.middleware.push(args);
  debug('use middlware on service: %s', this.name);
  return this;
};

Service.prototype.forward = function(url) {
  this.uri.set(url);
  return this;
};

Service.prototype.listen = function(url) {
  this.uri.set(url);
  return this;
};

Service.prototype.request = function() {
  var args = norma('path:s?, opts:o?, cb:f?', arguments);
  var cb   = args.cb || null;
  var opts = args.opts || {};
  var path = args.path || opts.url || opts.uri;

  opts.uri = this.uri.requestUrl(path);
  opts.url = null;

  _.defaults(opts, { json: true });

  debug('request on service: %s, %o', this.name, args);
  return request.apply(request, _.compact([opts, cb]));
};

// Each service is also an event emitter,
// to allow you to get notifications of
// start, stop and configure.

Service.createInstance = function(name, waif) {
  var _service = new Service(name);
  _service.setWaif(waif);

  // called directly
  var fn = function() {
    debug('request proxy on service: %s', name);
    return _service.request.apply(_service, arguments);
  };

  fn.instance = _service;

  var proxyMethods = [
    'request', 'listen', 'use', 'start', 'stop', 'on'
  ];

  _(proxyMethods).each(function(method) {
    fn[method] = function() {
      _service[method].apply(_service, arguments);
      return fn;
    };
  });

  fn.requestUrl = _service.uri.requestUrl.bind(_service.uri);

  return fn;
};

module.exports = Service;
<commit_msg>deprecate forward function<commit_after>
var assert       = require('assert');
var norma        = require('norma');
var debug        = require('debug')('waif:service');
var _            = require('lodash');
var EventEmitter = require('events').EventEmitter;
var request      = require('request');
var express      = require('express');
var util         = require('util');

var Uri          = require('./state/uri');
var Status       = require('./state/status');

/**
* Service constructor.
*
* Instances will contain a map to all of the
* services that have been mounted onto the
* system.
*/
function Service(name) {
  debug('new service: %s', name);
  assert(name, "service not supplied with name");

  this.name       = name;
  this.middleware = [];
  this.uri        = new Uri();
  this.status     = new Status();

  this.initialize();

  return this;
}
util.inherits(Service, EventEmitter);

Service.prototype.setWaif = function(waif) {
  this.waif = waif;
  return this;
};

Service.prototype.initialize = function() {};

Service.prototype.start = function () {
  debug('start listening on service: %s', this.name);

  // new express server
  this.server = express();

  // mount middleware
  _(this.middleware).each(this.mount, this);

  // listen on whatever url we need to
  if (this.listening) {
    var listenArgs = this.uri.listenUrl();
    listenArgs.push(listenFn.bind(this));
    this.server.listen.apply(this.server, listenArgs);
  }

  return this;

  //// helpers
  function listenFn(err) {
    debug('%s: start listening on %o', this.name, this.uri.get());
    this.emit('start');
    this.status.state().go('Running');
  }

};

Service.prototype.stop = function() {
  debug('%s: stop forwarding to %s', this.name, this.uri.get());
  this.emit('stop');
  this.status.state().go('start');
};

Service.prototype.mount = function mount(mw) {
  var _args = [];

  mw.path && _args.push(mw.path);
  _args.push(_initHandler.call(this, mw));

  this.server.use.apply(this.server, _args);

  function _initHandler(mw) {
    if (!mw.options) { return mw.handler; }
    var context = {
      waif: this.waif,
      service: this
    };
    return mw.handler.apply(context, mw.options);
  }
};

Service.prototype.use = function() {
  var args = norma('{path:s?, handler:f, options:.*}', arguments);
  this.middleware.push(args);
  debug('use middlware on service: %s', this.name);
  return this;
};

Service.prototype.forward = function(url) {
  console.log("Forward has been deprecated.");
  console.log("Instead do '.use(pipe, \"http://domain.com\").listen()'");
};

Service.prototype.listen = function(url) {
  this.listening = true;
  this.uri.set(url);
  return this;
};

Service.prototype.request = function() {
  var args = norma('path:s?, opts:o?, cb:f?', arguments);
  var cb   = args.cb || null;
  var opts = args.opts || {};
  var path = args.path || opts.url || opts.uri;

  opts.uri = this.uri.requestUrl(path);
  opts.url = null;

  _.defaults(opts, { json: true });

  debug('request on service: %s, %o', this.name, args);
  return request.apply(request, _.compact([opts, cb]));
};

// Each service is also an event emitter,
// to allow you to get notifications of
// start, stop and configure.

Service.createInstance = function(name, waif) {
  var _service = new Service(name);
  _service.setWaif(waif);

  // called directly
  var fn = function() {
    debug('request proxy on service: %s', name);
    return _service.request.apply(_service, arguments);
  };

  fn.instance = _service;

  var proxyMethods = [
    'request', 'listen', 'use', 'start', 'stop', 'on'
  ];

  _(proxyMethods).each(function(method) {
    fn[method] = function() {
      _service[method].apply(_service, arguments);
      return fn;
    };
  });

  fn.requestUrl = _service.uri.requestUrl.bind(_service.uri);

  return fn;
};

module.exports = Service;
<|endoftext|>


<commit_before>'use strict';
process.setMaxListeners(0);
require('events').EventEmitter.prototype._maxListeners = 100;

const newrelic = process.env.NEW_RELIC_ENABLED === 'true' ? require('newrelic') : undefined;
const senecaNR = require('seneca-newrelic');
var config = require('./config/config.js')();
var seneca = require('seneca')(config);
var _ = require('lodash');
var store = require('seneca-postgresql-store');
var storeQuery = require('seneca-store-query');
var service = 'cp-users-service';
var log = require('cp-logs-lib')({name: service, level: 'warn'});
config.log = log.log;
var util = require('util');
var dgram = require('dgram');

if (process.env.NODE_ENV !== 'production') {
  seneca.log.info('using config', JSON.stringify(config, null, 4));
}

seneca.options(config);
seneca.decorate('customValidatorLogFormatter', require('./lib/custom-validator-log-formatter'));
seneca.use(store, config['postgresql-store']);
seneca.use(storeQuery);
if (process.env.MAILDEV_ENABLED === 'true') {
  seneca.use('mail', config.maildev);
} else {
  seneca.use('mail', config.email);
}

function shutdown (err) {
  if (err !== undefined) {
    var error = {
      date: new Date().toString(),
      msg: err.stack !== undefined
        ? 'FATAL: UncaughtException, please report: ' + util.inspect(err.stack)
        : 'FATAL: UncaughtException, no stack trace',
      err: util.inspect(err)
    };
    console.error(JSON.stringify(error));
    process.exit(1);
  }
  process.exit(0);
}

require('./migrate-psql-db.js')(function (err) {
  if (err) {
    console.error(err);
    process.exit(-1);
  }
  console.log('Migrations ok');

  seneca.use(require('./email-notifications.js'));
  seneca.use(require('./agreements.js'));
  seneca.use(require('./profiles.js'),
            { postgresql: config['postgresql-store'],
              logger: log.logger
            });
  seneca.use(require('./oauth2.js'), {clients: config.oauth2.clients});
  seneca.use('user');
  seneca.use('auth');
  seneca.use(require('./users.js'),
            { 'email-notifications': config['email-notifications'],
              'postgresql': config['postgresql-store'],
              'users': config['users'],
              'logger': log.logger
            });
  seneca.use(require('./user-profile.js'),
            { postgresql: config['postgresql-store'],
              logger: log.logger
            });
  seneca.use(require('./nodebb-api.js'), config.nodebb);
  seneca.use(require('cp-permissions-plugin'), {
    config: __dirname + '/config/permissions'
  });
  if (!_.isUndefined(newrelic)) {
    seneca.use(senecaNR, {
      newrelic,
      roles: ['cd-users', 'cd-profiles', 'cd-oauth2', 'cd-user-profile'],
      filter (p) {
        p.user = p.user ? p.user.id : undefined;
        p.login = p.login ? p.login.id : undefined;
        return p;
      }
    });
  }
  process.on('SIGINT', shutdown);
  process.on('SIGTERM', shutdown);
  process.on('uncaughtException', shutdown);
  process.on('SIGUSR2', shutdown);

  require('./network.js')(seneca);

  seneca.ready(function (err) {
    if (err) return shutdown(err);
    var message = new Buffer(service);
    var client = dgram.createSocket('udp4');
    client.send(message, 0, message.length, 11404, 'localhost', function (err, bytes) {
      if (err) return shutdown(err);
      client.close();
    });

    var escape = require('seneca-standard-query/lib/relational-util').escapeStr;
    ['load', 'list'].forEach(function (cmd) {
      seneca.wrap('role: entity, cmd: ' + cmd, function filterFields (args, cb) {
        try {
          ['limit$', 'skip$'].forEach(function (field) {
            if (args.q[field] && args.q[field] !== 'NULL' && !/^[0-9]+$/g.test(args.q[field] + '')) {
              throw new Error('Expect limit$, skip$ to be a number');
            }
          });
          if (args.q.sort$) {
            if (args.q.sort$ && typeof args.q.sort$ === 'object') {
              var order = args.q.sort$;
              _.each(order, function (ascdesc, column) {
                if (!/^[a-zA-Z0-9_]+$/g.test(column)) {
                  throw new Error('Unexpect characters in sort$');
                }
              });
            } else {
              throw new Error('Expect sort$ to be an object');
            }
          }
          if (args.q.fields$) {
            args.q.fields$.forEach(function (field, index) {
              args.q.fields$[index] = '\"' + escape(field) + '\"';
            });
          }
          this.prior(args, cb);
        } catch (err) {
          // cb to avoid seneca-transport to hang while waiting for timeout error
          return cb(err);
        }
      });
    });
  });
});
<commit_msg>Bugfix/ensure guid nin (#291)<commit_after>'use strict';
process.setMaxListeners(0);
require('events').EventEmitter.prototype._maxListeners = 100;

const newrelic = process.env.NEW_RELIC_ENABLED === 'true' ? require('newrelic') : undefined;
const senecaNR = require('seneca-newrelic');
var config = require('./config/config.js')();
var seneca = require('seneca')(config);
var _ = require('lodash');
var store = require('seneca-postgresql-store');
var storeQuery = require('seneca-store-query');
var service = 'cp-users-service';
var log = require('cp-logs-lib')({name: service, level: 'warn'});
config.log = log.log;
var util = require('util');
var dgram = require('dgram');

if (process.env.NODE_ENV !== 'production') {
  seneca.log.info('using config', JSON.stringify(config, null, 4));
}

seneca.options(config);
seneca.decorate('customValidatorLogFormatter', require('./lib/custom-validator-log-formatter'));
seneca.use(store, config['postgresql-store']);
seneca.use(storeQuery);
if (process.env.MAILDEV_ENABLED === 'true') {
  seneca.use('mail', config.maildev);
} else {
  seneca.use('mail', config.email);
}

function shutdown (err) {
  if (err !== undefined) {
    var error = {
      date: new Date().toString(),
      msg: err.stack !== undefined
        ? 'FATAL: UncaughtException, please report: ' + util.inspect(err.stack)
        : 'FATAL: UncaughtException, no stack trace',
      err: util.inspect(err)
    };
    console.error(JSON.stringify(error));
    process.exit(1);
  }
  process.exit(0);
}

require('./migrate-psql-db.js')(function (err) {
  if (err) {
    console.error(err);
    process.exit(-1);
  }
  console.log('Migrations ok');

  seneca.use(require('./email-notifications.js'));
  seneca.use(require('./agreements.js'));
  seneca.use(require('./profiles.js'),
            { postgresql: config['postgresql-store'],
              logger: log.logger
            });
  seneca.use(require('./oauth2.js'), {clients: config.oauth2.clients});
  seneca.use('user');
  seneca.use('auth');
  seneca.use(require('./users.js'),
            { 'email-notifications': config['email-notifications'],
              'postgresql': config['postgresql-store'],
              'users': config['users'],
              'logger': log.logger
            });
  seneca.use(require('./user-profile.js'),
            { postgresql: config['postgresql-store'],
              logger: log.logger
            });
  seneca.use(require('./nodebb-api.js'), config.nodebb);
  seneca.use(require('cp-permissions-plugin'), {
    config: __dirname + '/config/permissions'
  });
  if (!_.isUndefined(newrelic)) {
    seneca.use(senecaNR, {
      newrelic,
      roles: ['cd-users', 'cd-profiles', 'cd-oauth2', 'cd-user-profile'],
      filter (p) {
        p.user = p.user ? p.user.id : undefined;
        p.login = p.login ? p.login.id : undefined;
        return p;
      }
    });
  }
  process.on('SIGINT', shutdown);
  process.on('SIGTERM', shutdown);
  process.on('uncaughtException', shutdown);
  process.on('SIGUSR2', shutdown);

  require('./network.js')(seneca);

  seneca.ready(function (err) {
    if (err) return shutdown(err);
    var message = new Buffer(service);
    var client = dgram.createSocket('udp4');
    client.send(message, 0, message.length, 11404, 'localhost', function (err, bytes) {
      if (err) return shutdown(err);
      client.close();
    });

    var escape = require('seneca-standard-query/lib/relational-util').escapeStr;
    ['load', 'list'].forEach(function (cmd) {
      seneca.wrap('role: entity, cmd: ' + cmd, function filterFields (args, cb) {
        try {
          ['limit$', 'skip$'].forEach(function (field) {
            if (args.q[field] && args.q[field] !== 'NULL' && !/^[0-9]+$/g.test(args.q[field] + '')) {
              throw new Error('Expect limit$, skip$ to be a number');
            }
          });
          if (args.q.sort$) {
            if (args.q.sort$ && typeof args.q.sort$ === 'object') {
              var order = args.q.sort$;
              _.each(order, function (ascdesc, column) {
                if (!/^[a-zA-Z0-9_]+$/g.test(column)) {
                  throw new Error('Unexpect characters in sort$');
                }
              });
            } else {
              throw new Error('Expect sort$ to be an object');
            }
          }
          if (args.q.fields$) {
            args.q.fields$.forEach(function (field, index) {
              args.q.fields$[index] = '\"' + escape(field) + '\"';
            });
          }
          // Loop over each props
          Object.values(args.q).forEach((value, key) => {
            const insecureProp = ['nin$', 'in$'];
            const detected = Object.keys(value).filter((val) => insecureProp.indexOf(val) > -1);
            if (detected.length > 0) {
              // Loop over each detected insecureProp being used (nin or in)
              detected.forEach((col, key) => {
                const ids = value[col];
                // Loop over each value of the array of the dangerous field
                ids.forEach((id) => {
                  if (!/^[a-zA-Z0-9-]+$/g.test(id)) {
                    throw new Error(`Unexpected characters in ${col}`);
                  }
                });
              });
            }
          });
          this.prior(args, cb);
        } catch (err) {
          // cb to avoid seneca-transport to hang while waiting for timeout error
          return cb(err);
        }
      });
    });
  });
});
<|endoftext|>


<commit_before>/**
 * @file ListStep component
 * @author chao(chao.zhang@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';

import ListStepItem from '../_ListStepItem';

class ListStep extends Component {

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            activatedStep: props.activatedStep,
            finishedStep: props.finishedStep
        };

        this.touchTapHandler = ::this.touchTapHandler;

    }

    touchTapHandler(activatedStep) {

        const {onChange} = this.props;

        this.setState({
            activatedStep
        }, () => {
            onChange && onChange({
                activatedStep,
                finishedStep: this.state.finishedStep
            });
        });

    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.activatedStep !== this.state.activatedStep
            || nextProps.finishedStep !== this.state.finishedStep) {
            this.setState({
                activatedStep: nextProps.activatedStep,
                finishedStep: nextProps.finishedStep
            });
        }
    }

    render() {

        const {className, style, steps} = this.props;
        const {activatedStep, finishedStep} = this.state;

        return (
            <div className={`list-step ${className}`}
                 style={style}>

                {
                    steps.map((item, index) => {
                        return (
                            <ListStepItem key={index}
                                          index={index}
                                          className={item.className}
                                          style={{
                                              ...item.style,
                                              zIndex: steps.length - index
                                          }}
                                          activatedStep={activatedStep}
                                          finishedStep={finishedStep}
                                          data={item}
                                          onTouchTap={this.touchTapHandler}/>
                        );
                    })
                }

        );

    }
}

ListStep.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The render content of step.
     */
    steps: PropTypes.arrayOf(PropTypes.shape({

        /**
         * The CSS class name of step element.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the step element.
         */
        style: PropTypes.object,

        /**
         * The text value of step.
         */
        title: PropTypes.string

    })).isRequired,

    /**
     * Sets the step as active.
     */
    activatedStep: PropTypes.number,

    /**
     * The final step.
     */
    finishedStep: PropTypes.number,

    /**
     * Callback function fired when step change.
     */
    onChange: PropTypes.func

};

ListStep.defaultProps = {

    className: '',
    style: null,

    steps: [],

    activatedStep: 0,
    finishedStep: 0

};

export default ListStep;<commit_msg>update ListStep<commit_after>/**
 * @file ListStep component
 * @author chao(chao.zhang@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import ListStepItem from '../_ListStepItem';

class ListStep extends Component {

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            activatedStep: props.activatedStep,
            finishedStep: props.finishedStep
        };

        this.touchTapHandler = ::this.touchTapHandler;

    }

    touchTapHandler(activatedStep) {

        const {onChange} = this.props;

        this.setState({
            activatedStep
        }, () => {
            onChange && onChange({
                activatedStep,
                finishedStep: this.state.finishedStep
            });
        });

    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.activatedStep !== this.state.activatedStep
            || nextProps.finishedStep !== this.state.finishedStep) {
            this.setState({
                activatedStep: nextProps.activatedStep,
                finishedStep: nextProps.finishedStep
            });
        }
    }

    render() {

        const {className, style, steps} = this.props,
            {activatedStep, finishedStep} = this.state,

            stepClassName = classNames('list-step', {
                [className]: className
            });

        return (

                {
                    steps.map((item, index) =>
                        <ListStepItem key={index}
                                      index={index}
                                      className={item.className}
                                      style={{
                                          ...item.style,
                                          zIndex: steps.length - index
                                      }}
                                      activatedStep={activatedStep}
                                      finishedStep={finishedStep}
                                      data={item}
                                      onTouchTap={this.touchTapHandler}/>
                    )
                }

        );

    }
}

ListStep.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The render content of step.
     */
    steps: PropTypes.arrayOf(PropTypes.shape({

        /**
         * The CSS class name of step element.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the step element.
         */
        style: PropTypes.object,

        /**
         * The text value of step.
         */
        title: PropTypes.string

    })).isRequired,

    /**
     * Sets the step as active.
     */
    activatedStep: PropTypes.number,

    /**
     * The final step.
     */
    finishedStep: PropTypes.number,

    /**
     * Callback function fired when step change.
     */
    onChange: PropTypes.func

};

ListStep.defaultProps = {

    className: '',
    style: null,

    steps: [],

    activatedStep: 0,
    finishedStep: 0

};

export default ListStep;<|endoftext|>


<commit_before>var
    sys = require('sys'),
    path = require('path'),
    http = require('http'),
    paperboy = require('paperboy'),
    nowjs = require('now'),
    uuid = require('uuid');

var webroot = path.join(path.dirname(__filename), 'web');

server = http.createServer(function (req, res) {
    paperboy .deliver(webroot, req, res);
});

var everyone = nowjs.initialize(server);
var chatrooms = {};

var BACKLOG_SIZE = 100;

function backlog_append(room, clientId, nick, type, data) {
    data = data || {};
    data.type = type;
    data.clientId = clientId;
    data.nick = nick;
    room.backlog.push(data);
    console.log("Adding to backlog: " + data.type);
    room.backlog = room.backlog.slice(-1 * BACKLOG_SIZE);
}

function backlog_replay(client, room) {
    for (var i in room.backlog) {
        var d = room.backlog[i];
        switch (d.type) {
            case 'join':
                client.now.receiveJoin(d.clientId, d.nick);
                break;
            case 'leave':
                client.now.receiveLeave(d.clientId, d.nick);
                break;
            case 'nick':
                client.now.receiveNickChange(d.clientId, d.old_nick, d.nick);
                break;
            case 'message':
                client.now.receiveMessage(d.clientId, d.nick, d.message);
                break;
            default:
                console.log('Unknown event ' + d.type + ', ignoring');
        }
    }
}

everyone.now.createRoom = function(cb) {
    var room_id = Buffer(uuid.generate('binary')).toString('base64').slice(0, 10);
    var group = nowjs.getGroup(room_id);

    chatrooms[room_id] = {
        group: group,
        backlog: [],
        members: {}
    };

    console.log('New room created: ' + room_id);
    cb(room_id);
}

everyone.now.joinRoom = function(room_id, nick, cb) {
    var r = chatrooms[room_id];
    if (!r) {
        console.log("Client " + this.user.clientId + " tried to open unexistent room " + room_id);
        cb(false);
        return;
    }

    var people = [];
    for (k in r.members)
        people.push(r.members[k]);

    cb(true);
    r.group.addUser(this.user.clientId);
    r.members[this.user.clientId] = nick;

    backlog_replay(this, r);
    r.group.now.receiveJoin(this.user.clientId, nick);
    backlog_append(r, this.user.clientId, nick, 'join');
    console.log('Client ' + this.user.clientId + ' joined the room ' + room_id);

    this.now.receiveNicknameList(people);
};

everyone.now.sendMessage = function(room_id, message) {
    var r = chatrooms[room_id];
    if (!r) return;

    var nick = r.members[this.user.clientId];
    if (nick == undefined) return;

    if (!message) return;

    r.group.now.receiveMessage(this.user.clientId, nick, message);

    console.log('Client ' + this.user.clientId + ' sent message in room ' + room_id);
    backlog_append(r, this.user.clientId, nick, 'message', { message: message });
}

everyone.now.changeNickname = function(room_id, nick) {
    var r = chatrooms[room_id];
    if (!r) return;

    var old_nick = r.members[this.user.clientId];
    if (old_nick == undefined) return;

    r.members[this.user.clientId] = nick;
    r.group.now.receiveNickChange(this.user.clientId, old_nick, nick);

    console.log('Client ' + this.user.clientId + ' changed nickname');
    backlog_append(r, this.user.clientId, nick, 'nick', { old_nick: old_nick });
}

everyone.on('disconnect', function() {
    for (var room_id in chatrooms) {
        var r = chatrooms[room_id];
        var nick = r.members[this.user.clientId];

        if (nick == undefined)
            continue;

        delete r.members[this.user.clientId];
        console.log('Client ' + this.user.clientId + ' left room ' + room_id);

        if (Object.keys(r.members).length > 0) {
            r.group.now.receiveLeave(this.user.clientId, nick);
            backlog_append(r, this.user.clientId, nick, 'leave');
        } else{
            delete chatrooms[room_id];
            console.log('Deleted empty room ' + room_id);
        }
    }
});

server.listen(7070);

<commit_msg>message tweaks, typo fixes<commit_after>var
    sys = require('sys'),
    path = require('path'),
    http = require('http'),
    paperboy = require('paperboy'),
    nowjs = require('now'),
    uuid = require('uuid');

var webroot = path.join(path.dirname(__filename), 'web');

server = http.createServer(function (req, res) {
    paperboy.deliver(webroot, req, res);
});

var everyone = nowjs.initialize(server);
var chatrooms = {};

var BACKLOG_SIZE = 100;

function backlog_append(room, clientId, nick, type, data) {
    data = data || {};
    data.type = type;
    data.clientId = clientId;
    data.nick = nick;
    room.backlog.push(data);
    console.log("Adding to backlog: " + data.type);
    room.backlog = room.backlog.slice(-1 * BACKLOG_SIZE);
}

function backlog_replay(client, room) {
    for (var i in room.backlog) {
        var d = room.backlog[i];
        switch (d.type) {
            case 'join':
                client.now.receiveJoin(d.clientId, d.nick);
                break;
            case 'leave':
                client.now.receiveLeave(d.clientId, d.nick);
                break;
            case 'nick':
                client.now.receiveNickChange(d.clientId, d.old_nick, d.nick);
                break;
            case 'message':
                client.now.receiveMessage(d.clientId, d.nick, d.message);
                break;
            default:
                console.log('Unknown event ' + d.type + ', ignoring');
        }
    }
}

everyone.now.createRoom = function(cb) {
    var room_id = Buffer(uuid.generate('binary')).toString('base64').slice(0, 10);
    var group = nowjs.getGroup(room_id);

    chatrooms[room_id] = {
        group: group,
        backlog: [],
        members: {}
    };

    console.log('New room created: ' + room_id);
    cb(room_id);
}

everyone.now.joinRoom = function(room_id, nick, cb) {
    var r = chatrooms[room_id];
    if (!r) {
        console.log("Client " + this.user.clientId + " tried to open non-existent room " + room_id);
        cb(false);
        return;
    }

    var people = [];
    for (k in r.members)
        people.push(r.members[k]);

    cb(true);
    r.group.addUser(this.user.clientId);
    r.members[this.user.clientId] = nick;

    backlog_replay(this, r);
    r.group.now.receiveJoin(this.user.clientId, nick);
    backlog_append(r, this.user.clientId, nick, 'join');
    console.log('Client ' + this.user.clientId + ' joined the room ' + room_id);

    this.now.receiveNicknameList(people);
};

everyone.now.sendMessage = function(room_id, message) {
    var r = chatrooms[room_id];
    if (!r) return;

    var nick = r.members[this.user.clientId];
    if (nick == undefined) return;

    if (!message) return;

    r.group.now.receiveMessage(this.user.clientId, nick, message);

    console.log('Client ' + this.user.clientId + ' sent message in room ' + room_id);
    backlog_append(r, this.user.clientId, nick, 'message', { message: message });
}

everyone.now.changeNickname = function(room_id, nick) {
    var r = chatrooms[room_id];
    if (!r) return;

    var old_nick = r.members[this.user.clientId];
    if (old_nick == undefined) return;

    r.members[this.user.clientId] = nick;
    r.group.now.receiveNickChange(this.user.clientId, old_nick, nick);

    console.log('Client ' + this.user.clientId + ' changed nickname');
    backlog_append(r, this.user.clientId, nick, 'nick', { old_nick: old_nick });
}

everyone.on('disconnect', function() {
    for (var room_id in chatrooms) {
        var r = chatrooms[room_id];
        var nick = r.members[this.user.clientId];

        if (nick == undefined)
            continue;

        delete r.members[this.user.clientId];
        console.log('Client ' + this.user.clientId + ' left room ' + room_id);

        if (Object.keys(r.members).length > 0) {
            r.group.now.receiveLeave(this.user.clientId, nick);
            backlog_append(r, this.user.clientId, nick, 'leave');
        } else{
            delete chatrooms[room_id];
            console.log('Deleted empty room ' + room_id);
        }
    }
});

server.listen(7070);

<|endoftext|>


<commit_before>var gulp = require('gulp')

var autoprefixer = require('gulp-autoprefixer')
var browserify = require('browserify')
var concat = require('gulp-concat')
var del = require('del')
var exorcist = require('exorcist')
var fs = require('fs')
var KarmaServer = require('karma').Server
var minifyCSS = require('gulp-minify-css')
var source = require('vinyl-source-stream')
var standard = require('gulp-standard')
var shell = require('gulp-shell')
var ts = require('gulp-typescript')
var tsify = require('tsify')
var tslint = require('gulp-tslint')
var watchify = require('watchify')
var argv = require('yargs').argv

var browserSync = require('browser-sync').create()

var paths = {
  mapillaryjs: 'mapillaryjs',
  css: './styles/**/*.css',
  build: './build',
  ts: {
    src: './src/**/*.ts',
    tests: './spec/**/*.ts',
    dest: 'build',
    testDest: 'build/spec'
  },
  js: {
    src: './build/**/*.js',
    tests: './spec/**/*.js'
  },
  sourceMaps: './build/bundle.js.map',
  sourceMapsDist: './dist/mapillary-js.map'
}

var config = {
  browserify: {
    entries: ['./src/Mapillary.ts'],
    debug: true,
    standalone: 'Mapillary',
    cache: {},
    packageCache: {}
  },
  uglifyify: {
    global: true,
    ignore: ['**/node_modules/rest/*',
             '**/node_modules/rest/**/*',
             '**/node_modules/when/*',
             '**/node_modules/when/**/*'
            ]
  },
  ts: JSON.parse(fs.readFileSync('./tsconfig.json', 'utf8')).compilerOptions,
  typedoc: {
    includes: [
      './src/Mapillary.ts'
    ],
    options: {
      target: 'ES5',
      module: 'commonjs',
      theme: 'minimal',
      mode: 'file',
      out: './docs-out',
      name: 'mapillary-js'
    }
  }
}

gulp.task('clean', function () {
  return del([
    'docs/ts/**/*',
    'build/**/*',
    'debug/**/*.js'
  ])
})

var parsedOptions = []
for (var key in config.typedoc.options) {
  parsedOptions.push('--' + key + ' ' + config.typedoc.options[key])
}

gulp.task('documentation', shell.task('./node_modules/typedoc/bin/typedoc ' +
                                      parsedOptions.join(' ') +
                                      ' ' +
                                      config.typedoc.includes.join(' ')
                                     ))

gulp.task('js-lint', function () {
  return gulp.src('./Gulpfile.js')
    .pipe(standard())
    .pipe(standard.reporter('default', {
      breakOnError: true
    }))
})

gulp.task('serve', ['ts'], function () {
  browserSync.init({
    server: {
      baseDir: './debug',
      routes: {
        '/dist': 'dist',
        '/build': 'build'
      }
    },
    logFileChanges: false
  })
})

gulp.task('test', function (done) {
  var config
  if (argv.grep) {
    config = extendKarmaConfig(__dirname + '/karma.conf.js', {
      client: {
        args: ['--grep', argv.grep]
      },
      singleRun: true
    })
  } else {
    config = extendKarmaConfig(__dirname + '/karma.conf.js', {
      singleRun: true
    })
  }

  new KarmaServer(config, function (exitCode) {
    if (exitCode) {
      process.exit(exitCode)
    }
  }, done).start()
})

gulp.task('test-watch', function (done) {
  var config
  if (argv.grep) {
    config = extendKarmaConfig(__dirname + '/karma.conf.js', {
      client: {
        args: ['--grep', argv.grep]
      },
      singleRun: false
    })
  } else {
    config = extendKarmaConfig(__dirname + '/karma.conf.js', {
      singleRun: false
    })
  }

  new KarmaServer(config, function (exitCode) {
    if (exitCode) {
      process.exit(exitCode)
    }
  }, done).start()
})

gulp.task('ts-lint', function (cb) {
  var stream = gulp.src(paths.ts.src)
    .pipe(tslint())
    .pipe(tslint.report('verbose'))
  return stream
})

gulp.task('tsd', shell.task('./node_modules/tsd/build/cli.js install'))

gulp.task('typescript', ['ts-lint', 'typescript-src', 'typescript-test'], function (cb) { cb() })

gulp.task('typescript-src', function () {
  var stream = gulp.src(paths.ts.src)
    .pipe(ts(config.ts))
    .pipe(gulp.dest(paths.ts.dest))
  return stream
})

gulp.task('watch', ['css'], function () {
  gulp.watch([paths.ts.src, paths.ts.tests], ['dev:ts'])
  gulp.watch([paths.css], ['css'])
})

gulp.task('default', ['serve', 'watch'])

// Helpers
function extendKarmaConfig (path, conf) {
  conf.configFile = path
  return conf
}

gulp.task('prepublish', ['ts-lint', 'css'], function () {
  browserify(config.browserify)
    .plugin(tsify, config.ts)
    .transform('brfs')
    .transform('envify')
    .transform(config.uglifyify, 'uglifyify')
    .bundle()
    .on('error', function (error) {
      console.error(error.toString())
    })
    .pipe(exorcist(paths.sourceMapsDist))
    .pipe(source('mapillary-js.min.js'))
    .pipe(gulp.dest('./dist'))
})

// TODO: Refine this task
gulp.task('ts', ['ts-lint'], function () {
  return browserify(config.browserify)
    .plugin(watchify)
    .plugin(tsify, config.ts)
    .transform('brfs')
    .transform('envify')
    .transform(config.uglifyify, 'uglifyify')
    .bundle()
    .on('error', function (error) {
      console.error(error.toString())
    })
    .pipe(exorcist(paths.sourceMaps))
    .pipe(source('bundle.js'))
    .pipe(gulp.dest('./build'))
})

gulp.task('dev:ts', ['ts --env=DEV'], function () {
  browserSync.reload()
})

gulp.task('copy-style-assets', function () {
  gulp.src('styles/**/!(*.css)')
    .pipe(gulp.dest('dist'))
})

gulp.task('css', ['copy-style-assets'], function () {
  gulp.src([
    'styles/mapillary-js.css',
    'styles/**/!(mapillary-js)*.css'
  ])
    .pipe(autoprefixer('last 2 version', 'safari 7', 'ie 11'))
    .pipe(minifyCSS())
    .pipe(concat('mapillary-js.min.css'))
    .pipe(gulp.dest('dist'))
    .pipe(browserSync.stream())
})
<commit_msg>Apply uglifyify transfrom only in the `prepublish` task<commit_after>var gulp = require('gulp')

var autoprefixer = require('gulp-autoprefixer')
var browserify = require('browserify')
var concat = require('gulp-concat')
var del = require('del')
var exorcist = require('exorcist')
var fs = require('fs')
var KarmaServer = require('karma').Server
var minifyCSS = require('gulp-minify-css')
var source = require('vinyl-source-stream')
var standard = require('gulp-standard')
var shell = require('gulp-shell')
var ts = require('gulp-typescript')
var tsify = require('tsify')
var tslint = require('gulp-tslint')
var watchify = require('watchify')
var argv = require('yargs').argv

var browserSync = require('browser-sync').create()

var paths = {
  mapillaryjs: 'mapillaryjs',
  css: './styles/**/*.css',
  build: './build',
  ts: {
    src: './src/**/*.ts',
    tests: './spec/**/*.ts',
    dest: 'build',
    testDest: 'build/spec'
  },
  js: {
    src: './build/**/*.js',
    tests: './spec/**/*.js'
  },
  sourceMaps: './build/bundle.js.map',
  sourceMapsDist: './dist/mapillary-js.map'
}

var config = {
  browserify: {
    entries: ['./src/Mapillary.ts'],
    debug: true,
    standalone: 'Mapillary',
    cache: {},
    packageCache: {}
  },
  uglifyify: {
    global: true,
    ignore: ['**/node_modules/rest/*',
             '**/node_modules/rest/**/*',
             '**/node_modules/when/*',
             '**/node_modules/when/**/*'
            ]
  },
  ts: JSON.parse(fs.readFileSync('./tsconfig.json', 'utf8')).compilerOptions,
  typedoc: {
    includes: [
      './src/Mapillary.ts'
    ],
    options: {
      target: 'ES5',
      module: 'commonjs',
      theme: 'minimal',
      mode: 'file',
      out: './docs-out',
      name: 'mapillary-js'
    }
  }
}

gulp.task('clean', function () {
  return del([
    'docs/ts/**/*',
    'build/**/*',
    'debug/**/*.js'
  ])
})

var parsedOptions = []
for (var key in config.typedoc.options) {
  parsedOptions.push('--' + key + ' ' + config.typedoc.options[key])
}

gulp.task('documentation', shell.task('./node_modules/typedoc/bin/typedoc ' +
                                      parsedOptions.join(' ') +
                                      ' ' +
                                      config.typedoc.includes.join(' ')
                                     ))

gulp.task('js-lint', function () {
  return gulp.src('./Gulpfile.js')
    .pipe(standard())
    .pipe(standard.reporter('default', {
      breakOnError: true
    }))
})

gulp.task('serve', ['ts'], function () {
  browserSync.init({
    server: {
      baseDir: './debug',
      routes: {
        '/dist': 'dist',
        '/build': 'build'
      }
    },
    logFileChanges: false
  })
})

gulp.task('test', function (done) {
  var config
  if (argv.grep) {
    config = extendKarmaConfig(__dirname + '/karma.conf.js', {
      client: {
        args: ['--grep', argv.grep]
      },
      singleRun: true
    })
  } else {
    config = extendKarmaConfig(__dirname + '/karma.conf.js', {
      singleRun: true
    })
  }

  new KarmaServer(config, function (exitCode) {
    if (exitCode) {
      process.exit(exitCode)
    }
  }, done).start()
})

gulp.task('test-watch', function (done) {
  var config
  if (argv.grep) {
    config = extendKarmaConfig(__dirname + '/karma.conf.js', {
      client: {
        args: ['--grep', argv.grep]
      },
      singleRun: false
    })
  } else {
    config = extendKarmaConfig(__dirname + '/karma.conf.js', {
      singleRun: false
    })
  }

  new KarmaServer(config, function (exitCode) {
    if (exitCode) {
      process.exit(exitCode)
    }
  }, done).start()
})

gulp.task('ts-lint', function (cb) {
  var stream = gulp.src(paths.ts.src)
    .pipe(tslint())
    .pipe(tslint.report('verbose'))
  return stream
})

gulp.task('tsd', shell.task('./node_modules/tsd/build/cli.js install'))

gulp.task('typescript', ['ts-lint', 'typescript-src', 'typescript-test'], function (cb) { cb() })

gulp.task('typescript-src', function () {
  var stream = gulp.src(paths.ts.src)
    .pipe(ts(config.ts))
    .pipe(gulp.dest(paths.ts.dest))
  return stream
})

gulp.task('watch', ['css'], function () {
  gulp.watch([paths.ts.src, paths.ts.tests], ['dev:ts'])
  gulp.watch([paths.css], ['css'])
})

gulp.task('default', ['serve', 'watch'])

// Helpers
function extendKarmaConfig (path, conf) {
  conf.configFile = path
  return conf
}

gulp.task('prepublish', ['ts-lint', 'css'], function () {
  browserify(config.browserify)
    .plugin(tsify, config.ts)
    .transform('brfs')
    .transform('envify')
    .transform(config.uglifyify, 'uglifyify')
    .bundle()
    .on('error', function (error) {
      console.error(error.toString())
    })
    .pipe(exorcist(paths.sourceMapsDist))
    .pipe(source('mapillary-js.min.js'))
    .pipe(gulp.dest('./dist'))
})

// TODO: Refine this task
gulp.task('ts', ['ts-lint'], function () {
  return browserify(config.browserify)
    .plugin(watchify)
    .plugin(tsify, config.ts)
    .transform('brfs')
    .transform('envify')
    .bundle()
    .on('error', function (error) {
      console.error(error.toString())
    })
    .pipe(exorcist(paths.sourceMaps))
    .pipe(source('bundle.js'))
    .pipe(gulp.dest('./build'))
})

gulp.task('dev:ts', ['ts --env=DEV'], function () {
  browserSync.reload()
})

gulp.task('copy-style-assets', function () {
  gulp.src('styles/**/!(*.css)')
    .pipe(gulp.dest('dist'))
})

gulp.task('css', ['copy-style-assets'], function () {
  gulp.src([
    'styles/mapillary-js.css',
    'styles/**/!(mapillary-js)*.css'
  ])
    .pipe(autoprefixer('last 2 version', 'safari 7', 'ie 11'))
    .pipe(minifyCSS())
    .pipe(concat('mapillary-js.min.css'))
    .pipe(gulp.dest('dist'))
    .pipe(browserSync.stream())
})
<|endoftext|>