<commit_before>zr.controller('IdeController', ['$scope', '$modal', '$http', '$timeout', '$location', 'config', 'realtime', 'drive', 'resources', 'zrdb',
		function($scope, $modal, $http, $timeout, $location, config, realtime, drive, resources, zrdb) {
	//Hide the footer
	document.getElementById('footer').style['display'] = 'none';
	var realtimeDocument = resources[0];
	$scope.model = realtimeDocument.getModel();
	var graphical = $scope.model.getRoot().get('graphical');
	$scope.graphical = graphical;
	$scope.editorMode = graphical ? 'graphical' : 'text';
	$scope.pages = $scope.model.getRoot().get('pages');
	$scope.currentPageName = '';
	$scope.currentPage = {
		text: ''
	};
	$scope.simRunning = false;
	if(graphical && resources[1].data.hllBlockSet) {
		$scope.blocklyTreeUrl = '/blockly/games/' + resources[1].data.hllBlockSet + 'tree.xml';
	}
	else {
		$scope.blocklyTreeUrl = null;
	}

	var collabLog = $scope.model.getRoot().get('log');
	$scope.log = null;
	var updateLog = function() {
		$scope.log = collabLog.items().sort(function(a,b) {
			return parseInt(b[0]) - parseInt(a[0]);
		});
	};
	updateLog();

	$scope.logOpen = false;
	$scope.chat = {
		message: ''
	};

	$scope.projectName = '';
	var setProjectName = function() {
		drive.getFileMetadata(realtime.id, function(data) {
			$timeout(function() {
				$scope.projectName = data.title;
			});
		});
	}
	setProjectName();

	$scope.blocklyText='';
	$scope.aceEditor = null;
	$scope.aceOptions = {
		theme:'chrome',
		mode: 'c_cpp',
		showPrintMargin: false,
		onLoad: function(ace) {
			$scope.aceEditor = ace;
		}
	};

	$scope.newProject = function() {
		drive.newProject();
	}

	$scope.openProject = function() {
		drive.openProject();
	}

	$scope.focusLog = function(item) {
		if(item.content) {
			var template = '
<button type="button" class="close" aria-hidden="true" ng-click="$dismiss()">×</button>
'
				+ item.title + '

'
				+ item.content + '
';
			$modal.open({
				template: template
			});
		}
	};

	var logRemoteChange = function(e) {
		if(!e.isLocal) {
			$scope.$apply(updateLog);
		}
	};
	collabLog.addEventListener(gapi.drive.realtime.EventType.VALUE_CHANGED, logRemoteChange);

	var getMyName = function() {
		var collaborators = realtimeDocument.getCollaborators();
		var len = collaborators.length;
		for(var i = 0; i < len; i++) {
			if(collaborators[i].isMe) {
				return collaborators[i].displayName;
			}
		}
		return 'Anonymous';
	}

	//Opens the new page dialog
	$scope.newPage = function() {
		$modal.open({
			templateUrl: '/partials/new-page-modal.html',
			controller: 'NewPageController',
			resolve: {
				isGraphical: function(){ return graphical; }
			}
		}).result.then(function(result) {
			if(result.title==='') {
				alert('Enter a page name.');
				return;
			}
			if($scope.pages.has(result.title)) {
				alert('Page "' + result.title + '" already exists.');
				return;
			}
			if(!graphical) {
				$scope.pages.set(result.title, $scope.model.createString(''));
			}
			else {
				if(!Blockly.Blocks.CNameValidator(result.title)) {
					alert('Not a valid C function name.');
					return;
				}
				var pageRoot = $scope.model.createMap();
				$scope.pages.set(result.title, pageRoot);
				//This code copied from blockly/core/realtime.js
				var blocksMap = $scope.model.createMap();
				pageRoot.set('blocks', blocksMap);
				var topBlocks = $scope.model.createList();
				pageRoot.set('topBlocks', topBlocks);
				pageRoot.set('type',result.returnValue ? 'return' : 'noreturn');
			}
			$scope.setActivePage(result.title);
		});
	};

	$scope.go = function (path) {
		$location.path( path );
	};

	//Opens the simulation dialog
	$scope.openSimDialog = function() {
		$modal.open({
			templateUrl: '/partials/simulation-modal.html',
			controller: 'SimulationController',
			resolve: {
				gameResource: function() {
					return resources[1];
				}
			},
			windowClass: {
				'max-width': '800px'
			}
		}).result.then(function(data) {
			simulate(data);
		});
	};

	//Opens the submission dialog
	$scope.openSubmitDialog = function() {
		$modal.open({
			templateUrl: '/partials/submit-modal.html',
			controller: 'SubmitModalController',
			resolve: {
				projectText: function() { return realtime.getDocAsString($scope.model.getRoot()); }
			}
		}).result.then(function(data) {
		});
	};

	//Opens the project rename dialog
	$scope.renameProject = function() {
		$modal.open({
			templateUrl: '/partials/rename-project-modal.html',
			controller: 'RenameProjectController',
			resolve: {
				callback: function() { return setProjectName; }
			}
		});
	};

	$scope.deletePage = function(title) {
		if(title === 'main') {
			alert('The main page cannot be deleted.');
			return;
		}
		if(!$scope.pages.has(title)) {
			alert('Page "' + title + '" does not exist.');
			return;
		}
		if(graphical && title === 'init') {
			alert('The init page cannot be deleted.');
			return;
		}
		//Dispose of blocks properly to avoid ghost procedures, etc.
		if(graphical) {
			Blockly.mainWorkspace.clear();
		}
		$scope.pages.delete(title);
		$scope.setActivePage('main');
	};

	//Changes the active page
	$scope.setActivePage = function(title) {
		if(!$scope.pages.has(title)) {
			alert('Page "' + title + '" does not exist.');
			return;
		}
		$scope.currentPageName = title;
		$scope.currentPage = $scope.pages.get(title);
		if(graphical && Blockly.mainWorkspace && Blockly.mainWorkspace.getMetrics()) {
			Blockly.Realtime.loadPage($scope.currentPageName);
			//Reload the Blockly toolbox to account for changes in blocks
			$timeout(function() {
				if(Blockly.Toolbox.HtmlDiv && graphical) {
					Blockly.Toolbox.HtmlDiv.innerHTML = '';
					Blockly.languageTree = document.getElementById('blockly-toolbox');
					Blockly.Toolbox.init();
				}
			}, 0);
		}
		//If Blockly is not yet loaded, it will load the page on its own when it finishes

		//Exit the read-only C mode in a graphical project
		$scope.editorMode = graphical ? 'graphical' : 'text';
	};

	$scope.testGen = function() {
		alert(realtime.getDocAsString($scope.model.getRoot()));
	}

	var parseErrorMessage = function(msg, startLines) {
		var re = /^\/zr.cpp:([0-9]+):([0-9]+): (error|warning): (.*)$/gm;
		var toIgnore = '‘game’ defined but not used [-Wunused-variable]\n'
			+ '‘api’ defined but not used [-Wunused-variable]\n';
		var out = '';
		do {
		    var err = re.exec(msg);
		    //The toIgnore check ignores certain useless warnings
		    if (err && toIgnore.indexOf(err[4]) === -1) {
		    	//Get rid of GCC junk
		    	err[4] = err[4].replace('[-Wunused-variable]','');
		    	//Find the right page
		    	var lineNum = parseInt(err[1]);
		    	var page = {
		    		name: 'NONE',
		    		line: 26
		    	};
		    	for(var i = startLines.length; i--; ) {
		    		if(startLines[i].line < lineNum) {
		    			page = startLines[i];
		    			break;
		    		}
		    	}
		        out = out.concat(err[3].toUpperCase() + ' on page ' + page.name
		        	+ ' at line ' + String(lineNum - page.line) + ', col ' + err[2] + ': ' + err[4] + '\n');
		    }
		} while (err);
		console.log(startLines);
		return out;
	};

	$scope.compile = function(codesize) {
		var code = realtime.getDocAsString($scope.model.getRoot(), true);
		var data = {
			gameId: $scope.model.getRoot().get('gameId'),
			code: code[0],
			codesize: codesize
		};

		zrdb.compile(data).then(function(response) { //Success callback
			//Convert from number of words to percentage
			var size = response.codesizePct;
			if(size > 0) {
				size = Math.ceil((size - resources[1].data.emptyProjectSize) * 100 / resources[1].data.codesizeAllocation)
			}
			else {
				size = null;
			}
			$scope.logInsert('Compilation succeeded. '
					+ (size !== null ? size + '% codesize usage.\n' : '\n'),
					response.message);
		}, function(response) { //Error callback
			$scope.logInsert(response.message.split('\n')[0] + '\n', parseErrorMessage(response.message, code[1]));
		}).finally(function() {
			$scope.logOpen = true;
			$scope.simRunning = false;
		});

		$scope.simRunning = true;
	}

	var simulate = function(dataIn) {
		var data = {
			"gameId": $scope.model.getRoot().get('gameId'),
			"snapshot1": 94857,
			"snapshot2": 203458,
			"simConfig": {
				"timeout": dataIn.timeout,
				"state1": dataIn.sph1init,
				"state2": dataIn.sph2init,
				"gameVariables": dataIn.gameVars
			}
		};

		if(dataIn.sph === 1) {
			data['code1'] = realtime.getDocAsString($scope.model.getRoot());
			data['code2'] = dataIn.opponentCode;
		}
		else {
			data['code2'] = realtime.getDocAsString($scope.model.getRoot());
			data['code1'] = dataIn.opponentCode;
		}

		zrdb.compile(data, true).then(function(response) { //Success callback
			$scope.logInsert('Simulation succeeded.\n', response.message, response.id);
		}, function(response) { //Error callback
			$scope.logInsert('Simulation failed.\n', response.message);
		}).finally(function() {
			$scope.logOpen = true;
			$scope.simRunning = false;
		});

		$scope.simRunning = true;
	}

	$scope.download = function() {
		//Create phantom link with data URI to download content. Needed to specify the name of the file with
		//download attribute (window.open gives the file a random name in Firefox.)
		var link = document.createElement('a');
		link.setAttribute('href', 'data:text/x-c,' + encodeURIComponent(realtime.getDocAsString($scope.model.getRoot())));
		link.setAttribute('download', 'project.cpp');
		link.setAttribute('target', '_blank');
		var randomDiv = document.getElementById('main-collapse');
		randomDiv.appendChild(link);
		//Need to pause here for some reason
		setTimeout(function() {
			link.click();
			randomDiv.removeChild(link);
		}, 100);
	};

	$scope.sendChatMessage = function() {
		$scope.logInsert($scope.chat.message, '');
		$scope.chat.message = '';
	};

	$scope.logInsert = function(title, content, simId) {
		//Log entries are identified by timestamp, plus some random digits to avoid collisions
		var key = String(new Date().getTime() + Math.random());
		var value = {
			user: getMyName(),
			title: title,
			content: content,
			simId: simId
		}
		collabLog.set(key, value);
		updateLog();
	};

	$scope.toggleBlocklyText = function(title, content) {
		if($scope.editorMode === 'graphical-c') {
			$scope.editorMode = 'graphical';
		}
		else if($scope.editorMode === 'graphical') {
			$scope.blocklyText = Blockly.zr_cpp.workspaceToCode();
			$scope.editorMode = 'graphical-c';
		}
	}

	var shareClient = null;
	$scope.share = function() {
		if(!shareClient) {
			shareClient = new gapi.drive.share.ShareClient(config.appId);
		}
		shareClient.setItemIds(realtime.id);
		shareClient.showSettingsDialog();
	};

	//Blockly cut/copy/paste callbacks
	$scope.cut = function() {
		if(graphical) {
	        Blockly.copy_(Blockly.selected);
	        Blockly.selected.dispose(true, true);
		}
	}

	$scope.copy = function() {
		if(graphical) {
	        Blockly.copy_(Blockly.selected);
		}
	}

	$scope.paste = function() {
		if(graphical && Blockly.clipboard_) {
	        Blockly.mainWorkspace.paste(Blockly.clipboard_);
		}
	}

	//Callback to load Blockly when everything is rendered
	if(graphical) {
		$scope.loadBlockly = function() {
			Blockly.inject(document.getElementById('blockly-frame'),{path:'/blockly/',toolbox: document.getElementById('blockly-toolbox')});
			//Scroll over to keep procedure in center
			var dims = Blockly.mainWorkspace.getMetrics();
			Blockly.mainWorkspace.scrollX += dims.viewWidth / 3;
			Blockly.mainWorkspace.scrollY += dims.viewHeight / 4;
			Blockly.Realtime.loadPage($scope.currentPageName);
		};
		//This triggers after the DOM is all compiled/rendered
		if(!$scope.blocklyTreeUrl) {
			$timeout($scope.loadBlockly);
		}
	}

	//Listener to log leaving the document
	var closeAction = function() {
		//$scope.logInsert('Stopped editing','');
		collabLog.removeEventListener(gapi.drive.realtime.EventType.VALUE_CHANGED, logRemoteChange);
		return null;
	};
	//TODO: This is disabled because it has lots of timing issues
	//For leaving ZR
	//window.addEventListener('beforeunload',closeAction,false);
	//For switching views within Angular
	$scope.$on("$destroy", closeAction);

	//Last initialization
	$scope.logInsert('Started editing','');
	$scope.setActivePage('main');
}]);
<commit_msg>Hiding footer in IDE and vis<commit_after>zr.controller('IdeController', ['$scope', '$modal', '$http', '$timeout', '$location', 'config', 'realtime', 'drive', 'resources', 'zrdb',
		function($scope, $modal, $http, $timeout, $location, config, realtime, drive, resources, zrdb) {
	//Hide the footer
	document.getElementById('footer').style['display'] = 'none';
	document.getElementById('push').style['display'] = 'none';
	var realtimeDocument = resources[0];
	$scope.model = realtimeDocument.getModel();
	var graphical = $scope.model.getRoot().get('graphical');
	$scope.graphical = graphical;
	$scope.editorMode = graphical ? 'graphical' : 'text';
	$scope.pages = $scope.model.getRoot().get('pages');
	$scope.currentPageName = '';
	$scope.currentPage = {
		text: ''
	};
	$scope.simRunning = false;
	if(graphical && resources[1].data.hllBlockSet) {
		$scope.blocklyTreeUrl = '/blockly/games/' + resources[1].data.hllBlockSet + 'tree.xml';
	}
	else {
		$scope.blocklyTreeUrl = null;
	}

	var collabLog = $scope.model.getRoot().get('log');
	$scope.log = null;
	var updateLog = function() {
		$scope.log = collabLog.items().sort(function(a,b) {
			return parseInt(b[0]) - parseInt(a[0]);
		});
	};
	updateLog();

	$scope.logOpen = false;
	$scope.chat = {
		message: ''
	};

	$scope.projectName = '';
	var setProjectName = function() {
		drive.getFileMetadata(realtime.id, function(data) {
			$timeout(function() {
				$scope.projectName = data.title;
			});
		});
	}
	setProjectName();

	$scope.blocklyText='';
	$scope.aceEditor = null;
	$scope.aceOptions = {
		theme:'chrome',
		mode: 'c_cpp',
		showPrintMargin: false,
		onLoad: function(ace) {
			$scope.aceEditor = ace;
		}
	};

	$scope.newProject = function() {
		drive.newProject();
	}

	$scope.openProject = function() {
		drive.openProject();
	}

	$scope.focusLog = function(item) {
		if(item.content) {
			var template = '
<button type="button" class="close" aria-hidden="true" ng-click="$dismiss()">×</button>
'
				+ item.title + '

'
				+ item.content + '
';
			$modal.open({
				template: template
			});
		}
	};

	var logRemoteChange = function(e) {
		if(!e.isLocal) {
			$scope.$apply(updateLog);
		}
	};
	collabLog.addEventListener(gapi.drive.realtime.EventType.VALUE_CHANGED, logRemoteChange);

	var getMyName = function() {
		var collaborators = realtimeDocument.getCollaborators();
		var len = collaborators.length;
		for(var i = 0; i < len; i++) {
			if(collaborators[i].isMe) {
				return collaborators[i].displayName;
			}
		}
		return 'Anonymous';
	}

	//Opens the new page dialog
	$scope.newPage = function() {
		$modal.open({
			templateUrl: '/partials/new-page-modal.html',
			controller: 'NewPageController',
			resolve: {
				isGraphical: function(){ return graphical; }
			}
		}).result.then(function(result) {
			if(result.title==='') {
				alert('Enter a page name.');
				return;
			}
			if($scope.pages.has(result.title)) {
				alert('Page "' + result.title + '" already exists.');
				return;
			}
			if(!graphical) {
				$scope.pages.set(result.title, $scope.model.createString(''));
			}
			else {
				if(!Blockly.Blocks.CNameValidator(result.title)) {
					alert('Not a valid C function name.');
					return;
				}
				var pageRoot = $scope.model.createMap();
				$scope.pages.set(result.title, pageRoot);
				//This code copied from blockly/core/realtime.js
				var blocksMap = $scope.model.createMap();
				pageRoot.set('blocks', blocksMap);
				var topBlocks = $scope.model.createList();
				pageRoot.set('topBlocks', topBlocks);
				pageRoot.set('type',result.returnValue ? 'return' : 'noreturn');
			}
			$scope.setActivePage(result.title);
		});
	};

	$scope.go = function (path) {
		$location.path( path );
	};

	//Opens the simulation dialog
	$scope.openSimDialog = function() {
		$modal.open({
			templateUrl: '/partials/simulation-modal.html',
			controller: 'SimulationController',
			resolve: {
				gameResource: function() {
					return resources[1];
				}
			},
			windowClass: {
				'max-width': '800px'
			}
		}).result.then(function(data) {
			simulate(data);
		});
	};

	//Opens the submission dialog
	$scope.openSubmitDialog = function() {
		$modal.open({
			templateUrl: '/partials/submit-modal.html',
			controller: 'SubmitModalController',
			resolve: {
				projectText: function() { return realtime.getDocAsString($scope.model.getRoot()); }
			}
		}).result.then(function(data) {
		});
	};

	//Opens the project rename dialog
	$scope.renameProject = function() {
		$modal.open({
			templateUrl: '/partials/rename-project-modal.html',
			controller: 'RenameProjectController',
			resolve: {
				callback: function() { return setProjectName; }
			}
		});
	};

	$scope.deletePage = function(title) {
		if(title === 'main') {
			alert('The main page cannot be deleted.');
			return;
		}
		if(!$scope.pages.has(title)) {
			alert('Page "' + title + '" does not exist.');
			return;
		}
		if(graphical && title === 'init') {
			alert('The init page cannot be deleted.');
			return;
		}
		//Dispose of blocks properly to avoid ghost procedures, etc.
		if(graphical) {
			Blockly.mainWorkspace.clear();
		}
		$scope.pages.delete(title);
		$scope.setActivePage('main');
	};

	//Changes the active page
	$scope.setActivePage = function(title) {
		if(!$scope.pages.has(title)) {
			alert('Page "' + title + '" does not exist.');
			return;
		}
		$scope.currentPageName = title;
		$scope.currentPage = $scope.pages.get(title);
		if(graphical && Blockly.mainWorkspace && Blockly.mainWorkspace.getMetrics()) {
			Blockly.Realtime.loadPage($scope.currentPageName);
			//Reload the Blockly toolbox to account for changes in blocks
			$timeout(function() {
				if(Blockly.Toolbox.HtmlDiv && graphical) {
					Blockly.Toolbox.HtmlDiv.innerHTML = '';
					Blockly.languageTree = document.getElementById('blockly-toolbox');
					Blockly.Toolbox.init();
				}
			}, 0);
		}
		//If Blockly is not yet loaded, it will load the page on its own when it finishes

		//Exit the read-only C mode in a graphical project
		$scope.editorMode = graphical ? 'graphical' : 'text';
	};

	$scope.testGen = function() {
		alert(realtime.getDocAsString($scope.model.getRoot()));
	}

	var parseErrorMessage = function(msg, startLines) {
		var re = /^\/zr.cpp:([0-9]+):([0-9]+): (error|warning): (.*)$/gm;
		var toIgnore = '‘game’ defined but not used [-Wunused-variable]\n'
			+ '‘api’ defined but not used [-Wunused-variable]\n';
		var out = '';
		do {
		    var err = re.exec(msg);
		    //The toIgnore check ignores certain useless warnings
		    if (err && toIgnore.indexOf(err[4]) === -1) {
		    	//Get rid of GCC junk
		    	err[4] = err[4].replace('[-Wunused-variable]','');
		    	//Find the right page
		    	var lineNum = parseInt(err[1]);
		    	var page = {
		    		name: 'NONE',
		    		line: 26
		    	};
		    	for(var i = startLines.length; i--; ) {
		    		if(startLines[i].line < lineNum) {
		    			page = startLines[i];
		    			break;
		    		}
		    	}
		        out = out.concat(err[3].toUpperCase() + ' on page ' + page.name
		        	+ ' at line ' + String(lineNum - page.line) + ', col ' + err[2] + ': ' + err[4] + '\n');
		    }
		} while (err);
		console.log(startLines);
		return out;
	};

	$scope.compile = function(codesize) {
		var code = realtime.getDocAsString($scope.model.getRoot(), true);
		var data = {
			gameId: $scope.model.getRoot().get('gameId'),
			code: code[0],
			codesize: codesize
		};

		zrdb.compile(data).then(function(response) { //Success callback
			//Convert from number of words to percentage
			var size = response.codesizePct;
			if(size > 0) {
				size = Math.ceil((size - resources[1].data.emptyProjectSize) * 100 / resources[1].data.codesizeAllocation)
			}
			else {
				size = null;
			}
			$scope.logInsert('Compilation succeeded. '
					+ (size !== null ? size + '% codesize usage.\n' : '\n'),
					response.message);
		}, function(response) { //Error callback
			$scope.logInsert(response.message.split('\n')[0] + '\n', parseErrorMessage(response.message, code[1]));
		}).finally(function() {
			$scope.logOpen = true;
			$scope.simRunning = false;
		});

		$scope.simRunning = true;
	}

	var simulate = function(dataIn) {
		var data = {
			"gameId": $scope.model.getRoot().get('gameId'),
			"snapshot1": 94857,
			"snapshot2": 203458,
			"simConfig": {
				"timeout": dataIn.timeout,
				"state1": dataIn.sph1init,
				"state2": dataIn.sph2init,
				"gameVariables": dataIn.gameVars
			}
		};

		if(dataIn.sph === 1) {
			data['code1'] = realtime.getDocAsString($scope.model.getRoot());
			data['code2'] = dataIn.opponentCode;
		}
		else {
			data['code2'] = realtime.getDocAsString($scope.model.getRoot());
			data['code1'] = dataIn.opponentCode;
		}

		zrdb.compile(data, true).then(function(response) { //Success callback
			$scope.logInsert('Simulation succeeded.\n', response.message, response.id);
		}, function(response) { //Error callback
			$scope.logInsert('Simulation failed.\n', response.message);
		}).finally(function() {
			$scope.logOpen = true;
			$scope.simRunning = false;
		});

		$scope.simRunning = true;
	}

	$scope.download = function() {
		//Create phantom link with data URI to download content. Needed to specify the name of the file with
		//download attribute (window.open gives the file a random name in Firefox.)
		var link = document.createElement('a');
		link.setAttribute('href', 'data:text/x-c,' + encodeURIComponent(realtime.getDocAsString($scope.model.getRoot())));
		link.setAttribute('download', 'project.cpp');
		link.setAttribute('target', '_blank');
		var randomDiv = document.getElementById('main-collapse');
		randomDiv.appendChild(link);
		//Need to pause here for some reason
		setTimeout(function() {
			link.click();
			randomDiv.removeChild(link);
		}, 100);
	};

	$scope.sendChatMessage = function() {
		$scope.logInsert($scope.chat.message, '');
		$scope.chat.message = '';
	};

	$scope.logInsert = function(title, content, simId) {
		//Log entries are identified by timestamp, plus some random digits to avoid collisions
		var key = String(new Date().getTime() + Math.random());
		var value = {
			user: getMyName(),
			title: title,
			content: content,
			simId: simId
		}
		collabLog.set(key, value);
		updateLog();
	};

	$scope.toggleBlocklyText = function(title, content) {
		if($scope.editorMode === 'graphical-c') {
			$scope.editorMode = 'graphical';
		}
		else if($scope.editorMode === 'graphical') {
			$scope.blocklyText = Blockly.zr_cpp.workspaceToCode();
			$scope.editorMode = 'graphical-c';
		}
	}

	var shareClient = null;
	$scope.share = function() {
		if(!shareClient) {
			shareClient = new gapi.drive.share.ShareClient(config.appId);
		}
		shareClient.setItemIds(realtime.id);
		shareClient.showSettingsDialog();
	};

	//Blockly cut/copy/paste callbacks
	$scope.cut = function() {
		if(graphical) {
	        Blockly.copy_(Blockly.selected);
	        Blockly.selected.dispose(true, true);
		}
	}

	$scope.copy = function() {
		if(graphical) {
	        Blockly.copy_(Blockly.selected);
		}
	}

	$scope.paste = function() {
		if(graphical && Blockly.clipboard_) {
	        Blockly.mainWorkspace.paste(Blockly.clipboard_);
		}
	}

	//Callback to load Blockly when everything is rendered
	if(graphical) {
		$scope.loadBlockly = function() {
			Blockly.inject(document.getElementById('blockly-frame'),{path:'/blockly/',toolbox: document.getElementById('blockly-toolbox')});
			//Scroll over to keep procedure in center
			var dims = Blockly.mainWorkspace.getMetrics();
			Blockly.mainWorkspace.scrollX += dims.viewWidth / 3;
			Blockly.mainWorkspace.scrollY += dims.viewHeight / 4;
			Blockly.Realtime.loadPage($scope.currentPageName);
		};
		//This triggers after the DOM is all compiled/rendered
		if(!$scope.blocklyTreeUrl) {
			$timeout($scope.loadBlockly);
		}
	}

	//Listener to log leaving the document
	var closeAction = function() {
		//$scope.logInsert('Stopped editing','');
		collabLog.removeEventListener(gapi.drive.realtime.EventType.VALUE_CHANGED, logRemoteChange);
		return null;
	};
	//TODO: This is disabled because it has lots of timing issues
	//For leaving ZR
	//window.addEventListener('beforeunload',closeAction,false);
	//For switching views within Angular
	$scope.$on("$destroy", closeAction);

	//Last initialization
	$scope.logInsert('Started editing','');
	$scope.setActivePage('main');
}]);
<|endoftext|>


