<commit_before>(function (undefined) {
	var isMSIE = /*@cc_on!@*/false;

	function BBSDat (thread) {
		this.thread = thread;
		this.ajax = new Ajax();
		this.init();
	}

	(function (p) {
		p.init = function () {
			this.data = "";
			this.lastmodified = "Thu, 01 Jun 1970 00:00:00 GMT";
		};
		p.renderHTML = function (options) {
			var html = [];
			var lines = this.data.getResLines();
			var rescnt;

			if(options.end == null)
			{
				options.end = lines.length;
			}

			rescnt = lines.length;

			if((options.first == true) && (options.start > 1))
			{
				html.push(lines[0].createResLine(1));
			}

			for(var i = (options.start - 1) ; ((i < options.end) && (i < rescnt)) ; i++)
			{
				if(lines[i] == "")
				{
					break;
				}

				html.push(lines[i].createResLine(i+1));
			}

			return html.join("\n");
		};

		p.requestDat = function (callback) {
			var url = this.thread.createDatURL();
			var self = this;
			var headers = {};

			headers["Content-Type"] = "text/plain; charset=x-sjis";
			headers["If-Modified-Since"] = this.lastmodified;

			this.ajax.get(url, {
				callback: function (data, status) {
					if(status === 404 || status === 302)
					{
						callback.call(self.thread, false, "YXbh͍폜ꂽA݂܂B");
					}
					else if(status !== 200 && status !== 304)
					{
						callback.call(self.thread, false, "ʐMG[܂B");
					}
					else if(status === 200)
					{
						self.data = data;
						var lastmodified;

						if(!(lastmodified = self.ajax.getResponseHeader("Last-Modified")))
						{
							callback.call(self.thread, false, "dat̍ŏIXV擾ł܂łB");
						}
						else
						{
							self.lastmodified = lastmodified;
							callback.call(self.thread, true, "");
						}
					}
					else
					{
						callback.call(self.thread, true, "");
					}
				},
				headers: headers
			});
		};
	})(BBSDat.prototype);

	function Rooter () {

	};

	Rooter.dispatch = function (thread, paths) {
		var	bbs = paths[1],
			key = paths[2],
			options = paths[3] || "";

		if(thread.bbs != bbs || thread.key != key) thread.datdata.init();

		thread.bbs = bbs;
		thread.key = key;

		thread.loadThread(function () {
			this.terminateLoadingView();
			this.parseOptions(decodeURIComponent(options));
			this.render();
		}, function () {
			if(this.requestcomp == false)
			{
				window.alert("ʐMł...");
				return false;
			}
			return true;
		});
	};

	Rooter.readPath = function (src) {
		if(/^\/(:bbs)\/index.html$/.test(src)) return src;
		else if(/^#!ID\/(\d+)(-\d+)?$/.test(src)) return src.substr(2);
		else if(/^#!\/.*$/.test(src)) return src.substr(2);
		return src;
	};

	(function (p) {

	})(Rooter.prototype);

	function BBSThread (paths) {
		this.requestcomp = true;
		this.shiftkey = false;

		var match = window.location.pathname.match(/^.*(\/test\/read.html)/g);

		this.urlbase = match[0].replace("test/read.html", "");

		var self = this;

		var onKeyDown = function (e) {
			var key = self.keyCode(e);

			if(key === 16) self.shiftkey = true;
			if(key === 13 && self.shiftkey)
			{
				e.preventDefault();
				self.postRes();
			}
		};

		if(window.opera)
		{
			$("#message").on("keypress", function (e) {
				return onKeyDown(e);
			});
		}
		else
		{
			$("#message").on("keydown", function (e) {
				return onKeyDown(e);
			});
		}

		$("#message").on("keyup", function (e) {
			var key = self.keyCode(e);
			if(key === 16) self.shiftkey = false;
		});

		$("#resparams").submit(function (e) {
			e.preventDefault();
			self.postRes();
			return false;
		});

		$("#name").val(Cookie.get("FROM"));
		$("#e-mail").val(Cookie.get("mail"));

		this.datdata = new BBSDat(this);
		this.ajax = new Ajax();

		this.startLoadingView();
		Rooter.dispatch(this, paths.split("/"));

		$("a").click(function (e) {
			var m,
				path = Rooter.readPath(
					$(this).get(0).getAttribute && $(this).get(0).getAttribute("href", 2) || $(this).attr("href")
				);

			if(path === "/:reload")
			{
				e.preventDefault();
				self.reload();
			}
			else if((m = path.match(/^ID\/(\d+)(-\d+)?$/)))
			{
				e.preventDefault();
				if(!m[2]) window.location.hash = "a" + m[1];
			}
			else if((m = path.match(/^\/(:bbs)\/index.html$/)))
			{
				e.preventDefault();
				window.location.href = self.urlbase + self.bbs + "/index.html";
			}
			else if((m = path.match(/^\/(:bbs)\/(:key)\/(:pastfrom)-(:pastto)?$/)))
			{
				e.preventDefault();
				if(!self.options) return;
				var bbs = self.bbs,
					key = self.key,
					options = self.pastfrom + "-" + self.pastto;
				window.location.hash = "#!/" + bbs + "/" + key + "/" + options;
				Rooter.dispatch(self, ["", bbs, key, options]);
			}
			else if((m = path.match(/^\/(:bbs)\/(:key)\/(:nextfrom)-(:nextto)?$/)))
			{
				e.preventDefault();
				if(!self.options) return;
				var bbs = self.bbs,
					key = self.key,
					options = self.nextfrom + "-" + self.nextto;
				window.location.hash = "#!/" + bbs + "/" + key + "/" + options;
				Rooter.dispatch(self, ["", bbs, key, options]);
			}
			else if((m = path.match(/^\/(:bbs)\/(:key)\/([^\/]+)?$/)))
			{
				e.preventDefault();
				var bbs = self.bbs,
					key = self.key,
					options = m[3] || "";
				window.location.hash = "#!/" + bbs + "/" + key + "/" + options;
				Rooter.dispatch(self, ["", bbs, key, options]);
			}
			else if((m = path.match(/^\/([^\/]+)\/([^\/]+)\/([^\/]+)?$/)))
			{
				var bbs = m[1],
					key = m[2],
					options = m[3] || "" ;
				window.location.hash = "#!/" + bbs + "/" + key + "/" + options;
				Rooter.dispatch(self, ["", bbs, key, options]);
			}
		});
	}

	(function (p) {
		p.keyCode = function (e) {
			if(document.all) return e.originalEvent.keyCode;
			else if(document.getElementById) return (e.originalEvent.keyCode) ? e.originalEvent.keyCode : e.originalEvent.charCode;
			else if(document.layers) return e.originalEvent.which;
			else return 0;
		};
		p.createDatURL = function () {
			return (this.urlbase + this.bbs + "/dat/" + this.key + ".dat?" + (new Date()).getTime());
		};
		p.createPostURL = function () {
			return (this.urlbase + "test/bbs.cgi?guid=On");
		};
		p.loadThread = function (callback, beforeLoad) {
			if(beforeLoad && !beforeLoad.call(this)) return;

			this.requestcomp = false;

			this.datdata.requestDat(function (result, message) {
				this.requestcomp = true;
				if(!result) {
					alert(message);
				}
				else
				{
					callback.call(this);
				}
			});
		};
		p.postRes = function () {
			var self = this;
			var params = $("#resparams");

			this.startSendingView();

			this.ajax.post(this.createPostURL(), {
				callback: function (data, status) {
					self.terminateSendingView();

					var params = $("#resparams");
					if( (status == 200) && (//.test(data)) )
					{
						msgwindow = window.open();
						msgwindow.document.write(data);
					}
					params.find("#message").val("");

					self.options.end = null;
					self.loadThread(function () {
						this.render();
					});
				},
				params: {
					bbs: self.bbs,
					key: self.key,
					FROM: params.find("input[name='FROM']").val(),
					mail: params.find("input[name='mail']").val(),
					MESSAGE: params.find("#message").val(),
					submit: "",
					utn: "utn",
					time: params.find("input[name='time']").val(),
					suka: params.find("input[name='suka']").val()
				},
				headers: {
					"Referer": this.urlbase + "/" + this.bbs + "/",
					"Content-Type": "application/x-www-form-urlencoded"
				},
				encoder: EscapeSJIS
			});
		};
		p.reload = function () {
			this.startLoadingView();
			this.loadThread(function () {
				this.terminateLoadingView();
				this.render();
			});
		};
		p.startLoadingView = function () {
			var count = 3;

			this.timerid = window.setInterval(function () {
				count++;
				var str = "ǂݍݒ";
				for(var i=0; i < count; i++)
				{
					str += ".";
				}

				if(count > 20)
				{
					count = 0;
				}

				$("#resbodys").html("" + str + "");
			}, 100);
		};
		p.terminateLoadingView = function () {
			window.clearInterval(this.timerid);
		};
		p.startSendingView = function () {
			var count = 3;

			this.timerid = window.setInterval( function () {
				count++;
				var str = "ݒ";
				for(var i=0; i < count; i++)
				{
					str += ".";
				}

				if(count > 20)
				{
					count = 0;
				}

				$("#resbodys").html("" + str + "");
			}, 100);
		};
		p.terminateSendingView = function () {
			window.clearInterval(this.timerid);
		};
		p.render = function() {
			$("#resbodys").html(this.datdata.renderHTML(this.options));
			var lines = this.datdata.data.getResLines();
			var subject = lines[0].split("<>")[4];

			if(subject == undefined)
			{
				subject = 'X^Cs';
			}

			$("title").html(subject);
			$("#subject").html(subject);
			var date = new Date();
			var speed = (lines.length - 1) / (Math.floor(date.getTime() / 60000) - Math.floor(this.key / 60)) * 60 * 24;
			$("#speed").html("Speed:" + speed + "");
			$("#size").html(this.datdata.data.length - 1);
		};
		p.parseOptions = function(options) {
			var reslines = this.datdata.data.getResLines();

			this.options = {};

			if(/^\|(\d+)n?$/.test(options))
			{
				var match = options.match(/\d+/g);

				if(/n$/.test(options))
				{
					this.options.first = false;
				}
				else
				{
					this.options.first = true;
				}

				this.options.start = reslines.length - match[0];

				if(this.options.start < 1)
				{
					this.options.start = 1;
				}

				this.options.end = reslines.length;
			}
			else if(/^(\d+)-(\d+)n?$/.test(options))
			{
				var match = options.match(/\d+/g);

				if(/n$/.test(options))
				{
					this.options.first = false;
				}
				else
				{
					this.options.first = true;
				}

				this.options.start = Number(match[0]);
				this.options.end   = Number(match[1]);
			}
			else if(/^-(\d+)n?$/.test(options))
			{
				var match = options.match(/\d+/g);

				if(/n$/.test(options))
				{
					this.options.first = false;
				}
				else
				{
					this.options.first = true;
				}

				this.options.start = 1;
				this.options.end   = Number(match[0]);
			}
			else if(/^(\d+)-n?$/.test(options))
			{
				var match = options.match(/\d+/g);

				if(/n$/.test(options))
				{
					this.options.first = false;
				}
				else
				{
					this.options.first = true;
				}

				this.options.start = Number(match[0]);
				this.options.end   = reslines.length;
			}
			else if(/^(\d+)n?$/.test(options))
			{
				var match = options.match(/\d+/g);

				if(/n$/.test(options))
				{
					this.options.first = false;
				}
				else
				{
					this.options.first = true;
				}

				this.options.start = Number(match[0]);
				this.options.end   = Number(match[0]);
			}
			else if(/^$/.test(options))
			{
				this.options.first = false;
				this.options.start = 1;
				this.options.end   = reslines.length;
			}
			else
			{
				window.alert("IvVw肪słB");
			}

			this.pastfrom = this.options.start - 100;
			if(this.pastfrom < 1)
			{
				this.pastfrom = 1;
			}

			this.pastto = this.options.start - 1;
			if(this.pastto < 1)
			{
				this.pastto = 1;
			}

			this.nextfrom = this.options.end + 1;
			this.nextto   = this.options.end + 100;

		};
	})(BBSThread.prototype);

	window.BBSDat = BBSDat;
	window.BBSThread = BBSThread;
})();
<commit_msg>postRes,reloadメソッドに通信の排他処理を入れてなかったので入れた<commit_after>(function (undefined) {
	var isMSIE = /*@cc_on!@*/false;

	function BBSDat (thread) {
		this.thread = thread;
		this.ajax = new Ajax();
		this.init();
	}

	(function (p) {
		p.init = function () {
			this.data = "";
			this.lastmodified = "Thu, 01 Jun 1970 00:00:00 GMT";
		};
		p.renderHTML = function (options) {
			var html = [];
			var lines = this.data.getResLines();
			var rescnt;

			if(options.end == null)
			{
				options.end = lines.length;
			}

			rescnt = lines.length;

			if((options.first == true) && (options.start > 1))
			{
				html.push(lines[0].createResLine(1));
			}

			for(var i = (options.start - 1) ; ((i < options.end) && (i < rescnt)) ; i++)
			{
				if(lines[i] == "")
				{
					break;
				}

				html.push(lines[i].createResLine(i+1));
			}

			return html.join("\n");
		};

		p.requestDat = function (callback) {
			var url = this.thread.createDatURL();
			var self = this;
			var headers = {};

			headers["Content-Type"] = "text/plain; charset=x-sjis";
			headers["If-Modified-Since"] = this.lastmodified;

			this.ajax.get(url, {
				callback: function (data, status) {
					if(status === 404 || status === 302)
					{
						callback.call(self.thread, false, "YXbh͍폜ꂽA݂܂B");
					}
					else if(status !== 200 && status !== 304)
					{
						callback.call(self.thread, false, "ʐMG[܂B");
					}
					else if(status === 200)
					{
						self.data = data;
						var lastmodified;

						if(!(lastmodified = self.ajax.getResponseHeader("Last-Modified")))
						{
							callback.call(self.thread, false, "dat̍ŏIXV擾ł܂łB");
						}
						else
						{
							self.lastmodified = lastmodified;
							callback.call(self.thread, true, "");
						}
					}
					else
					{
						callback.call(self.thread, true, "");
					}
				},
				headers: headers
			});
		};
	})(BBSDat.prototype);

	function Rooter () {

	};

	Rooter.dispatch = function (thread, paths) {
		var	bbs = paths[1],
			key = paths[2],
			options = paths[3] || "";

		if(thread.bbs != bbs || thread.key != key) thread.datdata.init();

		thread.bbs = bbs;
		thread.key = key;

		thread.loadThread(function () {
			this.terminateLoadingView();
			this.parseOptions(decodeURIComponent(options));
			this.render();
		}, function () {
			if(this.requestcomp == false)
			{
				window.alert("ʐMł...");
				return false;
			}
			return true;
		});
	};

	Rooter.readPath = function (src) {
		if(/^\/(:bbs)\/index.html$/.test(src)) return src;
		else if(/^#!ID\/(\d+)(-\d+)?$/.test(src)) return src.substr(2);
		else if(/^#!\/.*$/.test(src)) return src.substr(2);
		return src;
	};

	(function (p) {

	})(Rooter.prototype);

	function BBSThread (paths) {
		this.requestcomp = true;
		this.shiftkey = false;

		var match = window.location.pathname.match(/^.*(\/test\/read.html)/g);

		this.urlbase = match[0].replace("test/read.html", "");

		var self = this;

		var onKeyDown = function (e) {
			var key = self.keyCode(e);

			if(key === 16) self.shiftkey = true;
			if(key === 13 && self.shiftkey)
			{
				e.preventDefault();
				self.postRes();
			}
		};

		if(window.opera)
		{
			$("#message").on("keypress", function (e) {
				return onKeyDown(e);
			});
		}
		else
		{
			$("#message").on("keydown", function (e) {
				return onKeyDown(e);
			});
		}

		$("#message").on("keyup", function (e) {
			var key = self.keyCode(e);
			if(key === 16) self.shiftkey = false;
		});

		$("#resparams").submit(function (e) {
			e.preventDefault();
			self.postRes();
			return false;
		});

		$("#name").val(Cookie.get("FROM"));
		$("#e-mail").val(Cookie.get("mail"));

		this.datdata = new BBSDat(this);
		this.ajax = new Ajax();

		this.startLoadingView();
		Rooter.dispatch(this, paths.split("/"));

		$("a").click(function (e) {
			var m,
				path = Rooter.readPath(
					$(this).get(0).getAttribute && $(this).get(0).getAttribute("href", 2) || $(this).attr("href")
				);

			if(path === "/:reload")
			{
				e.preventDefault();
				self.reload();
			}
			else if((m = path.match(/^ID\/(\d+)(-\d+)?$/)))
			{
				e.preventDefault();
				if(!m[2]) window.location.hash = "a" + m[1];
			}
			else if((m = path.match(/^\/(:bbs)\/index.html$/)))
			{
				e.preventDefault();
				window.location.href = self.urlbase + self.bbs + "/index.html";
			}
			else if((m = path.match(/^\/(:bbs)\/(:key)\/(:pastfrom)-(:pastto)?$/)))
			{
				e.preventDefault();
				if(!self.options) return;
				var bbs = self.bbs,
					key = self.key,
					options = self.pastfrom + "-" + self.pastto;
				window.location.hash = "#!/" + bbs + "/" + key + "/" + options;
				Rooter.dispatch(self, ["", bbs, key, options]);
			}
			else if((m = path.match(/^\/(:bbs)\/(:key)\/(:nextfrom)-(:nextto)?$/)))
			{
				e.preventDefault();
				if(!self.options) return;
				var bbs = self.bbs,
					key = self.key,
					options = self.nextfrom + "-" + self.nextto;
				window.location.hash = "#!/" + bbs + "/" + key + "/" + options;
				Rooter.dispatch(self, ["", bbs, key, options]);
			}
			else if((m = path.match(/^\/(:bbs)\/(:key)\/([^\/]+)?$/)))
			{
				e.preventDefault();
				var bbs = self.bbs,
					key = self.key,
					options = m[3] || "";
				window.location.hash = "#!/" + bbs + "/" + key + "/" + options;
				Rooter.dispatch(self, ["", bbs, key, options]);
			}
			else if((m = path.match(/^\/([^\/]+)\/([^\/]+)\/([^\/]+)?$/)))
			{
				var bbs = m[1],
					key = m[2],
					options = m[3] || "" ;
				window.location.hash = "#!/" + bbs + "/" + key + "/" + options;
				Rooter.dispatch(self, ["", bbs, key, options]);
			}
		});
	}

	(function (p) {
		p.keyCode = function (e) {
			if(document.all) return e.originalEvent.keyCode;
			else if(document.getElementById) return (e.originalEvent.keyCode) ? e.originalEvent.keyCode : e.originalEvent.charCode;
			else if(document.layers) return e.originalEvent.which;
			else return 0;
		};
		p.createDatURL = function () {
			return (this.urlbase + this.bbs + "/dat/" + this.key + ".dat?" + (new Date()).getTime());
		};
		p.createPostURL = function () {
			return (this.urlbase + "test/bbs.cgi?guid=On");
		};
		p.loadThread = function (callback, beforeLoad) {
			if(beforeLoad && !beforeLoad.call(this)) return;

			this.requestcomp = false;

			this.datdata.requestDat(function (result, message) {
				this.requestcomp = true;
				if(!result) {
					alert(message);
				}
				else
				{
					callback.call(this);
				}
			});
		};
		p.postRes = function () {
			if(this.requestcomp == false)
			{
				window.alert("ʐMł...");
				return false;
			}

			var self = this;
			var params = $("#resparams");

			this.startSendingView();

			this.ajax.post(this.createPostURL(), {
				callback: function (data, status) {
					self.terminateSendingView();

					var params = $("#resparams");
					if( (status == 200) && (//.test(data)) )
					{
						msgwindow = window.open();
						msgwindow.document.write(data);
					}
					params.find("#message").val("");

					self.options.end = null;
					self.loadThread(function () {
						this.render();
					});
				},
				params: {
					bbs: self.bbs,
					key: self.key,
					FROM: params.find("input[name='FROM']").val(),
					mail: params.find("input[name='mail']").val(),
					MESSAGE: params.find("#message").val(),
					submit: "",
					utn: "utn",
					time: params.find("input[name='time']").val(),
					suka: params.find("input[name='suka']").val()
				},
				headers: {
					"Referer": this.urlbase + "/" + this.bbs + "/",
					"Content-Type": "application/x-www-form-urlencoded"
				},
				encoder: EscapeSJIS
			});
		};
		p.reload = function () {
			this.startLoadingView();
			this.loadThread(function () {
				this.terminateLoadingView();
				this.render();
			}, function () {
				if(this.requestcomp == false)
				{
					window.alert("ʐMł...");
					return false;
				}
				return true;
			});
		};
		p.startLoadingView = function () {
			var count = 3;

			this.timerid = window.setInterval(function () {
				count++;
				var str = "ǂݍݒ";
				for(var i=0; i < count; i++)
				{
					str += ".";
				}

				if(count > 20)
				{
					count = 0;
				}

				$("#resbodys").html("" + str + "");
			}, 100);
		};
		p.terminateLoadingView = function () {
			window.clearInterval(this.timerid);
		};
		p.startSendingView = function () {
			var count = 3;

			this.timerid = window.setInterval( function () {
				count++;
				var str = "ݒ";
				for(var i=0; i < count; i++)
				{
					str += ".";
				}

				if(count > 20)
				{
					count = 0;
				}

				$("#resbodys").html("" + str + "");
			}, 100);
		};
		p.terminateSendingView = function () {
			window.clearInterval(this.timerid);
		};
		p.render = function() {
			$("#resbodys").html(this.datdata.renderHTML(this.options));
			var lines = this.datdata.data.getResLines();
			var subject = lines[0].split("<>")[4];

			if(subject == undefined)
			{
				subject = 'X^Cs';
			}

			$("title").html(subject);
			$("#subject").html(subject);
			var date = new Date();
			var speed = (lines.length - 1) / (Math.floor(date.getTime() / 60000) - Math.floor(this.key / 60)) * 60 * 24;
			$("#speed").html("Speed:" + speed + "");
			$("#size").html(this.datdata.data.length - 1);
		};
		p.parseOptions = function(options) {
			var reslines = this.datdata.data.getResLines();

			this.options = {};

			if(/^\|(\d+)n?$/.test(options))
			{
				var match = options.match(/\d+/g);

				if(/n$/.test(options))
				{
					this.options.first = false;
				}
				else
				{
					this.options.first = true;
				}

				this.options.start = reslines.length - match[0];

				if(this.options.start < 1)
				{
					this.options.start = 1;
				}

				this.options.end = reslines.length;
			}
			else if(/^(\d+)-(\d+)n?$/.test(options))
			{
				var match = options.match(/\d+/g);

				if(/n$/.test(options))
				{
					this.options.first = false;
				}
				else
				{
					this.options.first = true;
				}

				this.options.start = Number(match[0]);
				this.options.end   = Number(match[1]);
			}
			else if(/^-(\d+)n?$/.test(options))
			{
				var match = options.match(/\d+/g);

				if(/n$/.test(options))
				{
					this.options.first = false;
				}
				else
				{
					this.options.first = true;
				}

				this.options.start = 1;
				this.options.end   = Number(match[0]);
			}
			else if(/^(\d+)-n?$/.test(options))
			{
				var match = options.match(/\d+/g);

				if(/n$/.test(options))
				{
					this.options.first = false;
				}
				else
				{
					this.options.first = true;
				}

				this.options.start = Number(match[0]);
				this.options.end   = reslines.length;
			}
			else if(/^(\d+)n?$/.test(options))
			{
				var match = options.match(/\d+/g);

				if(/n$/.test(options))
				{
					this.options.first = false;
				}
				else
				{
					this.options.first = true;
				}

				this.options.start = Number(match[0]);
				this.options.end   = Number(match[0]);
			}
			else if(/^$/.test(options))
			{
				this.options.first = false;
				this.options.start = 1;
				this.options.end   = reslines.length;
			}
			else
			{
				window.alert("IvVw肪słB");
			}

			this.pastfrom = this.options.start - 100;
			if(this.pastfrom < 1)
			{
				this.pastfrom = 1;
			}

			this.pastto = this.options.start - 1;
			if(this.pastto < 1)
			{
				this.pastto = 1;
			}

			this.nextfrom = this.options.end + 1;
			this.nextto   = this.options.end + 100;

		};
	})(BBSThread.prototype);

	window.BBSDat = BBSDat;
	window.BBSThread = BBSThread;
})();
<|endoftext|>


<commit_before>import { addPlugin, getPlugins } from '../config';
import { installPlugins } from '../plugins';

/**
 * Registers the `plugins` commands.
 *
 * @param vorpal The Vorpal instance.
 */
export function pluginsFactory(vorpal) {
  vorpal
    .command('plugins install <plugin>')
    .description('Installs a plugin.')
    .action(async function (args, callback) {
      const { plugin } = args;
      addPlugin(plugin);
      try {
        await installPlugins();
      } catch (err) {
        this.log(chalk.red(err.message));
      }
      callback();
    });
  vorpal
    .command('plugins list')
    .alias('plugins ls')
    .description('Lists installed plugins.')
    .action(function (args, callback) {
      const plugins = getPlugins();
      this.log(`Installed Plugins (${plugins.length}):`);
      this.log(plugins.map(plugin => `    * ${plugin}`).join('\n'));
      callback();
    });
}
<commit_msg>Add plugins command to remove plugins<commit_after>import { addPlugin, getPlugins } from '../config';
import { installPlugins } from '../plugins';

/**
 * Registers the `plugins` commands.
 *
 * @param vorpal The Vorpal instance.
 */
export default function pluginsFactory(vorpal) {
  vorpal
    .command('plugins install <plugin>')
    .description('Installs a plugin.')
    .action(async function (args, callback) {
      const { plugin } = args;
      addPlugin(plugin);
      try {
        await installPlugins();
      } catch (err) {
        this.log(chalk.red(err.message));
      }
      callback();
    });
  vorpal
    .command('plugins list')
    .alias('plugins ls')
    .description('Lists installed plugins.')
    .action(function (args, callback) {
      const plugins = getPlugins();
      this.log(`Installed Plugins (${plugins.length}):`);
      this.log(plugins.map(plugin => `    * ${plugin}`).join('\n'));
      callback();
    });
  vorpal
    .command('plugins remove <plugin>')
    .alias('plugins rm <plugin>')
    .description('Removes a plugin.')
    .action(async function (args, callback) {
      const { plugin } = args;
      removePlugin(plugin);
      try {
        await installPlugins();
      } catch (err) {
        this.log(chalk.red(err.message));
      }
      callback();
    });
}
<|endoftext|>


<commit_before>import React from 'react';
import assert from 'assert';
import { mount } from 'enzyme';
import sinon from 'sinon';
import apiClient from 'panoptes-client/lib/api-client';
import WorkflowSelection from './workflow-selection';

function StubPage() {
  return
Hello
;
}

const location = {
  query: {}
};

const context = {
  router: {}
};

const projectRoles = [
  {
    roles: ['owner'],
    links: {
      owner: {
        id: '1'
      }
    }
  },
  {
    roles: ['collaborator'],
    links: {
      owner: {
        id: '2'
      }
    }
  },
  {
    roles: ['tester'],
    links: {
      owner: {
        id: '3'
      }
    }
  }
];

function mockPanoptesResource(type, options) {
  const resource = apiClient.type(type).create(options);
  apiClient._typesCache = {};
  sinon.stub(resource, 'save').callsFake(() => Promise.resolve(resource));
  sinon.stub(resource, 'get');
  sinon.stub(resource, 'delete');
  return resource;
}

const project = mockPanoptesResource('projects',
  {
    id: 'a',
    display_name: 'A test project',
    experimental_tools: [],
    links: {
      active_workflows: ['1', '2', '3', '4', '5'],
      owner: { id: '1' }
    }
  }
);

const owner = mockPanoptesResource(
  'users',
  {
    id: project.links.owner.id
  }
);

const preferences = mockPanoptesResource(
  'project_preferences',
  {
    preferences: {},
    links: {
      project: project.id
    }
  }
);

describe('WorkflowSelection', function () {
  const actions = {
    translations: {
      load: () => null
    }
  };
  const translations = {
    locale: 'en'
  };
  const wrapper = mount(
    <WorkflowSelection
      actions={actions}
      project={project}
      preferences={preferences}
      projectRoles={projectRoles}
      location={location}
      translations={translations}
    >
      <StubPage />
    </WorkflowSelection>,
    { context }
  );
  const controller = wrapper.instance();
  const workflowStub = sinon.stub(controller, 'getWorkflow').callsFake(() => {});

  before(function () {
    sinon.stub(apiClient, 'request').callsFake((method, url, payload) => {
      let response = [];
      if (url === '/workflows') {
        const workflow = mockPanoptesResource(
          'workflows',
          {
            id: payload.id,
            tasks: []
          }
        );
        response = [workflow];
      }
      return Promise.resolve(response);
    });
  });

  beforeEach(function () {
    workflowStub.resetHistory();
    wrapper.update();
  });

  afterEach(function () {
    project.experimental_tools = [];
    location.query = {};
  });

  after(function () {
    apiClient.request.restore();
  });

  it('should fetch a random active workflow by default', function () {
    controller.getSelectedWorkflow({ project });
    const selectedWorkflowID = workflowStub.getCall(0).args[0];
    sinon.assert.calledOnce(workflowStub);
    assert.notEqual(project.links.active_workflows.indexOf(selectedWorkflowID.toString()), -1);
  });

  it('should respect the workflow query param if "allow workflow query" is set', function () {
    location.query.workflow = '6';
    project.experimental_tools = ['allow workflow query'];
    controller.getSelectedWorkflow({ project });
    sinon.assert.calledOnce(workflowStub);
    sinon.assert.calledWith(workflowStub, '6', true);
  });

  describe('with a logged-in user', function () {
    beforeEach(function () {
      controller.setupSplits = () => null;
      location.query.workflow = '6';
    });

    it('should load the specified workflow for the project owner', function () {
      const user = owner;
      controller.getSelectedWorkflow({ project, preferences, user });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '6', false);
    });

    it('should load the specified workflow for a collaborator', function () {
      const user = apiClient.type('users').create({ id: '2' });
      controller.getSelectedWorkflow({ project, preferences, user });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '6', false);
    });

    it('should load the specified workflow for a tester', function () {
      const user = apiClient.type('users').create({ id: '3' });
      controller.getSelectedWorkflow({ project, preferences, user });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '6', false);
    });

    it('should load an active workflow for a general user', function () {
      const user = apiClient.type('users').create({ id: '4' });
      controller.getSelectedWorkflow({ project, preferences, user });
      sinon.assert.calledOnce(workflowStub);
      const selectedWorkflowID = workflowStub.getCall(0).args[0];
      const activeFilter = workflowStub.getCall(0).args[1];
      assert.notEqual(project.links.active_workflows.indexOf(selectedWorkflowID), -1);
      assert.equal(activeFilter, true);
    });
  });

  describe('with a workflow saved in preferences', function () {
    beforeEach(function () {
      location.query = {};
      preferences.update({ preferences: {}});
      const user = mockPanoptesResource('users', { id: '4' });
      wrapper.setProps({ user });
    });

    it('should try to load the stored workflow', function () {
      preferences.update({ 'preferences.selected_workflow': '4' });
      controller.getSelectedWorkflow({ project, preferences });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '4', true);
    });

    it('should parse the stored user workflow as an int', function () {
      preferences.update({ 'preferences.selected_workflow': '4random' });
      controller.getSelectedWorkflow({ project, preferences });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '4', true);
    });

    it('should try to load a stored project workflow', function () {
      preferences.update({ 'settings.workflow_id': '2' });
      controller.getSelectedWorkflow({ project, preferences });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '2', true);
    });

    it('parse the stored project workflow as an int', function () {
      preferences.update({ 'settings.workflow_id': '2random' });
      controller.getSelectedWorkflow({ project, preferences });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '2', true);
    });
  });

  describe('without a saved workflow', function () {
    beforeEach(function () {
      location.query = {};
      project.update({ 'configuration.default_workflow': '1' });
      preferences.update({ settings: {}, preferences: {}});
    });

    it('should load the project default workflow', function () {
      const user = apiClient.type('users').create({ id: '4' });
      controller.getSelectedWorkflow({ project, preferences, user });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '1', true);
    });
  });

  describe('on project change', function () {
    it('should load a workflow for the new project', function () {
      const newProject = mockPanoptesResource('projects',
        {
          id: 'b',
          display_name: 'Another test project',
          experimental_tools: [],
          configuration: {
            default_workflow: '10'
          },
          links: {
            active_workflows: ['10'],
            owner: { id: '1' }
          }
        }
      );
      wrapper.setProps({ project: newProject });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '10', true);
    });
  });
});<commit_msg>Test that workflow query params are sanitised<commit_after>import React from 'react';
import assert from 'assert';
import { mount } from 'enzyme';
import sinon from 'sinon';
import apiClient from 'panoptes-client/lib/api-client';
import WorkflowSelection from './workflow-selection';

