<commit_before>$(document).ready(function() {
	var Q = Quintus()
		.include("Sprites, Scenes, Input, 2D, Anim, Touch, UI")
		.setup("lights-out", { maximize: false })
		.controls()
		.touch();

	//var W = $('#lights-out');

	var currLevel = 0;
	var levels = ["level-one", "level-two", "level-three"];

	Q.Sprite.extend("Player", {
		init: function(p) {
			this._super(p, {
				sheet: "player",
				x: 64,
				y: Q.height - 48
			});

			this.add("2d, platformerControls");

			this.on("hit.sprite", function(collision) {
				if (collision.obj.isA("Gateway")) {
					Q.stageScene(levels[currLevel], 1);
					this.destroy();
				}

			});
		}
	});

	Q.Sprite.extend("Gateway", {
		init: function(p) {
			this._super(p, { sheet: "gateway" });
		}
	});

	Q.Sprite.extend("BouncePad", {
		init: function(p) {
			this._super(p, { sheet: "bounce-pad" });

			this.add("2d");

			this.on("bump.top", function(collision) {
				if (collision.obj.isA("Player")) {
					collision.obj.p.vy = -500;
				}

			});
		}
	});

	Q.Sprite.extend("Switch", {
		init: function(p) {
			this._super(p, { sheet: "switch-unactivated" });

			this.on("bump.top", function(collision) {
				if (collision.obj.isA("Player")) {
					alert("switch activated");
				}

			});

		}
	});

	//var player = new Q.Player();

	Q.scene("title", function(stage) {
		var container = stage.insert(new Q.UI.Container({
			x: Q.width / 2, y: Q.height / 2, fill: "gray"
		}));

		var button = container.insert(new Q.UI.Button({ x: 0, y: 0, fill: "black", label: "Start!" }));

		var label = container.insert(new Q.UI.Text({ x: 10, y: -10 - button.p.h, label: stage.options.label }));

		button.on("click", function() {
			Q.clearStages();
			Q.stageScene("level-one");
		});

		container.fit(20);
	});

	Q.scene("level-one", function(stage) {
		stage.insert(new Q.Repeater({ asset: "background.png", speedX: 1, speedY: 1}));

		stage.collisionLayer(new Q.TileLayer({
			dataAsset: "level-one.json",
			sheet: "tiles"
		}));

		var player = stage.insert(new Q.Player());

		stage.insert(new Q.Gateway({ x: Q.width - 48, y: 144 }));

		stage.add("viewport").follow(player, { x: true, y: true });
		stage.viewport.scale = 2;

		currLevel += 1;
	});

	Q.scene("level-two", function(stage) {
		stage.insert(new Q.Repeater({ asset: "background.png", speedX: 0.5, speedY: 0.5}));

		stage.collisionLayer(new Q.TileLayer({
			dataAsset: "level-two.json",
			sheet: "tiles"
		}));

		var player = stage.insert(new Q.Player());

		stage.insert(new Q.BouncePad({ x: 128, y: Q.height - 32 }));
		stage.insert(new Q.BouncePad({ x: 240, y: Q.height - 256 }));
		stage.insert(new Q.BouncePad({ x: Q.width - 7 * 32 + 16, y: Q.height - 12 * 32 }));

		stage.insert(new Q.Gateway({ x: 64, y: 8 * 32 - 16}));

		//stage.insert(new Q.Switch({ x: 256, y: Q.height - 32 }));

		stage.add("viewport").follow(player, { x: true, y: true });
		stage.viewport.scale = 2;

		currLevel += 1;
	});

	Q.scene("level-three", function(stage) {
		stage.insert(new Q.Repeater({ asset: "background.png", speedX: 0.5, speedY: 0.5}));

		stage.collisionLayer(new Q.TileLayer({
			dataAsset: "level-three.json",
			sheet: "tiles"
		}));

		var player = stage.insert(new Q.Player());

		// stage.insert(new Q.BouncePad({ x: 128, y: Q.height - 32 }));
		// stage.insert(new Q.BouncePad({ x: 240, y: Q.height - 256 }));
		// stage.insert(new Q.BouncePad({ x: Q.width - 7 * 32 + 16, y: Q.height - 12 * 32 }));

		// stage.insert(new Q.Gateway({ x: 64, y: 8 * 32 - 16}));

		//stage.insert(new Q.Switch({ x: 256, y: Q.height - 32 }));

		stage.add("viewport").follow(player, { x: true, y: true });
		stage.viewport.scale = 2;

		currLevel += 1;
	});

	Q.load("sprites.png, sprites.json, tiles.png, level-one.json, level-two.json, level-three.json, background.png", function() {
		Q.sheet("tiles", "tiles.png", { tilew: 32, tileh: 32 });

		Q.compileSheets("sprites.png", "sprites.json");
		Q.compileSheets("tiles.png", "level-one.json");

		Q.clearStages();
		//Q.stageScene(levels[currLevel]);
		Q.stageScene("title", 1, { label: "Start" });
	});
});
<commit_msg>Title screen is now a bit fancier<commit_after>$(document).ready(function() {
	var Q = Quintus()
		.include("Sprites, Scenes, Input, 2D, Anim, Touch, UI")
		.setup("lights-out", { maximize: false })
		.controls()
		.touch();

	//var W = $('#lights-out');

	var currLevel = 0;
	var levels = ["level-one", "level-two", "level-three"];

	Q.Sprite.extend("Player", {
		init: function(p) {
			this._super(p, {
				sheet: "player",
				x: 64,
				y: Q.height - 48
			});

			this.add("2d, platformerControls");

			this.on("hit.sprite", function(collision) {
				if (collision.obj.isA("Gateway")) {
					Q.stageScene(levels[currLevel], 1);
					this.destroy();
				}

			});
		}
	});

	Q.Sprite.extend("Gateway", {
		init: function(p) {
			this._super(p, { sheet: "gateway" });
		}
	});

	Q.Sprite.extend("BouncePad", {
		init: function(p) {
			this._super(p, { sheet: "bounce-pad" });

			this.add("2d");

			this.on("bump.top", function(collision) {
				if (collision.obj.isA("Player")) {
					collision.obj.p.vy = -500;
				}

			});
		}
	});

	Q.Sprite.extend("Switch", {
		init: function(p) {
			this._super(p, { sheet: "switch-unactivated" });

			this.on("bump.top", function(collision) {
				if (collision.obj.isA("Player")) {
					alert("switch activated");
				}

			});

		}
	});

	//var player = new Q.Player();

	Q.scene("title", function(stage) {
		stage.insert(new Q.Repeater({ asset: "background.png", speedX: 1, speedY: 1}));

		var container = stage.insert(new Q.UI.Container({
			x: Q.width / 2, y: Q.height / 2, fill: "#404040"
		}));

		var button = container.insert(new Q.UI.Button({ x: 0, y: 0, fill: "white", label: "Start Game" }));

		var label = container.insert(new Q.UI.Text({ x: 0, y: -10 - button.p.h, label: stage.options.label }));

		button.on("click", function() {
			Q.clearStages();
			Q.stageScene("level-one");
		});

		container.fit(20);
	});

	Q.scene("level-one", function(stage) {
		stage.insert(new Q.Repeater({ asset: "background.png", speedX: 1, speedY: 1}));

		stage.collisionLayer(new Q.TileLayer({
			dataAsset: "level-one.json",
			sheet: "tiles"
		}));

		var player = stage.insert(new Q.Player());

		stage.insert(new Q.Gateway({ x: Q.width - 48, y: 144 }));

		stage.add("viewport").follow(player, { x: true, y: true });
		stage.viewport.scale = 2;

		currLevel += 1;
	});

	Q.scene("level-two", function(stage) {
		stage.insert(new Q.Repeater({ asset: "background.png", speedX: 0.5, speedY: 0.5}));

		stage.collisionLayer(new Q.TileLayer({
			dataAsset: "level-two.json",
			sheet: "tiles"
		}));

		var player = stage.insert(new Q.Player());

		stage.insert(new Q.BouncePad({ x: 128, y: Q.height - 32 }));
		stage.insert(new Q.BouncePad({ x: 240, y: Q.height - 256 }));
		stage.insert(new Q.BouncePad({ x: Q.width - 7 * 32 + 16, y: Q.height - 12 * 32 }));

		stage.insert(new Q.Gateway({ x: 64, y: 8 * 32 - 16}));

		//stage.insert(new Q.Switch({ x: 256, y: Q.height - 32 }));

		stage.add("viewport").follow(player, { x: true, y: true });
		stage.viewport.scale = 2;

		currLevel += 1;
	});

	Q.scene("level-three", function(stage) {
		stage.insert(new Q.Repeater({ asset: "background.png", speedX: 0.5, speedY: 0.5}));

		stage.collisionLayer(new Q.TileLayer({
			dataAsset: "level-three.json",
			sheet: "tiles"
		}));

		var player = stage.insert(new Q.Player());

		// stage.insert(new Q.BouncePad({ x: 128, y: Q.height - 32 }));
		// stage.insert(new Q.BouncePad({ x: 240, y: Q.height - 256 }));
		// stage.insert(new Q.BouncePad({ x: Q.width - 7 * 32 + 16, y: Q.height - 12 * 32 }));

		// stage.insert(new Q.Gateway({ x: 64, y: 8 * 32 - 16}));

		//stage.insert(new Q.Switch({ x: 256, y: Q.height - 32 }));

		stage.add("viewport").follow(player, { x: true, y: true });
		stage.viewport.scale = 2;

		currLevel += 1;
	});

	Q.load("sprites.png, sprites.json, tiles.png, level-one.json, level-two.json, level-three.json, background.png", function() {
		Q.sheet("tiles", "tiles.png", { tilew: 32, tileh: 32 });

		Q.compileSheets("sprites.png", "sprites.json");
		Q.compileSheets("tiles.png", "level-one.json");

		Q.clearStages();
		//Q.stageScene(levels[currLevel]);
		Q.stageScene("title", 1, { label: "In Search Of Light" });
	});
});
<|endoftext|>