<commit_before>/**
*  Dialog to add a new visualization from any of your
*  existing tables.
*
*/
cdb.admin.NewVisualizationDialogTableModel = cdb.core.Model.extend({
  defaults: {
    name: "Table name"
  }
});

cdb.admin.NewVisualizationDialogTableCollection = Backbone.Collection.extend({
  model: "NewVisualizationDialogTableModel"
});

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

  events: {
    "click .remove" : "_onRemove"
  },

  tagName: "li",
  className: "table",

  initialize: function() {

    _.bindAll(this, "_onRemove");

    this.template = this.getTemplate('dashboard/views/new_visualization_dialog_table_item');
  },

  show: function() {
    this.$el.show();
  },

  clear: function() {
    this.$el.hide();
  },

  _onRemove: function(e) {
    this.killEvent(e);
    this.clear();
    this.trigger("remove", this);
  },

  render: function() {
    this.$el.html(this.template(this.model.toJSON()));
    return this.$el;
  }

});

cdb.admin.NewVisualizationDialog = cdb.admin.BaseDialog.extend({

  _TEXTS: {
    title: _t('Create visualization'),
    description: _t('Select the layers you will use on this visualization (you will be able to add more later)'),
    new_vis_title: _t("Give a name to your visualization")
  },

  events: cdb.core.View.extendEvents({ // do not remove
    "click .add" : "_onAddTableItem",
  }),

  initialize: function() {

    // Dialog options
    _.extend(this.options, {
      title: this._TEXTS.title,
      template_name: 'common/views/dialog_base',
      clean_on_hide: true,
      ok_button_classes: "button green",
      ok_title: this._TEXTS.title,
      modal_type: "creation",
      modal_class: 'new_visualization_dialog',
      width: 464
    });

    this.ok = this.options.ok;

    this.tableSelection = new cdb.core.Model();

    // Collection to manage the tables
    this.table_items = new cdb.admin.NewVisualizationDialogTableCollection();
    this.table_items.bind("add", this._addTableItem, this);
    this.table_items.bind("remove", this._onRemove, this);

    this.constructor.__super__.initialize.apply(this);
    this.setWizard(this.options.wizard_option);
    this.tables = new cdb.admin.Tables();

  },

  render_content: function() {

    this.$content = $("<div>");

    var temp_content = this.getTemplate('dashboard/views/new_visualization_dialog');

    this.$content.append(temp_content({ description: this._TEXTS.description }));

    this.tables.fetch()
    this.tables.bind('reset', this._onReset, this)

    this.disableOkButton();

    return this.$content;
  },

  _onAddTableItem: function(e) {

    this.killEvent(e);

    var model = new cdb.admin.NewVisualizationDialogTableModel({ name: this.table_name });
    this.table_items.add(model);
  },

  _addTableItem: function(model) {

    this.enableOkButton();

    var view  = new cdb.admin.NewVisualizationDialogTableItem({ model: model });
    this.$(".tables").append(view.render());
    view.bind("remove", this._onRemoveItem, this);
    view.show();
  },

  _onRemoveItem: function(item) {
    this.table_items.remove(item.model);
  },

  _onRemove: function() {
    if (this.table_items.length == 0) this.disableOkButton();
  },

  _onReset: function() {

    this.tables.unbind(null, null, this); // do this one time and one time only

    if (this.tableCombo) this.tableCombo.clean();

    this.tableList = this.tables.pluck('name')

    this.table_name = this.tableList[0];

    this._addCombo();

  },

  _addCombo: function() {

    this.tableCombo = new cdb.forms.Combo({
      el: this.$content.find('.tableListCombo'),
      model: this.tableSelection,
      property: "table",
      width: "309px",
      extra: this.tableList
    });

    this.tableCombo.bind('change', this._onChange, this);
    this.tableCombo.render();

  },

  _onChange: function(table_name) {
    this.table_name = table_name;
  },

  _ok: function(ev) {
    this.killEvent(ev);

    if (this.table_items.length == 0) return;

    this.hide();

    var tables = this.table_items.pluck("name");
    var self = this;

    new cdb.admin.NameVisualization({
      msg: this._TEXTS.new_vis_title,
      onResponse: function(name) {

        var vis = new cdb.admin.Visualization();
        vis.save({ name: name, tables: tables }).success(function(visualization) {
          window.location.href = "/viz/" + visualization.id + "/";
        });

      }
    }).appendToBody().open();

  }

});
<commit_msg>refactor vis url redirect<commit_after>/**
*  Dialog to add a new visualization from any of your
*  existing tables.
*
*/
cdb.admin.NewVisualizationDialogTableModel = cdb.core.Model.extend({
  defaults: {
    name: "Table name"
  }
});