function StubPage() {
  return
Hello
;
}

const location = {
  query: {}
};

const context = {
  router: {}
};

const projectRoles = [
  {
    roles: ['owner'],
    links: {
      owner: {
        id: '1'
      }
    }
  },
  {
    roles: ['collaborator'],
    links: {
      owner: {
        id: '2'
      }
    }
  },
  {
    roles: ['tester'],
    links: {
      owner: {
        id: '3'
      }
    }
  }
];

function mockPanoptesResource(type, options) {
  const resource = apiClient.type(type).create(options);
  apiClient._typesCache = {};
  sinon.stub(resource, 'save').callsFake(() => Promise.resolve(resource));
  sinon.stub(resource, 'get');
  sinon.stub(resource, 'delete');
  return resource;
}

const project = mockPanoptesResource('projects',
  {
    id: 'a',
    display_name: 'A test project',
    experimental_tools: [],
    links: {
      active_workflows: ['1', '2', '3', '4', '5'],
      owner: { id: '1' }
    }
  }
);

const owner = mockPanoptesResource(
  'users',
  {
    id: project.links.owner.id
  }
);

const preferences = mockPanoptesResource(
  'project_preferences',
  {
    preferences: {},
    links: {
      project: project.id
    }
  }
);

describe('WorkflowSelection', function () {
  const actions = {
    translations: {
      load: () => null
    }
  };
  const translations = {
    locale: 'en'
  };
  const wrapper = mount(
    <WorkflowSelection
      actions={actions}
      project={project}
      preferences={preferences}
      projectRoles={projectRoles}
      location={location}
      translations={translations}
    >
      <StubPage />
    </WorkflowSelection>,
    { context }
  );
  const controller = wrapper.instance();
  const workflowStub = sinon.stub(controller, 'getWorkflow').callsFake(() => {});

  before(function () {
    sinon.stub(apiClient, 'request').callsFake((method, url, payload) => {
      let response = [];
      if (url === '/workflows') {
        const workflow = mockPanoptesResource(
          'workflows',
          {
            id: payload.id,
            tasks: []
          }
        );
        response = [workflow];
      }
      return Promise.resolve(response);
    });
  });

  beforeEach(function () {
    workflowStub.resetHistory();
    wrapper.update();
  });

  afterEach(function () {
    project.experimental_tools = [];
    location.query = {};
  });

  after(function () {
    apiClient.request.restore();
  });

  it('should fetch a random active workflow by default', function () {
    controller.getSelectedWorkflow({ project });
    const selectedWorkflowID = workflowStub.getCall(0).args[0];
    sinon.assert.calledOnce(workflowStub);
    assert.notEqual(project.links.active_workflows.indexOf(selectedWorkflowID.toString()), -1);
  });

  it('should respect the workflow query param if "allow workflow query" is set', function () {
    location.query.workflow = '6';
    project.experimental_tools = ['allow workflow query'];
    controller.getSelectedWorkflow({ project });
    sinon.assert.calledOnce(workflowStub);
    sinon.assert.calledWith(workflowStub, '6', true);
  });

  it('should sanitise the workflow query param if "allow workflow query" is set', function () {
    location.query.workflow = '6random78';
    project.experimental_tools = ['allow workflow query'];
    controller.getSelectedWorkflow({ project });
    sinon.assert.calledOnce(workflowStub);
    sinon.assert.calledWith(workflowStub, '6', true);
  });

  describe('with a logged-in user', function () {
    beforeEach(function () {
      controller.setupSplits = () => null;
      location.query.workflow = '6';
    });

    it('should load the specified workflow for the project owner', function () {
      const user = owner;
      controller.getSelectedWorkflow({ project, preferences, user });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '6', false);
    });

    it('should load the specified workflow for a collaborator', function () {
      const user = apiClient.type('users').create({ id: '2' });
      controller.getSelectedWorkflow({ project, preferences, user });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '6', false);
    });

    it('should load the specified workflow for a tester', function () {
      const user = apiClient.type('users').create({ id: '3' });
      controller.getSelectedWorkflow({ project, preferences, user });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '6', false);
    });

    it('should load an active workflow for a general user', function () {
      const user = apiClient.type('users').create({ id: '4' });
      controller.getSelectedWorkflow({ project, preferences, user });
      sinon.assert.calledOnce(workflowStub);
      const selectedWorkflowID = workflowStub.getCall(0).args[0];
      const activeFilter = workflowStub.getCall(0).args[1];
      assert.notEqual(project.links.active_workflows.indexOf(selectedWorkflowID), -1);
      assert.equal(activeFilter, true);
    });
  });

  describe('with a workflow saved in preferences', function () {
    beforeEach(function () {
      location.query = {};
      preferences.update({ preferences: {}});
      const user = mockPanoptesResource('users', { id: '4' });
      wrapper.setProps({ user });
    });

    it('should try to load the stored workflow', function () {
      preferences.update({ 'preferences.selected_workflow': '4' });
      controller.getSelectedWorkflow({ project, preferences });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '4', true);
    });

    it('should parse the stored user workflow as an int', function () {
      preferences.update({ 'preferences.selected_workflow': '4random' });
      controller.getSelectedWorkflow({ project, preferences });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '4', true);
    });

    it('should try to load a stored project workflow', function () {
      preferences.update({ 'settings.workflow_id': '2' });
      controller.getSelectedWorkflow({ project, preferences });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '2', true);
    });

    it('parse the stored project workflow as an int', function () {
      preferences.update({ 'settings.workflow_id': '2random' });
      controller.getSelectedWorkflow({ project, preferences });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '2', true);
    });
  });

  describe('without a saved workflow', function () {
    beforeEach(function () {
      location.query = {};
      project.update({ 'configuration.default_workflow': '1' });
      preferences.update({ settings: {}, preferences: {}});
    });

    it('should load the project default workflow', function () {
      const user = apiClient.type('users').create({ id: '4' });
      controller.getSelectedWorkflow({ project, preferences, user });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '1', true);
    });
  });

  describe('on project change', function () {
    it('should load a workflow for the new project', function () {
      const newProject = mockPanoptesResource('projects',
        {
          id: 'b',
          display_name: 'Another test project',
          experimental_tools: [],
          configuration: {
            default_workflow: '10'
          },
          links: {
            active_workflows: ['10'],
            owner: { id: '1' }
          }
        }
      );
      wrapper.setProps({ project: newProject });
      sinon.assert.calledOnce(workflowStub);
      sinon.assert.calledWith(workflowStub, '10', true);
    });
  });
});<|endoftext|>