<commit_before>partsGenieApp.controller("partsGenieCtrl", ["$scope", "$uibModal", "ErrorService", "PartsGenieService", "PathwayGenieService", "ProgressService", "ResultService", "UniprotService", function($scope, $uibModal, ErrorService, PartsGenieService, PathwayGenieService, ProgressService, ResultService, UniprotService) {
	var self = this;
	var jobIds = [];
	var jobId = null;
	var search = false;
	var nucl_regex = new RegExp("^[ACGTacgt ]+$");

	self.codons_regex = new RegExp("^[ACGTacgt\s]{3}$");
	self.query = PartsGenieService.query;
	self.response = {"update": {"values": [], "status": "waiting", "message": "Waiting..."}};

	self.restrEnzs = PathwayGenieService.restrEnzs;

	self.pagination = {
			current: 1
		};

	self.selectRestEnzs = function(selected) {
		self.restrEnzs = remove(self.restrEnzs, selected);
		self.query.filters.restr_enzs.push.apply(self.query.filters.restr_enzs, selected);
	}

	self.deselectRestEnzs = function(selected) {
		self.restrEnzs.push.apply(self.restrEnzs, selected);
		self.query.filters.restr_enzs = remove(self.query.filters.restr_enzs, selected);
	}

	self.showHelp = function() {
		return PathwayGenieService.showHelp();
	}

	self.hasFeatures = function() {
		for(var i = 0; i < self.query.designs.length; i++) {
			design = self.query.designs[i];

			for(var j = 0; j < design.features.length; j++) {
				return true;
			}
		}

		return false;
	}

	self.templates = [
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000001",
			name: "Defined sequence",
			seq: "",
			temp_params: {
				fixed: true,
				required: ["name", "seq"],
				valid: false,
				id: "_1"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000449",
			end: 100,
			name: "Randomised sequence",
			temp_params: {
				fixed: false,
				required: ["name", "len"],
				min_end: 1,
				max_end: 10000,
				valid: true,
				id: "_2"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000143",
			name: "Sequence of defined melting temperature",
			seq: "",
			parameters: {
				"Tm target": 70
			},
			temp_params: {
				fixed: true,
				required: ["name", "tm"],
				valid: true,
				id: "_3"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000296",
			name: "Origin of replication",
			seq: "",
			temp_params: {
				fixed: true,
				required: ["name", "seq"],
				valid: false,
				id: "_4"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000167",
			name: "Promoter",
			seq: "",
			temp_params: {
				fixed: true,
				required: ["name", "seq"],
				valid: false,
				id: "_5"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000139",
			name:"RBS",
			end: 60,
			parameters: {
				"TIR target": 15000
			},
			temp_params: {
				fixed: false,
				required: ["name", "tir"],
				min_end: 35,
				max_end: 10000,
				valid: true,
				id: "_6"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000316",
			name: "CDS",
			temp_params: {
				fixed: false,
				required: ["name", "prot"],
				valid: false,
				id: "_7"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000316",
			name: "Fixed coding sequence",
			temp_params: {
				fixed: true,
				required: ["name", "seq"],
				valid: false,
				id: "_8"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000141",
			name: "Terminator",
			seq: "",
			temp_params: {
				fixed: true,
				required: ["name", "seq"],
				valid: false,
				id: "_9"
			}
		},
	];

	self.addFeature = function(feature) {
		var copiedFeature = angular.copy(feature)
		self.copyFeature(copiedFeature);
		self.query.designs[self.pagination.current - 1].features.push(copiedFeature);
	}

	self.copyFeature = function(feature) {
		feature.temp_params.id = "_" + Math.floor(Math.random() * 65536) + "_" + (new Date()).getTime();
	}

	self.selected = function() {
		return PartsGenieService.selected;
	};

	self.toggleSelected = function(selected) {
		return PartsGenieService.toggleSelected(selected);
	};

	self.setValid = function(valid) {
		if(PartsGenieService.selected) {
			PartsGenieService.selected.temp_params.valid = valid;
		}
	};

	self.addDesign = function() {
		PartsGenieService.addDesign();
		self.pagination.current = self.query.designs.length;
	};

	self.copyDesign = function() {
		var origDesign = self.query.designs[self.pagination.current - 1];
		var copiedDesign = angular.copy(origDesign);

		for(var i = 0; i < copiedDesign.features.length; i++) {
			copiedDesign.features[i].temp_params.id = "_" + i + "_" + (new Date()).getTime();
		}

		self.query.designs.push(copiedDesign);
		self.pagination.current = self.query.designs.length;

		return copiedDesign;
	};

	self.bulkUniprot = function(feature_idx) {
		$uibModal.open({
			animation: true,
			ariaLabelledBy: 'modal-title',
			ariaDescribedBy: 'modal-body',
			templateUrl: '/static/uniprot/uniprotTerms.html',
			controller: 'uniprotTermsCtrl',
			controllerAs: 'ctrl',
		}).result.then(function(uniprotIds) {
			for(var i = 0; i < uniprotIds.length; i++) {
            	autoUniprot(uniprotIds[i], i, self.pagination.current - 1, feature_idx);
            }
        });
	}

	self.removeDesign = function() {
		self.query.designs.splice(self.pagination.current - 1, 1);
		self.pagination.current = self.pagination.current == 1 ? 1 : self.pagination.current - 1;
		self.toggleSelected(null);
	};

	self.organismRequired = function() {
		for(var i = 0; i < self.query.designs.length; i++) {
			design = self.query.designs[i];

			for(var j = 0; j < design.features.length; j++) {
				if(design.features[j].typ == "http://purl.obolibrary.org/obo/SO_0000139"
					|| (design.features[j].typ == "http://purl.obolibrary.org/obo/SO_0000316"
						&& !design.features[j].temp_params.fixed)) {
					return true;
				}
			}
		}

		return false;
	}

	self.searchUniprot = function(query) {
		search = true;

		PartsGenieService.searchUniprot(query).then(
			function(resp) {
				UniprotService.open(resp.data, PartsGenieService.selected)
				search = false;
			},
			function(errResp) {
				search = false;
			});
	};

	self.searching = function() {
		return search;
	};

	self.isAmbiguousSeq = function(query) {
		return query && nucl_regex.test(query);
	};

	self.submit = function() {
		jobIds = [];
		jobId = null;
		self.response = {"update": {"values": [], "status": "submitting", "message": "Submitting..."}};
		error = null;
		self.toggleSelected(self.selected());
		ResultService.setResults(null);

		ProgressService.open(self.query["app"] + " dashboard", self.cancel, self.update);

		PathwayGenieService.submit(self.query).then(
			function(resp) {
				jobIds = resp.data.job_ids;
				listen();
			},
			function(errResp) {
				onerror(errResp.data.message);
			});
	};

	self.cancel = function() {
		return PathwayGenieService.cancel(jobId);
	};

	self.update = function() {
		return self.response.update;
	};

	listen = function() {
		if(jobIds.length == 0) {
			return;
		}

		jobId = jobIds[0];
		var source = new EventSource("/progress/" + jobId);

		source.onmessage = function(event) {
			self.response = JSON.parse(event.data);
			status = self.response.update.status;

			if(status == "cancelled" || status == "error" || status == "finished") {
				source.close();

				if(status == "finished") {
					ResultService.appendResults(self.response.result);
				}

				jobIds.splice(0, 1);
				listen();
			}

			$scope.$apply();
		};

		source.onerror = function(event) {
			source.close();
			jobIds.splice(0, 1);
			listen();
			onerror(event.message);
		}
	};

	onerror = function(message) {
		self.response.update.status = "error";
		self.response.update.message = "Error";
		ProgressService.close();
		ErrorService.open(message);
	};

	remove = function(array, toRemove) {
		array = array.filter(function(elem) {
			return !toRemove.includes(elem);
		});

		return array;
	};

	autoUniprot = function(uniprotId, idx, initial_idx, feature_idx) {
		search = true;

		PartsGenieService.searchUniprot(uniprotId).then(
				function(resp) {
					var curr_design = null;

					if(idx > 0) {
						curr_design = self.copyDesign();
					}
					else {
						curr_design = self.query.designs[initial_idx]
					}

					UniprotService.updateFeature(curr_design.features[feature_idx], resp.data[0]);
					search = false;
				},
				function(errResp) {
					search = false;
				});
	}

	self.queryJson = angular.toJson({selected: self.selected(), query: self.query}, true);

	$scope.$watch(function() {
		return self.selected();
	},
	function(values) {
		self.queryJson = angular.toJson({selected: self.selected(), query: self.query}, true);
	}, true);

	$scope.$watch(function() {
		return self.query;
	},
	function(values) {
		self.queryJson = angular.toJson({selected: self.selected(), query: self.query}, true);
	}, true);

	$scope.$watch(function() {
		return self.pagination;
	},
	function(values) {
		PartsGenieService.selected = null;
	}, true);
}]);<commit_msg>Added search flags.<commit_after>partsGenieApp.controller("partsGenieCtrl", ["$scope", "$uibModal", "ErrorService", "PartsGenieService", "PathwayGenieService", "ProgressService", "ResultService", "UniprotService", function($scope, $uibModal, ErrorService, PartsGenieService, PathwayGenieService, ProgressService, ResultService, UniprotService) {
	var self = this;
	var jobIds = [];
	var jobId = null;
	var search = false;
	var nucl_regex = new RegExp("^[ACGTacgt ]+$");

	self.codons_regex = new RegExp("^[ACGTacgt\s]{3}$");
	self.query = PartsGenieService.query;
	self.response = {"update": {"values": [], "status": "waiting", "message": "Waiting..."}};

	self.restrEnzs = PathwayGenieService.restrEnzs;

	self.pagination = {
			current: 1
		};

	self.selectRestEnzs = function(selected) {
		self.restrEnzs = remove(self.restrEnzs, selected);
		self.query.filters.restr_enzs.push.apply(self.query.filters.restr_enzs, selected);
	}

	self.deselectRestEnzs = function(selected) {
		self.restrEnzs.push.apply(self.restrEnzs, selected);
		self.query.filters.restr_enzs = remove(self.query.filters.restr_enzs, selected);
	}

	self.showHelp = function() {
		return PathwayGenieService.showHelp();
	}

	self.hasFeatures = function() {
		for(var i = 0; i < self.query.designs.length; i++) {
			design = self.query.designs[i];

			for(var j = 0; j < design.features.length; j++) {
				return true;
			}
		}

		return false;
	}

	self.templates = [
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000001",
			name: "Defined sequence",
			seq: "",
			temp_params: {
				fixed: true,
				required: ["name", "seq"],
				valid: false,
				id: "_1"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000449",
			end: 100,
			name: "Randomised sequence",
			temp_params: {
				fixed: false,
				required: ["name", "len"],
				min_end: 1,
				max_end: 10000,
				valid: true,
				id: "_2"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000143",
			name: "Sequence of defined melting temperature",
			seq: "",
			parameters: {
				"Tm target": 70
			},
			temp_params: {
				fixed: true,
				required: ["name", "tm"],
				valid: true,
				id: "_3"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000296",
			name: "Origin of replication",
			seq: "",
			temp_params: {
				fixed: true,
				required: ["name", "seq"],
				valid: false,
				id: "_4"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000167",
			name: "Promoter",
			seq: "",
			temp_params: {
				fixed: true,
				required: ["name", "seq"],
				valid: false,
				id: "_5"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000139",
			name:"RBS",
			end: 60,
			parameters: {
				"TIR target": 15000
			},
			temp_params: {
				fixed: false,
				required: ["name", "tir"],
				min_end: 35,
				max_end: 10000,
				valid: true,
				id: "_6"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000316",
			name: "CDS",
			temp_params: {
				fixed: false,
				required: ["name", "prot"],
				valid: false,
				id: "_7"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000316",
			name: "Fixed coding sequence",
			temp_params: {
				fixed: true,
				required: ["name", "seq"],
				valid: false,
				id: "_8"
			}
		},
		{
			typ: "http://purl.obolibrary.org/obo/SO_0000141",
			name: "Terminator",
			seq: "",
			temp_params: {
				fixed: true,
				required: ["name", "seq"],
				valid: false,
				id: "_9"
			}
		},
	];

	self.addFeature = function(feature) {
		var copiedFeature = angular.copy(feature)
		self.copyFeature(copiedFeature);
		self.query.designs[self.pagination.current - 1].features.push(copiedFeature);
	}

	self.copyFeature = function(feature) {
		feature.temp_params.id = "_" + Math.floor(Math.random() * 65536) + "_" + (new Date()).getTime();
	}

	self.selected = function() {
		return PartsGenieService.selected;
	};

	self.toggleSelected = function(selected) {
		return PartsGenieService.toggleSelected(selected);
	};

	self.setValid = function(valid) {
		if(PartsGenieService.selected) {
			PartsGenieService.selected.temp_params.valid = valid;
		}
	};

	self.addDesign = function() {
		PartsGenieService.addDesign();
		self.pagination.current = self.query.designs.length;
	};

	self.copyDesign = function() {
		var origDesign = self.query.designs[self.pagination.current - 1];
		var copiedDesign = angular.copy(origDesign);

		for(var i = 0; i < copiedDesign.features.length; i++) {
			copiedDesign.features[i].temp_params.id = "_" + i + "_" + (new Date()).getTime();
		}

		self.query.designs.push(copiedDesign);
		self.pagination.current = self.query.designs.length;

		return copiedDesign;
	};

	self.bulkUniprot = function(feature_idx) {
		search = true;

		$uibModal.open({
			animation: true,
			ariaLabelledBy: 'modal-title',
			ariaDescribedBy: 'modal-body',
			templateUrl: '/static/uniprot/uniprotTerms.html',
			controller: 'uniprotTermsCtrl',
			controllerAs: 'ctrl',
		}).result.then(function(uniprotIds) {
			for(var i = 0; i < uniprotIds.length; i++) {
            	autoUniprot(uniprotIds[i], i, self.pagination.current - 1, feature_idx);
            }
			search = false;
        });
	}

	self.removeDesign = function() {
		self.query.designs.splice(self.pagination.current - 1, 1);
		self.pagination.current = self.pagination.current == 1 ? 1 : self.pagination.current - 1;
		self.toggleSelected(null);
	};

	self.organismRequired = function() {
		for(var i = 0; i < self.query.designs.length; i++) {
			design = self.query.designs[i];

			for(var j = 0; j < design.features.length; j++) {
				if(design.features[j].typ == "http://purl.obolibrary.org/obo/SO_0000139"
					|| (design.features[j].typ == "http://purl.obolibrary.org/obo/SO_0000316"
						&& !design.features[j].temp_params.fixed)) {
					return true;
				}
			}
		}

		return false;
	}

	self.searchUniprot = function(query) {
		search = true;

		PartsGenieService.searchUniprot(query).then(
			function(resp) {
				UniprotService.open(resp.data, PartsGenieService.selected)
				search = false;
			},
			function(errResp) {
				search = false;
			});
	};

	self.searching = function() {
		return search;
	};

	self.isAmbiguousSeq = function(query) {
		return query && nucl_regex.test(query);
	};

	self.submit = function() {
		jobIds = [];
		jobId = null;
		self.response = {"update": {"values": [], "status": "submitting", "message": "Submitting..."}};
		error = null;
		self.toggleSelected(self.selected());
		ResultService.setResults(null);

		ProgressService.open(self.query["app"] + " dashboard", self.cancel, self.update);

		PathwayGenieService.submit(self.query).then(
			function(resp) {
				jobIds = resp.data.job_ids;
				listen();
			},
			function(errResp) {
				onerror(errResp.data.message);
			});
	};

	self.cancel = function() {
		return PathwayGenieService.cancel(jobId);
	};

	self.update = function() {
		return self.response.update;
	};

	listen = function() {
		if(jobIds.length == 0) {
			return;
		}

		jobId = jobIds[0];
		var source = new EventSource("/progress/" + jobId);

		source.onmessage = function(event) {
			self.response = JSON.parse(event.data);
			status = self.response.update.status;

			if(status == "cancelled" || status == "error" || status == "finished") {
				source.close();

				if(status == "finished") {
					ResultService.appendResults(self.response.result);
				}

				jobIds.splice(0, 1);
				listen();
			}

			$scope.$apply();
		};

		source.onerror = function(event) {
			source.close();
			jobIds.splice(0, 1);
			listen();
			onerror(event.message);
		}
	};

	onerror = function(message) {
		self.response.update.status = "error";
		self.response.update.message = "Error";
		ProgressService.close();
		ErrorService.open(message);
	};

	remove = function(array, toRemove) {
		array = array.filter(function(elem) {
			return !toRemove.includes(elem);
		});

		return array;
	};

	autoUniprot = function(uniprotId, idx, initial_idx, feature_idx) {
		search = true;

		PartsGenieService.searchUniprot(uniprotId).then(
				function(resp) {
					var curr_design = null;

					if(idx > 0) {
						curr_design = self.copyDesign();
					}
					else {
						curr_design = self.query.designs[initial_idx]
					}

					UniprotService.updateFeature(curr_design.features[feature_idx], resp.data[0]);
					search = false;
				},
				function(errResp) {
					search = false;
				});
	}

	self.queryJson = angular.toJson({selected: self.selected(), query: self.query}, true);

	$scope.$watch(function() {
		return self.selected();
	},
	function(values) {
		self.queryJson = angular.toJson({selected: self.selected(), query: self.query}, true);
	}, true);

	$scope.$watch(function() {
		return self.query;
	},
	function(values) {
		self.queryJson = angular.toJson({selected: self.selected(), query: self.query}, true);
	}, true);

	$scope.$watch(function() {
		return self.pagination;
	},
	function(values) {
		PartsGenieService.selected = null;
	}, true);
}]);<|endoftext|>


<commit_before>var PointConstants = require('./PointConstants');
var PointDispatcher = require('./PointDispatcher');
var EventEmitter = require('events').EventEmitter;
var assign = require('object-assign');
var mapObject = require('react/lib/mapObject');

var _points = {};

function addPoint(point) {
  // Would replace this with actual id creation
  var id = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
  _points[id] = {
    id : id,
    x : point.x,
    y : point.y
  };
}

function addPoints(points) {
  for (var i=0; i<points.length; i++) {
    addPoint(points[i]);
  }
}

function deletePoint(id) {
  delete _points[id];
}

function deleteAllPoints() {
  _points = {};
}

var PointStore = assign({}, EventEmitter.prototype, {
  getAll: function() {
    var points = [];
    mapObject(_points, function(point) {
      points.push({ x : point.x, y : point.y });
    });
    return _points;
  },

  emitChange: function() {
    // also add action in this??? prob want to filter in the views
    this.emit('change');
  },

  addListener: function(callback) {
    this.on('change', callback);
  },

  // why is this a callback and not an object or something?
  removeListener: function(callback) {
    this.removeListener('change', callback);
  },
});

PointDispatcher.register(function(payload) {
  var point;

  switch(payload.action) {
    case PointConstants.POINT_ADD:
      addPoint(payload.point);
      PointStore.emitChange();
      break;
    case PointConstants.POINT_ADD_DEMO:
      addPoints(payload.points);
      PointStore.emitChange();
      break;
    case PointConstants.POINT_DELETE:
      deletePoint(payload.id);
      PointStore.emitChange();
      break;
    case PointConstants.POINT_DELETE_ALL:
      deleteAllPoints();
      PointStore.emitChange();
      break;
    default:
      // do nothing
  }
});

module.exports = PointStore;
<commit_msg>Cleanup<commit_after>var PointConstants = require('./PointConstants');
var PointDispatcher = require('./PointDispatcher');
var EventEmitter = require('events').EventEmitter;
var assign = require('object-assign');
var mapObject = require('react/lib/mapObject');

var _points = {};

function addPoint(point) {
  // Would replace this with actual id creation
  var id = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
  _points[id] = {
    id : id,
    x : point.x,
    y : point.y
  };
}

function addPoints(points) {
  for (var i=0; i<points.length; i++) {
    addPoint(points[i]);
  }
}

function deletePoint(id) {
  delete _points[id];
}

function deleteAllPoints() {
  _points = {};
}

var PointStore = assign({}, EventEmitter.prototype, {
  getAll: function() {
    var points = [];
    mapObject(_points, function(point) {
      points.push({ x : point.x, y : point.y });
    });
    return _points;
  },

  emitChange: function() {
    this.emit('change');
  },

  addListener: function(callback) {
    this.on('change', callback);
  },

  removeListener: function(callback) {
    this.removeListener('change', callback);
  },
});

PointDispatcher.register(function(payload) {
  var point;

  switch(payload.action) {
    case PointConstants.POINT_ADD:
      addPoint(payload.point);
      PointStore.emitChange();
      break;
    case PointConstants.POINT_ADD_DEMO:
      addPoints(payload.points);
      PointStore.emitChange();
      break;
    case PointConstants.POINT_DELETE:
      deletePoint(payload.id);
      PointStore.emitChange();
      break;
    case PointConstants.POINT_DELETE_ALL:
      deleteAllPoints();
      PointStore.emitChange();
      break;
    default:
      // do nothing
  }
});

module.exports = PointStore;
<|endoftext|>


<commit_before>/**
 * @fileOverview XMLHttpRequest wrapper module for restartless addons
 * @author       YUKI "Piro" Hiroshi
 * @version      1
 * @description
 *
 * @license
 *   The MIT License, Copyright (c) 2014 YUKI "Piro" Hiroshi.
 *   https://github.com/piroor/restartless/blob/master/license.txt
 * @url http://github.com/piroor/restartless
 */

var EXPORTED_SYMBOLS = [
  'get',
  'post'
];

var Deferred = require('jsdeferred').Deferred;

function get(aURI, aHeaders) {
  return sendRequest({
    method:  'GET',
    uri:     aURI,
    headers: aHeaders
  });
}

function post(aURI, aPostData, aHeaders) {
  return sendRequest({
    method:   'POST',
    uri:      aURI,
    headers:  aHeaders,
    postData: aPostData
  });
}

function sendRequest(aParams) {
  var deferred = new Deferred();

  var method   = (aParams.method || 'GET').toUpperCase();
  var uri      = aParams.uri || null;
  var headers  = aParams.headers || {};
  var postData = aParams.postData || null;

  if (!uri)
    throw new Error('no URL');

  var request;
  var listener = function(aEvent) {
    switch (aEvent.type) {
      case 'load':
      case 'error':
        break;
      default:
        return;
    }
    request.removeEventListener('load', listener, false);
    request.removeEventListener('error', listener, false);

    if (request.status == 200) {
      deferred.call(request);
    } else {
      try {
        deferred.fail(new Error(JSON.stringify({
          statusCode: request.status,
          body:       request.responseText,
          event:      {
            type:   aEvent.type,
            detail: aEvent.detail
          }
        })));
      } catch(error) {
        deferred.fail(new Error(JSON.stringify({
          error: {
            name:    error.name,
            message: error.message,
            error:   error
          },
          event: {
            type:   aEvent.type,
            detail: aEvent.detail
          }
        })));
      }
    }
  };

  Deferred.next(function() {
    request = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
                .createInstance(Ci.nsIXMLHttpRequest)
                .QueryInterface(Ci.nsIDOMEventTarget);
    request.open(method, uri, true);
    request.addEventListener('load', listener, false);
    request.addEventListener('error', listener, false);
    Object.keys(headers).forEach(function(aKey) {
      request.setRequestHeader(aKey, headers[aKey]);
    });
    request.send(postData);
  });

  return deferred;
}
<commit_msg>Support overriding of the response content type<commit_after>/**
 * @fileOverview XMLHttpRequest wrapper module for restartless addons
 * @author       YUKI "Piro" Hiroshi
 * @version      2
 * @description
 *
 * @license
 *   The MIT License, Copyright (c) 2014 YUKI "Piro" Hiroshi.
 *   https://github.com/piroor/restartless/blob/master/license.txt
 * @url http://github.com/piroor/restartless
 */

var EXPORTED_SYMBOLS = [
  'get',
  'post',
  'RESPONSE_CONTENT_TYPE'
];

var RESPONSE_CONTENT_TYPE = 'X-Override-Content-Type';

var Deferred = require('jsdeferred').Deferred;

function get(aURI, aHeaders) {
  return sendRequest({
    method:  'GET',
    uri:     aURI,
    headers: aHeaders
  });
}

function post(aURI, aPostData, aHeaders) {
  return sendRequest({
    method:   'POST',
    uri:      aURI,
    headers:  aHeaders,
    postData: aPostData
  });
}

function sendRequest(aParams) {
  var deferred = new Deferred();

  var method   = (aParams.method || 'GET').toUpperCase();
  var uri      = aParams.uri || null;
  var headers  = aParams.headers || {};
  var postData = aParams.postData || null;

  if (!uri)
    throw new Error('no URL');

  var request;
  var listener = function(aEvent) {
    switch (aEvent.type) {
      case 'load':
      case 'error':
        break;
      default:
        return;
    }
    request.removeEventListener('load', listener, false);
    request.removeEventListener('error', listener, false);

    if (request.status == 200) {
      deferred.call(request);
    } else {
      try {
        deferred.fail(new Error(JSON.stringify({
          statusCode: request.status,
          body:       request.responseText,
          event:      {
            type:   aEvent.type,
            detail: aEvent.detail
          }
        })));
      } catch(error) {
        deferred.fail(new Error(JSON.stringify({
          error: {
            name:    error.name,
            message: error.message,
            error:   error
          },
          event: {
            type:   aEvent.type,
            detail: aEvent.detail
          }
        })));
      }
    }
  };

  Deferred.next(function() {
    request = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
                .createInstance(Ci.nsIXMLHttpRequest)
                .QueryInterface(Ci.nsIDOMEventTarget);
    request.open(method, uri, true);
    request.addEventListener('load', listener, false);
    request.addEventListener('error', listener, false);
    Object.keys(headers).forEach(function(aKey) {
      switch (aKey) {
        case RESPONSE_CONTENT_TYPE:
          request.overrideMimeType(headers[aKey]);
          break;

        default:
          request.setRequestHeader(aKey, headers[aKey]);
          break;
      }
    });
    request.send(postData);
  });

  return deferred;
}
<|endoftext|>


<commit_before>const NoriCanvas = (() => {

    let handleCanvasData = (canvas, buffer, start, len) => {
        let ctx = canvas.getContext('2d');
        let cvWidth = canvas.width;
        let cvHeight = canvas.height;
        let end = start + len;
        let r, g, b, a, w, h, x, y, lineWidth, x2, y2, hex, img;
        let tx, ty, sx, sy, tw, th, sw, sh;
        let i = start;
        let imgLookup = canvas._NORI_imgLookup;
        if (!imgLookup) {
            imgLookup = {};
            canvas._NORI_imgLookup = imgLookup;
        }
        while (i < end) {
            r = buffer[i + 1];
            g = buffer[i + 2];
            b = buffer[i + 3];
            hex = NoriUtil.encodeHex(r, g, b);
            switch (buffer[i]) {
                case 'F':
                    i += 4;
                    ctx.fillStyle = hex;
                    ctx.fillRect(0, 0, cvWidth, cvHeight);
                    break;

                case 'R':
                    a = buffer[i + 4];
                    x = buffer[i + 5];
                    y = buffer[i + 6];
                    w = buffer[i + 7];
                    h = buffer[i + 8];
                    i += 9;
                    if (a !== 255) {
                        ctx.globalAlpha = a / 255;
                        ctx.fillStyle = hex;
                        ctx.fillRect(x, y, w, h);
                        ctx.globalAlpha = 1;
                    } else {
                        ctx.fillStyle = hex;
                        ctx.fillRect(x, y, w, h);
                    }
                    break;

                case 'E':
                    a = buffer[i + 4];
                    x = buffer[i + 5];
                    y = buffer[i + 6];
                    w = buffer[i + 7];
                    h = buffer[i + 8];
                    i += 9;
                    w = w * 4 / 3; // no idea why this needs to exist to look correct...
                    ctx.beginPath();
                    ctx.moveTo(x, y - h);
                    ctx.bezierCurveTo(
                        x + w, y - h,
                        x + w, y + h,
                        x, y + h);
                    ctx.bezierCurveTo(
                        x - w, y + h,
                        x - w, y - h,
                        x, y - h);

                    ctx.fillStyle = hex;
                    if (a !== 255) {
                        ctx.globalAlpha = a / 255;
                        ctx.fill();
                        ctx.closePath();
                        ctx.globalAlpha = 1;
                    } else {
                        ctx.fill();
                        ctx.closePath();
                    }
                    break;

                case 'L':
                    r = buffer[i + 1];
                    g = buffer[i + 2];
                    b = buffer[i + 3];
                    a = buffer[i + 4];
                    x = buffer[i + 5];
                    y = buffer[i + 6];
                    x2 = buffer[i + 7];
                    y2 = buffer[i + 8];
                    lineWidth = buffer[i + 9];
                    i += 10;
                    // TODO: this
                    break;

                case 'ImgData':
                    r = buffer[i + 4]; // version key
                    g = buffer[i + 5]; // resource ID
                    b = buffer[i + 6]; // actual image data
                    ((imageData, versionKey) => {
                        let imgLoader = new Image();
                        imgLoader.onload = () => {
                            let newImg = document.createElement('canvas');
                            newImg.width = imgLoader.width;
                            newImg.height = imgLoader.height;
                            let ctx = newImg.getContext('2d');
                            ctx.drawImage(imgLoader, 0, 0);
                            imgLookup[versionKey] = newImg;
                        };
                        imgLoader.src = 'data:image/png;base64,' + imageData;
                    })(b, r);
                    i += 7;
                    break;

                case 'I1':
                    r = buffer[i + 4]; // version key
                    img = imgLookup[r];
                    if (img) {
                        tx = buffer[i + 5];
                        ty = buffer[i + 6];
                        ctx.drawImage(img, tx, ty);
                    }
                    i += 7;
                    break;

                case 'I2':
                    r = buffer[i + 4]; // version key
                    img = imgLookup[r];
                    if (img) {
                        tx = buffer[i + 5];
                        ty = buffer[i + 6];
                        sx = buffer[i + 7];
                        sy = buffer[i + 8];
                        sw = buffer[i + 9];
                        sh = buffer[i + 10];
                        ctx.drawImage(img, sx, sy, sw, sh, tx, ty, sw, sh);
                    }
                    i += 11;
                    break;

                case 'I3':
                    r = buffer[i + 4]; // version key
                    img = imgLookup[r];
                    if (img) {
                        tx = buffer[i + 5];
                        ty = buffer[i + 6];
                        r = buffer[i + 7];
                        w = img.width;
                        h = img.height;

                        ctx.save();
                        ctx.translate(tx, ty);
                        ctx.rotate(r);

                        //if (a === 255) {
                            ctx.drawImage(img, -w / 2, -h / 2);
                        //} else {
                        //    ctx.globalAlpha = a / 255;
                        //    ctx.drawImage(canvas, -w / 2, -h / 2);
                        //    ctx.globalAlpha = 1;
                        //}
                        ctx.restore();
                    }
                    i += 8;
                    break;

                default:
                    throw new Error("Unknown draw instruction: " + buffer[i]);
            }
        }
    };

    return {
        handleCanvasData,
    };

})();
<commit_msg>U3: Fix some math in the ellipse drawing code.<commit_after>const NoriCanvas = (() => {

    let handleCanvasData = (canvas, buffer, start, len) => {
        let ctx = canvas.getContext('2d');
        let cvWidth = canvas.width;
        let cvHeight = canvas.height;
        let end = start + len;
        let r, g, b, a, w, h, x, y, lineWidth, x2, y2, hex, img;
        let tx, ty, sx, sy, tw, th, sw, sh;
        let i = start;
        let imgLookup = canvas._NORI_imgLookup;
        if (!imgLookup) {
            imgLookup = {};
            canvas._NORI_imgLookup = imgLookup;
        }
        while (i < end) {
            r = buffer[i + 1];
            g = buffer[i + 2];
            b = buffer[i + 3];
            hex = NoriUtil.encodeHex(r, g, b);
            switch (buffer[i]) {
                case 'F':
                    i += 4;
                    ctx.fillStyle = hex;
                    ctx.fillRect(0, 0, cvWidth, cvHeight);
                    break;

                case 'R':
                    a = buffer[i + 4];
                    x = buffer[i + 5];
                    y = buffer[i + 6];
                    w = buffer[i + 7];
                    h = buffer[i + 8];
                    i += 9;
                    if (a !== 255) {
                        ctx.globalAlpha = a / 255;
                        ctx.fillStyle = hex;
                        ctx.fillRect(x, y, w, h);
                        ctx.globalAlpha = 1;
                    } else {
                        ctx.fillStyle = hex;
                        ctx.fillRect(x, y, w, h);
                    }
                    break;

                case 'E':
                    a = buffer[i + 4];
                    x = buffer[i + 5];
                    y = buffer[i + 6];
                    w = buffer[i + 7];
                    h = buffer[i + 8];
                    i += 9;
                    x += w / 2;
                    w /= 2;
                    y += h / 2;
                    h /= 2;
                    w = w * 4 / 3; // no idea why this needs to exist to look correct...
                    ctx.beginPath();
                    ctx.moveTo(x, y - h);
                    ctx.bezierCurveTo(
                        x + w, y - h,
                        x + w, y + h,
                        x, y + h);
                    ctx.bezierCurveTo(
                        x - w, y + h,
                        x - w, y - h,
                        x, y - h);

                    ctx.fillStyle = hex;
                    if (a !== 255) {
                        ctx.globalAlpha = a / 255;
                        ctx.fill();
                        ctx.closePath();
                        ctx.globalAlpha = 1;
                    } else {
                        ctx.fill();
                        ctx.closePath();
                    }
                    break;

                case 'L':
                    r = buffer[i + 1];
                    g = buffer[i + 2];
                    b = buffer[i + 3];
                    a = buffer[i + 4];
                    x = buffer[i + 5];
                    y = buffer[i + 6];
                    x2 = buffer[i + 7];
                    y2 = buffer[i + 8];
                    lineWidth = buffer[i + 9];
                    i += 10;
                    // TODO: this
                    break;

                case 'ImgData':
                    r = buffer[i + 4]; // version key
                    g = buffer[i + 5]; // resource ID
                    b = buffer[i + 6]; // actual image data
                    ((imageData, versionKey) => {
                        let imgLoader = new Image();
                        imgLoader.onload = () => {
                            let newImg = document.createElement('canvas');
                            newImg.width = imgLoader.width;
                            newImg.height = imgLoader.height;
                            let ctx = newImg.getContext('2d');
                            ctx.drawImage(imgLoader, 0, 0);
                            imgLookup[versionKey] = newImg;
                        };
                        imgLoader.src = 'data:image/png;base64,' + imageData;
                    })(b, r);
                    i += 7;
                    break;

                case 'I1':
                    r = buffer[i + 4]; // version key
                    img = imgLookup[r];
                    if (img) {
                        tx = buffer[i + 5];
                        ty = buffer[i + 6];
                        ctx.drawImage(img, tx, ty);
                    }
                    i += 7;
                    break;

                case 'I2':
                    r = buffer[i + 4]; // version key
                    img = imgLookup[r];
                    if (img) {
                        tx = buffer[i + 5];
                        ty = buffer[i + 6];
                        sx = buffer[i + 7];
                        sy = buffer[i + 8];
                        sw = buffer[i + 9];
                        sh = buffer[i + 10];
                        ctx.drawImage(img, sx, sy, sw, sh, tx, ty, sw, sh);
                    }
                    i += 11;
                    break;

                case 'I3':
                    r = buffer[i + 4]; // version key
                    img = imgLookup[r];
                    if (img) {
                        tx = buffer[i + 5];
                        ty = buffer[i + 6];
                        r = buffer[i + 7];
                        w = img.width;
                        h = img.height;

                        ctx.save();
                        ctx.translate(tx, ty);
                        ctx.rotate(r);

                        //if (a === 255) {
                            ctx.drawImage(img, -w / 2, -h / 2);
                        //} else {
                        //    ctx.globalAlpha = a / 255;
                        //    ctx.drawImage(canvas, -w / 2, -h / 2);
                        //    ctx.globalAlpha = 1;
                        //}
                        ctx.restore();
                    }
                    i += 8;
                    break;

                default:
                    throw new Error("Unknown draw instruction: " + buffer[i]);
            }
        }
    };

    return {
        handleCanvasData,
    };

})();
<|endoftext|>


<commit_before>'use strict';

var appCfg = {};

var ngModule = angular.module('woAppConfig', []);
ngModule.factory('appConfig', function() {
    return appCfg;
});
module.exports = appCfg;

/**
 * Global app configurations
 */
appCfg.config = {
    oauthClientId: '440907777130-bnk8b12nsqmpcf5cdbnhpskefhfhfgu1.apps.googleusercontent.com',
    oauthScopes: [
        'https://mail.google.com/',
        'https://www.googleapis.com/auth/userinfo.email'
    ],
    oauthRedirectUrl: window.location.origin,
    pgpComment: 'Whiteout Mail - https://whiteout.io',
    hkpUrl: 'https://keyserver.ubuntu.com',
    adminUrl: 'https://admin-node.whiteout.io',
    settingsUrl: 'https://settings.whiteout.io/autodiscovery/',
    mailServer: {
        domain: 'wmail.io',
        imap: {
            hostname: 'imap.wmail.io',
            port: 993,
            secure: true
        },
        smtp: {
            hostname: 'smtp.wmail.io',
            port: 465,
            secure: true
        }
    },
    oauthDomains: [/\.gmail\.com$/, /\.googlemail\.com$/],
    ignoreUploadOnSentDomains: [/\.gmail\.com$/, /\.googlemail\.com$/],
    symKeySize: 256,
    symIvSize: 96,
    asymKeySize: 2048,
    workerPath: 'js',
    reconnectInterval: 10000,
    checkOutboxInterval: 5000,
    iconPath: '/img/icon-128-chrome.png',
    verificationUrl: '/verify/',
    verificationUuidLength: 36,
    dbVersion: 6,
    appVersion: undefined,
    outboxMailboxPath: 'OUTBOX',
    outboxMailboxName: 'Outbox',
    outboxMailboxType: 'Outbox',
    connDocTimeout: 5000,
    imapUpdateBatchSize: 25
};

// parse manifest to get configurations for current runtime
if (typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.getManifest) {
    setConfigParams(chrome.runtime.getManifest());
} else if (typeof $ !== 'undefined' && $.get) {
    $.get('/manifest.json', setConfigParams, 'json');
}

function setConfigParams(manifest) {
    var cfg = appCfg.config;
    // get the app version
    cfg.appVersion = manifest.version;
}

/**
 * Strings are maintained here
 */
appCfg.string = {
    fallbackSubject: '(no subject)',
    invitationSubject: 'Invitation to a private conversation',
    invitationMessage: 'Hi,\n\nI use Whiteout Mail to send and receive encrypted email. I would like to exchange encrypted messages with you as well.\n\nPlease install the Whiteout Mail application. This application makes it easy to read and write messages securely with PGP encryption applied.\n\nGo to the Whiteout Networks homepage to learn more and to download the application: https://whiteout.io\n\n',
    signature: '\n\n\n--\nSent from Whiteout Mail - https://whiteout.io\n\nMy PGP key: ',
    webSite: 'http://whiteout.io',
    verificationSubject: '[whiteout] New public key uploaded',
    sendBtnClear: 'Send',
    sendBtnSecure: 'Send securely',
    updatePublicKeyTitle: 'Public Key Updated',
    updatePublicKeyMsgNewKey: '{0} updated his key and may not be able to read encrypted messages sent with his old key. Update the key?',
    updatePublicKeyMsgRemovedKey: '{0} revoked his key and may no longer be able to read encrypted messages. Remove the key?',
    updatePublicKeyPosBtn: 'Yes',
    updatePublicKeyNegBtn: 'No',
    outdatedCertificateTitle: 'Warning',
    outdatedCertificateMessage: 'The SSL certificate for the mail server {0} changed, the connection was refused.',
    updateCertificateTitle: 'Warning',
    updateCertificateMessage: 'The SSL certificate for the mail server {0} changed. Do you want to proceed?',
    updateCertificatePosBtn: 'Yes',
    updateCertificateNegBtn: 'No',
    certificateFaqLink: 'https://github.com/whiteout-io/mail-html5/wiki/FAQ#what-does-the-ssl-certificate-for-the-mail-server--changed-mean',
    bugReportTitle: 'Report a bug',
    bugReportSubject: '[Bug] I want to report a bug',
    bugReportBody: 'Steps to reproduce\n1. \n2. \n3. \n\nWhat happens?\n\n\nWhat do you expect to happen instead?\n\n\n\n== PLEASE DONT PUT ANY KEYS HERE! ==\n\n\n## Log\n\nBelow is the log. It includes your interactions with your email provider from the point where you started the app for the last time. Login data and email content has been stripped. Any information provided by you will be used for the purpose of locating and fixing the bug you reported. It will be deleted subsequently. However, you can edit this log and/or remove log data in the event that something would show up.\n\nUser-Agent: {0}\nVersion: {1}\n\n',
    supportAddress: 'mail.support@whiteout.io',
    connDocOffline: 'It appears that you are offline. Please retry when you are online.',
    connDocTlsWrongCert: 'A connection to {0} was rejected because the TLS certificate is invalid. Please have a look at the FAQ for information on how to fix this error.',
    connDocHostUnreachable: 'We could not establish a connection to {0}. Please check the server settings!',
    connDocHostTimeout: 'We could not establish a connection to {0} within {1} ms. Please check the server settings and encryption mode!',
    connDocAuthRejected: 'Your credentials for {0} were rejected. Please check your username and password!',
    connDocNoInbox: 'We could not detect an IMAP inbox folder on {0}.  Please have a look at the FAQ for information on how to fix this error.',
    connDocGenericError: 'There was an error connecting to {0}: {1}',
    logoutTitle: 'Logout',
    logoutMessage: 'Are you sure you want to log out? Please back up your encryption key before proceeding!',
    removePreAuthAccountTitle: 'Remove account',
    removePreAuthAccountMessage: 'Are you sure you want to remove your account from this device?'
};<commit_msg>Replace deprecated email oauth scope<commit_after>'use strict';

var appCfg = {};

var ngModule = angular.module('woAppConfig', []);
ngModule.factory('appConfig', function() {
    return appCfg;
});
module.exports = appCfg;

/**
 * Global app configurations
 */
appCfg.config = {
    oauthClientId: '440907777130-bnk8b12nsqmpcf5cdbnhpskefhfhfgu1.apps.googleusercontent.com',
    oauthScopes: [
        'https://mail.google.com/',
        'email'
    ],
    oauthRedirectUrl: window.location.origin,
    pgpComment: 'Whiteout Mail - https://whiteout.io',
    hkpUrl: 'https://keyserver.ubuntu.com',
    adminUrl: 'https://admin-node.whiteout.io',
    settingsUrl: 'https://settings.whiteout.io/autodiscovery/',
    mailServer: {
        domain: 'wmail.io',
        imap: {
            hostname: 'imap.wmail.io',
            port: 993,
            secure: true
        },
        smtp: {
            hostname: 'smtp.wmail.io',
            port: 465,
            secure: true
        }
    },
    oauthDomains: [/\.gmail\.com$/, /\.googlemail\.com$/],
    ignoreUploadOnSentDomains: [/\.gmail\.com$/, /\.googlemail\.com$/],
    symKeySize: 256,
    symIvSize: 96,
    asymKeySize: 2048,
    workerPath: 'js',
    reconnectInterval: 10000,
    checkOutboxInterval: 5000,
    iconPath: '/img/icon-128-chrome.png',
    verificationUrl: '/verify/',
    verificationUuidLength: 36,
    dbVersion: 6,
    appVersion: undefined,
    outboxMailboxPath: 'OUTBOX',
    outboxMailboxName: 'Outbox',
    outboxMailboxType: 'Outbox',
    connDocTimeout: 5000,
    imapUpdateBatchSize: 25
};

// parse manifest to get configurations for current runtime
if (typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.getManifest) {
    setConfigParams(chrome.runtime.getManifest());
} else if (typeof $ !== 'undefined' && $.get) {
    $.get('/manifest.json', setConfigParams, 'json');
}

function setConfigParams(manifest) {
    var cfg = appCfg.config;
    // get the app version
    cfg.appVersion = manifest.version;
}

/**
 * Strings are maintained here
 */
appCfg.string = {
    fallbackSubject: '(no subject)',
    invitationSubject: 'Invitation to a private conversation',
    invitationMessage: 'Hi,\n\nI use Whiteout Mail to send and receive encrypted email. I would like to exchange encrypted messages with you as well.\n\nPlease install the Whiteout Mail application. This application makes it easy to read and write messages securely with PGP encryption applied.\n\nGo to the Whiteout Networks homepage to learn more and to download the application: https://whiteout.io\n\n',
    signature: '\n\n\n--\nSent from Whiteout Mail - https://whiteout.io\n\nMy PGP key: ',
    webSite: 'http://whiteout.io',
    verificationSubject: '[whiteout] New public key uploaded',
    sendBtnClear: 'Send',
    sendBtnSecure: 'Send securely',
    updatePublicKeyTitle: 'Public Key Updated',
    updatePublicKeyMsgNewKey: '{0} updated his key and may not be able to read encrypted messages sent with his old key. Update the key?',
    updatePublicKeyMsgRemovedKey: '{0} revoked his key and may no longer be able to read encrypted messages. Remove the key?',
    updatePublicKeyPosBtn: 'Yes',
    updatePublicKeyNegBtn: 'No',
    outdatedCertificateTitle: 'Warning',
    outdatedCertificateMessage: 'The SSL certificate for the mail server {0} changed, the connection was refused.',
    updateCertificateTitle: 'Warning',
    updateCertificateMessage: 'The SSL certificate for the mail server {0} changed. Do you want to proceed?',
    updateCertificatePosBtn: 'Yes',
    updateCertificateNegBtn: 'No',
    certificateFaqLink: 'https://github.com/whiteout-io/mail-html5/wiki/FAQ#what-does-the-ssl-certificate-for-the-mail-server--changed-mean',
    bugReportTitle: 'Report a bug',
    bugReportSubject: '[Bug] I want to report a bug',
    bugReportBody: 'Steps to reproduce\n1. \n2. \n3. \n\nWhat happens?\n\n\nWhat do you expect to happen instead?\n\n\n\n== PLEASE DONT PUT ANY KEYS HERE! ==\n\n\n## Log\n\nBelow is the log. It includes your interactions with your email provider from the point where you started the app for the last time. Login data and email content has been stripped. Any information provided by you will be used for the purpose of locating and fixing the bug you reported. It will be deleted subsequently. However, you can edit this log and/or remove log data in the event that something would show up.\n\nUser-Agent: {0}\nVersion: {1}\n\n',
    supportAddress: 'mail.support@whiteout.io',
    connDocOffline: 'It appears that you are offline. Please retry when you are online.',
    connDocTlsWrongCert: 'A connection to {0} was rejected because the TLS certificate is invalid. Please have a look at the FAQ for information on how to fix this error.',
    connDocHostUnreachable: 'We could not establish a connection to {0}. Please check the server settings!',
    connDocHostTimeout: 'We could not establish a connection to {0} within {1} ms. Please check the server settings and encryption mode!',
    connDocAuthRejected: 'Your credentials for {0} were rejected. Please check your username and password!',
    connDocNoInbox: 'We could not detect an IMAP inbox folder on {0}.  Please have a look at the FAQ for information on how to fix this error.',
    connDocGenericError: 'There was an error connecting to {0}: {1}',
    logoutTitle: 'Logout',
    logoutMessage: 'Are you sure you want to log out? Please back up your encryption key before proceeding!',
    removePreAuthAccountTitle: 'Remove account',
    removePreAuthAccountMessage: 'Are you sure you want to remove your account from this device?'
};<|endoftext|>


<commit_before>export function osmIsInterestingTag(key) {
    return key !== 'attribution' &&
        key !== 'created_by' &&
        key !== 'source' &&
        key !== 'odbl' &&
        key.indexOf('source:') !== 0 &&
        key.indexOf('source_ref') !== 0 && // purposely exclude colon
        key.indexOf('tiger:') !== 0;
}

export var osmAreaKeys = {};
export function osmSetAreaKeys(value) {
    osmAreaKeys = value;
}

// returns an object with the tag from `tags` that implies an area geometry, if any
export function osmTagSuggestingArea(tags) {
    if (tags.area === 'yes') return { area: 'yes' };
    if (tags.area === 'no') return null;

    // `highway` and `railway` are typically linear features, but there
    // are a few exceptions that should be treated as areas, even in the
    // absence of a proper `area=yes` or `areaKeys` tag.. see #4194
    var lineKeys = {
        highway: {
            rest_area: true,
            services: true
        },
        railway: {
            roundhouse: true,
            station: true,
            traverser: true,
            turntable: true,
            wash: true
        }
    };
    var returnTags = {};
    for (var key in tags) {
        if (key in osmAreaKeys && !(tags[key] in osmAreaKeys[key])) {
            returnTags[key] = tags[key];
            return returnTags;
        }
        if (key in lineKeys && tags[key] in lineKeys[key]) {
            returnTags[key] = tags[key];
            return returnTags;
        }
    }
    return null;
}

// Tags that indicate a node can be a standalone point
// e.g. { amenity: { bar: true, parking: true, ... } ... }
export var osmPointTags = {};
export function osmSetPointTags(value) {
    osmPointTags = value;
}
// Tags that indicate a node can be part of a way
// e.g. { amenity: { parking: true, ... }, highway: { stop: true ... } ... }
export var osmVertexTags = {};
export function osmSetVertexTags(value) {
    osmVertexTags = value;
}

export function osmNodeGeometriesForTags(nodeTags) {
    var geometries = {};
    for (var key in nodeTags) {
        if (osmPointTags[key] &&
            (osmPointTags[key]['*'] || osmPointTags[key][nodeTags[key]])) {
            geometries.point = true;
        }
        if (osmVertexTags[key] &&
            (osmVertexTags[key]['*'] || osmVertexTags[key][nodeTags[key]])) {
            geometries.vertex = true;
        }
        // break early if both are already supported
        if (geometries.point && geometries.vertex) break;
    }
    return geometries;
}

export var osmOneWayTags = {
    'aerialway': {
        'chair_lift': true,
        'drag_lift': true,
        'j-bar': true,
        'magic_carpet': true,
        'mixed_lift': true,
        'platter': true,
        'rope_tow': true,
        't-bar': true,
        'zip_line': true
    },
    'highway': {
        'motorway': true
    },
    'junction': {
        'circular': true,
        'roundabout': true
    },
    'man_made': {
        'goods_conveyor': true,
        'piste:halfpipe': true
    },
    'piste:type': {
        'downhill': true,
        'sled': true,
        'yes': true
    },
    'waterway': {
        'canal': true,
        'ditch': true,
        'drain': true,
        'fish_pass': true,
        'river': true,
        'stream': true,
        'tidal_channel': true
    }
};

// solid and smooth surfaces akin to the assumed default road surface in OSM
export var osmPavedTags = {
    'surface': {
        'paved': true,
        'asphalt': true,
        'concrete': true,
        'concrete:lanes': true,
        'concrete:plates': true
    },
    'tracktype': {
        'grade1': true
    }
};

// solid, if somewhat uncommon surfaces with a high range of smoothness
export var osmSemipavedTags = {
    'surface': {
        'cobblestone': true,
        'cobblestone:flattened': true,
        'unhewn_cobblestone': true,
        'sett': true,
        'paving_stones': true,
        'metal': true,
        'wood': true
    }
};

export var osmRightSideIsInsideTags = {
    'natural': {
        'cliff': true,
        'coastline': 'coastline',
    },
    'barrier': {
        'retaining_wall': true,
        'kerb': true,
        'guard_rail': true,
        'city_wall': true,
    },
    'man_made': {
        'embankment': true
    },
    'waterway': {
        'weir': true
    }
};

// "highway" tag values for pedestrian or vehicle right-of-ways that make up the routable network
// (does not include `raceway`)
export var osmRoutableHighwayTagValues = {
    motorway: true, trunk: true, primary: true, secondary: true, tertiary: true, residential: true,
    motorway_link: true, trunk_link: true, primary_link: true, secondary_link: true, tertiary_link: true,
    unclassified: true, road: true, service: true, track: true, living_street: true, bus_guideway: true,
    path: true, footway: true, cycleway: true, bridleway: true, pedestrian: true, corridor: true, steps: true
};
// "highway" tag values that generally do not allow motor vehicles
export var osmPathHighwayTagValues = {
    path: true, footway: true, cycleway: true, bridleway: true, pedestrian: true, corridor: true, steps: true
};

// "railway" tag values representing existing railroad tracks (purposely does not include 'abandoned')
export var osmRailwayTrackTagValues = {
    rail: true, light_rail: true, tram: true, subway: true,
    monorail: true, funicular: true, miniature: true, narrow_gauge: true,
    disused: true, preserved: true
};

// "waterway" tag values for line features representing water flow
export var osmFlowingWaterwayTagValues = {
    canal: true, ditch: true, drain: true, fish_pass: true, river: true, stream: true, tidal_channel: true
};
<commit_msg>seamark:type=separation_lane implies oneway<commit_after>export function osmIsInterestingTag(key) {
    return key !== 'attribution' &&
        key !== 'created_by' &&
        key !== 'source' &&
        key !== 'odbl' &&
        key.indexOf('source:') !== 0 &&
        key.indexOf('source_ref') !== 0 && // purposely exclude colon
        key.indexOf('tiger:') !== 0;
}

export var osmAreaKeys = {};
export function osmSetAreaKeys(value) {
    osmAreaKeys = value;
}

// returns an object with the tag from `tags` that implies an area geometry, if any
export function osmTagSuggestingArea(tags) {
    if (tags.area === 'yes') return { area: 'yes' };
    if (tags.area === 'no') return null;

    // `highway` and `railway` are typically linear features, but there
    // are a few exceptions that should be treated as areas, even in the
    // absence of a proper `area=yes` or `areaKeys` tag.. see #4194
    var lineKeys = {
        highway: {
            rest_area: true,
            services: true
        },
        railway: {
            roundhouse: true,
            station: true,
            traverser: true,
            turntable: true,
            wash: true
        }
    };
    var returnTags = {};
    for (var key in tags) {
        if (key in osmAreaKeys && !(tags[key] in osmAreaKeys[key])) {
            returnTags[key] = tags[key];
            return returnTags;
        }
        if (key in lineKeys && tags[key] in lineKeys[key]) {
            returnTags[key] = tags[key];
            return returnTags;
        }
    }
    return null;
}

// Tags that indicate a node can be a standalone point
// e.g. { amenity: { bar: true, parking: true, ... } ... }
export var osmPointTags = {};
export function osmSetPointTags(value) {
    osmPointTags = value;
}
// Tags that indicate a node can be part of a way
// e.g. { amenity: { parking: true, ... }, highway: { stop: true ... } ... }
export var osmVertexTags = {};
export function osmSetVertexTags(value) {
    osmVertexTags = value;
}

export function osmNodeGeometriesForTags(nodeTags) {
    var geometries = {};
    for (var key in nodeTags) {
        if (osmPointTags[key] &&
            (osmPointTags[key]['*'] || osmPointTags[key][nodeTags[key]])) {
            geometries.point = true;
        }
        if (osmVertexTags[key] &&
            (osmVertexTags[key]['*'] || osmVertexTags[key][nodeTags[key]])) {
            geometries.vertex = true;
        }
        // break early if both are already supported
        if (geometries.point && geometries.vertex) break;
    }
    return geometries;
}

export var osmOneWayTags = {
    'aerialway': {
        'chair_lift': true,
        'drag_lift': true,
        'j-bar': true,
        'magic_carpet': true,
        'mixed_lift': true,
        'platter': true,
        'rope_tow': true,
        't-bar': true,
        'zip_line': true
    },
    'highway': {
        'motorway': true
    },
    'junction': {
        'circular': true,
        'roundabout': true
    },
    'man_made': {
        'goods_conveyor': true,
        'piste:halfpipe': true
    },
    'piste:type': {
        'downhill': true,
        'sled': true,
        'yes': true
    },
    'seamark:type': {
        'separation_lane': true,
        'separation_roundabout': true
    },
    'waterway': {
        'canal': true,
        'ditch': true,
        'drain': true,
        'fish_pass': true,
        'river': true,
        'stream': true,
        'tidal_channel': true
    }
};

// solid and smooth surfaces akin to the assumed default road surface in OSM
export var osmPavedTags = {
    'surface': {
        'paved': true,
        'asphalt': true,
        'concrete': true,
        'concrete:lanes': true,
        'concrete:plates': true
    },
    'tracktype': {
        'grade1': true
    }
};

// solid, if somewhat uncommon surfaces with a high range of smoothness
export var osmSemipavedTags = {
    'surface': {
        'cobblestone': true,
        'cobblestone:flattened': true,
        'unhewn_cobblestone': true,
        'sett': true,
        'paving_stones': true,
        'metal': true,
        'wood': true
    }
};

export var osmRightSideIsInsideTags = {
    'natural': {
        'cliff': true,
        'coastline': 'coastline',
    },
    'barrier': {
        'retaining_wall': true,
        'kerb': true,
        'guard_rail': true,
        'city_wall': true,
    },
    'man_made': {
        'embankment': true
    },
    'waterway': {
        'weir': true
    }
};

// "highway" tag values for pedestrian or vehicle right-of-ways that make up the routable network
// (does not include `raceway`)
export var osmRoutableHighwayTagValues = {
    motorway: true, trunk: true, primary: true, secondary: true, tertiary: true, residential: true,
    motorway_link: true, trunk_link: true, primary_link: true, secondary_link: true, tertiary_link: true,
    unclassified: true, road: true, service: true, track: true, living_street: true, bus_guideway: true,
    path: true, footway: true, cycleway: true, bridleway: true, pedestrian: true, corridor: true, steps: true
};
// "highway" tag values that generally do not allow motor vehicles
export var osmPathHighwayTagValues = {
    path: true, footway: true, cycleway: true, bridleway: true, pedestrian: true, corridor: true, steps: true
};

// "railway" tag values representing existing railroad tracks (purposely does not include 'abandoned')
export var osmRailwayTrackTagValues = {
    rail: true, light_rail: true, tram: true, subway: true,
    monorail: true, funicular: true, miniature: true, narrow_gauge: true,
    disused: true, preserved: true
};

// "waterway" tag values for line features representing water flow
export var osmFlowingWaterwayTagValues = {
    canal: true, ditch: true, drain: true, fish_pass: true, river: true, stream: true, tidal_channel: true
};
<|endoftext|>


<commit_before>import m from 'mithril';
import prop from 'mithril/stream';
import _ from 'underscore';
import projectVM from '../vms/project-vm';
import addressVM from '../vms/address-vm';
import models from '../models';
import h from '../h';

const I18nScope = _.partial(h.i18nScope, 'projects.contributions.edit.errors');
const paymentInfoId = prop();
const { commonPayment, commonSubscriptionUpgrade, commonPaymentInfo, commonCreditCard, commonCreditCards, rechargeSubscription } = models;
const sendPaymentRequest = data => commonPayment.postWithToken(
    { data: _.extend({}, data, { payment_id: paymentInfoId() }) },
    null,
    (h.isDevEnv() ? { 'X-forwarded-For': '127.0.0.1' } : {})
)
.catch((error) => {
    h.captureException(error);
    throw error;
});

const sendSubscriptionUpgrade = data => commonSubscriptionUpgrade.postWithToken(
    { data },
    null,
    (h.isDevEnv() ? { 'X-forwarded-For': '127.0.0.1' } : {})
)
.catch((error) => {
    h.captureException(error);
    throw error;
});

const saveCreditCard = creditCardHash => commonCreditCard
.postWithToken({ data: { card_hash: creditCardHash } })
.catch((error) => {
    h.captureException(error);
    throw error;
});;

const updateUser = user => m.request({
    method: 'PUT',
    url: `/users/${user.id}.json`,
    data: {
        user
    },
    config: h.setCsrfToken
})
.catch((error) => {
    h.captureException(error);
    throw error;
});

const userPayload = (customer, address) => ({
    id: h.getUser().id,
    cpf: customer.ownerDocument(),
    name: customer.completeName(),
    address_attributes: {
        country_id: address.country_id,
        state_id: address.state_id,
        address_street: address.address_street,
        address_neighbourhood: address.address_neighbourhood,
        address_number: address.address_number,
        address_zip_code: address.address_zip_code,
        address_city: address.address_city,
        address_state: address.address_state,
        address_complement: address.address_complement,
        phone_number: address.phone_number
    }
});

const displayError = fields => (exception) => {
    const errorMsg = exception.message || window.I18n.t('submission.encryption_error', I18nScope());
    fields.isLoading(false);
    fields.submissionError(window.I18n.t('submission.error', I18nScope({ message: errorMsg })));
    m.redraw();
    h.captureException(exception);
};

const paymentInfo = paymentId => commonPaymentInfo
    .postWithToken({ id: paymentId }, null, (h.isDevEnv() ? { 'X-forwarded-For': '127.0.0.1' } : {}))
    .catch((error) => {
        h.captureException(error);
        throw error;
    });

const creditCardInfo = creditCard => commonCreditCards
    .getRowWithToken(h.idVM.id(creditCard.id).parameters())
    .catch((error) => {
        h.captureException(error);
        throw error;
    });

let retries = 10;
const isReactivation = () => {
    const subscriptionStatus = m.route.param('subscription_status');
    return subscriptionStatus === 'inactive' || subscriptionStatus === 'canceled';
};
const resolvePayment = (gateway_payment_method, payment_confirmed, payment_id, isEdit) => m.route.set(`/projects/${projectVM.currentProject().project_id}/subscriptions/thank_you?project_id=${projectVM.currentProject().project_id}&payment_method=${gateway_payment_method}&payment_confirmed=${payment_confirmed}${payment_id ? `&payment_id=${payment_id}` : ''}${isEdit && !isReactivation() ? '&is_edit=1' : ''}`);
const requestInfo = (promise, paymentId, defaultPaymentMethod, isEdit) => {
    if (retries <= 0) {
        return promise.resolve(resolvePayment(defaultPaymentMethod, false, paymentId, isEdit));
    }

    paymentInfo(paymentId).then((infoR) => {
        if (_.isNull(infoR.gateway_payment_method) || _.isUndefined(infoR.gateway_payment_method)) {
            if (!_.isNull(infoR.gateway_errors)) {
                return promise.reject(_.first(infoR.gateway_errors));
            }

            return h.sleep(4000).then(() => {
                retries -= 1;

                return requestInfo(promise, paymentId, defaultPaymentMethod);
            });
        }

        return promise.resolve(resolvePayment(infoR.gateway_payment_method, true, paymentId, isEdit));
    }).catch(error => promise.reject({}));
};

const getPaymentInfoUntilNoError = (paymentMethod, isEdit) => ({ id, catalog_payment_id }) => {
    const p = new Promise((resolve, reject) => {
        const paymentId = isEdit ? catalog_payment_id : id;

        if (paymentId) {
            paymentInfoId(paymentId);
            requestInfo({resolve, reject}, paymentId, paymentMethod, isEdit);
        } else {
            resolvePayment(paymentMethod, false, null, isEdit);
        }
    });

    return p;
};

let creditCardRetries = 5;
const waitForSavedCreditCard = promise => (creditCardId) => {
    if (creditCardRetries <= 0) {
        return promise.reject({ message: 'Could not save card' });
    }

    creditCardInfo(creditCardId).then(([infoR]) => {
        if (_.isEmpty(infoR.gateway_data)) {
            if (!_.isEmpty(infoR.gateway_errors)) {
                return promise.reject(_.first(infoR.gateway_errors));
            }

            return h.sleep(4000).then(() => {
                creditCardRetries -= 1;

                return waitForSavedCreditCard(promise)(creditCardId);
            });
        }

        return promise.resolve({ creditCardId });
    }).catch(error => promise.reject({ message: error.message }));

    return promise;
};

const processCreditCard = (cardHash, fields) => {
    const p = new Promise((resolve, reject) => {
        saveCreditCard(cardHash)
            .then(waitForSavedCreditCard({resolve, reject}))
            .catch(reject);
    });

    return p;
};

const kondutoExecute = function () {
    const customerID = h.getUserCommonID();

    if (customerID) {
        var period = 300;
        var limit = 20 * 1e3;
        var nTry = 0;
        var intervalID = setInterval(function () {
            var clear = limit / period <= ++nTry;
            if ((typeof (Konduto) !== "undefined") && (typeof (Konduto.setCustomerID) !== "undefined")) {
                window.Konduto.setCustomerID(customerID);
                clear = true;
            }
            if (clear) {
                clearInterval(intervalID);
            }
        }, period);
    }
};

const sendCreditCardPayment = (selectedCreditCard, fields, commonData, addVM) => {

    if (!fields) {
        return false;
    }
    fields.isLoading(true);
    m.redraw();

    const meta = _.first(document.querySelectorAll('[name=pagarme-encryption-key]'));
    const encryptionKey = meta.getAttribute('content');

    window.PagarMe.encryption_key = encryptionKey;
    const card = setNewCreditCard(fields.creditCardFields);

    const customer = fields.fields;
    const address = customer.address().getFields();
    const phoneDdd = address.phone_number ? h.extractPhoneDDD(address.phone_number) : null;
    const phoneNumber = address.phone_number ? h.extractPhoneNumber(address.phone_number) : null;
    const addressState = address.state_id ? _.findWhere(addVM.states(), { id: address.state_id }) : address.address_state;
    const addressCountry = _.findWhere(addVM.countries(), { id: address.country_id }) || {};

    window.pagarme.client.connect({ encryption_key: encryptionKey })
        .then(client => client.security.encrypt(card))
        .then((cardHash) => {
            const payload = {
                subscription: true,
                anonymous: customer.anonymous(),
                user_id: commonData.userCommonId,
                project_id: commonData.projectCommonId,
                amount: commonData.amount,
                payment_method: 'credit_card',
                credit_card_owner_document: fields.creditCardFields.cardOwnerDocument(),
                is_international: address.country_id !== addVM.defaultCountryID,
                customer: {
                    name: customer.completeName(),
                    document_number: customer.ownerDocument(),
                    address: {
                        neighborhood: address.address_neighbourhood,
                        street: address.address_street,
                        street_number: address.address_number,
                        zipcode: address.address_zip_code,
                        country: addressCountry.name,
                        country_code: addressCountry.code,
                        state: addressState.acronym ? addressState.acronym : addressState,
                        city: address.address_city,
                        complementary: address.address_complement
                    },
                    phone: {
                        ddi: '55',
                        ddd: phoneDdd,
                        number: phoneNumber
                    }
                }
            };

            if (commonData.rewardCommonId) {
                _.extend(payload, { reward_id: commonData.rewardCommonId });
            }

            if (commonData.subscription_id) {
                _.extend(payload, { id: commonData.subscription_id });
            }

            const pay = ({ creditCardId }) => {
                kondutoExecute()
                const p = new Promise((resolve, reject) => {
                    if (creditCardId) {
                        _.extend(payload, {
                            card_id: creditCardId.id,
                            credit_card_id: creditCardId.id
                        });
                    }

                    if (commonData.subscription_id) {
                        sendSubscriptionUpgrade(payload).then(resolve).catch(reject);
                    } else {
                        sendPaymentRequest(payload).then(resolve).catch(reject);
                    }
                });

                return p;
            };

            updateUser(userPayload(customer, address))
                .then(() => processCreditCard(cardHash, fields))
                .then(pay)
                .then(getPaymentInfoUntilNoError(payload.payment_method, Boolean(commonData.subscription_id)))
                .catch(displayError(fields));

        });
};

const sendSlipPayment = (fields, commonData) => {
    fields.isLoading(true);
    m.redraw();

    const customer = fields.fields;
    const address = customer.address().getFields();
    const phoneDdd = address.phone_number ? h.extractPhoneDDD(address.phone_number) : null;
    const phoneNumber = address.phone_number ? h.extractPhoneNumber(address.phone_number) : null;
    const addressState = _.findWhere(addressVM.states(), { id: address.state_id });
    const addressCountry = _.findWhere(addressVM.countries(), { id: address.country_id });
    const payload = {
        subscription: true,
        anonymous: customer.anonymous(),
        user_id: commonData.userCommonId,
        project_id: commonData.projectCommonId,
        amount: commonData.amount,
        payment_method: 'boleto',
        customer: {
            name: customer.completeName(),
            document_number: customer.ownerDocument(),
            address: {
                neighborhood: address.address_neighbourhood,
                street: address.address_street,
                street_number: address.address_number,
                zipcode: address.address_zip_code,
                // TOdO: remove hard-coded country when international support is added on the back-end
                country: 'Brasil',
                country_code: 'BR',
                state: addressState.acronym,
                city: address.address_city,
                complementary: address.address_complement
            },
            phone: {
                ddi: '55',
                ddd: phoneDdd,
                number: phoneNumber
            }
        }
    };

    if (commonData.rewardCommonId) {
        _.extend(payload, { reward_id: commonData.rewardCommonId });
    }

    if (commonData.subscription_id) {
        _.extend(payload, { id: commonData.subscription_id });
    }

    const sendPayment = () => {
        const p = new Promise((resolve, reject) => {
            if (commonData.subscription_id) {
                sendSubscriptionUpgrade(payload).then(resolve).catch(reject);
            } else {
                sendPaymentRequest(payload).then(resolve).catch(reject);
            }
        });

        return p;
    };

    updateUser(userPayload(customer, address))
        .then(sendPayment)
        .then(getPaymentInfoUntilNoError(payload.payment_method, Boolean(commonData.subscription_id)))
        .catch(displayError(fields));
};

// Makes a request count down of retries of getting payment info
const trialsToGetPaymentInfo = (p, catalog_payment_id, retries) => {
    if (retries > 0) {
        paymentInfo(catalog_payment_id).then((infoR) => {
            if (_.isNull(infoR.gateway_payment_method) || _.isUndefined(infoR.gateway_payment_method)) {
                if (!_.isNull(infoR.gateway_errors)) {
                    return p.reject(_.first(infoR.gateway_errors));
                }

                return h.sleep(4000).then(() => trialsToGetPaymentInfo(p, catalog_payment_id, retries - 1));
            }

            return p.resolve({
                boleto_url: infoR.boleto_url,
                boleto_expiration_date: infoR.boleto_expiration_date,
                boleto_barcode: infoR.boleto_barcode,
                status: infoR.status
            });
        }).catch(() => p.reject({}));
    } else {
        return p.reject({});
    }

    return p.promise;
};

// Try recharge a payment if it's slip is expired, pinging /rpc/payment_info endpoint
// looking up for new payment_info
const tryRechargeSubscription = (subscription_id) => {
    const p = new Promise((resolve, reject) => {
        rechargeSubscription
            .postWithToken({ subscription_id })
            .then(payment_data => trialsToGetPaymentInfo({resolve, reject}, payment_data.catalog_payment_id, 5))
            .catch((error) => {
                h.captureException(error);
                throw error;
            })
            .catch(reject);
    });

    return p;
};

const commonPaymentVM = {
    sendCreditCardPayment,
    sendSlipPayment,
    paymentInfo,
    tryRechargeSubscription
};

export default commonPaymentVM;
<commit_msg>Fix front-end pagarme variable<commit_after>import m from 'mithril';
import prop from 'mithril/stream';
import _ from 'underscore';
import projectVM from '../vms/project-vm';
import addressVM from '../vms/address-vm';
import models from '../models';
import h from '../h';

const I18nScope = _.partial(h.i18nScope, 'projects.contributions.edit.errors');
const paymentInfoId = prop();
const { commonPayment, commonSubscriptionUpgrade, commonPaymentInfo, commonCreditCard, commonCreditCards, rechargeSubscription } = models;
const sendPaymentRequest = data => commonPayment.postWithToken(
    { data: _.extend({}, data, { payment_id: paymentInfoId() }) },
    null,
    (h.isDevEnv() ? { 'X-forwarded-For': '127.0.0.1' } : {})
)
.catch((error) => {
    h.captureException(error);
    throw error;
});

const sendSubscriptionUpgrade = data => commonSubscriptionUpgrade.postWithToken(
    { data },
    null,
    (h.isDevEnv() ? { 'X-forwarded-For': '127.0.0.1' } : {})
)
.catch((error) => {
    h.captureException(error);
    throw error;
});

const saveCreditCard = creditCardHash => commonCreditCard
.postWithToken({ data: { card_hash: creditCardHash } })
.catch((error) => {
    h.captureException(error);
    throw error;
});;

const updateUser = user => m.request({
    method: 'PUT',
    url: `/users/${user.id}.json`,
    data: {
        user
    },
    config: h.setCsrfToken
})
.catch((error) => {
    h.captureException(error);
    throw error;
});

const userPayload = (customer, address) => ({
    id: h.getUser().id,
    cpf: customer.ownerDocument(),
    name: customer.completeName(),
    address_attributes: {
        country_id: address.country_id,
        state_id: address.state_id,
        address_street: address.address_street,
        address_neighbourhood: address.address_neighbourhood,
        address_number: address.address_number,
        address_zip_code: address.address_zip_code,
        address_city: address.address_city,
        address_state: address.address_state,
        address_complement: address.address_complement,
        phone_number: address.phone_number
    }
});

const displayError = fields => (exception) => {
    const errorMsg = exception.message || window.I18n.t('submission.encryption_error', I18nScope());
    fields.isLoading(false);
    fields.submissionError(window.I18n.t('submission.error', I18nScope({ message: errorMsg })));
    m.redraw();
    h.captureException(exception);
};

const paymentInfo = paymentId => commonPaymentInfo
    .postWithToken({ id: paymentId }, null, (h.isDevEnv() ? { 'X-forwarded-For': '127.0.0.1' } : {}))
    .catch((error) => {
        h.captureException(error);
        throw error;
    });

const creditCardInfo = creditCard => commonCreditCards
    .getRowWithToken(h.idVM.id(creditCard.id).parameters())
    .catch((error) => {
        h.captureException(error);
        throw error;
    });

let retries = 10;
const isReactivation = () => {
    const subscriptionStatus = m.route.param('subscription_status');
    return subscriptionStatus === 'inactive' || subscriptionStatus === 'canceled';
};
const resolvePayment = (gateway_payment_method, payment_confirmed, payment_id, isEdit) => m.route.set(`/projects/${projectVM.currentProject().project_id}/subscriptions/thank_you?project_id=${projectVM.currentProject().project_id}&payment_method=${gateway_payment_method}&payment_confirmed=${payment_confirmed}${payment_id ? `&payment_id=${payment_id}` : ''}${isEdit && !isReactivation() ? '&is_edit=1' : ''}`);
const requestInfo = (promise, paymentId, defaultPaymentMethod, isEdit) => {
    if (retries <= 0) {
        return promise.resolve(resolvePayment(defaultPaymentMethod, false, paymentId, isEdit));
    }

    paymentInfo(paymentId).then((infoR) => {
        if (_.isNull(infoR.gateway_payment_method) || _.isUndefined(infoR.gateway_payment_method)) {
            if (!_.isNull(infoR.gateway_errors)) {
                return promise.reject(_.first(infoR.gateway_errors));
            }

            return h.sleep(4000).then(() => {
                retries -= 1;

                return requestInfo(promise, paymentId, defaultPaymentMethod);
            });
        }

        return promise.resolve(resolvePayment(infoR.gateway_payment_method, true, paymentId, isEdit));
    }).catch(error => promise.reject({}));
};

const getPaymentInfoUntilNoError = (paymentMethod, isEdit) => ({ id, catalog_payment_id }) => {
    const p = new Promise((resolve, reject) => {
        const paymentId = isEdit ? catalog_payment_id : id;

        if (paymentId) {
            paymentInfoId(paymentId);
            requestInfo({resolve, reject}, paymentId, paymentMethod, isEdit);
        } else {
            resolvePayment(paymentMethod, false, null, isEdit);
        }
    });

    return p;
};

let creditCardRetries = 5;
const waitForSavedCreditCard = promise => (creditCardId) => {
    if (creditCardRetries <= 0) {
        return promise.reject({ message: 'Could not save card' });
    }

    creditCardInfo(creditCardId).then(([infoR]) => {
        if (_.isEmpty(infoR.gateway_data)) {
            if (!_.isEmpty(infoR.gateway_errors)) {
                return promise.reject(_.first(infoR.gateway_errors));
            }

            return h.sleep(4000).then(() => {
                creditCardRetries -= 1;

                return waitForSavedCreditCard(promise)(creditCardId);
            });
        }

        return promise.resolve({ creditCardId });
    }).catch(error => promise.reject({ message: error.message }));

    return promise;
};

const processCreditCard = (cardHash, fields) => {
    const p = new Promise((resolve, reject) => {
        saveCreditCard(cardHash)
            .then(waitForSavedCreditCard({resolve, reject}))
            .catch(reject);
    });

    return p;
};

const kondutoExecute = function () {
    const customerID = h.getUserCommonID();

    if (customerID) {
        var period = 300;
        var limit = 20 * 1e3;
        var nTry = 0;
        var intervalID = setInterval(function () {
            var clear = limit / period <= ++nTry;
            if ((typeof (Konduto) !== "undefined") && (typeof (Konduto.setCustomerID) !== "undefined")) {
                window.Konduto.setCustomerID(customerID);
                clear = true;
            }
            if (clear) {
                clearInterval(intervalID);
            }
        }, period);
    }
};

const sendCreditCardPayment = (selectedCreditCard, fields, commonData, addVM) => {

    if (!fields) {
        return false;
    }
    fields.isLoading(true);
    m.redraw();

    const meta = _.first(document.querySelectorAll('[name=pagarme-encryption-key]'));
    const encryptionKey = meta.getAttribute('content');

    window.pagarme.encryption_key = encryptionKey;
    const card = setNewCreditCard(fields.creditCardFields);

    const customer = fields.fields;
    const address = customer.address().getFields();
    const phoneDdd = address.phone_number ? h.extractPhoneDDD(address.phone_number) : null;
    const phoneNumber = address.phone_number ? h.extractPhoneNumber(address.phone_number) : null;
    const addressState = address.state_id ? _.findWhere(addVM.states(), { id: address.state_id }) : address.address_state;
    const addressCountry = _.findWhere(addVM.countries(), { id: address.country_id }) || {};

    window.pagarme.client.connect({ encryption_key: encryptionKey })
        .then(client => client.security.encrypt(card))
        .then((cardHash) => {
            const payload = {
                subscription: true,
                anonymous: customer.anonymous(),
                user_id: commonData.userCommonId,
                project_id: commonData.projectCommonId,
                amount: commonData.amount,
                payment_method: 'credit_card',
                credit_card_owner_document: fields.creditCardFields.cardOwnerDocument(),
                is_international: address.country_id !== addVM.defaultCountryID,
                customer: {
                    name: customer.completeName(),
                    document_number: customer.ownerDocument(),
                    address: {
                        neighborhood: address.address_neighbourhood,
                        street: address.address_street,
                        street_number: address.address_number,
                        zipcode: address.address_zip_code,
                        country: addressCountry.name,
                        country_code: addressCountry.code,
                        state: addressState.acronym ? addressState.acronym : addressState,
                        city: address.address_city,
                        complementary: address.address_complement
                    },
                    phone: {
                        ddi: '55',
                        ddd: phoneDdd,
                        number: phoneNumber
                    }
                }
            };

            if (commonData.rewardCommonId) {
                _.extend(payload, { reward_id: commonData.rewardCommonId });
            }

            if (commonData.subscription_id) {
                _.extend(payload, { id: commonData.subscription_id });
            }

            const pay = ({ creditCardId }) => {
                kondutoExecute()
                const p = new Promise((resolve, reject) => {
                    if (creditCardId) {
                        _.extend(payload, {
                            card_id: creditCardId.id,
                            credit_card_id: creditCardId.id
                        });
                    }

                    if (commonData.subscription_id) {
                        sendSubscriptionUpgrade(payload).then(resolve).catch(reject);
                    } else {
                        sendPaymentRequest(payload).then(resolve).catch(reject);
                    }
                });

                return p;
            };

            updateUser(userPayload(customer, address))
                .then(() => processCreditCard(cardHash, fields))
                .then(pay)
                .then(getPaymentInfoUntilNoError(payload.payment_method, Boolean(commonData.subscription_id)))
                .catch(displayError(fields));

        });
};

const sendSlipPayment = (fields, commonData) => {
    fields.isLoading(true);
    m.redraw();

    const customer = fields.fields;
    const address = customer.address().getFields();
    const phoneDdd = address.phone_number ? h.extractPhoneDDD(address.phone_number) : null;
    const phoneNumber = address.phone_number ? h.extractPhoneNumber(address.phone_number) : null;
    const addressState = _.findWhere(addressVM.states(), { id: address.state_id });
    const addressCountry = _.findWhere(addressVM.countries(), { id: address.country_id });
    const payload = {
        subscription: true,
        anonymous: customer.anonymous(),
        user_id: commonData.userCommonId,
        project_id: commonData.projectCommonId,
        amount: commonData.amount,
        payment_method: 'boleto',
        customer: {
            name: customer.completeName(),
            document_number: customer.ownerDocument(),
            address: {
                neighborhood: address.address_neighbourhood,
                street: address.address_street,
                street_number: address.address_number,
                zipcode: address.address_zip_code,
                // TOdO: remove hard-coded country when international support is added on the back-end
                country: 'Brasil',
                country_code: 'BR',
                state: addressState.acronym,
                city: address.address_city,
                complementary: address.address_complement
            },
            phone: {
                ddi: '55',
                ddd: phoneDdd,
                number: phoneNumber
            }
        }
    };

    if (commonData.rewardCommonId) {
        _.extend(payload, { reward_id: commonData.rewardCommonId });
    }

    if (commonData.subscription_id) {
        _.extend(payload, { id: commonData.subscription_id });
    }

    const sendPayment = () => {
        const p = new Promise((resolve, reject) => {
            if (commonData.subscription_id) {
                sendSubscriptionUpgrade(payload).then(resolve).catch(reject);
            } else {
                sendPaymentRequest(payload).then(resolve).catch(reject);
            }
        });

        return p;
    };

    updateUser(userPayload(customer, address))
        .then(sendPayment)
        .then(getPaymentInfoUntilNoError(payload.payment_method, Boolean(commonData.subscription_id)))
        .catch(displayError(fields));
};

// Makes a request count down of retries of getting payment info
const trialsToGetPaymentInfo = (p, catalog_payment_id, retries) => {
    if (retries > 0) {
        paymentInfo(catalog_payment_id).then((infoR) => {
            if (_.isNull(infoR.gateway_payment_method) || _.isUndefined(infoR.gateway_payment_method)) {
                if (!_.isNull(infoR.gateway_errors)) {
                    return p.reject(_.first(infoR.gateway_errors));
                }

                return h.sleep(4000).then(() => trialsToGetPaymentInfo(p, catalog_payment_id, retries - 1));
            }

            return p.resolve({
                boleto_url: infoR.boleto_url,
                boleto_expiration_date: infoR.boleto_expiration_date,
                boleto_barcode: infoR.boleto_barcode,
                status: infoR.status
            });
        }).catch(() => p.reject({}));
    } else {
        return p.reject({});
    }

    return p.promise;
};

// Try recharge a payment if it's slip is expired, pinging /rpc/payment_info endpoint
// looking up for new payment_info
const tryRechargeSubscription = (subscription_id) => {
    const p = new Promise((resolve, reject) => {
        rechargeSubscription
            .postWithToken({ subscription_id })
            .then(payment_data => trialsToGetPaymentInfo({resolve, reject}, payment_data.catalog_payment_id, 5))
            .catch((error) => {
                h.captureException(error);
                throw error;
            })
            .catch(reject);
    });

    return p;
};

const commonPaymentVM = {
    sendCreditCardPayment,
    sendSlipPayment,
    paymentInfo,
    tryRechargeSubscription
};

export default commonPaymentVM;
<|endoftext|>