cdb.admin.NewVisualizationDialogTableCollection = Backbone.Collection.extend({
  model: "NewVisualizationDialogTableModel"
});

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

  events: {
    "click .remove" : "_onRemove"
  },

  tagName: "li",
  className: "table",

  initialize: function() {

    _.bindAll(this, "_onRemove");

    this.template = this.getTemplate('dashboard/views/new_visualization_dialog_table_item');
  },

  show: function() {
    this.$el.show();
  },

  clear: function() {
    this.$el.hide();
  },

  _onRemove: function(e) {
    this.killEvent(e);
    this.clear();
    this.trigger("remove", this);
  },

  render: function() {
    this.$el.html(this.template(this.model.toJSON()));
    return this.$el;
  }

});

cdb.admin.NewVisualizationDialog = cdb.admin.BaseDialog.extend({

  _TEXTS: {
    title: _t('Create visualization'),
    description: _t('Select the layers you will use on this visualization (you will be able to add more later)'),
    new_vis_title: _t("Give a name to your visualization")
  },

  events: cdb.core.View.extendEvents({ // do not remove
    "click .add" : "_onAddTableItem",
  }),

  initialize: function() {

    // Dialog options
    _.extend(this.options, {
      title: this._TEXTS.title,
      template_name: 'common/views/dialog_base',
      clean_on_hide: true,
      ok_button_classes: "button green",
      ok_title: this._TEXTS.title,
      modal_type: "creation",
      modal_class: 'new_visualization_dialog',
      width: 464
    });

    this.ok = this.options.ok;

    this.tableSelection = new cdb.core.Model();

    // Collection to manage the tables
    this.table_items = new cdb.admin.NewVisualizationDialogTableCollection();
    this.table_items.bind("add", this._addTableItem, this);
    this.table_items.bind("remove", this._onRemove, this);

    this.constructor.__super__.initialize.apply(this);
    this.setWizard(this.options.wizard_option);
    this.tables = new cdb.admin.Tables();

  },

  render_content: function() {

    this.$content = $("<div>");

    var temp_content = this.getTemplate('dashboard/views/new_visualization_dialog');

    this.$content.append(temp_content({ description: this._TEXTS.description }));

    this.tables.fetch()
    this.tables.bind('reset', this._onReset, this)

    this.disableOkButton();

    return this.$content;
  },

  _onAddTableItem: function(e) {

    this.killEvent(e);

    var model = new cdb.admin.NewVisualizationDialogTableModel({ name: this.table_name });
    this.table_items.add(model);
  },

  _addTableItem: function(model) {

    this.enableOkButton();

    var view  = new cdb.admin.NewVisualizationDialogTableItem({ model: model });
    this.$(".tables").append(view.render());
    view.bind("remove", this._onRemoveItem, this);
    view.show();
  },

  _onRemoveItem: function(item) {
    this.table_items.remove(item.model);
  },

  _onRemove: function() {
    if (this.table_items.length == 0) this.disableOkButton();
  },

  _onReset: function() {

    this.tables.unbind(null, null, this); // do this one time and one time only

    if (this.tableCombo) this.tableCombo.clean();

    this.tableList = this.tables.pluck('name')

    this.table_name = this.tableList[0];

    this._addCombo();

  },

  _addCombo: function() {

    this.tableCombo = new cdb.forms.Combo({
      el: this.$content.find('.tableListCombo'),
      model: this.tableSelection,
      property: "table",
      width: "309px",
      extra: this.tableList
    });

    this.tableCombo.bind('change', this._onChange, this);
    this.tableCombo.render();

  },

  _onChange: function(table_name) {
    this.table_name = table_name;
  },

  _ok: function(ev) {
    this.killEvent(ev);

    if (this.table_items.length === 0) return;

    this.hide();

    var tables = this.table_items.pluck("name");
    var self = this;

    new cdb.admin.NameVisualization({
      msg: this._TEXTS.new_vis_title,
      onResponse: function(name) {
        var vis = new cdb.admin.Visualization();
        vis.save({ name: name, tables: tables }).success(function(visualization) {
          window.location.href = visualization.viewUrl();
        });
      }
    }).appendToBody().open();

  }

});
<|endoftext|>