<commit_before>(function($){
    // Pulled from here
    // url of json data
    //   here, instead of pointing to the google calendar link that you'll want to use,
    //   I'm pointing to a static file so that this example doesn't break in the future even
    //   if the calendar it was based upon changes.
    //   you'll want to use a link in the form of:
    //   http://www.google.com/calendar/feeds/your-calendar@gmail.com/public/full?orderby=starttime&sortorder=ascending&max-results=3&futureevents=true&alt=json
    var calendar_json_url = "http://www.google.com/calendar/feeds/bnhe2fs01i2q0a0h2es0dmt2i4@group.calendar.google.com/public/full?orderby=starttime&sortorder=ascending&max-results=3&futureevents=true&alt=json";

    // Get list of upcoming events formatted in JSON
    $.getJSON(calendar_json_url, function(data){

        // Parse and render each event
        $.each(data.feed.entry, function(i, item){

            // Render the event
            $("#gcal-events").find("li").last().after(
                "
" +
                    "DATE" +
                    ", " +
                    item.title.$t +
                    ", " +
                    "Location" +
                "
"
            );

        });
        $("#gcal-events").find("li").first().remove()
    });
})($);
<commit_msg>add where<commit_after>(function($){
    // Pulled from here
    // url of json data
    //   here, instead of pointing to the google calendar link that you'll want to use,
    //   I'm pointing to a static file so that this example doesn't break in the future even
    //   if the calendar it was based upon changes.
    //   you'll want to use a link in the form of:
    //   http://www.google.com/calendar/feeds/your-calendar@gmail.com/public/full?orderby=starttime&sortorder=ascending&max-results=3&futureevents=true&alt=json
    var calendar_json_url = "http://www.google.com/calendar/feeds/bnhe2fs01i2q0a0h2es0dmt2i4@group.calendar.google.com/public/full?orderby=starttime&sortorder=ascending&max-results=3&futureevents=true&alt=json";

    // Get list of upcoming events formatted in JSON
    $.getJSON(calendar_json_url, function(data){

        // Parse and render each event
        $.each(data.feed.entry, function(i, item){

            // Render the event
            $("#gcal-events").find("li").last().after(
                "
" +
                    "DATE" +
                    ", " +
                    item.title.$t +
                    ", " +
                    item.gd$where[0].valueString +
                "
"
            );

        });
        $("#gcal-events").find("li").first().remove()
    });
})($);
<|endoftext|>