<commit_before>/*@pjs preload="data/images/logo1.png";*/

var sketchProc=function(processingInstance){ with (processingInstance){

//Setup
var wi = window.innerWidth ||
        document.documentElement.clientWidth ||
        document.body.clientWidth;
var he = window.innerHeight ||
         document.documentElement.clientHeight ||
         document.body.clientHeight;
size(wi*0.9,he*0.9);
frameRate(60);

setup = function() {
	mainfont = createFont("Times New Roman");
	logo = loadImage("data/images/logo1.png");

	keys = [];
	page = 0;
	chapter1 = [];

	m = false;
	bw = width/8;
	bh = width/16;
	prim = color(15,15,15);
	sec = color(100,30,30);
	tert = color(150,150,150);

	loadpanels = function(name,number,target) {
		for (i = 0; i < number; i ++) {
			target[i] = loadImage("data/images/panels"+name+i+".png");
		}
	};

	buttons = {
		start:{x:width*(3/4),y:height/2,w:bw,h:bh,text:"Enter"},
		next:{x:width*(3/4),y:height*(4/5),w:bw,h:bh,text:"Next"},
	};

	displaypanel = function(img,x,y) {
		imageMode(CENTER);
		pushMatrix();
		translate(x,y);
		scale(0.001*height,0.001*height);
			image(img,0,0);
		popMatrix();
	};

	button = function(con) {
		bux = con.x
		buy = con.y
		buw = con.w
		buh = con.h
		butext = con.text
		con.pressed = false;

		if (mouseX>bux&&mouseX<bux+buw && mouseY>buy&&mouseY<buy+buh) {
			fill(prim);
		} else {
			fill(sec);
		}
		stroke(prim);
		strokeWeight(buh/10);
		rect(bux,buy,buw,buh,buh/3);

		if (mouseX>bux&&mouseX<bux+buw && mouseY>buy&&mouseY<buy+buh) {
			fill(sec);
		} else {
			fill(prim);
		}
		textFont(mainfont,buh/2);
		textAlign(CENTER,CENTER);
		text(butext,bux+buw/2,buy+buh/2);

		if (mouseX>bux&&mouseX<bux+buw && mouseY>buy&&mouseY<buy+buh && m || mouseClicked) {
			con.pressed = true;
		}
		return con.pressed;
	};

	loadpanels("chap1",0,chapter1);

	pages = [
		function() {
			background(55,55,55)

			displaypanel(logo,width/4,height/2)

			button(buttons.start)
			if (buttons.start.pressed==true) {
				page += 1
			}
		},
		function() {
			background(55,55,55)

			button(buttons.next)
			if (buttons.next.pressed) {
				page += 1
			}
		},

	];

};

draw = function() {
	pages[page]();
	fill(0,0,0);
	text(m,width/2,height/3);
};

keyPressed = function() {
	keys[keyCode] = true;
};
keyReleased = function() {
	keys[keyCode] = false;
};
mousePressed = function() {
	m = true;
};
mouseReleased = function() {
	m = false;
};

}};
<commit_msg>Update main.js<commit_after>/*@pjs preload="data/images/logo1.png";*/

var sketchProc=function(processingInstance){ with (processingInstance){

//Setup
var wi = window.innerWidth ||
        document.documentElement.clientWidth ||
        document.body.clientWidth;
var he = window.innerHeight ||
         document.documentElement.clientHeight ||
         document.body.clientHeight;
size(wi*0.9,he*0.9);
frameRate(60);

setup = function() {
	mainfont = createFont("Times New Roman");
	logo = loadImage("data/images/logo1.png");

	keys = [];
	page = 0;
	chapter1 = [];

	m = false;
	bw = width/8;
	bh = width/16;
	prim = color(15,15,15);
	sec = color(100,30,30);
	tert = color(150,150,150);

	loadpanels = function(name,number,target) {
		for (i = 0; i < number; i ++) {
			target[i] = loadImage("data/images/panels"+name+i+".png");
		}
	};

	buttons = {
		start:{x:width*(3/4),y:height/2,w:bw,h:bh,text:"Enter"},
		next:{x:width*(3/4),y:height*(4/5),w:bw,h:bh,text:"Next"},
	};

	displaypanel = function(img,x,y) {
		imageMode(CENTER);
		pushMatrix();
		translate(x,y);
		scale(0.001*height,0.001*height);
			image(img,0,0);
		popMatrix();
	};

	button = function(con) {
		bux = con.x
		buy = con.y
		buw = con.w
		buh = con.h
		butext = con.text
		con.pressed = false;

		if (mouseX>bux&&mouseX<bux+buw && mouseY>buy&&mouseY<buy+buh) {
			fill(prim);
		} else {
			fill(sec);
		}
		stroke(prim);
		strokeWeight(buh/10);
		rect(bux,buy,buw,buh,buh/3);

		if (mouseX>bux&&mouseX<bux+buw && mouseY>buy&&mouseY<buy+buh) {
			fill(sec);
		} else {
			fill(prim);
		}
		textFont(mainfont,buh/2);
		textAlign(CENTER,CENTER);
		text(butext,bux+buw/2,buy+buh/2);

		if (mouseX>bux&&mouseX<bux+buw && mouseY>buy&&mouseY<buy+buh && m || mouseDragged) {
			con.pressed = true;
		}
		return con.pressed;
	};

	loadpanels("chap1",0,chapter1);

	pages = [
		function() {
			background(55,55,55)

			displaypanel(logo,width/4,height/2)

			button(buttons.start)
			if (buttons.start.pressed==true) {
				page += 1
			}
		},
		function() {
			background(55,55,55)

			button(buttons.next)
			if (buttons.next.pressed) {
				page += 1
			}
		},

	];

};

draw = function() {
	pages[page]();
	fill(0,0,0);
	text(m+" "+mouseDragged,width/2,height/3);
};

keyPressed = function() {
	keys[keyCode] = true;
};
keyReleased = function() {
	keys[keyCode] = false;
};
mousePressed = function() {
	m = true;
};
mouseReleased = function() {
	m = false;
};

}};
<|endoftext|>


<commit_before>/* globals define */

(function () {
  'use strict';

  define([
    'jquery',
    'underscore',
    'backbone',
    'marionette',
    'routers/app-router',
    'apis/archive-api',
    'controllers/single-controller',
    'controllers/archive-controller',
    'controllers/search-controller',
    'controllers/loading-controller',
    'controllers/taxonomy-controller',
    'buses/communicator',
    'models/settings-model',
    'models/user-model',
    'models/sidebar-model',
    'collections/post-collection',
    'collections/taxonomy-collection',
    'views/header-view',
    'views/sidebar-view',
    'views/footer-view'
  ], function ($, _, Backbone, Marionette, AppRouter, ArchiveAPI, SingleController, ArchiveController, SearchController, LoadingController, TaxonomyController, Communicator, Settings, User, Sidebar, Posts, Taxonomies, HeaderView, SidebarView, FooterView) {

    var App = new Backbone.Marionette.Application(),
        user = new User({ID: 'me'});

    App.navigate = function(route, options){
      options = options || {};
      this.appRouter.navigate(route, options);
    };

    App.titleChange = function(title) {
      var separator = ' | ';
      var newTitle  = '';

      if (_.isFunction(title)) {
        newTitle = title.apply(this, arguments) + separator;

      } else if (_.isString(title)) {
        newTitle = title + separator;
      }

      document.title = newTitle + Settings.get('name');
    };

    function isMobile() {
      var ua = (navigator.userAgent || navigator.vendor || window.opera, window, window.document);
      return (/iPhone|iPod|iPad|Android|BlackBerry|Opera Mini|IEMobile/).test(ua);
    }

    function getMenus () {
      return $.get(Settings.get('api_url') + '/b3:menus');
    }

    function getSidebars () {
      return $.get(Settings.get('api_url') + '/b3:sidebars');
    }

    function getSettings () {
      return Settings.fetch();
    }

    function getTaxonomies () {
      return new Taxonomies().fetch();
    }

    function initializeLayout (menus, sidebars) {
      App.header.show(new HeaderView({menus: menus}));

      if (sidebars && sidebars.sidebar) {
        App.sidebar.show(new SidebarView({model: new Sidebar(sidebars.sidebar)}));
      }

      App.footer.show(new FooterView());
    }

    function initializeRoutes () {
      var apis = [
        new ArchiveAPI({ app: App }),
        new SingleController({
          app:  App,
          user: user
        }),
        // new ArchiveController({
        //   app:   App,
        //   posts: new Posts(),
        //   user:  user
        // }),
        new SearchController({
          app:   App,
          posts: new Posts(),
          user:  user
        })
      ];

      App.appRouter = new AppRouter({
        controller: apis,
      });

      if (Backbone.history) {
        Backbone.history.start({pushState: true, root: Settings.get('site_path')});
      }
    }

    function initializeControllers (params) {
      Communicator.commands.setHandler('loading:show', function (data) {
        new LoadingController(data).displayLoading();
      });

      new TaxonomyController({
        taxonomies: new Taxonomies(params.taxonomies)
      });
    }

    function initializeResources () {
      $.when(getSettings(), getMenus(), getSidebars(), getTaxonomies()).then(function (settings, menus, sidebars, taxonomies) {
        Settings.set(settings[0]);
        var params = {
          taxonomies: taxonomies[0]
        };
        user.fetch();
        initializeLayout(menus[0], sidebars[0]);
        initializeControllers(params);
        initializeRoutes(menus[0]);
      }); /* TODO: need a fail view on .fail() */

      App.addRegions({
        header:  '#header',
        main:    '#main',
        sidebar: '#sidebar',
        footer:  '#footer'
      });
    }

    Communicator.requests.setHandler('default:region', function () {
      return App.main;
    });

    Communicator.events.on('router:nav', function (options) {
      App.navigate(options.route, options.options);
    });

    Communicator.events.on('title:change', function (title) {
      App.titleChange(title);
    });

    App.mobile = isMobile();

    App.addInitializer(initializeResources);

    return App;
  });

})();
<commit_msg>Use new API<commit_after>/* globals define */

(function () {
  'use strict';

  define([
    'jquery',
    'underscore',
    'backbone',
    'marionette',
    'routers/app-router',
    'apis/archive-api',
    'apis/single-api',
    'controllers/archive-controller',
    'controllers/search-controller',
    'controllers/loading-controller',
    'controllers/taxonomy-controller',
    'buses/communicator',
    'models/settings-model',
    'models/user-model',
    'models/sidebar-model',
    'collections/post-collection',
    'collections/taxonomy-collection',
    'views/header-view',
    'views/sidebar-view',
    'views/footer-view'
  ], function ($, _, Backbone, Marionette, AppRouter, ArchiveAPI, SingleAPI, ArchiveController, SearchController, LoadingController, TaxonomyController, Communicator, Settings, User, Sidebar, Posts, Taxonomies, HeaderView, SidebarView, FooterView) {

    var App = new Backbone.Marionette.Application(),
        user = new User({ID: 'me'});

    App.navigate = function(route, options){
      options = options || {};
      this.appRouter.navigate(route, options);
    };

    App.titleChange = function(title) {
      var separator = ' | ';
      var newTitle  = '';

      if (_.isFunction(title)) {
        newTitle = title.apply(this, arguments) + separator;

      } else if (_.isString(title)) {
        newTitle = title + separator;
      }

      document.title = newTitle + Settings.get('name');
    };

    function isMobile() {
      var ua = (navigator.userAgent || navigator.vendor || window.opera, window, window.document);
      return (/iPhone|iPod|iPad|Android|BlackBerry|Opera Mini|IEMobile/).test(ua);
    }

    function getMenus () {
      return $.get(Settings.get('api_url') + '/b3:menus');
    }

    function getSidebars () {
      return $.get(Settings.get('api_url') + '/b3:sidebars');
    }

    function getSettings () {
      return Settings.fetch();
    }

    function getTaxonomies () {
      return new Taxonomies().fetch();
    }

    function initializeLayout (menus, sidebars) {
      App.header.show(new HeaderView({menus: menus}));

      if (sidebars && sidebars.sidebar) {
        App.sidebar.show(new SidebarView({model: new Sidebar(sidebars.sidebar)}));
      }

      App.footer.show(new FooterView());
    }

    function initializeRoutes () {
      var apis = [
        new ArchiveAPI(),
        new SingleAPI(),
        new SearchController({
          app:   App,
          posts: new Posts(),
          user:  user
        })
      ];

      App.appRouter = new AppRouter({
        controller: apis,
      });

      if (Backbone.history) {
        Backbone.history.start({pushState: true, root: Settings.get('site_path')});
      }
    }

    function initializeControllers (params) {
      Communicator.commands.setHandler('loading:show', function (data) {
        new LoadingController(data).displayLoading();
      });

      new TaxonomyController({
        taxonomies: new Taxonomies(params.taxonomies)
      });
    }

    function initializeResources () {
      $.when(getSettings(), getMenus(), getSidebars(), getTaxonomies()).then(function (settings, menus, sidebars, taxonomies) {
        Settings.set(settings[0]);
        var params = {
          taxonomies: taxonomies[0]
        };
        user.fetch();
        initializeLayout(menus[0], sidebars[0]);
        initializeControllers(params);
        initializeRoutes(menus[0]);
      }); /* TODO: need a fail view on .fail() */

      App.addRegions({
        header:  '#header',
        main:    '#main',
        sidebar: '#sidebar',
        footer:  '#footer'
      });
    }

    Communicator.requests.setHandler('default:region', function () {
      return App.main;
    });

    Communicator.events.on('router:nav', function (options) {
      App.navigate(options.route, options.options);
    });

    Communicator.events.on('title:change', function (title) {
      App.titleChange(title);
    });

    App.mobile = isMobile();

    App.addInitializer(initializeResources);

    return App;
  });

})();
<|endoftext|>


<commit_before>'use strict';

angular.module('scegratooApp')
  .service('X3domUtils', function X3domutils($window, $routeParams, $templateCache, Constants) {
    // AngularJS will instantiate a singleton by calling "new" on this function
    var vecOffset = {
    	x: 0,
    	y: 0,
    	z: 0,
    }
    var options = {
		  useHitPnt: false,
		  x: '',
		  y: '',
		  z: '',
    }
    var inlines
    var crosshairs        = angular.element($templateCache.get('crosshairs.html')).get(0)
    var translationGizmoX = angular.element($templateCache.get('planeSensor-X.html')).get(0);
    var translationGizmoY = angular.element($templateCache.get('planeSensor-Y.html')).get(0);

    var start = function(event) {
      // event.hitPnt is in global space so for this to work one would have to
      // add it to the scene and translate it inside the move function.
      // runtime.getCenter(hitObject) seems to return sth in local space
      // which works
      var runtime = document.querySelector('X3D').runtime
      // var crosshairs = document.querySelector('[DEF=crosshairs]')
      var translationString = ''

      console.debug('hitPnt:', new $window.x3dom.fields.SFVec3f(event.hitPnt[0], event.hitPnt[1], event.hitPnt[2]));
      console.debug('center of HitObject:', runtime.getCenter(event.hitObject));

      if (options.useHitPnt) {
        vecOffset = new $window.x3dom.fields.SFVec3f(event.hitPnt[0], event.hitPnt[1], event.hitPnt[2])
      } else {
        vecOffset = runtime.getCenter(event.hitObject)
      }

      event.hitObject.parentNode.parentNode.appendChild(crosshairs)
      translationString = vecOffset.x + ' ' + vecOffset.y + ' ' + vecOffset.z
      crosshairs.setAttribute('translation', translationString)
    }

    var move = function(event) {
      var moveableTranslation = event.getAttribute('translation').split(' ')

      moveableTranslation[0] = parseFloat(moveableTranslation[0]) + vecOffset.x
      moveableTranslation[1] = parseFloat(moveableTranslation[1]) + vecOffset.y
      moveableTranslation[2] = parseFloat(moveableTranslation[2]) + vecOffset.z

      options.x = moveableTranslation[0]
      options.y = moveableTranslation[1]
      options.z = moveableTranslation[2]

      // console.debug('moveableTranslation: %o\ntransform: %o', moveableTranslation, vecOffset.x)

      // crosshairs.setAttribute('translation', moveableTranslation.join(' '))
    }

    var stop = function(event) {
      if (crosshairs.parentNode) {
        crosshairs.parentNode.removeChild(crosshairs)
      }
    }

    var processTranslationGizmoEventX = function(event) {
        var sensorToWorldMatrix, translationValue;

        if (event.fieldName === 'translation_changed') {
          //convert the sensor's output from sensor coordinates to world coordinates (i.e., include its 'axisRotation')
          sensorToWorldMatrix = $window.x3dom.fields.SFMatrix4f.parseRotation(event.target.getAttribute('axisRotation'));

          translationValue = sensorToWorldMatrix.multMatrixVec(event.value);

          if (options.snapToGrid) {
            translationValue.x = Math.floor(translationValue.x)
          }

          angular.forEach(inlines, function(inline){
            var oldTranslationValue = inline.parentNode.getFieldValue('translation')
            oldTranslationValue.x = translationValue.x
            inline.parentNode.setFieldValue('translation', oldTranslationValue)
          });
        }
    }

    var processTranslationGizmoEventY = function(event) {
        var sensorToWorldMatrix, translationValue;

        if (event.fieldName === 'translation_changed') {
          //convert the sensor's output from sensor coordinates to world coordinates (i.e., include its 'axisRotation')
          sensorToWorldMatrix = $window.x3dom.fields.SFMatrix4f.parseRotation(event.target.getAttribute('axisRotation'));

          translationValue = sensorToWorldMatrix.multMatrixVec(event.value);

          if (options.snapToGrid) {
            translationValue.y = Math.floor(translationValue.y)
          }

          angular.forEach(inlines, function(inline){
            var oldTranslationValue = inline.parentNode.getFieldValue('translation')
            oldTranslationValue.y = translationValue.y
            inline.parentNode.setFieldValue('translation', oldTranslationValue)
          });
        }
    }

    var setUp = function(x3dElement) {
    	var inlines = x3dElement.find('inline')

    	angular.forEach(inlines, function(inline){
	      var url = inline.getAttribute('url')
	      inline.setAttribute('url', Constants.apiRoot +
	        '/' + 'projects' +
	        '/' + $routeParams.project +
	        '/' + $routeParams.file.replace(/\/[^\/]*$/, '') +
	        '/' + url)
	    });

	    $window.x3dom.reload()

	    angular.forEach(inlines, function(inline){
	      inline.addEventListener('mousedown', start)
	      inline.addEventListener('mouseup', stop)
	      // debugger
	      new $window.x3dom.Moveable(x3dElement.children().get(0),
	        inline.parentElement, move, 0, 'all')
	    });

	    return options
      angular.forEach(x3dElement.find('scene'), function(scene){
        scene.appendChild(translationGizmoX)
        scene.appendChild(translationGizmoY)
      })

      translationGizmoX.children[0].addEventListener('onoutputchange', processTranslationGizmoEventX)
      translationGizmoY.children[0].addEventListener('onoutputchange', processTranslationGizmoEventY)
    }

    return {
    	setUp: setUp
    }
  });
<commit_msg>Remove move function as it was also changing translations<commit_after>'use strict';