<commit_before>define(["backbone", "underscore", "places/models/CategoryModel", "moxie.conf"], function(Backbone, _, Category, conf) {

    var DEPTH_LIMIT = 3;
    var CategoryCollection = Backbone.Collection.extend({
        model: Category,
        url: conf.urlFor('places_categories'),
        parse: function(data) {
            // The data Moxie presents for categories is in a (sensible) tree structure.
            // This kind of structure doesn't fit the Model/Collection paradigm in Backbone
            // too well, so we flatten the structure. We leave behind markers for 'depth'
            // and build a '/' delimited path for the branches of the tree. That way we can
            // make fast queries on the content at depth 2 without any need to traverse again.
            var flattened_cats = [];
            function flatten_categories(prefix, depth, cats) {
                depth++;
                for (var i=0; i < cats.length; i++) {
                    var cat_data = cats[i];
                    // Since the top level type is simply '/' we need this logic to stop us prefixing with '//'
                    var new_prefix = (prefix.length > 1) ? prefix + '/' + cat_data.type : prefix + cat_data.type;
                    // A '/' delimited path which reflects the tree structure
                    // eg. /transport/car-park/park-and-ride
                    cat_data.type_prefixed = new_prefix;
                    // How far into the tree are we? This is kept around as a convenience.
                    cat_data.depth = depth;
                    if (cat_data.types && depth < DEPTH_LIMIT) {
                        cat_data.hasTypes = true;
                        flatten_categories(new_prefix, depth, cat_data.types);
                    }
                    // Don't include the recursive structure in the models
                    flattened_cats.push(_.omit(cat_data, ['types']));
                }
            }
            data.type = data.type || '/';
            flatten_categories('', 0, [data]);
            return flattened_cats;
        }
    });

    return CategoryCollection;

});
<commit_msg>Moved to MoxieCollection for fetch behaviour<commit_after>define(["core/collections/MoxieCollection", "underscore", "places/models/CategoryModel", "moxie.conf"], function(MoxieCollection, _, Category, conf) {

    var DEPTH_LIMIT = 3;
    var CategoryCollection = MoxieCollection.extend({
        model: Category,
        url: conf.urlFor('places_categories'),
        parse: function(data) {
            // The data Moxie presents for categories is in a (sensible) tree structure.
            // This kind of structure doesn't fit the Model/Collection paradigm in Backbone
            // too well, so we flatten the structure. We leave behind markers for 'depth'
            // and build a '/' delimited path for the branches of the tree. That way we can
            // make fast queries on the content at depth 2 without any need to traverse again.
            var flattened_cats = [];
            function flatten_categories(prefix, depth, cats) {
                depth++;
                for (var i=0; i < cats.length; i++) {
                    var cat_data = cats[i];
                    // Since the top level type is simply '/' we need this logic to stop us prefixing with '//'
                    var new_prefix = (prefix.length > 1) ? prefix + '/' + cat_data.type : prefix + cat_data.type;
                    // A '/' delimited path which reflects the tree structure
                    // eg. /transport/car-park/park-and-ride
                    cat_data.type_prefixed = new_prefix;
                    // How far into the tree are we? This is kept around as a convenience.
                    cat_data.depth = depth;
                    if (cat_data.types && depth < DEPTH_LIMIT) {
                        cat_data.hasTypes = true;
                        flatten_categories(new_prefix, depth, cat_data.types);
                    }
                    // Don't include the recursive structure in the models
                    flattened_cats.push(_.omit(cat_data, ['types']));
                }
            }
            data.type = data.type || '/';
            flatten_categories('', 0, [data]);
            return flattened_cats;
        }
    });

    return CategoryCollection;

});
<|endoftext|>


<commit_before>/**
 * TeamController: Let the user change player names, when she clicks a player
 * name
 *
 * @return TeamController
 * @author Erik E. Lorenz <erik@tuvero.de>
 * @license MIT License
 * @see LICENSE
 */
define(["lib/extend", "ui/renamecontroller", "ui/toast", "ui/strings",
  "ui/state", "ui/tabshandle"
], function (extend, RenameController, Toast, Strings, State, TabsHandle) {

  function TeamController(view, $input) {
    TeamController.superconstructor.call(this, view);

    this.view.$view.find(".teamno").click(this.openModal.bind(this));
  }
  extend(TeamController, RenameController);

  TeamController.prototype.getPlayer = function ($name) {
    var index, $names;

    $names = this.view.$view.find(".name");
    if ($names.length === 0) {
      $names = this.view.$view.filter(".name");
    }
    index = $names.index($name);

    return this.model.getPlayer(index);
  };

  TeamController.prototype.getNameModel = function ($anchor) {
    if (this.$anchor.hasClass("teamname")) {
      return this.model;
    } else {
      return this.getPlayer(this.$anchor);
    }
  }

  TeamController.prototype.getName = function () {
    var nameModel;

    if (!this.$anchor) {
      return "";
    }

    nameModel = this.getNameModel(this.$anchor);

    return nameModel.getName();
  };

  TeamController.prototype.setName = function (name) {
    var nameModel;

    if (!this.$anchor || !name) {
      return false;
    }

    nameModel = this.getNameModel(this.$anchor);

    nameModel.setName(name);

    return true;
  };

  TeamController.prototype.openModal = function () {
    State.focusedteam.set(this.model);

    TabsHandle.focus("team");
  };

  TeamController.prototype.destroy = function () {
    if (State.focusedteam.get() === this.model) {
      State.focusedteam.set(undefined);
    }

    TeamController.superclass.destroy.call(this);
  };

  return TeamController;
});<commit_msg>Allow setting the teamname to an empty string<commit_after>/**
 * TeamController: Let the user change player names, when she clicks a player
 * name
 *
 * @return TeamController
 * @author Erik E. Lorenz <erik@tuvero.de>
 * @license MIT License
 * @see LICENSE
 */
define(["lib/extend", "ui/renamecontroller", "ui/toast", "ui/strings",
  "ui/state", "ui/tabshandle"
], function (extend, RenameController, Toast, Strings, State, TabsHandle) {

  function TeamController(view, $input) {
    TeamController.superconstructor.call(this, view);

    this.view.$view.find(".teamno").click(this.openModal.bind(this));
  }
  extend(TeamController, RenameController);

  TeamController.prototype.getPlayer = function ($name) {
    var index, $names;

    $names = this.view.$view.find(".name");
    if ($names.length === 0) {
      $names = this.view.$view.filter(".name");
    }
    index = $names.index($name);

    return this.model.getPlayer(index);
  };

  TeamController.prototype.getNameModel = function ($anchor) {
    if (this.$anchor.hasClass("teamname")) {
      return this.model;
    } else {
      return this.getPlayer(this.$anchor);
    }
  }

  TeamController.prototype.getName = function () {
    var nameModel;

    if (!this.$anchor) {
      return "";
    }

    nameModel = this.getNameModel(this.$anchor);

    return nameModel.getName();
  };

  TeamController.prototype.setName = function (name) {
    var nameModel;

    if (!this.$anchor) {
      return false;
    }

    nameModel = this.getNameModel(this.$anchor);

    nameModel.setName(name);

    return true;
  };

  TeamController.prototype.openModal = function () {
    State.focusedteam.set(this.model);

    TabsHandle.focus("team");
  };

  TeamController.prototype.destroy = function () {
    if (State.focusedteam.get() === this.model) {
      State.focusedteam.set(undefined);
    }

    TeamController.superclass.destroy.call(this);
  };

  return TeamController;
});<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

module.exports = function( environment, mongoInstance ) {

  var mongoosastic = require( "mongoosastic" ),
      validate = require( "mongoose-validator" ).validate,
      deferred = require( "deferred" ),
      env = environment,
      url = require( "url" ),
      mongoose = mongoInstance,
      elasticSearchURL = env.get( "FOUNDELASTICSEARCH_URL" ) ||
                         env.get( "BONSAI_URL" ) ||
                         env.get( "ELASTIC_SEARCH_URL" );

      elasticSearchURL = url.parse( elasticSearchURL );

  var Timestamp = {
    type: Number,
    es_type: "long",
    es_indexed: true,
    es_index: "not_analyzed"
  };

  // Schema
  var schema = new mongoose.Schema({
    url: {
      type: String,
      required: true,
      es_indexed: true,
      validate: validate( "isUrl" ),
      unique: true,
      es_index: "not_analyzed"
    },
    contentType: {
      type: String,
      es_indexed: true,
      required: true,
      es_index: "not_analyzed"
    },
    locale: {
      type: String,
      "default": "en_us",
      es_indexed: true,
      es_index: "not_analyzed"
    },
    title: {
      type: String,
      es_indexed: true,
      required: true
    },
    description: {
      type: String,
      es_indexed: true
    },
    thumbnail: {
      type: String,
      es_indexed: true,
      es_index: "not_analyzed"
    },
    author: {
      type: String,
      required: false,
      es_indexed: true,
      es_index: "not_analyzed"
    },
    email: {
      type: String,
      required: true,
      validate: validate( "isEmail" ),
      es_indexed: true,
      es_index: "not_analyzed"
    },
    published: {
      type: Boolean,
      "default": true,
      es_index: "not_analyzed"
    },
    tags: {
      type: [ String ],
      es_indexed: true,
      es_index: "not_analyzed",
      es_type: "String"
    },
    remixedFrom: {
      type: String,
      "default": null,
      es_indexed: true,
      es_index: "not_analyzed"
    },
    createdAt: Timestamp,
    updatedAt: Timestamp,
    deletedAt: {
      type: Number,
      "default": null,
      es_indexed: true,
      es_type: "long"
    }
  });

  schema.set( "toJSON", { virtuals: true } );

  schema.virtual( "id" ).get(function() {
    return this._id;
  });

  // Hooks
  schema.pre( "save", function ( next ) {
    this.updatedAt = Date.now();
    next();
  });

  schema.plugin( mongoosastic, {
    port: elasticSearchURL.port || 80,
    host: ( elasticSearchURL.auth ? elasticSearchURL.auth + "@" : "" ) + elasticSearchURL.hostname,
    hydrate: true
  });

  var Make = mongoose.model( "Make", schema );

  Make.createMapping(function( err, mapping ) {
    if ( err ) {
      console.log( "failed to create mapping", err.toString() );
    }
  });

  Make.publicFields = [ "url", "contentType", "locale",
                        "title", "description", "author", "published", "tags",
                        "thumbnail", "remixedFrom" ];

  return Make;
};
<commit_msg>Fix Bug 879432 - Synchronize existing makes in mongo with Elastic Search<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

module.exports = function( environment, mongoInstance ) {

  var mongoosastic = require( "mongoosastic" ),
      validate = require( "mongoose-validator" ).validate,
      deferred = require( "deferred" ),
      env = environment,
      url = require( "url" ),
      mongoose = mongoInstance,
      elasticSearchURL = env.get( "FOUNDELASTICSEARCH_URL" ) ||
                         env.get( "BONSAI_URL" ) ||
                         env.get( "ELASTIC_SEARCH_URL" );

      elasticSearchURL = url.parse( elasticSearchURL );

  var Timestamp = {
    type: Number,
    es_type: "long",
    es_indexed: true,
    es_index: "not_analyzed"
  };

  // Schema
  var schema = new mongoose.Schema({
    url: {
      type: String,
      required: true,
      es_indexed: true,
      validate: validate( "isUrl" ),
      unique: true,
      es_index: "not_analyzed"
    },
    contentType: {
      type: String,
      es_indexed: true,
      required: true,
      es_index: "not_analyzed"
    },
    locale: {
      type: String,
      "default": "en_us",
      es_indexed: true,
      es_index: "not_analyzed"
    },
    title: {
      type: String,
      es_indexed: true,
      required: true
    },
    description: {
      type: String,
      es_indexed: true
    },
    thumbnail: {
      type: String,
      es_indexed: true,
      es_index: "not_analyzed"
    },
    author: {
      type: String,
      required: false,
      es_indexed: true,
      es_index: "not_analyzed"
    },
    email: {
      type: String,
      required: true,
      validate: validate( "isEmail" ),
      es_indexed: true,
      es_index: "not_analyzed"
    },
    published: {
      type: Boolean,
      "default": true,
      es_index: "not_analyzed"
    },
    tags: {
      type: [ String ],
      es_indexed: true,
      es_index: "not_analyzed",
      es_type: "String"
    },
    remixedFrom: {
      type: String,
      "default": null,
      es_indexed: true,
      es_index: "not_analyzed"
    },
    createdAt: Timestamp,
    updatedAt: Timestamp,
    deletedAt: {
      type: Number,
      "default": null,
      es_indexed: true,
      es_type: "long"
    }
  });

  schema.set( "toJSON", { virtuals: true } );

  schema.virtual( "id" ).get(function() {
    return this._id;
  });

  // Hooks
  schema.pre( "save", function ( next ) {
    this.updatedAt = Date.now();
    next();
  });

  schema.plugin( mongoosastic, {
    port: elasticSearchURL.port || 80,
    host: ( elasticSearchURL.auth ? elasticSearchURL.auth + "@" : "" ) + elasticSearchURL.hostname,
    hydrate: true
  });

  var Make = mongoose.model( "Make", schema );

  Make.createMapping(function( err, mapping ) {
    if ( err ) {
      console.log( "failed to create mapping", err.toString() );
    }
  });

  // Synchronize existing makes with Elastic Search
  Make.synchronize();

  Make.publicFields = [ "url", "contentType", "locale",
                        "title", "description", "author", "published", "tags",
                        "thumbnail", "remixedFrom" ];

  return Make;
};
<|endoftext|>