angular.module('scegratooApp')
  .service('X3domUtils', function X3domutils($window, $routeParams, $templateCache, Constants) {
    // AngularJS will instantiate a singleton by calling "new" on this function
    var vecOffset = {
    	x: 0,
    	y: 0,
    	z: 0,
    }
    var options = {
		  useHitPnt: false,
		  x: '',
		  y: '',
		  z: '',
    }
    var inlines
    var crosshairs        = angular.element($templateCache.get('crosshairs.html')).get(0)
    var translationGizmoX = angular.element($templateCache.get('planeSensor-X.html')).get(0);
    var translationGizmoY = angular.element($templateCache.get('planeSensor-Y.html')).get(0);

    var start = function(event) {
      // event.hitPnt is in global space so for this to work one would have to
      // add it to the scene and translate it inside the move function.
      // runtime.getCenter(hitObject) seems to return sth in local space
      // which works
      var runtime = document.querySelector('X3D').runtime
      // var crosshairs = document.querySelector('[DEF=crosshairs]')
      var translationString = ''

      console.debug('hitPnt:', new $window.x3dom.fields.SFVec3f(event.hitPnt[0], event.hitPnt[1], event.hitPnt[2]));
      console.debug('center of HitObject:', runtime.getCenter(event.hitObject));

      if (options.useHitPnt) {
        vecOffset = new $window.x3dom.fields.SFVec3f(event.hitPnt[0], event.hitPnt[1], event.hitPnt[2])
      } else {
        vecOffset = runtime.getCenter(event.hitObject)
      }

      event.hitObject.parentNode.parentNode.appendChild(crosshairs)
      translationString = vecOffset.x + ' ' + vecOffset.y + ' ' + vecOffset.z
      crosshairs.setAttribute('translation', translationString)
    }

    var move = function(event) {
    }

    var stop = function(event) {
      if (crosshairs.parentNode) {
        crosshairs.parentNode.removeChild(crosshairs)
      }
    }

    var processTranslationGizmoEventX = function(event) {
        var sensorToWorldMatrix, translationValue;

        if (event.fieldName === 'translation_changed') {
          //convert the sensor's output from sensor coordinates to world coordinates (i.e., include its 'axisRotation')
          sensorToWorldMatrix = $window.x3dom.fields.SFMatrix4f.parseRotation(event.target.getAttribute('axisRotation'));

          translationValue = sensorToWorldMatrix.multMatrixVec(event.value);

          if (options.snapToGrid) {
            translationValue.x = Math.floor(translationValue.x)
          }

          angular.forEach(inlines, function(inline){
            var oldTranslationValue = inline.parentNode.getFieldValue('translation')
            oldTranslationValue.x = translationValue.x
            inline.parentNode.setFieldValue('translation', oldTranslationValue)
          });
        }
    }

    var processTranslationGizmoEventY = function(event) {
        var sensorToWorldMatrix, translationValue;

        if (event.fieldName === 'translation_changed') {
          //convert the sensor's output from sensor coordinates to world coordinates (i.e., include its 'axisRotation')
          sensorToWorldMatrix = $window.x3dom.fields.SFMatrix4f.parseRotation(event.target.getAttribute('axisRotation'));

          translationValue = sensorToWorldMatrix.multMatrixVec(event.value);

          if (options.snapToGrid) {
            translationValue.y = Math.floor(translationValue.y)
          }

          angular.forEach(inlines, function(inline){
            var oldTranslationValue = inline.parentNode.getFieldValue('translation')
            oldTranslationValue.y = translationValue.y
            inline.parentNode.setFieldValue('translation', oldTranslationValue)
          });
        }
    }

    var setUp = function(x3dElement) {
    	var inlines = x3dElement.find('inline')

    	angular.forEach(inlines, function(inline){
	      var url = inline.getAttribute('url')
	      inline.setAttribute('url', Constants.apiRoot +
	        '/' + 'projects' +
	        '/' + $routeParams.project +
	        '/' + $routeParams.file.replace(/\/[^\/]*$/, '') +
	        '/' + url)
	    });

	    $window.x3dom.reload()

	    angular.forEach(inlines, function(inline){
	      inline.addEventListener('mousedown', start)
	      inline.addEventListener('mouseup', stop)
	      // debugger
	      new $window.x3dom.Moveable(x3dElement.children().get(0),
	        inline.parentElement, move, 0, 'all')
	    });

	    return options
      angular.forEach(x3dElement.find('scene'), function(scene){
        scene.appendChild(translationGizmoX)
        scene.appendChild(translationGizmoY)
      })

      translationGizmoX.children[0].addEventListener('onoutputchange', processTranslationGizmoEventX)
      translationGizmoY.children[0].addEventListener('onoutputchange', processTranslationGizmoEventY)
    }

    return {
    	setUp: setUp
    }
  });
<|endoftext|>


<commit_before>define([
  // Libraries.
  "jquery",
  "lodash",
  "backbone",

  // Plugins.
  "plugins/backbone.layoutmanager"
],

function($, _, Backbone) {

  // Provide a global location to place configuration settings and module
  // creation.
  var app = {
    // The root path to run the application.
    root: "/"
  };

  // Localize or create a new JavaScript Template object.
  var JST = window.JST = window.JST || {};

  // Configure LayoutManager with Backbone Boilerplate defaults.
  Backbone.LayoutManager.configure({
    // Allow LayoutManager to augment Backbone.View.prototype.
    manage: true,

    paths: {
      layout: "app/templates/layouts/",
      template: "app/templates/"
    },

    fetch: function(path) {
      // Initialize done for use in async-mode
      var done;

      // Concatenate the file extension.
      path = path + ".html";

      // If cached, use the compiled template.
      if (JST[path]) {
        return JST[path];
      } else {
        // Put fetch into `async-mode`.
        done = this.async();

        // Seek out the template asynchronously.
        return $.ajax({ url: app.root + path }).then(function(contents) {
          done(JST[path] = _.template(contents));
        });
      }
    }
  });

  // Mix Backbone.Events, modules, and layout management into the app object.
  return _.extend(app, {
    // Create a custom object with a nested Views object.
    module: function(additionalProps) {
      return _.extend({ Views: {} }, additionalProps);
    },

    // Helper for using layouts.
    useLayout: function(name, options) {
      // If already using this Layout, then don't re-inject into the DOM.
      if (this.layout && this.layout.options.template === name) {
        return this.layout;
      }

      // If a layout already exists, remove it from the DOM.
      if (this.layout) {
        this.layout.remove();
      }

      // Create a new Layout with options.
      var layout = new Backbone.Layout(_.extend({
        template: name,
        className: "layout " + name,
        id: "layout"
      }, options));

      // Insert into the DOM.
      $("#main").empty().append(layout.el);

      // Render the layout.
      layout.render();

      // Cache the refererence.
      this.layout = layout;

      // Return the reference, for chainability.
      return layout;
    }
  }, Backbone.Events);

});
<commit_msg>updated app.js<commit_after>define([
  // Libraries.
  "jquery",
  "lodash",
  "backbone",

  // Plugins.
  "plugins/backbone.layoutmanager"
],

function($, _, Backbone) {

  // Provide a global location to place configuration settings and module
  // creation.
  var app = {
    // The root path to run the application.
    root: "/"
  };

  // Localize or create a new JavaScript Template object.
  var JST = window.JST = window.JST || {};

  // Configure LayoutManager with Backbone Boilerplate defaults.
  Backbone.LayoutManager.configure({
    // Allow LayoutManager to augment Backbone.View.prototype.
    manage: true,

    prefix: "app/templates/",

    fetch: function(path) {
      // Concatenate the file extension.
      path = path + ".html";

      // If cached, use the compiled template.
      if (JST[path]) {
        return JST[path];
      }

      // Put fetch into `async-mode`.
      var done = this.async();

      // Seek out the template asynchronously.
      $.get(app.root + path, function(contents) {
        done(JST[path] = _.template(contents));
      });
    }
  });

  // Mix Backbone.Events, modules, and layout management into the app object.
  return _.extend(app, {
    // Create a custom object with a nested Views object.
    module: function(additionalProps) {
      return _.extend({ Views: {} }, additionalProps);
    },

    // Helper for using layouts.
    useLayout: function(options) {
      // Create a new Layout with options.
      var layout = new Backbone.Layout(_.extend({
        el: "body"
      }, options));

      // Cache the refererence.
      return this.layout = layout;
    }
  }, Backbone.Events);

});
<|endoftext|>


<commit_before>const path = require('path')
const webpack = require('webpack')
const OfflinePlugin = require('offline-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const dev = process.env.NODE_ENV !== 'production'

baseConfig = {
  mode: dev ? 'development' : 'production',
  module: {
    rules: [
      { test: /\.sass$/, use: ['css-loader', 'sass-loader'] },
      {
        test: /\.jsx$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env'],
              plugins: ['@babel/plugin-transform-react-jsx']
            }
          }
        ]
      },
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env']
            }
          }
        ]
      },
      {
        test: /\.png$/,
        use: 'file-loader'
      },
      {
        test: /\.pug$/,
        use: [
          {
            loader: 'pug-loader',
            options: {}
          }
        ]
      }
    ]
  },
  devtool: 'source-map'
}

module.exports = [
  Object.assign({}, baseConfig, {
    entry: {
      'clientrender': './view/clientrender.jsx',
    },
    output: {
      path: path.join(__dirname, './dist'),
      publicPath: '/resources/',
      filename: '[name].js'
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: './view/index.pug',
        minify: dev ? false : {removeComments: true, useShortDoctype: true, sortClassName: true, sortAttributes: true},
        chunks: [ 'clientrender' ],
        inject: false
      }),
      new OfflinePlugin({
        caches: {
          main: [':rest:', '/resources/pdfjs/pdf.min.js', '/resources/pdfjs/pdf.worker.min.js']
        },
        responseStrategy: 'cache-first',
        ServiceWorker: {
          scope: '/',
          publicPath: '/sw.js',
          minify: !dev
        },
        AppCache: null,
        rewrites: {
          'index.html': '/'
        },
        autoUpdate: true
      })
    ].filter(x => x !== null)
  }),
  Object.assign({}, baseConfig, {
    module: Object.assign({}, baseConfig.module, {
      rules: [
        { test: /\.sass$/, use: ['css-loader', 'sass-loader'] },
        {
          test: /\.jsx$/,
          use: [
            {
              loader: 'babel-loader',
              options: {
                presets: [['@babel/preset-env', {
                  targets: {
                    node: 'current'
                  }
                }]],
                plugins: ['@babel/plugin-transform-react-jsx']
              }
            }
          ]
        },
        {
          test: /\.js$/,
          use: [
            {
              loader: 'babel-loader',
              options: {
                presets: [['@babel/preset-env', {
                  targets: {
                    node: 'current'
                  }
                }]]
              }
            }
          ]
        }
      ]
    }),
    entry: {
      'serverrender': './view/serverrender.jsx'
    },
    target: 'node',
    optimization: {
      minimize: false
    },
    output: {
      path: path.join(__dirname, './dist-server'),
      publicPath: '/resources/',
      filename: '[name].js'
    },
    plugins: [
    ]
  })
]
<commit_msg>Add targets option for babel<commit_after>const path = require('path')
const webpack = require('webpack')
const OfflinePlugin = require('offline-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const dev = process.env.NODE_ENV !== 'production'

baseConfig = {
  mode: dev ? 'development' : 'production',
  module: {
    rules: [
      { test: /\.sass$/, use: ['css-loader', 'sass-loader'] },
      {
        test: /\.jsx$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env'],
              plugins: ['@babel/plugin-transform-react-jsx'],
              targets: "> 0.25%, not dead"
            }
          }
        ]
      },
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env'],
              targets: "> 0.25%, not dead"
            }
          }
        ]
      },
      {
        test: /\.png$/,
        use: 'file-loader'
      },
      {
        test: /\.pug$/,
        use: [
          {
            loader: 'pug-loader',
            options: {}
          }
        ]
      }
    ]
  },
  devtool: 'source-map'
}

module.exports = [
  Object.assign({}, baseConfig, {
    entry: {
      'clientrender': './view/clientrender.jsx',
    },
    output: {
      path: path.join(__dirname, './dist'),
      publicPath: '/resources/',
      filename: '[name].js'
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: './view/index.pug',
        minify: dev ? false : {removeComments: true, useShortDoctype: true, sortClassName: true, sortAttributes: true},
        chunks: [ 'clientrender' ],
        inject: false
      }),
      new OfflinePlugin({
        caches: {
          main: [':rest:', '/resources/pdfjs/pdf.min.js', '/resources/pdfjs/pdf.worker.min.js']
        },
        responseStrategy: 'cache-first',
        ServiceWorker: {
          scope: '/',
          publicPath: '/sw.js',
          minify: !dev
        },
        AppCache: null,
        rewrites: {
          'index.html': '/'
        },
        autoUpdate: true
      })
    ].filter(x => x !== null)
  }),
  Object.assign({}, baseConfig, {
    module: Object.assign({}, baseConfig.module, {
      rules: [
        { test: /\.sass$/, use: ['css-loader', 'sass-loader'] },
        {
          test: /\.jsx$/,
          use: [
            {
              loader: 'babel-loader',
              options: {
                presets: [['@babel/preset-env', {
                  targets: {
                    node: 'current'
                  }
                }]],
                plugins: ['@babel/plugin-transform-react-jsx']
              }
            }
          ]
        },
        {
          test: /\.js$/,
          use: [
            {
              loader: 'babel-loader',
              options: {
                presets: [['@babel/preset-env', {
                  targets: {
                    node: 'current'
                  }
                }]]
              }
            }
          ]
        }
      ]
    }),
    entry: {
      'serverrender': './view/serverrender.jsx'
    },
    target: 'node',
    optimization: {
      minimize: false
    },
    output: {
      path: path.join(__dirname, './dist-server'),
      publicPath: '/resources/',
      filename: '[name].js'
    },
    plugins: [
    ]
  })
]
<|endoftext|>


<commit_before>var $revert = $('#revert'); //.next().addClass('left').end();
$(document).bind('codeChange', function (event, revert, onload) {
  if (revert == undefined) {
    revert = false;
  } else {
    $revert.removeClass('enable');
  }

  updateTitle(revert, onload);
});

$(window).bind('beforeunload', function(revert){
  if (document.title.indexOf('[unsaved]') != -1){
    return 'You should stay and save your page first.\n';
  }
});

function updateTitle(revert, onload) {
  var title = !documentTitle ? 'openHTML' : documentTitle;
  // if (jsbin.settings.home) title = jsbin.settings.home + '@' + title;
  if (editors.html.ready && editors.javascript.ready) {
    if (!revert) {
      document.title = title + ' [unsaved]';
      if ($revert.addClass('enable').is(':hidden')) {
        $revert[onload ? 'show' : 'fadeIn']().next().removeClass('left');
      }
    } else {
      document.title = title;
    }
  }
}
<commit_msg>Disable unsaved warning<commit_after>var $revert = $('#revert'); //.next().addClass('left').end();
$(document).bind('codeChange', function (event, revert, onload) {
  if (revert == undefined) {
    revert = false;
  } else {
    $revert.removeClass('enable');
  }

  updateTitle(revert, onload);
});

// $(window).bind('beforeunload', function(revert){
//   if (document.title.indexOf('[unsaved]') != -1){
//     return 'You should stay and save your page first.\n';
//   }
// });

function updateTitle(revert, onload) {
  var title = !documentTitle ? 'openHTML' : documentTitle;
  // if (jsbin.settings.home) title = jsbin.settings.home + '@' + title;
  if (editors.html.ready && editors.javascript.ready) {
    if (!revert) {
      document.title = title + ' [unsaved]';
      if ($revert.addClass('enable').is(':hidden')) {
        $revert[onload ? 'show' : 'fadeIn']().next().removeClass('left');
      }
    } else {
      document.title = title;
    }
  }
}
<|endoftext|>


<commit_before>const path = require('path');
const glob = require('glob');

const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const PurifyCSSPlugin = require('purifycss-webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = function(env) {
    const production = (env === 'production');

    return {
        resolve: { alias: { '@': path.resolve(__dirname, './src') } },
        entry: {
            main: [
                './src/js/main.js',
                './src/css/main.scss',
            ],
        },
        output: {
            path: path.resolve(__dirname, './public'),
            filename: 'assets/js/[name].[hash:6].js',
        },
        devtool: (production) ? false : '#cheap-module-eval-source-map',
        module: {
            loaders: [
                {
                    test: /\.js$/,
                    exclude: /node_modules/,
                    loader: 'babel-loader'
                },
                {
                    test: /\.vue$/,
                    loader: 'vue-loader',
                },
                {
                    test: /\.scss$/,
                    use: ExtractTextPlugin.extract({
                        fallback: 'style-loader',
                        publicPath: '../../',
                        use: [
                            {
                                loader: 'css-loader',
                                options: { sourceMap: !production },
                            },
                            {
                                loader: 'postcss-loader',
                                options: { sourceMap: !production },
                            },
                            {
                                loader: 'sass-loader',
                                options: { sourceMap: !production },
                            },
                        ],
                    }),
                },
                {
                    test: /\.(woff2?|ttf|eot)$/,
                    loader: 'file-loader?name=assets/fonts/[name].[hash:6].[ext]',
                },
                {
                    test: /\.(png|jpe?g|gif|svg)$/,
                    loader: 'file-loader?name=assets/img/[name].[hash:6].[ext]',
                },
                {
                    test: /favicon\.ico$/,
                    loader: 'file-loader?name=favicon.ico',
                }
            ],
        },
        plugins: [
            // Remove old files
            // new CleanWebpackPlugin([
            //     'public/assets/css/*',
            //     'public/assets/js/*',
            // ]),
            // Extract CSS to a separate file
            new ExtractTextPlugin({
                filename: 'assets/css/[name].[contenthash:6].css',
                disable: !production,
            }),
            // Remove unused CSS styles
            new PurifyCSSPlugin({
                paths: [
                    ...glob.sync(path.join(__dirname, 'src/html/*.html')),
                    ...glob.sync(path.join(__dirname, 'src/js/components/*.vue')),
                ],
                minimize: production,
                purifyOptions: {
                    whitelist: [
                        '.title:not(.is-spaced)+.subtitle', // Fix subtitle spacing
                    ],
                    cleanCssOptions: {
                        rebase: false, // Leave relative paths alone when minifying CSS
                    },
                },
            }),
            // Build HTML
            new HtmlWebpackPlugin({
                filename: 'index.html',
                template: 'src/html/index.html',
                minify: { collapseWhitespace: true },
            }),
            // Copy additional favicons
            new CopyWebpackPlugin([
                { from: 'src/icons/public' },
            ]),
        ],
    }
}
<commit_msg>Fix CSS purification paths<commit_after>const path = require('path');
const glob = require('glob');

const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const PurifyCSSPlugin = require('purifycss-webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = function(env) {
    const production = (env === 'production');

    return {
        resolve: { alias: { '@': path.resolve(__dirname, './src') } },
        entry: {
            main: [
                './src/js/main.js',
                './src/css/main.scss',
            ],
        },
        output: {
            path: path.resolve(__dirname, './public'),
            filename: 'assets/js/[name].[hash:6].js',
        },
        devtool: (production) ? false : '#cheap-module-eval-source-map',
        module: {
            loaders: [
                {
                    test: /\.js$/,
                    exclude: /node_modules/,
                    loader: 'babel-loader'
                },
                {
                    test: /\.vue$/,
                    loader: 'vue-loader',
                },
                {
                    test: /\.scss$/,
                    use: ExtractTextPlugin.extract({
                        fallback: 'style-loader',
                        publicPath: '../../',
                        use: [
                            {
                                loader: 'css-loader',
                                options: { sourceMap: !production },
                            },
                            {
                                loader: 'postcss-loader',
                                options: { sourceMap: !production },
                            },
                            {
                                loader: 'sass-loader',
                                options: { sourceMap: !production },
                            },
                        ],
                    }),
                },
                {
                    test: /\.(woff2?|ttf|eot)$/,
                    loader: 'file-loader?name=assets/fonts/[name].[hash:6].[ext]',
                },
                {
                    test: /\.(png|jpe?g|gif|svg)$/,
                    loader: 'file-loader?name=assets/img/[name].[hash:6].[ext]',
                },
                {
                    test: /favicon\.ico$/,
                    loader: 'file-loader?name=favicon.ico',
                }
            ],
        },
        plugins: [
            // Remove old files
            // new CleanWebpackPlugin([
            //     'public/assets/css/*',
            //     'public/assets/js/*',
            // ]),
            // Extract CSS to a separate file
            new ExtractTextPlugin({
                filename: 'assets/css/[name].[contenthash:6].css',
                disable: !production,
            }),
            // Remove unused CSS styles
            new PurifyCSSPlugin({
                paths: [
                    ...glob.sync(path.join(__dirname, 'src/html/**/*.html')),
                    ...glob.sync(path.join(__dirname, 'src/js/components/**/*.vue')),
                ],
                minimize: production,
                purifyOptions: {
                    whitelist: [
                        '.title:not(.is-spaced)+.subtitle', // Fix subtitle spacing
                    ],
                    cleanCssOptions: {
                        rebase: false, // Leave relative paths alone when minifying CSS
                    },
                },
            }),
            // Build HTML
            new HtmlWebpackPlugin({
                filename: 'index.html',
                template: 'src/html/index.html',
                minify: { collapseWhitespace: true },
            }),
            // Copy additional favicons
            new CopyWebpackPlugin([
                { from: 'src/icons/public' },
            ]),
        ],
    }
}
<|endoftext|>


<commit_before>'use strict';

angular.module('myApp', [
  'ngRoute',
  'hljs',
  'angularSpinners',
  'ui.bootstrap',
  'ngCookies',
  'myApp.challenge',
  'myApp.container',
  'myApp.setting',
  'myApp.authentication',
  'myApp.staticpages',
  'myApp.admin'
])

.config(['$locationProvider', '$routeProvider', '$httpProvider', 'hljsServiceProvider',
function($locationProvider, $routeProvider, $httpProvider, hljsServiceProvider) {
  hljsServiceProvider.setOptions({
    // replace tab with 4 spaces
    tabReplace: '    '
  });

  hljs.initHighlighting();

  // Lets cache all the things
  $httpProvider.defaults.cache = true;

  $routeProvider.otherwise({redirectTo: '/staticpages/index'});
}])

.run(function($rootScope, AuthenticationServices) {
  AuthenticationServices.useToken();
})