<commit_before>var rest = require('restler');
var db = require('./db');
var util = require('./util');
var auth = require('./auth');
var sessions = require('./sessions');

var MSG_INFO = "\nType /back to go back. Type /cancel to cancel feedback.";

function start(chatId, bot, callback) {
    function authCallback(row) {
        if (!row) {
            callback('Sorry you\'re not registered. Type /register to register.');
            // } else if (!row.isCinnamonResident) {
            //     bot.sendMessage(chatId, 'Sorry you must be a Cinnamon resident to use this feature :(');
        } else {
            var faultSession = sessions.createFaultSession(chatId);
            ask_category(chatId, bot, faultSession);
        }
    }
    auth.isCinnamonResident(chatId, authCallback);
}

function continueFeedback(chatId, body, bot) {
    var faultSession = sessions.getFaultSession(chatId);
    if (faultSession.key === 'phone') {
        if ((body.length !== 8) || isNaN(parseInt(body))) {
            return bot.sendMessage(chatId, 'Phone number must be 8 numerical digits.').then(function() {
                ask_phone(chatId, bot, faultSession);
            });
        }
    }
    if (faultSession.key === 'description') {
        var remindDone = function() {
            bot.sendMessage(chatId, "Please remember to type /done when you are done.");
            //setTimeout(remindDone, 20 * 1000);
        };
        setTimeout(remindDone, 20 * 1000);
        if (body.endsWith('/done')) {
            faultSession.faultFeedback[faultSession.key] += body.substring(0, body.length - 6);
            if (faultSession.faultFeedback.description.length < 24) {
                return bot.sendMessage(chatId, 'You have entered:\n"' + faultSession.faultFeedback.description.trim() + '"\nDescription should be at least 23 characters.').then(function() {
                    ask_continue_description(chatId, bot, faultSession);
                });
            }
            return submit(chatId, bot, faultSession.faultFeedback);
        }
        faultSession.faultFeedback[faultSession.key] += body;
    } else {
        faultSession.faultFeedback[faultSession.key] = body;
    }
    return faultSession.next(chatId, bot, faultSession);
}

function ask_category(chatId, bot, faultSession) {
    var opts = {
        parse_mode: "Markdown",
        reply_markup: JSON.stringify({
            keyboard: [
                ['New'],
                ['Reported but not rectified'],
                ['Reported, rectified but re-occurred'],
            ],
            one_time_keyboard: true
        })
    };
    bot.sendMessage(chatId, "*Welcome to Cinnabot's Fault Reporting System*\nThis will send an email to OHS, Cinnamon so please do not abuse it.", {
        parse_mode: "Markdown"
    }).then(function() {
        msg = "What is your *Problem Category*?\n" + MSG_INFO;
        bot.sendMessage(chatId, msg, opts);
    });
    faultSession.key = "category";
    faultSession.next = ask_urgency;
    faultSession.back = ask_category;
}

function ask_urgency(chatId, bot, faultSession) {
    var opts = {
        parse_mode: "Markdown",
        reply_markup: JSON.stringify({
            keyboard: [
                ['Very Urgent', 'Urgent'],
                ['Slightly Urgent', 'Can Wait'],
            ],
            one_time_keyboard: true
        })
    };
    msg = "How *urgent* is your problem?\n" + MSG_INFO;
    bot.sendMessage(chatId, msg, opts);
    faultSession.key = "urgency";
    faultSession.next = ask_location;
    faultSession.back = ask_category;
}

function ask_location(chatId, bot, faultSession) {
    var opts = {
        parse_mode: "Markdown",
        reply_markup: JSON.stringify({
            hide_keyboard: true
        })
    };
    msg = "Where is the problem *located*?:\n" + MSG_INFO;
    bot.sendMessage(chatId, msg, opts);
    faultSession.key = "location";
    faultSession.next = ask_name;
    faultSession.back = ask_urgency;
}

function ask_name(chatId, bot, faultSession) {
    db.getUser(chatId, callback);

    function callback(err, row) {
        var opts = {
            parse_mode: "Markdown",
            reply_markup: JSON.stringify({
                keyboard: [
                    [row.name],
                ],
                one_time_keyboard: true
            })
        };
        msg = "Select your *name* below:\n\nOr write your name if it doesn't match.\n" + MSG_INFO;
        bot.sendMessage(chatId, msg, opts);
        faultSession.key = "name";
        faultSession.next = ask_room;
        faultSession.back = ask_location;
    }
}

function ask_room(chatId, bot, faultSession) {
    var opts = {
        parse_mode: "Markdown",
        reply_markup: JSON.stringify({
            hide_keyboard: true
        })
    };
    msg = "Please enter your *room number*:\n" + MSG_INFO;
    bot.sendMessage(chatId, msg, opts);
    faultSession.key = "room";
    faultSession.next = ask_matric;
    faultSession.back = ask_name;
}

function ask_matric(chatId, bot, faultSession) {
    db.getUser(chatId, callback);

    function callback(err, row) {
        var opts = {
            parse_mode: "Markdown",
            reply_markup: JSON.stringify({
                keyboard: [
                    [util.calculateNUSMatricNumber(row.matric)],
                ],
                one_time_keyboard: true
            })
        };
        msg = "Select your *matric no.* below:\n\nOr write your matric no. if it doesn't match.\n" + MSG_INFO;
        bot.sendMessage(chatId, msg, opts);
        faultSession.key = "matric";
        faultSession.next = ask_email;
        faultSession.back = ask_room;
    }
}

function ask_email(chatId, bot, faultSession) {
    db.getUser(chatId, callback);

    function callback(err, row) {
        var opts = {
            parse_mode: "Markdown",
            reply_markup: JSON.stringify({
                keyboard: [
                    [row.email],
                ],
                one_time_keyboard: true
            })
        };
        msg = "Select your *email* below:\n\nOr write your email if it doesn't match.\n" + MSG_INFO;
        bot.sendMessage(chatId, msg, opts);
        faultSession.key = "email";
        faultSession.next = ask_phone;
        faultSession.back = ask_matric;
    }
}

function ask_phone(chatId, bot, faultSession) {
    var opts = {
        parse_mode: "Markdown",
        reply_markup: JSON.stringify({
            hide_keyboard: true
        })
    };
    msg = "Please enter your *phone number*:\n" + MSG_INFO;
    bot.sendMessage(chatId, msg, opts);
    faultSession.key = "phone";
    faultSession.next = ask_permission;
    faultSession.back = ask_email;
}

function ask_permission(chatId, bot, faultSession) {
    var opts = {
        parse_mode: "Markdown",
        reply_markup: JSON.stringify({
            keyboard: [
                ['Yes', 'No']
            ],
            one_time_keyboard: true
        })
    };
    msg = "*Do you consent to OHS entering your room without your presence to rectify the fault?*\n" + MSG_INFO;
    bot.sendMessage(chatId, msg, opts);
    faultSession.key = "permission";
    faultSession.back = ask_phone;
    faultSession.next = ask_description;
}

function ask_description(chatId, bot, faultSession) {
    var opts = {
        parse_mode: "Markdown",
        reply_markup: JSON.stringify({
            hide_keyboard: true
        })
    };
    msg = "Enter the problem description. Type /done to end the description.\n" + MSG_INFO;
    bot.sendMessage(chatId, msg, opts);
    faultSession.key = "description";
    faultSession.next = ask_continue_description;
    faultSession.back = ask_phone;
}

function ask_continue_description(chatId, bot, faultSession) {
    faultSession.faultFeedback.description += "\n";
    faultSession.key = "description";
    faultSession.next = ask_continue_description;
    faultSession.back = ask_phone;
}

function submit(chatId, bot, faultFeedback) {
    var feedbackURL = "https://docs.google.com/forms/d/1mh5jD1RfstgrbJPefjyPoM2OyLqsZt6C87g1suQ1TuI/formResponse?";
    feedbackURL +=
        'entry.2132193706=' + faultFeedback.category +
        // '&entry.2132193706.other_option_response=' + faultFeedback.category +
        '&entry.749088216=' + faultFeedback.urgency +
        '&entry.2133800720=' + faultFeedback.location +
        '&entry.787536878=' + faultFeedback.name +
        '&entry.1813223989=' + faultFeedback.room +
        '&entry.1836226199=' + faultFeedback.matric +
        '&entry.2119962668=' + faultFeedback.email +
        '&entry.858293967=' + faultFeedback.phone +
        '&entry.1755718880=' + faultFeedback.permission +
        '&entry.113024073=' + faultFeedback.description;

    sessions.deleteFaultSession(chatId);
    console.log(feedbackURL);
}

module.exports = {
    ask_category,
    ask_urgency,
    ask_location,
    ask_name,
    ask_matric,
    ask_phone,
    ask_room,
    ask_permission,
    ask_description,
    ask_continue_description,
    start,
    continueFeedback,
    submit
};
<commit_msg>uncomment fault reporting submission<commit_after>var rest = require('restler');
var db = require('./db');
var util = require('./util');
var auth = require('./auth');
var sessions = require('./sessions');

var MSG_INFO = "\nType /back to go back. Type /cancel to cancel feedback.";

function start(chatId, bot, callback) {
    function authCallback(row) {
        if (!row) {
            callback('Sorry you\'re not registered. Type /register to register.');
            // } else if (!row.isCinnamonResident) {
            //     bot.sendMessage(chatId, 'Sorry you must be a Cinnamon resident to use this feature :(');
        } else {
            var faultSession = sessions.createFaultSession(chatId);
            ask_category(chatId, bot, faultSession);
        }
    }
    auth.isCinnamonResident(chatId, authCallback);
}

function continueFeedback(chatId, body, bot) {
    var faultSession = sessions.getFaultSession(chatId);
    if (faultSession.key === 'phone') {
        if ((body.length !== 8) || isNaN(parseInt(body))) {
            return bot.sendMessage(chatId, 'Phone number must be 8 numerical digits.').then(function() {
                ask_phone(chatId, bot, faultSession);
            });
        }
    }
    if (faultSession.key === 'description') {
        var remindDone = function() {
            bot.sendMessage(chatId, "Please remember to type /done when you are done.");
            //setTimeout(remindDone, 20 * 1000);
        };
        setTimeout(remindDone, 20 * 1000);
        if (body.endsWith('/done')) {
            faultSession.faultFeedback[faultSession.key] += body.substring(0, body.length - 6);
            if (faultSession.faultFeedback.description.length < 24) {
                return bot.sendMessage(chatId, 'You have entered:\n"' + faultSession.faultFeedback.description.trim() + '"\nDescription should be at least 23 characters.').then(function() {
                    ask_continue_description(chatId, bot, faultSession);
                });
            }
            return submit(chatId, bot, faultSession.faultFeedback);
        }
        faultSession.faultFeedback[faultSession.key] += body;
    } else {
        faultSession.faultFeedback[faultSession.key] = body;
    }
    return faultSession.next(chatId, bot, faultSession);
}

function ask_category(chatId, bot, faultSession) {
    var opts = {
        parse_mode: "Markdown",
        reply_markup: JSON.stringify({
            keyboard: [
                ['New'],
                ['Reported but not rectified'],
                ['Reported, rectified but re-occurred'],
            ],
            one_time_keyboard: true
        })
    };
    bot.sendMessage(chatId, "*Welcome to Cinnabot's Fault Reporting System*\nThis will send an email to OHS, Cinnamon so please do not abuse it.", {
        parse_mode: "Markdown"
    }).then(function() {
        msg = "What is your *Problem Category*?\n" + MSG_INFO;
        bot.sendMessage(chatId, msg, opts);
    });
    faultSession.key = "category";
    faultSession.next = ask_urgency;
    faultSession.back = ask_category;
}

function ask_urgency(chatId, bot, faultSession) {
    var opts = {
        parse_mode: "Markdown",
        reply_markup: JSON.stringify({
            keyboard: [
                ['Very Urgent', 'Urgent'],
                ['Slightly Urgent', 'Can Wait'],
            ],
            one_time_keyboard: true
        })
    };
    msg = "How *urgent* is your problem?\n" + MSG_INFO;
    bot.sendMessage(chatId, msg, opts);
    faultSession.key = "urgency";
    faultSession.next = ask_location;
    faultSession.back = ask_category;
}

function ask_location(chatId, bot, faultSession) {
    var opts = {
        parse_mode: "Markdown",
        reply_markup: JSON.stringify({
            hide_keyboard: true
        })
    };
    msg = "Where is the problem *located*?:\n" + MSG_INFO;
    bot.sendMessage(chatId, msg, opts);
    faultSession.key = "location";
    faultSession.next = ask_name;
    faultSession.back = ask_urgency;
}

function ask_name(chatId, bot, faultSession) {
    db.getUser(chatId, callback);

    function callback(err, row) {
        var opts = {
            parse_mode: "Markdown",
            reply_markup: JSON.stringify({
                keyboard: [
                    [row.name],
                ],
                one_time_keyboard: true
            })
        };
        msg = "Select your *name* below:\n\nOr write your name if it doesn't match.\n" + MSG_INFO;
        bot.sendMessage(chatId, msg, opts);
        faultSession.key = "name";
        faultSession.next = ask_room;
        faultSession.back = ask_location;
    }
}

function ask_room(chatId, bot, faultSession) {
    var opts = {
        parse_mode: "Markdown",
        reply_markup: JSON.stringify({
            hide_keyboard: true
        })
    };
    msg = "Please enter your *room number*:\n" + MSG_INFO;
    bot.sendMessage(chatId, msg, opts);
    faultSession.key = "room";
    faultSession.next = ask_matric;
    faultSession.back = ask_name;
}

function ask_matric(chatId, bot, faultSession) {
    db.getUser(chatId, callback);

    function callback(err, row) {
        var opts = {
            parse_mode: "Markdown",
            reply_markup: JSON.stringify({
                keyboard: [
                    [util.calculateNUSMatricNumber(row.matric)],
                ],
                one_time_keyboard: true
            })
        };
        msg = "Select your *matric no.* below:\n\nOr write your matric no. if it doesn't match.\n" + MSG_INFO;
        bot.sendMessage(chatId, msg, opts);
        faultSession.key = "matric";
        faultSession.next = ask_email;
        faultSession.back = ask_room;
    }
}

function ask_email(chatId, bot, faultSession) {
    db.getUser(chatId, callback);

    function callback(err, row) {
        var opts = {
            parse_mode: "Markdown",
            reply_markup: JSON.stringify({
                keyboard: [
                    [row.email],
                ],
                one_time_keyboard: true
            })
        };
        msg = "Select your *email* below:\n\nOr write your email if it doesn't match.\n" + MSG_INFO;
        bot.sendMessage(chatId, msg, opts);
        faultSession.key = "email";
        faultSession.next = ask_phone;
        faultSession.back = ask_matric;
    }
}

function ask_phone(chatId, bot, faultSession) {
    var opts = {
        parse_mode: "Markdown",
        reply_markup: JSON.stringify({
            hide_keyboard: true
        })
    };
    msg = "Please enter your *phone number*:\n" + MSG_INFO;
    bot.sendMessage(chatId, msg, opts);
    faultSession.key = "phone";
    faultSession.next = ask_permission;
    faultSession.back = ask_email;
}

function ask_permission(chatId, bot, faultSession) {
    var opts = {
        parse_mode: "Markdown",
        reply_markup: JSON.stringify({
            keyboard: [
                ['Yes', 'No']
            ],
            one_time_keyboard: true
        })
    };
    msg = "*Do you consent to OHS entering your room without your presence to rectify the fault?*\n" + MSG_INFO;
    bot.sendMessage(chatId, msg, opts);
    faultSession.key = "permission";
    faultSession.back = ask_phone;
    faultSession.next = ask_description;
}

function ask_description(chatId, bot, faultSession) {
    var opts = {
        parse_mode: "Markdown",
        reply_markup: JSON.stringify({
            hide_keyboard: true
        })
    };
    msg = "Enter the problem description. Type /done to end the description.\n" + MSG_INFO;
    bot.sendMessage(chatId, msg, opts);
    faultSession.key = "description";
    faultSession.next = ask_continue_description;
    faultSession.back = ask_phone;
}

function ask_continue_description(chatId, bot, faultSession) {
    faultSession.faultFeedback.description += "\n";
    faultSession.key = "description";
    faultSession.next = ask_continue_description;
    faultSession.back = ask_phone;
}

function submit(chatId, bot, faultFeedback) {
    var feedbackURL = "https://docs.google.com/forms/d/1mh5jD1RfstgrbJPefjyPoM2OyLqsZt6C87g1suQ1TuI/formResponse?";
    feedbackURL +=
        'entry.2132193706=' + faultFeedback.category +
        // '&entry.2132193706.other_option_response=' + faultFeedback.category +
        '&entry.749088216=' + faultFeedback.urgency +
        '&entry.2133800720=' + faultFeedback.location +
        '&entry.787536878=' + faultFeedback.name +
        '&entry.1813223989=' + faultFeedback.room +
        '&entry.1836226199=' + faultFeedback.matric +
        '&entry.2119962668=' + faultFeedback.email +
        '&entry.858293967=' + faultFeedback.phone +
        '&entry.1755718880=' + faultFeedback.permission +
        '&entry.113024073=' + faultFeedback.description;

    rest.get(feedbackURL).on('complete', function(data) {
        bot.sendMessage(chatId, "Fault has been reported. Please check your email 😃");
    });
    sessions.deleteFaultSession(chatId);
    console.log(feedbackURL);
}

module.exports = {
    ask_category,
    ask_urgency,
    ask_location,
    ask_name,
    ask_matric,
    ask_phone,
    ask_room,
    ask_permission,
    ask_description,
    ask_continue_description,
    start,
    continueFeedback,
    submit
};
<|endoftext|>