.controller('menuCtrl', function($scope, $cookies, AuthenticationServices) {
  $scope.isAuthenticated = false;

  // For HL SSO auth
  var t = $cookies.get('token');
  if (t) {
    AuthenticationServices.saveToken(t);
    $cookies.remove('token');
  }

  if (AuthenticationServices.isAuthenticated()) {
    $scope.isAuthenticated = true;

    var token = AuthenticationServices.parseJwt(AuthenticationServices.getToken());
    $scope.loggedinUser = token.userId;
    $scope.isAdmin = token.admin;
  }
})

;
<commit_msg>fix redirect<commit_after>'use strict';

angular.module('myApp', [
  'ngRoute',
  'hljs',
  'angularSpinners',
  'ui.bootstrap',
  'ngCookies',
  'myApp.challenge',
  'myApp.container',
  'myApp.setting',
  'myApp.authentication',
  'myApp.staticpages',
  'myApp.admin'
])

.config(['$locationProvider', '$routeProvider', '$httpProvider', 'hljsServiceProvider',
function($locationProvider, $routeProvider, $httpProvider, hljsServiceProvider) {
  hljsServiceProvider.setOptions({
    // replace tab with 4 spaces
    tabReplace: '    '
  });

  hljs.initHighlighting();

  // Lets cache all the things
  $httpProvider.defaults.cache = true;

  $routeProvider.otherwise({redirectTo: '/index'});
}])

.run(function($rootScope, AuthenticationServices) {
  AuthenticationServices.useToken();
})

.controller('menuCtrl', function($scope, $cookies, AuthenticationServices) {
  $scope.isAuthenticated = false;

  // For HL SSO auth
  var t = $cookies.get('token');
  if (t) {
    AuthenticationServices.saveToken(t);
    $cookies.remove('token');
  }

  if (AuthenticationServices.isAuthenticated()) {
    $scope.isAuthenticated = true;

    var token = AuthenticationServices.parseJwt(AuthenticationServices.getToken());
    $scope.loggedinUser = token.userId;
    $scope.isAdmin = token.admin;
  }
})

;
<|endoftext|>


<commit_before>'use strict';

/**
 * ButtressJS - Realtime datastore for business software
 *
 * @file activity.js
 * @description Activity model definition.
 * @module Model
 * @exports model, schema, constants
 * @author Chris Bates-Keegan
 *
 */
const mongoose = require('mongoose');
const Model = require('../');
const Logging = require('../../logging');
// const Helpers = require('../../helpers');
// var Config = require('../../config');

/**
 * Constants
 */

const visibility = ['public', 'private'];
const Visibility = {
  PUBLIC: visibility[0],
  PRIVATE: visibility[1]
};

const constants = {
  Visibility: Visibility
};

/**
 * Schema
 */
const schema = new mongoose.Schema();
schema.add({
  timestamp: {
    type: Date,
    default: Date.create
  },
  title: String,
  description: String,
  visibility: {
    type: String,
    enum: visibility,
    index: true
  },
  path: String,
  verb: String,
  authLevel: Number,
  permissions: String,
  params: Object,
  query: Object,
  body: Object,
  response: Object,
  metadata: [{key: String, value: String}],
  _token: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Token'
  },
  _app: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Application',
    index: true
  },
  _user: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  }
});

let ModelDef = null;

/**
 * Schema Virtual Methods
 */
schema.virtual('details').get(function() {
  return {
    id: this._id,
    timestamp: this.timestamp,
    title: this.title,
    description: this.description,
    visibility: this.visibility,
    path: this.path,
    permissions: this.permissions,
    user: this._user,
    metadata: this.metadata.map(m => ({key: m.key, value: JSON.parse(m.value)}))
  };
});

schema.virtual('tokenValue').get(function() {
  if (!this._token) {
    return false;
  }
  if (!this._token.value) {
    return this._token;
  }
  return this._token.value;
});

/**
 * Schema Static Methods
 */

/**
 * @param {Object} route - route object that fulfilled the request
 * @param {Object} response - object containing the response data
 * @return {Promise} - fulfilled with App Object when the database request is completed
 */
schema.statics.add = (route, response) => {
  Logging.log(route.path, Logging.Constants.LogLevel.DEBUG);

  let user = Model.authUser;
  let userName = user && user._person ? `${user._person.forename} ${user._person.surname}` : 'System';

  route.activityTitle = route.activityTitle.replace('%USER_NAME%', userName);
  route.activityDescription = route.activityDescription.replace('%USER_NAME%', userName);

  let q = Object.assign({}, route.req.query);
  delete q.token;
  delete q.urq;

  const app = new ModelDef({
    title: route.activityTitle,
    description: route.activityDescription,
    visibility: route.activityVisibility,
    path: route.path,
    verb: route.verb,
    permissions: route.permissions,
    authLevel: route.auth,
    params: route.req.params,
    query: q,
    body: route.req.body,
    response: response,
    _token: Model.token.id,
    _user: Model.authUser,
    _app: Model.authApp
  });

  return app.save();
};

/**
 * @param {string} key - index name of the metadata
 * @param {*} value - value of the meta data
 * @return {Promise} - resolves when save operation is completed, rejects if metadata already exists
 */
schema.methods.addOrUpdateMetadata = function(key, value) {
  Logging.log(key, Logging.Constants.LogLevel.DEBUG);
  Logging.log(value, Logging.Constants.LogLevel.DEBUG);

  let exists = this.metadata.find(m => m.key === key);
  if (exists) {
    exists.value = value;
  } else {
    this.metadata.push({key, value});
  }

  return this.save();
};

schema.methods.findMetadata = function(key) {
  Logging.log(`findMetadata: ${key}`, Logging.Constants.LogLevel.VERBOSE);
  // Logging.log(this.metadata, Logging.Constants.LogLevel.DEBUG);
  let md = this.metadata.find(m => m.key === key);
  return md ? {key: md.key, value: JSON.parse(md.value)} : undefined;
};

/**
 * @return {Promise} - resolves to an array of Apps (native Mongoose objects)
 */
schema.statics.findAll = () => {
  Logging.log(`findAll: ${Model.authApp._id}`, Logging.Constants.LogLevel.DEBUG);

  if (Model.token.authLevel === Model.Constants.Token.AuthLevel.SUPER) {
    return ModelDef.find({});
  }

  return ModelDef.find({_app: Model.authApp._id, visibility: constants.Visibility.PUBLIC});
};

ModelDef = mongoose.model('Activity', schema);

/**
 * Exports
 */
module.exports.constants = constants;
module.exports.schema = schema;
module.exports.model = ModelDef;
<commit_msg>- FIXED: Super still probably doesn't want all the activity on earth.<commit_after>'use strict';

/**
 * ButtressJS - Realtime datastore for business software
 *
 * @file activity.js
 * @description Activity model definition.
 * @module Model
 * @exports model, schema, constants
 * @author Chris Bates-Keegan
 *
 */
const mongoose = require('mongoose');
const Model = require('../');
const Logging = require('../../logging');
// const Helpers = require('../../helpers');
// var Config = require('../../config');

/**
 * Constants
 */

const visibility = ['public', 'private'];
const Visibility = {
  PUBLIC: visibility[0],
  PRIVATE: visibility[1]
};

const constants = {
  Visibility: Visibility
};

/**
 * Schema
 */
const schema = new mongoose.Schema();
schema.add({
  timestamp: {
    type: Date,
    default: Date.create
  },
  title: String,
  description: String,
  visibility: {
    type: String,
    enum: visibility,
    index: true
  },
  path: String,
  verb: String,
  authLevel: Number,
  permissions: String,
  params: Object,
  query: Object,
  body: Object,
  response: Object,
  metadata: [{key: String, value: String}],
  _token: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Token'
  },
  _app: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Application',
    index: true
  },
  _user: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  }
});

let ModelDef = null;

/**
 * Schema Virtual Methods
 */
schema.virtual('details').get(function() {
  return {
    id: this._id,
    timestamp: this.timestamp,
    title: this.title,
    description: this.description,
    visibility: this.visibility,
    path: this.path,
    permissions: this.permissions,
    user: this._user,
    metadata: this.metadata.map(m => ({key: m.key, value: JSON.parse(m.value)}))
  };
});

schema.virtual('tokenValue').get(function() {
  if (!this._token) {
    return false;
  }
  if (!this._token.value) {
    return this._token;
  }
  return this._token.value;
});

/**
 * Schema Static Methods
 */

/**
 * @param {Object} route - route object that fulfilled the request
 * @param {Object} response - object containing the response data
 * @return {Promise} - fulfilled with App Object when the database request is completed
 */
schema.statics.add = (route, response) => {
  Logging.log(route.path, Logging.Constants.LogLevel.DEBUG);

  let user = Model.authUser;
  let userName = user && user._person ? `${user._person.forename} ${user._person.surname}` : 'System';

  route.activityTitle = route.activityTitle.replace('%USER_NAME%', userName);
  route.activityDescription = route.activityDescription.replace('%USER_NAME%', userName);

  let q = Object.assign({}, route.req.query);
  delete q.token;
  delete q.urq;

  const app = new ModelDef({
    title: route.activityTitle,
    description: route.activityDescription,
    visibility: route.activityVisibility,
    path: route.path,
    verb: route.verb,
    permissions: route.permissions,
    authLevel: route.auth,
    params: route.req.params,
    query: q,
    body: route.req.body,
    response: response,
    _token: Model.token.id,
    _user: Model.authUser,
    _app: Model.authApp
  });

  return app.save();
};

/**
 * @param {string} key - index name of the metadata
 * @param {*} value - value of the meta data
 * @return {Promise} - resolves when save operation is completed, rejects if metadata already exists
 */
schema.methods.addOrUpdateMetadata = function(key, value) {
  Logging.log(key, Logging.Constants.LogLevel.DEBUG);
  Logging.log(value, Logging.Constants.LogLevel.DEBUG);

  let exists = this.metadata.find(m => m.key === key);
  if (exists) {
    exists.value = value;
  } else {
    this.metadata.push({key, value});
  }

  return this.save();
};

schema.methods.findMetadata = function(key) {
  Logging.log(`findMetadata: ${key}`, Logging.Constants.LogLevel.VERBOSE);
  // Logging.log(this.metadata, Logging.Constants.LogLevel.DEBUG);
  let md = this.metadata.find(m => m.key === key);
  return md ? {key: md.key, value: JSON.parse(md.value)} : undefined;
};

/**
 * @return {Promise} - resolves to an array of Apps (native Mongoose objects)
 */
schema.statics.findAll = () => {
  Logging.log(`findAll: ${Model.authApp._id}`, Logging.Constants.LogLevel.DEBUG);

  if (Model.token.authLevel === Model.Constants.Token.AuthLevel.SUPER) {
    return ModelDef.find({visibility: constants.Visibility.PUBLIC});
  }

  return ModelDef.find({_app: Model.authApp._id, visibility: constants.Visibility.PUBLIC});
};

ModelDef = mongoose.model('Activity', schema);

/**
 * Exports
 */
module.exports.constants = constants;
module.exports.schema = schema;
module.exports.model = ModelDef;
<|endoftext|>