<commit_before>(function(){

    xtag.register('widget-PPG', {
        extends: 'div',
        lifecycle: {
            created: function() {
                var xString,
                    title = document.createElement('h1'),
                    controlWrap = document.createElement('form'),
                    savePPG = document.createElement('button'),
                    saveLoadPPG = document.createElement('button'),
                    encodedCycle = document.createElement('input'),
                    applyCycle = document.createElement('input'),
                    cycleNameLabel = document.createElement('label'),
                    cycleName = document.createElement('input'),
                    chooseCycleLabel = document.createElement('label'),
                    chooseCycle = document.createElement('select');

                XHR('http://'+this.MIDAS+'/?cmd=jcopy&odb=/PPG&encoding=json-nokeys', this.registerPPGODB.bind(this));

                xString = '
Cycle Configuration
<x-ribbon id="PPGribbon"></x-ribbon>';
                xtag.innerHTML(this,xString);
                this.ribbon = document.getElementById('PPGribbon')

                this.ribbon.wrapperForm.onchange = function(){
                    document.getElementById('cycleName').value = '';
                };

                controlWrap.setAttribute('class', 'PPGcontrol');
                controlWrap.setAttribute('method', 'POST');
                controlWrap.setAttribute('action', 'registerCycle');
                this.appendChild(controlWrap);

                encodedCycle.setAttribute('type', 'text');
                encodedCycle.setAttribute('id', 'encodedCycle');
                encodedCycle.setAttribute('style', 'display:none');
                encodedCycle.setAttribute('name', 'cycleString');
                controlWrap.appendChild(encodedCycle);

                applyCycle.setAttribute('type', 'checkbox');
                applyCycle.setAttribute('id', 'applyCycle');
                applyCycle.setAttribute('style', 'display:none');
                applyCycle.setAttribute('name', 'applyCycle');
                controlWrap.appendChild(applyCycle);

                cycleNameLabel.innerHTML = 'Cycle Name:';
                cycleName.setAttribute('class', 'stdin');
                cycleName.setAttribute('type', 'text');
                cycleName.setAttribute('id', 'cycleName');
                cycleName.setAttribute('name', 'cycleName');
                controlWrap.appendChild(cycleNameLabel);
                controlWrap.appendChild(cycleName);

                savePPG.setAttribute('class', 'stdin');
                savePPG.innerHTML = 'Save New Cycle Definition';
                savePPG.onclick = this.registerNewCycle.bind(this);
                controlWrap.appendChild(savePPG);

                saveLoadPPG.setAttribute('class', 'stdin');
                saveLoadPPG.innerHTML = 'Save & Apply New Cycle Definition';
                saveLoadPPG.onclick = function(){
                    this.registerNewCycle();
                    document.getElementById('applyCycle').checked = true;
                }.bind(this);
                controlWrap.appendChild(saveLoadPPG);

                chooseCycleLabel.innerHTML = 'Load Cycle:'
                controlWrap.appendChild(chooseCycleLabel);
                chooseCycle.setAttribute('class', 'stdin');
                chooseCycle.setAttribute('id', 'cycleList');
                controlWrap.appendChild(chooseCycle);

            },
            inserted: function() {},
            removed: function() {},
            attributeChanged: function() {}
        },
        events: {

        },
        accessors: {
            'MIDAS':{
                attribute: {} //this just needs to be declared
            }
        },
        methods: {
            'loadPPG' : function(ppgTable, durations){
                var i, j, lastStep, options, lastDuration;

                for(i=0; i<ppgTable.length; i++){
                    this.ribbon.endRibbon.onclick();

                    lastStep = this.ribbon.getElementsByTagName('ul');
                    lastStep = lastStep[lastStep.length-1];
                    options = lastStep.querySelectorAll('input[type="checkbox"]');

                    lastDuration = this.ribbon.querySelectorAll('input[type="number"]');
                    lastDuration = lastDuration[lastDuration.length-1];
                    if(durations[i] < 1000)
                        lastDuration.value = durations[i];
                    else if(durations[i] < 60000){
                        lastDuration.value = durations[i] / 1000;
                        lastDuration.nextSibling.value = 1000;
                    } else{
                        lastDuration.value = durations[i] / 60000;
                        lastDuration.nextSibling.value = 60000;
                    }

                    for(j=0; j<16; j++){
                        if( (1 << j) & ppgTable[i]){
                            options[j].checked = true;
                        }
                    }
                }
            },

            'traversePPGribbon' : function(){
                var steps = this.ribbon.getElementsByTagName('ul'),
                    durations = this.ribbon.querySelectorAll('input[type="number"]'),
                    units = this.ribbon.querySelectorAll('select'),
                    duration = 0,
                    options,
                    ppgConfig = [],
                    i, j;

                for(i=0; i<steps.length; i++){
                    duration = parseInt(durations[i].value) * selected(units[i].id);

                    options = steps[i].querySelectorAll('input[type="checkbox"]:checked');
                    if(options.length > 0){
                        ppgConfig.push({'PPGcode' : 0, 'duration' : duration});
                        for(j=0; j<options.length; j++){
                            ppgConfig[ppgConfig.length-1].PPGcode = ppgConfig[ppgConfig.length-1].PPGcode | parseInt(options[j].value,10);
                        }
                    }
                }

                return ppgConfig;
            },

            'registerNewCycle' : function(){
                document.getElementById('encodedCycle').value = JSON.stringify(this.traversePPGribbon());
            },

            'registerPPGODB' : function(responseText){
                var data = JSON.parse(responseText),
                    currentName = data.Current,
                    currentPPG = data.Cycles[currentName].PPGcodes,
                    currentDuration = data.Cycles[currentName].durations,
                    cycleSelect = document.getElementById('cycleList'),
                    cycleOptions, key;

                this.loadPPG(currentPPG, currentDuration);
                document.getElementById('cycleName').value = currentName;

                for(key in data.Cycles){
                    cycleOptions = document.createElement('option');
                    cycleOptions.innerHTML = key;
                    cycleOptions.value = key;
                    cycleSelect.appendChild(cycleOptions);

                }

                cycleSelect.value = currentName;
            }
        }
    });

})();<commit_msg>messing around with PPG control DOM<commit_after>(function(){

    xtag.register('widget-PPG', {
        extends: 'div',
        lifecycle: {
            created: function() {
                var xString,
                    title = document.createElement('h1'),
                    controlWrap = document.createElement('form'),
                    savePPG = document.createElement('button'),
                    saveLoadPPG = document.createElement('button'),
                    encodedCycle = document.createElement('input'),
                    applyCycle = document.createElement('input'),
                    cycleNameLabel = document.createElement('label'),
                    cycleName = document.createElement('input'),
                    chooseCycleLabel = document.createElement('label'),
                    chooseCycle = document.createElement('select'),
                    controlRows = [];

                XHR('http://'+this.MIDAS+'/?cmd=jcopy&odb=/PPG&encoding=json-nokeys', this.registerPPGODB.bind(this));

                xString = '
Cycle Configuration
<x-ribbon id="PPGribbon"></x-ribbon>';
                xtag.innerHTML(this,xString);
                this.ribbon = document.getElementById('PPGribbon')

                this.ribbon.wrapperForm.onchange = function(){
                    document.getElementById('cycleName').value = '';
                };

                controlWrap.setAttribute('class', 'PPGcontrol');
                controlWrap.setAttribute('method', 'POST');
                controlWrap.setAttribute('action', 'registerCycle');
                this.appendChild(controlWrap);

                controlRows[0] = document.createElement('span')
                controlWrap.appendChild(controlRows[0]);

                encodedCycle.setAttribute('type', 'text');
                encodedCycle.setAttribute('id', 'encodedCycle');
                encodedCycle.setAttribute('style', 'display:none');
                encodedCycle.setAttribute('name', 'cycleString');
                controlRows[0].appendChild(encodedCycle);

                applyCycle.setAttribute('type', 'checkbox');
                applyCycle.setAttribute('id', 'applyCycle');
                applyCycle.setAttribute('style', 'display:none');
                applyCycle.setAttribute('name', 'applyCycle');
                controlRows[0].appendChild(applyCycle);

                cycleNameLabel.innerHTML = 'Cycle Name:';
                cycleName.setAttribute('class', 'stdin');
                cycleName.setAttribute('type', 'text');
                cycleName.setAttribute('id', 'cycleName');
                cycleName.setAttribute('name', 'cycleName');
                controlRows[0].appendChild(cycleNameLabel);
                controlRows[0].appendChild(cycleName);

                savePPG.setAttribute('class', 'stdin');
                savePPG.innerHTML = 'Save New Cycle Definition';
                savePPG.onclick = this.registerNewCycle.bind(this);
                controlRows[0].appendChild(savePPG);

                saveLoadPPG.setAttribute('class', 'stdin');
                saveLoadPPG.innerHTML = 'Save & Apply New Cycle Definition';
                saveLoadPPG.onclick = function(){
                    this.registerNewCycle();
                    document.getElementById('applyCycle').checked = true;
                }.bind(this);
                controlRows[0].appendChild(saveLoadPPG);

                controlRows[1] = document.createElement('span');
                controlWrap.appendChild(controlRows[1]);

                chooseCycleLabel.innerHTML = 'Load Cycle:'
                controlRows[1].appendChild(chooseCycleLabel);
                chooseCycle.setAttribute('class', 'stdin');
                chooseCycle.setAttribute('id', 'cycleList');
                controlRows[1].appendChild(chooseCycle);

            },
            inserted: function() {},
            removed: function() {},
            attributeChanged: function() {}
        },
        events: {

        },
        accessors: {
            'MIDAS':{
                attribute: {} //this just needs to be declared
            }
        },
        methods: {
            'loadPPG' : function(ppgTable, durations){
                var i, j, lastStep, options, lastDuration;

                for(i=0; i<ppgTable.length; i++){
                    this.ribbon.endRibbon.onclick();

                    lastStep = this.ribbon.getElementsByTagName('ul');
                    lastStep = lastStep[lastStep.length-1];
                    options = lastStep.querySelectorAll('input[type="checkbox"]');

                    lastDuration = this.ribbon.querySelectorAll('input[type="number"]');
                    lastDuration = lastDuration[lastDuration.length-1];
                    if(durations[i] < 1000)
                        lastDuration.value = durations[i];
                    else if(durations[i] < 60000){
                        lastDuration.value = durations[i] / 1000;
                        lastDuration.nextSibling.value = 1000;
                    } else{
                        lastDuration.value = durations[i] / 60000;
                        lastDuration.nextSibling.value = 60000;
                    }

                    for(j=0; j<16; j++){
                        if( (1 << j) & ppgTable[i]){
                            options[j].checked = true;
                        }
                    }
                }
            },

            'traversePPGribbon' : function(){
                var steps = this.ribbon.getElementsByTagName('ul'),
                    durations = this.ribbon.querySelectorAll('input[type="number"]'),
                    units = this.ribbon.querySelectorAll('select'),
                    duration = 0,
                    options,
                    ppgConfig = [],
                    i, j;

                for(i=0; i<steps.length; i++){
                    duration = parseInt(durations[i].value) * selected(units[i].id);

                    options = steps[i].querySelectorAll('input[type="checkbox"]:checked');
                    if(options.length > 0){
                        ppgConfig.push({'PPGcode' : 0, 'duration' : duration});
                        for(j=0; j<options.length; j++){
                            ppgConfig[ppgConfig.length-1].PPGcode = ppgConfig[ppgConfig.length-1].PPGcode | parseInt(options[j].value,10);
                        }
                    }
                }

                return ppgConfig;
            },

            'registerNewCycle' : function(){
                document.getElementById('encodedCycle').value = JSON.stringify(this.traversePPGribbon());
            },

            'registerPPGODB' : function(responseText){
                var data = JSON.parse(responseText),
                    currentName = data.Current,
                    currentPPG = data.Cycles[currentName].PPGcodes,
                    currentDuration = data.Cycles[currentName].durations,
                    cycleSelect = document.getElementById('cycleList'),
                    cycleOptions, key;

                this.loadPPG(currentPPG, currentDuration);
                document.getElementById('cycleName').value = currentName;

                for(key in data.Cycles){
                    cycleOptions = document.createElement('option');
                    cycleOptions.innerHTML = key;
                    cycleOptions.value = key;
                    cycleSelect.appendChild(cycleOptions);

                }

                cycleSelect.value = currentName;
            }
        }
    });

})();<|endoftext|>


<commit_before>describe('Module: angulartics', function() {
  beforeEach(module('angulartics'));

  it('should be configurable', function() {
    module(function(_$analyticsProvider_) {
      _$analyticsProvider_.virtualPageviews(false);
    });
    inject(function(_$analytics_) {
      expect(_$analytics_.settings.pageTracking.autoTrackVirtualPages).toBe(false);
    });
  });

  describe('Provider: analytics', function() {
    var analytics,
      rootScope,
      location;
    beforeEach(inject(function(_$analytics_, _$rootScope_, _$location_) {
      analytics = _$analytics_;
      location = _$location_;
      rootScope = _$rootScope_;

      spyOn(analytics, 'pageTrack');

      location.path('/');
    }));

    describe('initialize', function() {
      it('should tracking pages by default', function() {
        expect(analytics.settings.pageTracking.autoTrackVirtualPages).toBe(true);
      });
    });

    it('should support tracking pages on route change when using build in router', function() {
      location.path('/abc');
      rootScope.$emit('$routeChangeSuccess');
      expect(analytics.pageTrack).toHaveBeenCalledWith('/abc');
    });

    it('should support tracking pages on route change when using ui-router', function() {
      location.path('/def');
      rootScope.$emit('$stateChangeSuccess');
      expect(analytics.pageTrack).toHaveBeenCalledWith('/def');
    });

  });
});<commit_msg>Fixed spelling in test<commit_after>describe('Module: angulartics', function() {
  beforeEach(module('angulartics'));

  it('should be configurable', function() {
    module(function(_$analyticsProvider_) {
      _$analyticsProvider_.virtualPageviews(false);
    });
    inject(function(_$analytics_) {
      expect(_$analytics_.settings.pageTracking.autoTrackVirtualPages).toBe(false);
    });
  });

  describe('Provider: analytics', function() {
    var analytics,
      rootScope,
      location;
    beforeEach(inject(function(_$analytics_, _$rootScope_, _$location_) {
      analytics = _$analytics_;
      location = _$location_;
      rootScope = _$rootScope_;

      spyOn(analytics, 'pageTrack');

      location.path('/');
    }));

    describe('initialize', function() {
      it('should tracking pages by default', function() {
        expect(analytics.settings.pageTracking.autoTrackVirtualPages).toBe(true);
      });
    });

    it('should support tracking pages on route change when using built in router', function() {
      location.path('/abc');
      rootScope.$emit('$routeChangeSuccess');
      expect(analytics.pageTrack).toHaveBeenCalledWith('/abc');
    });

    it('should support tracking pages on route change when using ui-router', function() {
      location.path('/def');
      rootScope.$emit('$stateChangeSuccess');
      expect(analytics.pageTrack).toHaveBeenCalledWith('/def');
    });

  });
});<|endoftext|>