<commit_before>// ==UserScript==
// @name         SampleCodeExtractor
// @version      1.3.0
// @author       larryhou@github.com
// @namespace    https://github.com/larryhou
// @description  Extract url of sample code zip-file from developer.apple.com
// @include      https://developer.apple.com/library/*
// ==/UserScript==

function install(callback)
{
	if (location.href.indexOf("https://developer.apple.com/library") != 0 ) return;

	var script = document.createElement("script");
	script.type = "text/javascript";
	script.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js";

	var cb = document.createElement("script");
	cb.type = "text/javascript";
	cb.textContent = "jQuery.noConflict();(" + callback.toString() + ")(jQuery);";
	script.addEventListener('load', function()
	{
		document.head.appendChild(cb);
	});

	document.head.appendChild(script);
}

// https://developer.apple.com/library/ios/navigation/#section=Resource%20Types&topic=Sample%20Code

install(function($)
{
	const TIME_OUT = 5000;
	if (location.href.indexOf("samplecode") > 0)
	{
		if (location.href.indexOf("src=larryhou") < 0)return;

		$(document).ready(function()
		{
			const INTERVAL = 100;
			const MAX_RETRY_COUNT = Math.ceil(TIME_OUT / INTERVAL);

			var id, retryCount = 0;
			function doJob()
			{
				clearTimeout(id);

				var href = $("#Sample_link").attr("href");
				if (href)
				{
					parent.displaySampleCode(href)
				}
				else
				if (retryCount < MAX_RETRY_COUNT)
				{
					retryCount++;
					id = setTimeout(doJob, INTERVAL);
				}
				else
				{
					parent.logExtractError();
					parent.extractSampleCode();
				}
			}

			doJob();
		});

		return;
	}

	var pagelist = [];
	var jsonlist = [];

	var ziplist = [];
	var zipjson = [];

	var id;
	var index = 0;
	window.extractSampleCode = function()
	{
		clearTimeout(id);
		if (index < pagelist.length)
		{
			$("#kernel").attr("src", pagelist[index]);
			index++;

			var callee = arguments.callee;
			id = setTimeout(function()
			{
				console.log(jsonlist[index - 1]);
				callee();
			}, TIME_OUT + 500);
		}
		else
		{
			$("#kernel").remove();
			$("").insertAfter($("#result"));

			var doc = window.frames["summrize"].contentDocument;
			$(doc).ready(function()
 			{
				$(doc.body).css("font-family", "Consolas,Menlo");
				for (var i = 0; i < ziplist.length; i++)
				{
					$(doc.body).append($("
" + ziplist[i] + "
"));
				}

				var sum = {}

				var prefix, prev;
				for (var i = 0; i < zipjson.length; i++)
				{
					prefix = zipjson[i][3].slice(0, 4);
					if (prefix != prev)
					{
						sum[prefix] = [i + 1];
						if (sum[prev])
						{
							sum[prev].push(i);
						}

						prev = prefix;
					}
					else
					if (i == zipjson.length - 1)
					{
						sum[prefix].push(zipjson.length);
					}
				}

				function padding(value, length)
				{
					var rlt = String(value);

					var offset = length - rlt.length
					while (offset > 0)
					{
						rlt += "&nbsp";
						offset--;
					}

					return rlt;
				}

				var group = [];
				for (var key in sum)
				{
					group.push("group " + padding(sum[key][0], 4) + padding(sum[key][1], 4) + "${dir}/" + key);
					group[group.length - 1] = "
" + group[group.length - 1] + "
";
				}

				$(doc.body).append($(group.join(" ")));
 			});

			console.log("============<DONE!>============");
		}
	}

	window.logExtractError = function()
	{
		var url = pagelist[index - 1];
		console.log("ERR:" + url);
	}

	window.displaySampleCode = function(url)
	{
		url = "https://developer.apple.com" + url;
		ziplist.push(url);

		function getFormatedIndex()
		{
			var str = ziplist.length + "";
			while (str.length < 3) str = "0" + str;
			return str;
		}

		url = "" + url + "";

		var data = jsonlist[index - 1];
		zipjson.push(data);

		var text = getFormatedIndex() + ".[" + data[3] + ":" + data[1] + "][" + data[0] + "] " + url;
		var item = $("
[" + new Date() + "]page: " + window.page + "
")
		$(window.frames["result"].contentDocument).find("p[id='content']").append("
" + text + "
\n");

		var ibody = window.frames["result"].contentDocument.body;
		ibody.scrollTop = ibody.scrollHeight;f

		extractSampleCode();
	}

	$("").prependTo("body");
	$(window.frames["result"].contentDocument.body).append($("
"));

	$("").prependTo("body");

	$.getJSON("https://developer.apple.com/library/prerelease/ios/navigation/library.json",
	function(data)
	{
		var docs = data.documents, keys = data.columns;
		docs.sort(function(a, b)
		{
			return a[keys.sortOrder] > b[keys.sortOrder]? -1 : 1;
		});

		var reg = /Sample\s*Code/i;
		var type = data.topics[0].contents.filter(function(item)
		{
			return reg.test(item.name);
		})[0].key;

		var url;
		for(var i = 0; i < docs.length; i++)
		{
			url = docs[i][keys.url];
			if (docs[i][keys.type] == type)
			{
				jsonlist.push(docs[i]);
				url = url.replace(/^../, "https://developer.apple.com/library/prerelease/ios") + "?src=larryhou";
				pagelist.push(url);
			}
		}

		extractSampleCode();
	});
});<commit_msg>Update<commit_after>// ==UserScript==
// @name         SampleCodeExtractor
// @version      1.3.1
// @author       larryhou@github.com
// @namespace    https://github.com/larryhou
// @description  Extract url of sample code zip-file from developer.apple.com
// @include      https://developer.apple.com/library/*
// ==/UserScript==

function install(callback)
{
	if (location.href.indexOf("https://developer.apple.com/library") != 0 ) return;

	var script = document.createElement("script");
	script.type = "text/javascript";
	script.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js";

	var cb = document.createElement("script");
	cb.type = "text/javascript";
	cb.textContent = "jQuery.noConflict();(" + callback.toString() + ")(jQuery);";
	script.addEventListener('load', function()
	{
		document.head.appendChild(cb);
	});

	document.head.appendChild(script);
}

// https://developer.apple.com/library/ios/navigation/#section=Resource%20Types&topic=Sample%20Code

install(function($)
{
	const TIME_OUT = 5000;
	if (location.href.indexOf("samplecode") > 0)
	{
		if (location.href.indexOf("src=larryhou") < 0)return;

		$(document).ready(function()
		{
			const INTERVAL = 100;
			const MAX_RETRY_COUNT = Math.ceil(TIME_OUT / INTERVAL);

			var id, retryCount = 0;
			function doJob()
			{
				clearTimeout(id);

				var href = $("#Sample_link").attr("href");
				if (href)
				{
					parent.displaySampleCode(href)
				}
				else
				if (retryCount < MAX_RETRY_COUNT)
				{
					retryCount++;
					id = setTimeout(doJob, INTERVAL);
				}
				else
				{
					parent.logExtractError();
					parent.extractSampleCode();
				}
			}

			doJob();
		});

		return;
	}

	var pagelist = [];
	var jsonlist = [];

	var ziplist = [];
	var zipjson = [];

	var id;
	var index = 0;
	window.extractSampleCode = function()
	{
		clearTimeout(id);
		if (index < pagelist.length)
		{
			$("#kernel").attr("src", pagelist[index]);
			index++;

			var callee = arguments.callee;
			id = setTimeout(function()
			{
				console.log(jsonlist[index - 1]);
				callee();
			}, TIME_OUT + 500);
		}
		else
		{
			$("#kernel").remove();
			$("").insertAfter($("#result"));

			var doc = window.frames["summrize"].contentDocument;
			$(doc).ready(function()
 			{
				$(doc.body).css("font-family", "Consolas,Menlo");
				for (var i = 0; i < ziplist.length; i++)
				{
					$(doc.body).append($("
" + ziplist[i] + "
"));
				}

				var sum = {}

				var prefix, prev;
				for (var i = 0; i < zipjson.length; i++)
				{
					prefix = zipjson[i][3].slice(0, 4);
					if (prefix != prev)
					{
						sum[prefix] = [i + 1];
						if (sum[prev])
						{
							sum[prev].push(i);
						}

						prev = prefix;
					}
					else
					if (i == zipjson.length - 1)
					{
						sum[prefix].push(zipjson.length);
					}
				}

				function padding(value, length)
				{
					var rlt = String(value);

					var offset = length - rlt.length
					while (offset > 0)
					{
						rlt += "&nbsp";
						offset--;
					}

					return rlt;
				}

				var group = [];
				for (var key in sum)
				{
					group.push("group " + padding(sum[key][0], 4) + padding(sum[key][1], 4) + "${dir}/" + key);
					group[group.length - 1] = "
" + group[group.length - 1] + "
";
				}

				$(doc.body).append($(group.join(" ")));
 			});

			console.log("============<DONE!>============");
		}
	}

	window.logExtractError = function()
	{
		var url = pagelist[index - 1];
		console.log("ERR:" + url);
	}

	window.displaySampleCode = function(url)
	{
		url = "https://developer.apple.com" + url;
		ziplist.push(url);

		function getFormatedIndex()
		{
			var str = ziplist.length + "";
			while (str.length < 3) str = "0" + str;
			return str;
		}

		var data = jsonlist[index - 1];
		zipjson.push(data);

		link = "" + data[0] + "";

		var text = getFormatedIndex() + ".[" + data[3] + ":" + data[1] + "]" + link;
		var item = $("
[" + new Date() + "]page: " + window.page + "
")
		$(window.frames["result"].contentDocument).find("p[id='content']").append("
" + text + "
\n");

		var ibody = window.frames["result"].contentDocument.body;
		ibody.scrollTop = ibody.scrollHeight;f

		extractSampleCode();
	}

	$("").prependTo("body");
	$(window.frames["result"].contentDocument.body).append($("
"));

	$("").prependTo("body");

	$.getJSON("https://developer.apple.com/library/prerelease/ios/navigation/library.json",
	function(data)
	{
		var docs = data.documents, keys = data.columns;
		docs.sort(function(a, b)
		{
			return a[keys.sortOrder] > b[keys.sortOrder]? -1 : 1;
		});

		var reg = /Sample\s*Code/i;
		var type = data.topics[0].contents.filter(function(item)
		{
			return reg.test(item.name);
		})[0].key;

		var url;
		for(var i = 0; i < docs.length; i++)
		{
			url = docs[i][keys.url];
			if (docs[i][keys.type] == type)
			{
				jsonlist.push(docs[i]);
				url = url.replace(/^../, "https://developer.apple.com/library/prerelease/ios") + "?src=larryhou";
				pagelist.push(url);
			}
		}

		extractSampleCode();
	});
});<|endoftext|>


<commit_before><commit_msg>Remove console.log statements<commit_after><|endoftext|>


<commit_before>/*globals requirejs: true */
require({
    deps: [
        'bootstrap',
        'less'
    ],

    paths: {
        'text': '/components/requirejs-text/text',
        'backbone': '/components/backbone/backbone-min',
        'backbone-forms-core': '/components/backbone-forms/distribution/backbone-forms.min',
        'backbone-forms': '/components/backbone-forms/distribution/templates/bootstrap',
        'jquery': '/components/jquery/jquery',
        'underscore': '/components/lodash/lodash.min',
        'garlicjs': '/components/garlicjs/garlic',
        'bootstrap': '/components/bootstrap.css/js/bootstrap.min',
        'moment-core': '/components/moment/moment',
        'moment': '/components/moment/lang/fr',
        'less': '/components/less.js/dist/less-1.3.1.min',
        'i18n': '/components/requirejs-i18n/i18n',
        'key': '/components/keymaster/keymaster.min'
    },

    shim: {
        'bootstrap': {
            'deps': [ 'jquery' ]
        },
        'backbone': {
            'deps': [ 'underscore', 'jquery' ],
            'exports': 'Backbone'
        },
        'backbone-forms-core': {
            'deps': [ 'jquery', 'backbone' ]
        },
        'backbone-forms': {
            'deps': [ 'backbone-forms-core' ]
        },
        'garlic': {
            'deps': [ 'jquery' ]
        },
        'moment-core': {
            'deps': [ 'jquery' ]
        },
        'moment': {
            'deps': [ 'moment-core' ]
        },
        'key': {
            'exports': 'key'
        }
    },

    config: {
        i18n: {
            locale: localStorage.getItem('locale') || 'en-us'
        }
    }
});

require(
    [
        'router',
        'views/canvas',
        'jquery',
        'backbone',
        't',
        'moment',
        'ventilator'
    ],
    function (router, canvasView, $, Backbone, t, moment, ventilator) {
        "use strict";

        // expose t in templates
        $.t = t;

        // configure ajax error handling
        $.ajaxSetup({
            statusCode: {
                500: function () {
                    ventilator.trigger('canvas:message:error', t('error.internal_server_error'));
                    $('.main').removeClass('loading');
                }
            }
        });

        // set language thanks to the i18n locale value
        moment.lang(requirejs.s.contexts._.config.config.i18n.locale.substr(0, 2));

        canvasView.render();
        $('body').prepend(canvasView.el);

        Backbone.history.start();
    }
);
<commit_msg>Send 'Accept-Language' header for each AJAX request<commit_after>/*globals requirejs: true */
require({
    deps: [
        'bootstrap',
        'less'
    ],

    paths: {
        'text': '/components/requirejs-text/text',
        'backbone': '/components/backbone/backbone-min',
        'backbone-forms-core': '/components/backbone-forms/distribution/backbone-forms.min',
        'backbone-forms': '/components/backbone-forms/distribution/templates/bootstrap',
        'jquery': '/components/jquery/jquery',
        'underscore': '/components/lodash/lodash.min',
        'garlicjs': '/components/garlicjs/garlic',
        'bootstrap': '/components/bootstrap.css/js/bootstrap.min',
        'moment-core': '/components/moment/moment',
        'moment': '/components/moment/lang/fr',
        'less': '/components/less.js/dist/less-1.3.1.min',
        'i18n': '/components/requirejs-i18n/i18n',
        'key': '/components/keymaster/keymaster.min'
    },

    shim: {
        'bootstrap': {
            'deps': [ 'jquery' ]
        },
        'backbone': {
            'deps': [ 'underscore', 'jquery' ],
            'exports': 'Backbone'
        },
        'backbone-forms-core': {
            'deps': [ 'jquery', 'backbone' ]
        },
        'backbone-forms': {
            'deps': [ 'backbone-forms-core' ]
        },
        'garlic': {
            'deps': [ 'jquery' ]
        },
        'moment-core': {
            'deps': [ 'jquery' ]
        },
        'moment': {
            'deps': [ 'moment-core' ]
        },
        'key': {
            'exports': 'key'
        }
    },

    config: {
        i18n: {
            locale: localStorage.getItem('locale') || 'en-us'
        }
    }
});

require(
    [
        'router',
        'views/canvas',
        'jquery',
        'backbone',
        't',
        'moment',
        'ventilator'
    ],
    function (router, canvasView, $, Backbone, t, moment, ventilator) {
        "use strict";

        // expose t in templates
        $.t = t;

        // configure ajax error handling
        $.ajaxSetup({
            statusCode: {
                500: function () {
                    ventilator.trigger('canvas:message:error', t('error.internal_server_error'));
                    $('.main').removeClass('loading');
                }
            },
            headers: {
                'Accept-Language': requirejs.s.contexts._.config.config.i18n.locale.substr(0, 2)
            }
        });

        // set language thanks to the i18n locale value
        moment.lang(requirejs.s.contexts._.config.config.i18n.locale.substr(0, 2));

        canvasView.render();
        $('body').prepend(canvasView.el);

        Backbone.history.start();
    }
);
<|endoftext|>


<commit_before>'use strict';

var sharedSteps = module.exports = function() {
  this.World = require('../support/world').World;
  var should = this.should;

  this.When(/^I have satisfied the required fields$/, function(next) {
    var my = this;

    // arbitrarily click the first background, first text color and define point position
    my.client
      .click('#acf-wtm_background_color .color-swatcher a:first-child')
      .click('#acf-wtm_font_color .color-swatcher a:first-child')
      .setValue('#acf-wtm_coord_percents .coordpicker-container input', "{'x_percent':'0.3','y_percent':'0.3'}", function(err) {
        // [Error: [setValue("#acf-wtm_coord_percents .coordpicker-container input","{'x_percent':'0.3','y_percent':'0.3'}")] <= [elementIdClear("5")] <= An unknown server-side error occurred while processing the command.]
        my.expect(err).to.be.null;
      })
      .call(next);
  });

  this.Then(/"([^"]*)" should contain "([^"]*)"$/, function (selector, value, next) {
    var my = this;

    // contents of selector should equal value
    my.client.getText(selector, function(err, text) {
        my.expect(err).to.be.null;
        text.should.equal(value);
    }).call(next);
  });

  this.Then(/value of "([^"]*)" should be "([^"]*)"$/, function (selector, value, next) {
    var my = this;

    // contents of selector should equal value
    my.client.getValue(selector, function(err, myValue) {
        my.expect(err).to.be.null;
        myValue.should.equal(value);
    }).call(next);
  });

};
<commit_msg>Cleanup for non-hidden position input<commit_after>'use strict';

var sharedSteps = module.exports = function() {
  this.World = require('../support/world').World;
  var should = this.should;

  this.When(/^I have satisfied the required fields$/, function(next) {
    var my = this;

    // arbitrarily click the first background, first text color and define point position
    my.client
      .click('#acf-wtm_background_color .color-swatcher a:first-child')
      .click('#acf-wtm_font_color .color-swatcher a:first-child')
      .setValue('#acf-wtm_coord_percents input', '{"x_percent":"0.323","y_percent":"0.102"}', function(err) {
        my.expect(err).to.be.null;
      })
      .call(next);
  });

  this.Then(/"([^"]*)" should contain "([^"]*)"$/, function (selector, value, next) {
    var my = this;

    my.client.getText(selector, function(err, text) {
      my.expect(err).to.be.null;
      text.should.equal(value);
    }).call(next);
  });

  this.Then(/value of "([^"]*)" should be "([^"]*)"$/, function (selector, value, next) {
    var my = this;

    // contents of selector should equal value
    my.client.getValue(selector, function(err, myValue) {
      my.expect(err).to.be.null;
      myValue.should.equal(value);
    }).call(next);
  });

};
<|endoftext|>


<commit_before>'use strict';

var Db       = require('dbjs')
  , relation = module.exports = require('dbjs/lib/_relation');

require('./base');

relation.set('toDOMInputBox', function (document/*, options*/) {
	var box, options = Object(arguments[1]);
	box = this.ns.toDOMInputBox(document, options);
	box.set(this.objectValue);
	box.setAttribute('name', this._id_);
	if (this.required && ((options.type !== 'checkbox') &&
			((options.required == null) || options.required))) {
		box.setAttribute('required', true);
	}
	this.on('change', function () { box.set(this.objectValue); });
	return box;
});

relation.set('toDOMInput', Db.Base.prototype.toDOMInput);
relation.get('fieldHint').ns = Db.String;
relation.set('DOMId', function () {
	return this._id_.replace(/:/g, '-');
});
<commit_msg>Disable option<commit_after>'use strict';

var Db       = require('dbjs')
  , relation = module.exports = require('dbjs/lib/_relation');

require('./base');

relation.set('toDOMInputBox', function (document/*, options*/) {
	var box, options = Object(arguments[1]);
	box = this.ns.toDOMInputBox(document, options);
	box.set(this.objectValue);
	box.setAttribute('name', this._id_);
	if (this.required && ((options.type !== 'checkbox') &&
			((options.required == null) || options.required))) {
		box.setAttribute('required', true);
	}
	if (options.disabled) box.setAttribute('disabled', true);
	this.on('change', function () { box.set(this.objectValue); });
	return box;
});

relation.set('toDOMInput', Db.Base.prototype.toDOMInput);
relation.get('fieldHint').ns = Db.String;
relation.set('DOMId', function () {
	return this._id_.replace(/:/g, '-');
});
<|endoftext|>


<commit_before>var library = (function() {

	var public = {},
		private = {};

	public.module = {};
	public.module.fs = require('fs');

	public.format = function( template, options ) {
		var matches = template.match(/({{)(.*)(}})/g),
			tag, tagData, replaceAll;

		if( matches ) {
			for( var match in matches ) {

				tag = matches[ match ].replace('{{','').replace('}}','');
				console.log( 'Tag: ' + tag );
				tagData = tag.split(':');
				replaceAll = new RegExp( '{{' + tag + '}}', "g");

				if( options != null && options[tag] ) {
					template = template.replace( replaceAll, options[tag] );
				} else {
					switch( tagData[0] ) {
						case 'script':
							var scriptTag = '';
							template = template.replace( replaceAll, scriptTag );
							break;
						case 'style':
							var styleTag = '<link href="' + options.site_url + options.asset_dir + '/styles/' + tagData[1] + '.css" rel="stylesheet" type="text/css">';
							template = template.replace( replaceAll, styleTag );
							break;
						case 'template':
							var templateLoad = 'nlapiRequestURL("' + options.site_url + options.asset_dir + '/templates/' + tagData[1] + '.html").getBody()',
							template = template.replace( replaceAll, templateLoad );
							break;
						case 'restlet':
							var environment = ( options.environment != 'production' ) ? 'sandbox.' : '',
								pieces = ( tagData[1] ) ? tagData[1].split('/') : false,
								url = '/app/site/hosting/restlet.nl?script=customscript_master_restlet&deploy=1';

							if( pieces && pieces[0] ) {
								url += '&module=' + pieces[0];
							}
							if( pieces && piecess[1] ) {
								url += '&restlet=' + pieces[1];
							}
							template = template.replace( replaceAll, url );
							break;
						case 'suitelet':
							var environment = ( options.environment != 'production' ) ? 'sandbox.' : '',
								pieces = ( tagData[1] ) ? tagData[1].split('/') : false,
								url = '/app/site/hosting/scriptlet.nl?script=customscript_master_suitelet&deploy=1';

							if( pieces && pieces[1] ) {
								url += '&module=' + pieces[0];
								url += '&suitelet=' + pieces[1];
							} else if( pieces && pieces[0] ) {
								url += '&suitelet=' + pieces[0];
							}
							template = template.replace( replaceAll, url );
							break;
					}
				}

			}
		}

		return template;
	};

	public.handleError = function( error ) {

		var errorTemplate = public.module.fs.readFileSync( './server/error.html', "utf8" ),
			errorOptions = {};

		errorOptions.code = error.name;
		errorOptions.details = error.message;
		errorOptions.stackRows = '';
		var stack = error.stack.split('\n');

		for( var stackItem in stack ) {

			var objectStart = stack[stackItem].indexOf('at ') + 3,
				objectEnd = stack[stackItem].indexOf(' ('),
				object = stack[stackItem].substring( objectStart, objectEnd ),
				fileStart = objectEnd + 2,
				fileEnd = stack[stackItem].indexOf(':', fileStart ),
				file = stack[stackItem].substring( fileStart, fileEnd ),
				lineNumStart = fileEnd + 1,
				lineNumEnd = stack[stackItem].indexOf(':', lineNumStart ),
				lineNum = stack[stackItem].substring( lineNumStart, lineNumEnd );

			if( stackItem == 1 ) {
				errorOptions.lineNum = lineNum;
				errorOptions.file = file;
			} else if( stackItem > 1 ) {
				errorOptions.stackRows += "
" + object + "	" + file + "	" + lineNum + "
";
			}
		}

		errorTemplate = public.format( errorTemplate, errorOptions );
		return errorTemplate;

	};

	return public;
})();

module.exports = library;<commit_msg>Fixed another regex issue<commit_after>var library = (function() {

	var public = {},
		private = {};

	public.module = {};
	public.module.fs = require('fs');

	public.format = function( template, options ) {
		var matches = template.match(/({{)([a-zA-Z0-9_]*)(}})/g),
			tag, tagData, replaceAll;

		if( matches ) {
			for( var match in matches ) {

				tag = matches[ match ].replace('{{','').replace('}}','');
				console.log( 'Tag: ' + tag );
				tagData = tag.split(':');
				replaceAll = new RegExp( '{{' + tag + '}}', "g");

				if( options != null && options[tag] ) {
					template = template.replace( replaceAll, options[tag] );
				} else {
					switch( tagData[0] ) {
						case 'script':
							var scriptTag = '';
							template = template.replace( replaceAll, scriptTag );
							break;
						case 'style':
							var styleTag = '<link href="' + options.site_url + options.asset_dir + '/styles/' + tagData[1] + '.css" rel="stylesheet" type="text/css">';
							template = template.replace( replaceAll, styleTag );
							break;
						case 'template':
							var templateLoad = 'nlapiRequestURL("' + options.site_url + options.asset_dir + '/templates/' + tagData[1] + '.html").getBody()',
							template = template.replace( replaceAll, templateLoad );
							break;
						case 'restlet':
							var environment = ( options.environment != 'production' ) ? 'sandbox.' : '',
								pieces = ( tagData[1] ) ? tagData[1].split('/') : false,
								url = '/app/site/hosting/restlet.nl?script=customscript_master_restlet&deploy=1';

							if( pieces && pieces[0] ) {
								url += '&module=' + pieces[0];
							}
							if( pieces && piecess[1] ) {
								url += '&restlet=' + pieces[1];
							}
							template = template.replace( replaceAll, url );
							break;
						case 'suitelet':
							var environment = ( options.environment != 'production' ) ? 'sandbox.' : '',
								pieces = ( tagData[1] ) ? tagData[1].split('/') : false,
								url = '/app/site/hosting/scriptlet.nl?script=customscript_master_suitelet&deploy=1';

							if( pieces && pieces[1] ) {
								url += '&module=' + pieces[0];
								url += '&suitelet=' + pieces[1];
							} else if( pieces && pieces[0] ) {
								url += '&suitelet=' + pieces[0];
							}
							template = template.replace( replaceAll, url );
							break;
					}
				}

			}
		}

		return template;
	};

	public.handleError = function( error ) {

		var errorTemplate = public.module.fs.readFileSync( './server/error.html', "utf8" ),
			errorOptions = {};

		errorOptions.code = error.name;
		errorOptions.details = error.message;
		errorOptions.stackRows = '';
		var stack = error.stack.split('\n');

		for( var stackItem in stack ) {

			var objectStart = stack[stackItem].indexOf('at ') + 3,
				objectEnd = stack[stackItem].indexOf(' ('),
				object = stack[stackItem].substring( objectStart, objectEnd ),
				fileStart = objectEnd + 2,
				fileEnd = stack[stackItem].indexOf(':', fileStart ),
				file = stack[stackItem].substring( fileStart, fileEnd ),
				lineNumStart = fileEnd + 1,
				lineNumEnd = stack[stackItem].indexOf(':', lineNumStart ),
				lineNum = stack[stackItem].substring( lineNumStart, lineNumEnd );

			if( stackItem == 1 ) {
				errorOptions.lineNum = lineNum;
				errorOptions.file = file;
			} else if( stackItem > 1 ) {
				errorOptions.stackRows += "
" + object + "	" + file + "	" + lineNum + "
";
			}
		}

		errorTemplate = public.format( errorTemplate, errorOptions );
		return errorTemplate;

	};

	return public;
})();

module.exports = library;<|endoftext|>


<commit_before>import models from '../models';

const favorite = models.Favorite;

/**
 * @exports addToFavorite
 * @param  {obj} req request object
 * @param  {obj} res result object
 * @return {obj}  newUser object
 */
export const addToFavorite = (req, res) => {
  const userId = req.userId;
  const recipeId = req.params.recipeId;
  const newFavorite = favorite
    .create({
      userId,
      recipeId
    })
    .then((createdFavorite) => {
      res.status(201).send(createdFavorite);
    })
    .catch(() => res.status(401).send({
      error: 'Error Adding Recipe to Favorites' }));

  return newFavorite;
};

/**
 * @exports removeFromFavorites
 * @param  {obj} req request object
 * @param  {obj} res result object
 * @return {obj}  newUser object
 */
export const removeFromFavorites = (req, res) => {
  const userId = req.params.userId;
  const recipeId = req.params.recipeId;
  const newFavorite = favorite
    .destroy({
      where: {
        $and: [
          { userId },
          { recipeId }
        ]
      },
    })
    .then(() => {
      res.status(204).end();
    })
    .catch(() => res.status(401).send({
      error: 'Error Removing Recipe from Favorites' }));

  return newFavorite;
};

/**
 * @exports getFavRecipes
 * @param  {obj} req request object
 * @param  {obj} res result object
 * @return {obj}  newUser object
 */
export const getFavRecipes = (req, res) => {
  const userId = req.params.userId;
  const favRecipes = favorite
    .findAll({
      where: { userId },
      include: [
        { model: models.Recipe },
        { model: models.User, attributes: ['name', 'updatedAt'] }
      ]
    })
    .then((foundRecipes) => {
      if (!foundRecipes) {
        return res.status(201).send({
          message: 'No Stored Favorite Recipes found',
        });
      }

      return res.status(201).send(foundRecipes);
    })
    .catch(() => res.status(401).send('Unable to fetch favorite recipes'));

  return favRecipes;
};
<commit_msg>Add success status to favorites controller<commit_after>import models from '../models';

const favorite = models.Favorite;

/**
 * @exports addToFavorite
 * @param  {obj} req request object
 * @param  {obj} res result object
 * @return {obj}  newUser object
 */
export const addToFavorite = (req, res) => {
  const userId = req.userId;
  const recipeId = req.params.recipeId;
  const newFavorite = favorite
    .create({
      userId,
      recipeId
    })
    .then((createdFavorite) => {
      createdFavorite.success = true;
      res.status(201).send(createdFavorite);
    })
    .catch(() => res.status(401).send({
      success: false,
      message: 'Error Adding Recipe to Favorites' }));

  return newFavorite;
};

/**
 * @exports removeFromFavorites
 * @param  {obj} req request object
 * @param  {obj} res result object
 * @return {obj}  newUser object
 */
export const removeFromFavorites = (req, res) => {
  const userId = req.params.userId;
  const recipeId = req.params.recipeId;
  const newFavorite = favorite
    .destroy({
      where: {
        $and: [
          { userId },
          { recipeId }
        ]
      },
    })
    .then(() => {
      res.status(204).end();
    })
    .catch(() => res.status(401).send({
      success: false,
      message: 'Error Removing Recipe from Favorites' }));

  return newFavorite;
};

/**
 * @exports getFavRecipes
 * @param  {obj} req request object
 * @param  {obj} res result object
 * @return {obj}  newUser object
 */
export const getFavRecipes = (req, res) => {
  const userId = req.params.userId;
  const favRecipes = favorite
    .findAll({
      where: { userId },
      include: [
        { model: models.Recipe },
        { model: models.User, attributes: ['name', 'updatedAt'] }
      ]
    })
    .then((foundRecipes) => {
      if (!foundRecipes) {
        return res.status(201).send({
          success: true,
          message: 'No Stored Favorite Recipes found',
        });
      }

      foundRecipes.success = true;
      return res.status(201).send(foundRecipes);
    })
    .catch(() => res.status(401).send({
      success: false,
      message: 'Unable to fetch favorite recipes' }));

  return favRecipes;
};
<|endoftext|>


<commit_before>export default {
  title: `On-site at Connect.tech`,
  time: '12:30',
  timezone: 'ET',
  guests: [
    {
      name: 'Connect.tech',
      twitter: 'connect_js',
      squareImage: true,
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
  ],
  description: `
    We'll be live and on site at Connect.tech in Atlanta Georgia. See you there!
  `,
  youTubeId: 'AdK5f3bCPXI',
  podbeanId: '',
  shortUrl: 'http://jsair.io/connect',
  host: {
    links: [
    ],
    tips: [
    ],
    picks: [
    ],
  },
  panelists: [
    {
      twitter: 'dan_abramov',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'drboolean',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'getify',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'kwuchu',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'linclark',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'mzabriskie',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'pamasaur',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'tylermcginnis33',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
  ],
}
<commit_msg>updage YouTube URL<commit_after>export default {
  title: `On-site at Connect.tech`,
  time: '12:30',
  timezone: 'ET',
  guests: [
    {
      name: 'Connect.tech',
      twitter: 'connect_js',
      squareImage: true,
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
  ],
  description: `
    We'll be live and on site at Connect.tech in Atlanta Georgia. See you there!
  `,
  youTubeId: 's9kNekW8B-8',
  podbeanId: '',
  shortUrl: 'http://jsair.io/connect',
  host: {
    links: [
    ],
    tips: [
    ],
    picks: [
    ],
  },
  panelists: [
    {
      twitter: 'dan_abramov',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'drboolean',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'getify',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'kwuchu',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'linclark',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'mzabriskie',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'pamasaur',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
    {
      twitter: 'tylermcginnis33',
      links: [
      ],
      tips: [
      ],
      picks: [
      ],
    },
  ],
}
<|endoftext|>


<commit_before>var url = '';

Ext.Loader.setConfig({
    enabled: true,
    paths: {
        'Ext': '../bundles/netresearchtimetracker/js/ext-js/src',
        'yourAppName': 'netresearch'
    }
});

// Link NR bundle to Namespace
Ext.Loader.setPath('Netresearch', '../bundles/netresearchtimetracker/js/netresearch');
Ext.Loader.setPath('Ext.ux.window', '../bundles/netresearchtimetracker/js');

/* Load necessary requirements */
Ext.require([
    'Ext.grid.*',
    'Ext.data.*',
    'Ext.util.*',
    'Ext.state.*',
    'Ext.container.Viewport',
    'Ext.form.*',
    'Ext.ux.window.Notification',
    'Netresearch.widget.Tracking',
    'Netresearch.widget.Interpretation',
    'Netresearch.widget.Extras',
    'Netresearch.widget.Settings',
    'Netresearch.widget.Controlling',
    'Netresearch.widget.Admin',
    'Netresearch.widget.Help'
]);

/* Define how many clicks are needed to active inline editing of tracking grid entries */
var cellEditing = Ext.create('Ext.grid.plugin.CellEditing', {
    clicksToEdit: 1
});

var strings = {
    'Today': 'Today',
    'Week' : 'Week',
    'Month': 'Month',
    'Monthly overview': 'Monthly overview',
    'Logout': 'Logout'
};

if ((undefined != settingsData) && (settingsData.locale == 'de')) {
    strings = {
        'Today': 'Heute',
        'Week' : 'Woche',
        'Month': 'Monat',
        'Monthly overview': 'Monatsauswertung',
        'Logout': 'Logout'
    };
}

var ttt_container = undefined;
var ttt_tabpanel = undefined;
var ttt_items = [];

function switchTab(number) {
    number = parseInt(number);
    if ((0 > number) || (number > ttt_items.length)) {
        return;
    }

    var itemId = ttt_items[(number-1)].getItemId();
    if (! ttt_tabpanel.isActiveTab(itemId))
        ttt_tabpanel.setActiveTab(ttt_tabpanel.child('#' + itemId));
    if (number == 1)
        ttt_items[0].getFocus();
}

function addTab(component) {
    var index = ttt_items.length + 1;
    component.title = index + ': ' + component.title;
    ttt_items.push(component);
}

Ext.onDocumentReady(function() {
    // Setup state manager
    Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));

    var trackingWidget = Ext.create('Netresearch.widget.Tracking',
        { itemId: 'tracking', plugins: [cellEditing] }
    );

    var interpretationWidget = Ext.create('Netresearch.widget.Interpretation', { itemId: 'interpretation' });
    var extrasWidget = Ext.create('Netresearch.widget.Extras', { itemId: 'extras'});
    var settingsWidget = Ext.create('Netresearch.widget.Settings', { itemId: 'settings' });

    addTab(trackingWidget);
    addTab(interpretationWidget);
    addTab(extrasWidget);
    addTab(settingsWidget);

    /* Show admin tab, if user is admin */
    if ((undefined != settingsData) && (settingsData['type'] == 'PL')) {
        var adminWidget = Ext.create('Netresearch.widget.Admin', { itemId: 'admin' });
        addTab(adminWidget);
    }

    if ((undefined != settingsData) && (settingsData['type'] != 'DEV')) {
        var controllingWidget = Ext.create('Netresearch.widget.Controlling', { itemId: 'controlling' });
        addTab(controllingWidget);
    }

    var helpWidget = Ext.create('Netresearch.widget.Help', { itemId: 'help' });
    addTab(helpWidget);

    Ext.tip.QuickTipManager.init();

    ttt_tabpanel = Ext.create('Ext.tab.Panel', {
        region: 'center',
        activeTab: 0,
        items: ttt_items,
        listeners: {
            tabchange: function(tabPanel, newCard, oldCard, eOpts) {
                newCard.focus();
                if (ttt_tabpanel.isActiveTab('tracking')) {
                    ttt_items[0].getFocus();
                }
            }
        },
        isActiveTab: function(name) {
            return this.getActiveTab() == ttt_tabpanel.child('#' + name);
        }
    });

    /* Render whole layout into grid div */
    ttt_container = Ext.create('Ext.container.Viewport', {
        layout: 'border',
        renderTo: Ext.get('grid'),
        items: [{
            region: 'north',
            height: 100,
            id: 'header',
            html: (globalConfig.header_url != ''? '' : '')
                    + '

'
                    + ''
                    + '
' + strings['Today'] + ': 0:00 / ' + strings['Week'] + ': 0:00 / ' + strings['Month'] + ': 0:00'
                    +   '
' + strings['Monthly overview'] + ''
                    + '
'
                    + '
' + strings['Logout'] + '
'
        },
            ttt_tabpanel
        ]
    });

    /* Key bindings */
    var keyMap = new Ext.util.KeyMap(Ext.get(document), [
        {
            key: Ext.EventObject.A,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.addInlineEntry();
            },
            defaultEventAction: 'stopEvent'
        }, {
            key: Ext.EventObject.C,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.continueSelectedEntry();
            },
            defaultEventAction: 'stopEvent'
        }, {
            key: Ext.EventObject.D,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.deleteSelectedEntry();
            },
            defaultEventAction: 'stopEvent'
        }, {
            key: Ext.EventObject.E,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.editSelectedEntry();
            },
            defaultEventAction: 'stopEvent'
        }, {
            key: Ext.EventObject.I,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.showInfoOnSelectedEntry();
            },
            defaultEventAction: 'stopEvent'
        }, {
            key: Ext.EventObject.P,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.prolongLastEntry();
            },
            defaultEventAction: 'stopEvent'
        }, {
            key: Ext.EventObject.R,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.refresh();
                if (ttt_tabpanel.isActiveTab('interpretation'))
                    interpretationWidget.refresh();
            },
            defaultEventAction: 'stopEvent'
        }, {
            key: Ext.EventObject.X,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.exportEntries();
            },
            defaultEventAction: 'stopEvent'
        }, {
            // Alt + Number is used for Tab switching
            key: [ Ext.EventObject.ONE, Ext.EventObject.TWO, Ext.EventObject.THREE, Ext.EventObject.FOUR, Ext.EventObject.FIVE, Ext.EventObject.SIX, Ext.EventObject.SEVEN ],
            alt: true,
            handler: function(key, e) {
                switchTab(parseInt(key) - 48);
                e.stopEvent();
            },
            defaultEventAction: 'stopEvent'
        }, {
            shift: true,
            key: 191,
            handler: function(key, e) {
                if (ttt_tabpanel.isActiveTab('tracking') && trackingWidget.isEditing()) {
                    return true;
                }

                if (ttt_tabpanel.isActiveTab('tracking')) {
                    trackingWidget.displayShortcuts();
                    e.stopEvent();
                }

                if (ttt_tabpanel.isActiveTab('interpretation')) {
                    interpretationWidget.displayShortcuts();
                    e.stopEvent();
                }

                return true;
            },
            defaultEventAction: 'stopEvent'
        }
    ]);

    countTime();
    trackingWidget.getFocus();
});

/**
 * Formats a duration from minutes into hours:minutes
 */
function formatDuration(duration, inDays)
{
    var days = Math.floor(duration / (60*8) * 100) / 100;
    var hours = Math.floor(duration / 60);
    var minutes = duration % 60;
    if (minutes < 10) {
        minutes = '0' + minutes;
    }

    var text = hours + ':' + minutes;
    if ((inDays)&&(days > 1.0)) {
        text += ' (' + days + ' PT)';
    }

    return text;
}

/*
 * Counts and displays worktime for today, this week and this month in the upper right corner
 */
function countTime() {
    Ext.Ajax.request({
        url: url + 'getTimeSummary',
        scope: this,
        success: function(response) {
            data = Ext.decode(response.responseText);
            Ext.get('worktime-day').update(strings['Today'] + ': ' + formatDuration(data.today.duration, false));
            Ext.get('worktime-week').update(strings['Week'] + ': ' + formatDuration(data.week.duration, false));
            Ext.get('worktime-month').update(strings['Month'] + ': ' + formatDuration(data.month.duration, true));
        }
    });
}

/*
 * Handles redirects
 * - Status code 403: Javascript Redirect
 * - everything else: Error message
 */
function handleRedirect(response, title, message) {
    if (response.status === 403) {
        showNotification(title, message, false);
        setTimeout("window.location.href = '" + response.responseText + "'", 2000);
    } else {
        showNotification('Fehler', response.responseText);
    }
}

var notification = undefined;

/**
 * Displays a toaster like message
 */
function showNotification(title, message, success)
{
    var cls = 'ux-notification-light';
    if (false == success) {
        cls = 'ux-notification-light-error';
    }

    if ((undefined != notification)
        && (null != notification))
    {
        notification.hide();
        notification.removeCls('ux-notification-light');
        notification.removeCls('ux-notification-light-error');
        notification.addCls(cls);
        notification.setTitle(title);
        notification.autoHideDelay = 5000;
        notification.autoHide = true;
        notification.spacing = 20;
        notification.width = 400;
        notification.autoHeight = true;
        notification.update(message);
        notification.doLayout();
        notification.show();
        return;
    }

    notification = Ext.create('widget.uxNotification', {
        title: title,
        position: 't',
        manager: 'instructions',
        cls: cls,
        plain: true,
        closable: false,
        autoHideDelay: 5000,
        autoHide: true,
        spacing: 20,
        width: 400,
        autoHeight: true,
        html: message,
        slideBackDuration: 700,
        slideInAnimation: 'bounceOut',
        slideBackAnimation: 'easeIn'
    });

    notification.show();
}

/**
 * Returns the prefix of a given ticket
 */
function extractTicketPrefix(ticket)
{
    var regexp = /([A-Za-z]+[A-Za-z0-9]*)-[0-9]+/;
    var ticket = ticket.toUpperCase() + '';
    var result = ticket.match(regexp);
    if (!result) {
        return false;
    }

    return result[1];
}

function findProjects(customer, ticket)
{
    // 1. Find all projects by this customer, if defined
    if ((null == customer) || (undefined == customer) || (1 > parseInt(customer)))
        customer = 'all';
    else
        customer = parseInt(customer);
    var projects = projectsData[customer];

    // 2. Filter projects by prefix, if defined
    if ((null == ticket) || (undefined == ticket)) {
        return projects;
    }

    // Support 2nd-trial mode: find projects without defined prefix
    var prefix = "";
    var regexp = /([ ,]+)?([A-Za-z]+)([ ,]+)?/;

    if (ticket == "") {
        prefix = "";
    } else {
        prefix = extractTicketPrefix(ticket);
        if (prefix === false)
            return projects;
    }

    var validProjects = [];
    var value;
    for (var key in projects) {
        value = projects[key];

        if (prefix == "") {
            if ((undefined == value['jiraId']) || (null == value['jiraId']) || ("" == value['jiraId'])) {
                validProjects.push(value);
            }
            continue;
        }

        if ((undefined == value['jiraId']) || (null == value['jiraId']))
            continue;

        if (value['jiraId'] == prefix) {
            validProjects.push(value);
            continue;
        }

        var result = value['jiraId'].match(regexp);
        if (!result) {
            continue;
        }

        for (var i=1; i < result.length; i++) {
            if (result[i] == prefix) {
                // console.log("Found project " + value['id'] + ", " + value['name'] + " of customer " + value['customer'] + " by prefix " + prefix);
                validProjects.push(value);

            }
        }
    }

    // If we searched with a prefix and didn't find something,
    // deliver all projects with an empty prefix defined
    if (("" != prefix) && (validProjects.length < 1))
        return findProjects(customer, "");

    return validProjects;
}
<commit_msg>check JavaScript variable before using - fixes JavaScript errors/exceptions<commit_after>var url = '';

Ext.Loader.setConfig({
    enabled: true,
    paths: {
        'Ext': '../bundles/netresearchtimetracker/js/ext-js/src',
        'yourAppName': 'netresearch'
    }
});

// Link NR bundle to Namespace
Ext.Loader.setPath('Netresearch', '../bundles/netresearchtimetracker/js/netresearch');
Ext.Loader.setPath('Ext.ux.window', '../bundles/netresearchtimetracker/js');

/* Load necessary requirements */
Ext.require([
    'Ext.grid.*',
    'Ext.data.*',
    'Ext.util.*',
    'Ext.state.*',
    'Ext.container.Viewport',
    'Ext.form.*',
    'Ext.ux.window.Notification',
    'Netresearch.widget.Tracking',
    'Netresearch.widget.Interpretation',
    'Netresearch.widget.Extras',
    'Netresearch.widget.Settings',
    'Netresearch.widget.Controlling',
    'Netresearch.widget.Admin',
    'Netresearch.widget.Help'
]);

/* Define how many clicks are needed to active inline editing of tracking grid entries */
var cellEditing = Ext.create('Ext.grid.plugin.CellEditing', {
    clicksToEdit: 1
});

var strings = {
    'Today': 'Today',
    'Week' : 'Week',
    'Month': 'Month',
    'Monthly overview': 'Monthly overview',
    'Logout': 'Logout'
};

if ((undefined != settingsData) && (settingsData.locale == 'de')) {
    strings = {
        'Today': 'Heute',
        'Week' : 'Woche',
        'Month': 'Monat',
        'Monthly overview': 'Monatsauswertung',
        'Logout': 'Logout'
    };
}

var ttt_container = undefined;
var ttt_tabpanel = undefined;
var ttt_items = [];

function switchTab(number) {
    number = parseInt(number);
    if ((0 > number) || (number > ttt_items.length)) {
        return;
    }

    var itemId = ttt_items[(number-1)].getItemId();
    if (! ttt_tabpanel.isActiveTab(itemId))
        ttt_tabpanel.setActiveTab(ttt_tabpanel.child('#' + itemId));
    if (number == 1)
        ttt_items[0].getFocus();
}

function addTab(component) {
    var index = ttt_items.length + 1;
    component.title = index + ': ' + component.title;
    ttt_items.push(component);
}

Ext.onDocumentReady(function() {
    // Setup state manager
    Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));

    var trackingWidget = Ext.create('Netresearch.widget.Tracking',
        { itemId: 'tracking', plugins: [cellEditing] }
    );

    var interpretationWidget = Ext.create('Netresearch.widget.Interpretation', { itemId: 'interpretation' });
    var extrasWidget = Ext.create('Netresearch.widget.Extras', { itemId: 'extras'});
    var settingsWidget = Ext.create('Netresearch.widget.Settings', { itemId: 'settings' });

    addTab(trackingWidget);
    addTab(interpretationWidget);
    addTab(extrasWidget);
    addTab(settingsWidget);

    /* Show admin tab, if user is admin */
    if ((undefined != settingsData) && (settingsData['type'] == 'PL')) {
        var adminWidget = Ext.create('Netresearch.widget.Admin', { itemId: 'admin' });
        addTab(adminWidget);
    }

    if ((undefined != settingsData) && (settingsData['type'] != 'DEV')) {
        var controllingWidget = Ext.create('Netresearch.widget.Controlling', { itemId: 'controlling' });
        addTab(controllingWidget);
    }

    var helpWidget = Ext.create('Netresearch.widget.Help', { itemId: 'help' });
    addTab(helpWidget);

    Ext.tip.QuickTipManager.init();

    ttt_tabpanel = Ext.create('Ext.tab.Panel', {
        region: 'center',
        activeTab: 0,
        items: ttt_items,
        listeners: {
            tabchange: function(tabPanel, newCard, oldCard, eOpts) {
                newCard.focus();
                if (ttt_tabpanel.isActiveTab('tracking')) {
                    ttt_items[0].getFocus();
                }
            }
        },
        isActiveTab: function(name) {
            return this.getActiveTab() == ttt_tabpanel.child('#' + name);
        }
    });

    /* Render whole layout into grid div */
    ttt_container = Ext.create('Ext.container.Viewport', {
        layout: 'border',
        renderTo: Ext.get('grid'),
        items: [{
            region: 'north',
            height: 100,
            id: 'header',
            html: (globalConfig.header_url != '' ? '' : '')
                    + '

'
                    + (typeof statusUrlHtml != 'undefined'
                        ? '' : '')
                    + '
'
                    + '' + strings['Today'] + ': 0:00 / ' + strings['Week'] + ': 0:00 / ' + strings['Month'] + ': 0:00'
                    + (typeof globalConfig.monthly_overview_url != 'undefined'
                        ? '
' + strings['Monthly overview'] + '' : '')
                    + '
'
                    + (typeof logoutUrlHtml != 'undefined'
                        ? '
' + strings['Logout'] + '
' : '')
        },
            ttt_tabpanel
        ]
    });

    /* Key bindings */
    var keyMap = new Ext.util.KeyMap(Ext.get(document), [
        {
            key: Ext.EventObject.A,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.addInlineEntry();
            },
            defaultEventAction: 'stopEvent'
        }, {
            key: Ext.EventObject.C,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.continueSelectedEntry();
            },
            defaultEventAction: 'stopEvent'
        }, {
            key: Ext.EventObject.D,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.deleteSelectedEntry();
            },
            defaultEventAction: 'stopEvent'
        }, {
            key: Ext.EventObject.E,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.editSelectedEntry();
            },
            defaultEventAction: 'stopEvent'
        }, {
            key: Ext.EventObject.I,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.showInfoOnSelectedEntry();
            },
            defaultEventAction: 'stopEvent'
        }, {
            key: Ext.EventObject.P,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.prolongLastEntry();
            },
            defaultEventAction: 'stopEvent'
        }, {
            key: Ext.EventObject.R,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.refresh();
                if (ttt_tabpanel.isActiveTab('interpretation'))
                    interpretationWidget.refresh();
            },
            defaultEventAction: 'stopEvent'
        }, {
            key: Ext.EventObject.X,
            alt: true,
            handler: function() {
                if (ttt_tabpanel.isActiveTab('tracking'))
                    trackingWidget.exportEntries();
            },
            defaultEventAction: 'stopEvent'
        }, {
            // Alt + Number is used for Tab switching
            key: [ Ext.EventObject.ONE, Ext.EventObject.TWO, Ext.EventObject.THREE, Ext.EventObject.FOUR, Ext.EventObject.FIVE, Ext.EventObject.SIX, Ext.EventObject.SEVEN ],
            alt: true,
            handler: function(key, e) {
                switchTab(parseInt(key) - 48);
                e.stopEvent();
            },
            defaultEventAction: 'stopEvent'
        }, {
            shift: true,
            key: 191,
            handler: function(key, e) {
                if (ttt_tabpanel.isActiveTab('tracking') && trackingWidget.isEditing()) {
                    return true;
                }

                if (ttt_tabpanel.isActiveTab('tracking')) {
                    trackingWidget.displayShortcuts();
                    e.stopEvent();
                }

                if (ttt_tabpanel.isActiveTab('interpretation')) {
                    interpretationWidget.displayShortcuts();
                    e.stopEvent();
                }

                return true;
            },
            defaultEventAction: 'stopEvent'
        }
    ]);

    countTime();
    trackingWidget.getFocus();
});

/**
 * Formats a duration from minutes into hours:minutes
 */
function formatDuration(duration, inDays)
{
    var days = Math.floor(duration / (60*8) * 100) / 100;
    var hours = Math.floor(duration / 60);
    var minutes = duration % 60;
    if (minutes < 10) {
        minutes = '0' + minutes;
    }

    var text = hours + ':' + minutes;
    if ((inDays)&&(days > 1.0)) {
        text += ' (' + days + ' PT)';
    }

    return text;
}

/*
 * Counts and displays worktime for today, this week and this month in the upper right corner
 */
function countTime() {
    Ext.Ajax.request({
        url: url + 'getTimeSummary',
        scope: this,
        success: function(response) {
            data = Ext.decode(response.responseText);
            Ext.get('worktime-day').update(strings['Today'] + ': ' + formatDuration(data.today.duration, false));
            Ext.get('worktime-week').update(strings['Week'] + ': ' + formatDuration(data.week.duration, false));
            Ext.get('worktime-month').update(strings['Month'] + ': ' + formatDuration(data.month.duration, true));
        }
    });
}

/*
 * Handles redirects
 * - Status code 403: Javascript Redirect
 * - everything else: Error message
 */
function handleRedirect(response, title, message) {
    if (response.status === 403) {
        showNotification(title, message, false);
        setTimeout("window.location.href = '" + response.responseText + "'", 2000);
    } else {
        showNotification('Fehler', response.responseText);
    }
}

var notification = undefined;

/**
 * Displays a toaster like message
 */
function showNotification(title, message, success)
{
    var cls = 'ux-notification-light';
    if (false == success) {
        cls = 'ux-notification-light-error';
    }

    if ((undefined != notification)
        && (null != notification))
    {
        notification.hide();
        notification.removeCls('ux-notification-light');
        notification.removeCls('ux-notification-light-error');
        notification.addCls(cls);
        notification.setTitle(title);
        notification.autoHideDelay = 5000;
        notification.autoHide = true;
        notification.spacing = 20;
        notification.width = 400;
        notification.autoHeight = true;
        notification.update(message);
        notification.doLayout();
        notification.show();
        return;
    }

    notification = Ext.create('widget.uxNotification', {
        title: title,
        position: 't',
        manager: 'instructions',
        cls: cls,
        plain: true,
        closable: false,
        autoHideDelay: 5000,
        autoHide: true,
        spacing: 20,
        width: 400,
        autoHeight: true,
        html: message,
        slideBackDuration: 700,
        slideInAnimation: 'bounceOut',
        slideBackAnimation: 'easeIn'
    });

    notification.show();
}

/**
 * Returns the prefix of a given ticket
 */
function extractTicketPrefix(ticket)
{
    var regexp = /([A-Za-z]+[A-Za-z0-9]*)-[0-9]+/;
    var ticket = ticket.toUpperCase() + '';
    var result = ticket.match(regexp);
    if (!result) {
        return false;
    }

    return result[1];
}

function findProjects(customer, ticket)
{
    // 1. Find all projects by this customer, if defined
    if ((null == customer) || (undefined == customer) || (1 > parseInt(customer)))
        customer = 'all';
    else
        customer = parseInt(customer);
    var projects = projectsData[customer];

    // 2. Filter projects by prefix, if defined
    if ((null == ticket) || (undefined == ticket)) {
        return projects;
    }

    // Support 2nd-trial mode: find projects without defined prefix
    var prefix = "";
    var regexp = /([ ,]+)?([A-Za-z]+)([ ,]+)?/;

    if (ticket == "") {
        prefix = "";
    } else {
        prefix = extractTicketPrefix(ticket);
        if (prefix === false)
            return projects;
    }

    var validProjects = [];
    var value;
    for (var key in projects) {
        value = projects[key];

        if (prefix == "") {
            if ((undefined == value['jiraId']) || (null == value['jiraId']) || ("" == value['jiraId'])) {
                validProjects.push(value);
            }
            continue;
        }

        if ((undefined == value['jiraId']) || (null == value['jiraId']))
            continue;

        if (value['jiraId'] == prefix) {
            validProjects.push(value);
            continue;
        }

        var result = value['jiraId'].match(regexp);
        if (!result) {
            continue;
        }

        for (var i=1; i < result.length; i++) {
            if (result[i] == prefix) {
                // console.log("Found project " + value['id'] + ", " + value['name'] + " of customer " + value['customer'] + " by prefix " + prefix);
                validProjects.push(value);

            }
        }
    }

    // If we searched with a prefix and didn't find something,
    // deliver all projects with an empty prefix defined
    if (("" != prefix) && (validProjects.length < 1))
        return findProjects(customer, "");

    return validProjects;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

function sanitizePlugins(plugins) {
  if (plugins !== undefined) {
    let cleanPlugins = plugins;
    if (typeof plugins === "string") {
      cleanPlugins = plugins.split(",").map(plugin => {
        return plugin.replace(/\s/g, "");
      });
    }
    return cleanPlugins;
  }
  return plugins;
}

const extPluginsToRemove = ["instructure_embed"];

function sanitizeExternalPlugins(external_plugins) {
  if (external_plugins !== undefined) {
    let cleanExternalPlugins = {};
    Object.keys(external_plugins).forEach(key => {
      if (external_plugins.hasOwnProperty(key)) {
        if (extPluginsToRemove.indexOf(key) == -1) {
          cleanExternalPlugins[key] = external_plugins[key];
        }
      }
    });
    return cleanExternalPlugins;
  }
  return external_plugins;
}

function sanitizeEditorOptions(options) {
  let fixed = Object.assign({}, options);

  fixed.plugins = sanitizePlugins(options.plugins);
  fixed.external_plugins = sanitizeExternalPlugins(options.external_plugins);
  fixed.toolbar = options.toolbar;

  return fixed;
}

module.exports = sanitizeEditorOptions;
<commit_msg>canvas-rce: convert module.exports to ‘export default’<commit_after>/*
 * Copyright (C) 2018 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

function sanitizePlugins(plugins) {
  if (plugins !== undefined) {
    let cleanPlugins = plugins;
    if (typeof plugins === "string") {
      cleanPlugins = plugins.split(",").map(plugin => {
        return plugin.replace(/\s/g, "");
      });
    }
    return cleanPlugins;
  }
  return plugins;
}

const extPluginsToRemove = ["instructure_embed"];

function sanitizeExternalPlugins(external_plugins) {
  if (external_plugins !== undefined) {
    let cleanExternalPlugins = {};
    Object.keys(external_plugins).forEach(key => {
      if (external_plugins.hasOwnProperty(key)) {
        if (extPluginsToRemove.indexOf(key) == -1) {
          cleanExternalPlugins[key] = external_plugins[key];
        }
      }
    });
    return cleanExternalPlugins;
  }
  return external_plugins;
}

export default function sanitizeEditorOptions(options) {
  const fixed = { ...options};

  fixed.plugins = sanitizePlugins(options.plugins);
  fixed.external_plugins = sanitizeExternalPlugins(options.external_plugins);
  fixed.toolbar = options.toolbar;

  return fixed;
}
<|endoftext|>


<commit_before>import React from 'react';
import * as activityFns from './activityfns.js';
import ActivityDay from './activityday.js';
import '../../styles/activities.css';
import * as DB from '../../constants/database.js';
import app from '../Firebase';

const db = app.firestore();

/**
 * The list of activities.
 *
 * @param {Object} props This component expects the following props:
 * - `tripId` {string} The trip's ID.
 */
class ActivityList extends React.Component {
  /** @inheritdoc */
  constructor(props) {
    super(props);
    this.state = { days : [] };

    this.getActivityList = this.getActivityList.bind(this);
  }

  /**
   * Gets the list of activities from the server.
   *
   * @param {string} tripId The trip ID.
   */
  async getActivityList(tripId) {
    let tripActivities = [];

    db.collection(DB.COLLECTION_TRIPS).doc(tripId)
    .collection(DB.COLLECTION_ACTIVITIES)
    .onSnapshot(querySnapshot => {
      this.setState({days: []});
      querySnapshot.forEach(doc => {
        let data = doc.data();
        data['id'] = doc.id;
        data['tripId'] = tripId;

        // TODO: if start date != end date, split into 2 days. (#37)

        // Eliminate nanoseconds, convert to milliseconds.
        data[DB.ACTIVITIES_START_TIME] =
          data[DB.ACTIVITIES_START_TIME]['seconds'] * 1000;
        data[DB.ACTIVITIES_END_TIME] =
          data[DB.ACTIVITIES_END_TIME]['seconds'] * 1000;

        tripActivities.push(data);
      });
      this.setState({ days: activityFns.sortByDate(tripActivities) });
    });

  }

  /**
   * @inheritdoc
   *
   * Get sorted list of activities from the database.
   *
   * This function only queries the database if `this.state` is defined.
   * `this.state` gains an entry with key `days` with the list of activities
   * sorted by date.
   */
  async componentDidMount() {
    if (this.state === null || this.props.tripId === null) { return; }
    await this.getActivityList(this.props.tripId);
  }

  /** @inheritdoc */
  render() {
    if (this.state === null) { return (

); }
    if (this.state.days === null) {
      return (
An error has occurred :(
 );
    } else if (this.state.days.length === 0) {
      return (
Plan your trip here!
);
    }

    return (

        {this.state.days.map((item, index) => (
          <ActivityDay date={item[0]} activities={item[1]} key={index}/>
        ))}

    );
  }
}

export default ActivityList;
<commit_msg>try to fix double add<commit_after>import React from 'react';
import * as activityFns from './activityfns.js';
import ActivityDay from './activityday.js';
import '../../styles/activities.css';
import * as DB from '../../constants/database.js';
import app from '../Firebase';

const db = app.firestore();

/**
 * The list of activities.
 *
 * @param {Object} props This component expects the following props:
 * - `tripId` {string} The trip's ID.
 */
class ActivityList extends React.Component {
  /** @inheritdoc */
  constructor(props) {
    super(props);
    this.state = { days : [] };

    this.getActivityList = this.getActivityList.bind(this);
  }

  /**
   * Gets the list of activities from the server.
   *
   * @param {string} tripId The trip ID.
   */
  async getActivityList(tripId) {

    db.collection(DB.COLLECTION_TRIPS).doc(tripId)
    .collection(DB.COLLECTION_ACTIVITIES)
    .onSnapshot(querySnapshot => {
      let tripActivities = [];
      this.setState({days: []});
      querySnapshot.forEach(doc => {
        let data = doc.data();
        data['id'] = doc.id;
        data['tripId'] = tripId;

        // TODO: if start date != end date, split into 2 days. (#37)

        // Eliminate nanoseconds, convert to milliseconds.
        data[DB.ACTIVITIES_START_TIME] =
          data[DB.ACTIVITIES_START_TIME]['seconds'] * 1000;
        data[DB.ACTIVITIES_END_TIME] =
          data[DB.ACTIVITIES_END_TIME]['seconds'] * 1000;

        tripActivities.push(data);
      });
      this.setState({ days: activityFns.sortByDate(tripActivities) });
    });

  }

  /**
   * @inheritdoc
   *
   * Get sorted list of activities from the database.
   *
   * This function only queries the database if `this.state` is defined.
   * `this.state` gains an entry with key `days` with the list of activities
   * sorted by date.
   */
  async componentDidMount() {
    if (this.state === null || this.props.tripId === null) { return; }
    await this.getActivityList(this.props.tripId);
  }

  /** @inheritdoc */
  render() {
    if (this.state === null) { return (

); }
    if (this.state.days === null) {
      return (
An error has occurred :(
 );
    } else if (this.state.days.length === 0) {
      return (
Plan your trip here!
);
    }

    return (

        {this.state.days.map((item, index) => (
          <ActivityDay date={item[0]} activities={item[1]} key={index}/>
        ))}

    );
  }
}

export default ActivityList;
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import {Point} from 'atom';
import path from 'path';

import {autobind} from '../helpers';
import FilePatchSelection from '../models/file-patch-selection';
import FilePatchItem from '../items/file-patch-item';
import FilePatchView from '../views/file-patch-view';

export default class FilePatchController extends React.Component {
  static propTypes = {
    repository: PropTypes.object.isRequired,
    stagingStatus: PropTypes.oneOf(['staged', 'unstaged']),
    relPath: PropTypes.string.isRequired,
    filePatch: PropTypes.object.isRequired,

    workspace: PropTypes.object.isRequired,
    commands: PropTypes.object.isRequired,
    tooltips: PropTypes.object.isRequired,

    destroy: PropTypes.func.isRequired,
    discardLines: PropTypes.func.isRequired,
    undoLastDiscard: PropTypes.func.isRequired,
  }

  constructor(props) {
    super(props);
    autobind(
      this,
      'mouseDownOnHeader', 'mouseDownOnLineNumber', 'mouseMoveOnLineNumber', 'mouseUp',
      'undoLastDiscard', 'diveIntoMirrorPatch', 'openFile',
      'toggleFile', 'selectAndToggleHunk', 'toggleLines', 'toggleModeChange', 'toggleSymlinkChange',
      'discardLines', 'selectAndDiscardHunk',
      'selectNextHunk', 'selectPreviousHunk', 'togglePatchSelectionMode',
    );

    this.state = {
      lastFilePatch: this.props.filePatch,
      selection: new FilePatchSelection(this.props.filePatch.getHunks()),
    };

    this.mouseSelectionInProgress = false;
    this.stagingOperationInProgress = false;

    this.patchChangePromise = new Promise(resolve => {
      this.resolvePatchChangePromise = resolve;
    });
  }

  static getDerivedStateFromProps(props, state) {
    if (props.filePatch !== state.lastFilePatch) {
      return {
        selection: state.selection.updateHunks(props.filePatch.getHunks()),
        lastFilePatch: props.filePatch,
      };
    }

    return null;
  }

  componentDidUpdate(prevProps) {
    if (prevProps.filePatch !== this.props.filePatch) {
      this.resolvePatchChangePromise();
      this.patchChangePromise = new Promise(resolve => {
        this.resolvePatchChangePromise = resolve;
      });
    }
  }

  render() {
    return (
      <FilePatchView
        {...this.props}

        selection={this.state.selection}

        mouseDownOnHeader={this.mouseDownOnHeader}
        mouseDownOnLineNumber={this.mouseDownOnLineNumber}
        mouseMoveOnLineNumber={this.mouseMoveOnLineNumber}
        mouseUp={this.mouseUp}

        diveIntoMirrorPatch={this.diveIntoMirrorPatch}
        openFile={this.openFile}
        toggleFile={this.toggleFile}
        selectAndToggleHunk={this.selectAndToggleHunk}
        toggleLines={this.toggleLines}
        toggleModeChange={this.toggleModeChange}
        toggleSymlinkChange={this.toggleSymlinkChange}
        undoLastDiscard={this.undoLastDiscard}
        discardLines={this.discardLines}
        selectAndDiscardHunk={this.selectAndDiscardHunk}
        selectNextHunk={this.selectNextHunk}
        selectPreviousHunk={this.selectPreviousHunk}
        togglePatchSelectionMode={this.togglePatchSelectionMode}
      />
    );
  }

  mouseDownOnHeader(event, hunk) {
    if (event.button !== 0) { return; }
    const windows = process.platform === 'win32';
    if (event.ctrlKey && !windows) { return; } // simply open context menu

    this.mouseSelectionInProgress = true;
    event.persist && event.persist();

    this.setState(prevState => {
      let selection = prevState.selection;
      if (event.metaKey || (event.ctrlKey && windows)) {
        if (selection.getMode() === 'hunk') {
          selection = selection.addOrSubtractHunkSelection(hunk);
        } else {
          // TODO: optimize
          selection = hunk.getLines().reduce(
            (current, line) => current.addOrSubtractLineSelection(line).coalesce(),
            selection,
          );
        }
      } else if (event.shiftKey) {
        if (selection.getMode() === 'hunk') {
          selection = selection.selectHunk(hunk, true);
        } else {
          const hunkLines = hunk.getLines();
          const tailIndex = selection.getLineSelectionTailIndex();
          const selectedHunkAfterTail = tailIndex < hunkLines[0].diffLineNumber;
          if (selectedHunkAfterTail) {
            selection = selection.selectLine(hunkLines[hunkLines.length - 1], true);
          } else {
            selection = selection.selectLine(hunkLines[0], true);
          }
        }
      } else {
        selection = selection.selectHunk(hunk, false);
      }

      return {selection};
    });
  }

  mouseDownOnLineNumber(event, hunk, line) {
    if (event.button !== 0) { return; }
    const windows = process.platform === 'win32';
    if (event.ctrlKey && !windows) { return; } // simply open context menu

    this.mouseSelectionInProgress = true;
    event.persist && event.persist();

    this.setState(prevState => {
      let selection = prevState.selection;

      if (event.metaKey || (event.ctrlKey && windows)) {
        if (selection.getMode() === 'hunk') {
          selection = selection.addOrSubtractHunkSelection(hunk);
        } else {
          selection = selection.addOrSubtractLineSelection(line);
        }
      } else if (event.shiftKey) {
        if (selection.getMode() === 'hunk') {
          selection = selection.selectHunk(hunk, true);
        } else {
          selection = selection.selectLine(line, true);
        }
      } else if (event.detail === 1) {
        selection = selection.selectLine(line, false);
      } else if (event.detail === 2) {
        selection = selection.selectHunk(hunk, false);
      }

      return {selection};
    });
  }

  mouseMoveOnLineNumber(event, hunk, line) {
    if (!this.mouseSelectionInProgress) { return; }

    this.setState(prevState => {
      let selection = null;
      if (prevState.selection.getMode() === 'hunk') {
        selection = prevState.selection.selectHunk(hunk, true);
      } else {
        selection = prevState.selection.selectLine(line, true);
      }
      return {selection};
    });
  }

  mouseUp() {
    this.mouseSelectionInProgress = false;
    this.setState(prevState => {
      return {selection: prevState.selection.coalesce()};
    });
  }

  undoLastDiscard() {
    return this.props.undoLastDiscard(this.props.relPath, this.props.repository);
  }

  async diveIntoMirrorPatch() {
    const mirrorStatus = this.withStagingStatus({staged: 'unstaged', unstaged: 'staged'});
    const workingDirectory = this.props.repository.getWorkingDirectoryPath();
    const uri = FilePatchItem.buildURI(this.props.relPath, workingDirectory, mirrorStatus);

    this.props.destroy();
    await this.props.workspace.open(uri);
  }

  async openFile(lineNumber = null) {
    const absolutePath = path.join(this.props.repository.getWorkingDirectoryPath(), this.props.relPath);
    const editor = await this.props.workspace.open(absolutePath, {pending: true});
    const position = new Point(lineNumber ? lineNumber - 1 : 0, 0);
    editor.scrollToBufferPosition(position, {center: true});
    editor.setCursorBufferPosition(position);
  }

  toggleFile() {
    return this.stagingOperation(() => {
      const methodName = this.withStagingStatus({staged: 'unstageFiles', unstaged: 'stageFiles'});
      return this.props.repository[methodName]([this.props.relPath]);
    });
  }

  async selectAndToggleHunk(hunk) {
    await this.selectHunk(hunk);

    return this.stagingOperation(() => {
      const patch = this.withStagingStatus({
        staged: () => this.props.filePatch.getUnstagePatchForHunk(hunk),
        unstaged: () => this.props.filePatch.getStagePatchForHunk(hunk),
      });
      return this.props.repository.applyPatchToIndex(patch);
    });
  }

  toggleLines(lines) {
    return this.stagingOperation(() => {
      const patch = this.withStagingStatus({
        staged: () => this.props.filePatch.getUnstagePatchForLines(lines),
        unstaged: () => this.props.filePatch.getStagePatchForLines(lines),
      });
      return this.props.repository.applyPatchToIndex(patch);
    });
  }

  toggleModeChange() {
    return this.stagingOperation(() => {
      const targetMode = this.withStagingStatus({
        unstaged: this.props.filePatch.getNewMode(),
        staged: this.props.filePatch.getOldMode(),
      });
      return this.props.repository.stageFileModeChange(this.props.relPath, targetMode);
    });
  }

  toggleSymlinkChange() {
    return this.stagingOperation(() => {
      const {filePatch, relPath, repository} = this.props;
      return this.withStagingStatus({
        unstaged: () => {
          if (filePatch.hasTypechange() && filePatch.getStatus() === 'added') {
            return repository.stageFileSymlinkChange(relPath);
          }

          return repository.stageFiles([relPath]);
        },
        staged: () => {
          if (filePatch.hasTypechange() && filePatch.getStatus() === 'deleted') {
            return repository.stageFileSymlinkChange(relPath);
          }

          return repository.unstageFiles([relPath]);
        },
      });
    });
  }

  discardLines(lines) {
    return this.props.discardLines(this.props.filePatch, lines, this.props.repository);
  }

  async selectAndDiscardHunk(hunk) {
    await this.selectHunk(hunk);
    return this.discardLines(hunk.getLines());
  }

  selectHunk(hunk) {
    return new Promise(resolve => {
      this.setState(prevState => ({selection: prevState.selection.selectHunk(hunk)}), resolve);
    });
  }

  selectNextHunk() {
    //
  }

  selectPreviousHunk() {
    //
  }

  togglePatchSelectionMode() {
    //
  }

  withStagingStatus(callbacks) {
    const callback = callbacks[this.props.stagingStatus];
    if (!callback) {
      throw new Error(`Unknown staging status: ${this.props.stagingStatus}`);
    }
    return callback instanceof Function ? callback() : callback;
  }

  stagingOperation(fn) {
    if (this.stagingOperationInProgress) {
      return null;
    }
    this.stagingOperationInProgress = true;
    this.patchChangePromise.then(() => {
      this.stagingOperationInProgress = false;
    });

    return fn();
  }
}
<commit_msg>Hunk navigation<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import {Point} from 'atom';
import path from 'path';

import {autobind} from '../helpers';
import FilePatchSelection from '../models/file-patch-selection';
import FilePatchItem from '../items/file-patch-item';
import FilePatchView from '../views/file-patch-view';

export default class FilePatchController extends React.Component {
  static propTypes = {
    repository: PropTypes.object.isRequired,
    stagingStatus: PropTypes.oneOf(['staged', 'unstaged']),
    relPath: PropTypes.string.isRequired,
    filePatch: PropTypes.object.isRequired,

    workspace: PropTypes.object.isRequired,
    commands: PropTypes.object.isRequired,
    tooltips: PropTypes.object.isRequired,

    destroy: PropTypes.func.isRequired,
    discardLines: PropTypes.func.isRequired,
    undoLastDiscard: PropTypes.func.isRequired,
  }

  constructor(props) {
    super(props);
    autobind(
      this,
      'mouseDownOnHeader', 'mouseDownOnLineNumber', 'mouseMoveOnLineNumber', 'mouseUp',
      'undoLastDiscard', 'diveIntoMirrorPatch', 'openFile',
      'toggleFile', 'selectAndToggleHunk', 'toggleLines', 'toggleModeChange', 'toggleSymlinkChange',
      'discardLines', 'selectAndDiscardHunk',
      'selectNextHunk', 'selectPreviousHunk', 'togglePatchSelectionMode',
    );

    this.state = {
      lastFilePatch: this.props.filePatch,
      selection: new FilePatchSelection(this.props.filePatch.getHunks()),
    };

    this.mouseSelectionInProgress = false;
    this.stagingOperationInProgress = false;

    this.patchChangePromise = new Promise(resolve => {
      this.resolvePatchChangePromise = resolve;
    });
  }

  static getDerivedStateFromProps(props, state) {
    if (props.filePatch !== state.lastFilePatch) {
      return {
        selection: state.selection.updateHunks(props.filePatch.getHunks()),
        lastFilePatch: props.filePatch,
      };
    }

    return null;
  }

  componentDidUpdate(prevProps) {
    if (prevProps.filePatch !== this.props.filePatch) {
      this.resolvePatchChangePromise();
      this.patchChangePromise = new Promise(resolve => {
        this.resolvePatchChangePromise = resolve;
      });
    }
  }

  render() {
    return (
      <FilePatchView
        {...this.props}

        selection={this.state.selection}

        mouseDownOnHeader={this.mouseDownOnHeader}
        mouseDownOnLineNumber={this.mouseDownOnLineNumber}
        mouseMoveOnLineNumber={this.mouseMoveOnLineNumber}
        mouseUp={this.mouseUp}

        diveIntoMirrorPatch={this.diveIntoMirrorPatch}
        openFile={this.openFile}
        toggleFile={this.toggleFile}
        selectAndToggleHunk={this.selectAndToggleHunk}
        toggleLines={this.toggleLines}
        toggleModeChange={this.toggleModeChange}
        toggleSymlinkChange={this.toggleSymlinkChange}
        undoLastDiscard={this.undoLastDiscard}
        discardLines={this.discardLines}
        selectAndDiscardHunk={this.selectAndDiscardHunk}
        selectNextHunk={this.selectNextHunk}
        selectPreviousHunk={this.selectPreviousHunk}
        togglePatchSelectionMode={this.togglePatchSelectionMode}
      />
    );
  }

  mouseDownOnHeader(event, hunk) {
    if (event.button !== 0) { return; }
    const windows = process.platform === 'win32';
    if (event.ctrlKey && !windows) { return; } // simply open context menu

    this.mouseSelectionInProgress = true;
    event.persist && event.persist();

    this.setState(prevState => {
      let selection = prevState.selection;
      if (event.metaKey || (event.ctrlKey && windows)) {
        if (selection.getMode() === 'hunk') {
          selection = selection.addOrSubtractHunkSelection(hunk);
        } else {
          // TODO: optimize
          selection = hunk.getLines().reduce(
            (current, line) => current.addOrSubtractLineSelection(line).coalesce(),
            selection,
          );
        }
      } else if (event.shiftKey) {
        if (selection.getMode() === 'hunk') {
          selection = selection.selectHunk(hunk, true);
        } else {
          const hunkLines = hunk.getLines();
          const tailIndex = selection.getLineSelectionTailIndex();
          const selectedHunkAfterTail = tailIndex < hunkLines[0].diffLineNumber;
          if (selectedHunkAfterTail) {
            selection = selection.selectLine(hunkLines[hunkLines.length - 1], true);
          } else {
            selection = selection.selectLine(hunkLines[0], true);
          }
        }
      } else {
        selection = selection.selectHunk(hunk, false);
      }

      return {selection};
    });
  }

  mouseDownOnLineNumber(event, hunk, line) {
    if (event.button !== 0) { return; }
    const windows = process.platform === 'win32';
    if (event.ctrlKey && !windows) { return; } // simply open context menu

    this.mouseSelectionInProgress = true;
    event.persist && event.persist();

    this.setState(prevState => {
      let selection = prevState.selection;

      if (event.metaKey || (event.ctrlKey && windows)) {
        if (selection.getMode() === 'hunk') {
          selection = selection.addOrSubtractHunkSelection(hunk);
        } else {
          selection = selection.addOrSubtractLineSelection(line);
        }
      } else if (event.shiftKey) {
        if (selection.getMode() === 'hunk') {
          selection = selection.selectHunk(hunk, true);
        } else {
          selection = selection.selectLine(line, true);
        }
      } else if (event.detail === 1) {
        selection = selection.selectLine(line, false);
      } else if (event.detail === 2) {
        selection = selection.selectHunk(hunk, false);
      }

      return {selection};
    });
  }

  mouseMoveOnLineNumber(event, hunk, line) {
    if (!this.mouseSelectionInProgress) { return; }

    this.setState(prevState => {
      let selection = null;
      if (prevState.selection.getMode() === 'hunk') {
        selection = prevState.selection.selectHunk(hunk, true);
      } else {
        selection = prevState.selection.selectLine(line, true);
      }
      return {selection};
    });
  }

  mouseUp() {
    this.mouseSelectionInProgress = false;
    this.setState(prevState => {
      return {selection: prevState.selection.coalesce()};
    });
  }

  undoLastDiscard() {
    return this.props.undoLastDiscard(this.props.relPath, this.props.repository);
  }

  async diveIntoMirrorPatch() {
    const mirrorStatus = this.withStagingStatus({staged: 'unstaged', unstaged: 'staged'});
    const workingDirectory = this.props.repository.getWorkingDirectoryPath();
    const uri = FilePatchItem.buildURI(this.props.relPath, workingDirectory, mirrorStatus);

    this.props.destroy();
    await this.props.workspace.open(uri);
  }

  async openFile(lineNumber = null) {
    const absolutePath = path.join(this.props.repository.getWorkingDirectoryPath(), this.props.relPath);
    const editor = await this.props.workspace.open(absolutePath, {pending: true});
    const position = new Point(lineNumber ? lineNumber - 1 : 0, 0);
    editor.scrollToBufferPosition(position, {center: true});
    editor.setCursorBufferPosition(position);
  }

  toggleFile() {
    return this.stagingOperation(() => {
      const methodName = this.withStagingStatus({staged: 'unstageFiles', unstaged: 'stageFiles'});
      return this.props.repository[methodName]([this.props.relPath]);
    });
  }

  async selectAndToggleHunk(hunk) {
    await this.selectHunk(hunk);

    return this.stagingOperation(() => {
      const patch = this.withStagingStatus({
        staged: () => this.props.filePatch.getUnstagePatchForHunk(hunk),
        unstaged: () => this.props.filePatch.getStagePatchForHunk(hunk),
      });
      return this.props.repository.applyPatchToIndex(patch);
    });
  }

  toggleLines(lines) {
    return this.stagingOperation(() => {
      const patch = this.withStagingStatus({
        staged: () => this.props.filePatch.getUnstagePatchForLines(lines),
        unstaged: () => this.props.filePatch.getStagePatchForLines(lines),
      });
      return this.props.repository.applyPatchToIndex(patch);
    });
  }

  toggleModeChange() {
    return this.stagingOperation(() => {
      const targetMode = this.withStagingStatus({
        unstaged: this.props.filePatch.getNewMode(),
        staged: this.props.filePatch.getOldMode(),
      });
      return this.props.repository.stageFileModeChange(this.props.relPath, targetMode);
    });
  }

  toggleSymlinkChange() {
    return this.stagingOperation(() => {
      const {filePatch, relPath, repository} = this.props;
      return this.withStagingStatus({
        unstaged: () => {
          if (filePatch.hasTypechange() && filePatch.getStatus() === 'added') {
            return repository.stageFileSymlinkChange(relPath);
          }

          return repository.stageFiles([relPath]);
        },
        staged: () => {
          if (filePatch.hasTypechange() && filePatch.getStatus() === 'deleted') {
            return repository.stageFileSymlinkChange(relPath);
          }

          return repository.unstageFiles([relPath]);
        },
      });
    });
  }

  discardLines(lines) {
    return this.props.discardLines(this.props.filePatch, lines, this.props.repository);
  }

  async selectAndDiscardHunk(hunk) {
    await this.selectHunk(hunk);
    return this.discardLines(hunk.getLines());
  }

  selectHunk(hunk) {
    return new Promise(resolve => {
      this.setState(prevState => ({selection: prevState.selection.selectHunk(hunk)}), resolve);
    });
  }

  selectNextHunk() {
    return new Promise(resolve => {
      this.setState(prevState => ({selection: prevState.selection.selectNextHunk()}), resolve);
    });
  }

  selectPreviousHunk() {
    return new Promise(resolve => {
      this.setState(prevState => ({selection: prevState.selection.selectPreviousHunk()}), resolve);
    });
  }

  togglePatchSelectionMode() {
    return new Promise(resolve => {
      this.setState(prevState => ({selection: prevState.selection.toggleMode()}), resolve);
    });
  }

  withStagingStatus(callbacks) {
    const callback = callbacks[this.props.stagingStatus];
    if (!callback) {
      throw new Error(`Unknown staging status: ${this.props.stagingStatus}`);
    }
    return callback instanceof Function ? callback() : callback;
  }

  stagingOperation(fn) {
    if (this.stagingOperationInProgress) {
      return null;
    }
    this.stagingOperationInProgress = true;
    this.patchChangePromise.then(() => {
      this.stagingOperationInProgress = false;
    });

    return fn();
  }
}
<|endoftext|>


<commit_before>const path = require('path')
const { validateGraph } = require('@frontiernav/graph')
const { transformSpreadsheets } = require('@frontiernav/spreadsheets')
const logger = require('@frontiernav/logger')
const fetch = require('isomorphic-fetch')
const { pick } = require('lodash')
const { addRelationshipReferences } = require('./addRelationshipReferences')
const { withVersion } = require('./withVersion')
const { emptyGraph } = require('./emptyGraph')
const { logOrphans } = require('./logOrphans')

const log = logger.get(__filename)

function bundleGameUsingSpreadsheet (gameRoot, game, offline) {
  const gameLog = log.child({ name: game.id })

  function getSpreadsheet (game) {
    if (offline) {
      const spreadsheetPath = path.resolve(__dirname, '../spreadsheets', `${game.id}.xlsx`)
      gameLog.info('Using local spreadsheet.', spreadsheetPath)
      return Promise.resolve(spreadsheetPath)
    }

    const gid = game.googleSpreadsheetId

    gameLog.info('Downloading spreadsheet.', `https://docs.google.com/spreadsheets/d/${gid}/`)

    return fetch(`https://docs.google.com/spreadsheets/d/${gid}/export?format=xlsx&id=${gid}`)
      .then(response => {
        if (response.status >= 400) {
          return Promise.reject(
            new Error(`Google Spreadsheets responded with "${response.status}" for "${gid}"`)
          )
        }

        return response.buffer()
      })
  }

  function generateGraph (game) {
    if (!game.googleSpreadsheetId) {
      gameLog.info('No spreadsheet found, using empty graph')
      return Promise.resolve(emptyGraph(game))
    }

    gameLog.info('Building spreadsheet graph.', gameRoot)
    return getSpreadsheet(game)
      .then(content => transformSpreadsheets(gameRoot, content))
      .then(graph => validateGraph(graph)
        .then(failures => {
          if (failures.length > 0) {
            gameLog.error({ failures }, 'Graph validation failures.')
            return Promise.reject(new Error('Graph validation failed.'))
          }
          return graph
        })
      )
      // .then(graph => {
      //   gameLog.info('bundling locales')
      //   return bundleLocales(graph)
      // })
      .then(graph => {
        gameLog.info('adding back references to incoming relationships')
        return addRelationshipReferences(graph)
      })
      .then(graph => {
        gameLog.info('finding orphan nodes')
        logOrphans(graph, gameLog)
        return graph
      })
  }

  function buildGameBundle (game, graph) {
    gameLog.info('building bundle')
    return withVersion({
      ...pick(game, ['id', 'data']),
      labels: {
        Game: true
      },
      graph
    })
  }

  return generateGraph(game)
    .then(graph => buildGameBundle(game, graph))
}

exports.bundleGameUsingSpreadsheet = bundleGameUsingSpreadsheet
<commit_msg>refactor(build-data): removing special case adding labels to games<commit_after>const path = require('path')
const { validateGraph } = require('@frontiernav/graph')
const { transformSpreadsheets } = require('@frontiernav/spreadsheets')
const logger = require('@frontiernav/logger')
const fetch = require('isomorphic-fetch')
const { pick } = require('lodash')
const { addRelationshipReferences } = require('./addRelationshipReferences')
const { withVersion } = require('./withVersion')
const { emptyGraph } = require('./emptyGraph')
const { logOrphans } = require('./logOrphans')

const log = logger.get(__filename)

function bundleGameUsingSpreadsheet (gameRoot, game, offline) {
  const gameLog = log.child({ name: game.id })

  function getSpreadsheet (game) {
    if (offline) {
      const spreadsheetPath = path.resolve(__dirname, '../spreadsheets', `${game.id}.xlsx`)
      gameLog.info('Using local spreadsheet.', spreadsheetPath)
      return Promise.resolve(spreadsheetPath)
    }

    const gid = game.googleSpreadsheetId

    gameLog.info('Downloading spreadsheet.', `https://docs.google.com/spreadsheets/d/${gid}/`)

    return fetch(`https://docs.google.com/spreadsheets/d/${gid}/export?format=xlsx&id=${gid}`)
      .then(response => {
        if (response.status >= 400) {
          return Promise.reject(
            new Error(`Google Spreadsheets responded with "${response.status}" for "${gid}"`)
          )
        }

        return response.buffer()
      })
  }

  function generateGraph (game) {
    if (!game.googleSpreadsheetId) {
      gameLog.info('No spreadsheet found, using empty graph')
      return Promise.resolve(emptyGraph(game))
    }

    gameLog.info('Building spreadsheet graph.', gameRoot)
    return getSpreadsheet(game)
      .then(content => transformSpreadsheets(gameRoot, content))
      .then(graph => validateGraph(graph)
        .then(failures => {
          if (failures.length > 0) {
            gameLog.error({ failures }, 'Graph validation failures.')
            return Promise.reject(new Error('Graph validation failed.'))
          }
          return graph
        })
      )
      // .then(graph => {
      //   gameLog.info('bundling locales')
      //   return bundleLocales(graph)
      // })
      .then(graph => {
        gameLog.info('adding back references to incoming relationships')
        return addRelationshipReferences(graph)
      })
      .then(graph => {
        gameLog.info('finding orphan nodes')
        logOrphans(graph, gameLog)
        return graph
      })
  }

  function buildGameBundle (game, graph) {
    gameLog.info('building bundle')
    return withVersion({
      ...pick(game, ['id', 'labels', 'data']),
      graph
    })
  }

  return generateGraph(game)
    .then(graph => buildGameBundle(game, graph))
}

exports.bundleGameUsingSpreadsheet = bundleGameUsingSpreadsheet
<|endoftext|>


<commit_before>// Teaspoon includes some support files, but you can use anything from your own support path too.
// require support/expect
//= require support/sinon
//= require support/chai
// require support/chai-jq-0.0.7
// require support/your-support-file
//= require magic_lamp

//
// PhantomJS (Teaspoons default driver) doesn't have support for Function.prototype.bind, which has caused confusion.
// Use this polyfill to avoid the confusion.
//= require support/bind-poly
//
// You can require your own javascript files here. By default this will include everything in application, however you
// may get better load performance if you require the specific files that are being used in the spec that tests them.
//= require application

//
// Deferring execution
// If you're using CommonJS, RequireJS or some other asynchronous library you can defer execution. Call
// Teaspoon.execute() after everything has been loaded. Simple example of a timeout:
//
// Teaspoon.defer = true
// setTimeout(Teaspoon.execute, 1000)
//
// Matching files
// By default Teaspoon will look for files that match _spec.{js,js.coffee,.coffee}. Add a filename_spec.js file in your
// spec path and it'll be included in the default suite automatically. If you want to customize suites, check out the
// configuration in teaspoon_env.rb
//
// Manifest
// If you'd rather require your spec files manually (to control order for instance) you can disable the suite matcher in
// the configuration and use this file as a manifest.
//
// For more information: http://github.com/modeset/teaspoon
//
// Chai
// If you're using Chai, you'll probably want to initialize your preferred assertion style. You can read more about Chai
// at: http://chaijs.com/guide/styles
//
 window.assert = chai.assert;
 window.expect = chai.expect;
 window.should = chai.should();
<commit_msg>Fixed "RangeError: Maximum call stack size exceeded." when running teaspoon tests<commit_after>// Teaspoon includes some support files, but you can use anything from your own support path too.
// require support/expect
//= require support/sinon
//= require support/chai
// require support/chai-jq-0.0.7
// require support/your-support-file
//= require magic_lamp

//
// PhantomJS (Teaspoons default driver) doesn't have support for Function.prototype.bind, which has caused confusion.
// Use this polyfill to avoid the confusion.
//= require support/bind-poly
//
// You can require your own javascript files here. By default this will include everything in application, however you
// may get better load performance if you require the specific files that are being used in the spec that tests them.
//= require application

//
// Deferring execution
// If you're using CommonJS, RequireJS or some other asynchronous library you can defer execution. Call
// Teaspoon.execute() after everything has been loaded. Simple example of a timeout:
//
// Teaspoon.defer = true
// setTimeout(Teaspoon.execute, 1000)
//
// Matching files
// By default Teaspoon will look for files that match _spec.{js,js.coffee,.coffee}. Add a filename_spec.js file in your
// spec path and it'll be included in the default suite automatically. If you want to customize suites, check out the
// configuration in teaspoon_env.rb
//
// Manifest
// If you'd rather require your spec files manually (to control order for instance) you can disable the suite matcher in
// the configuration and use this file as a manifest.
//
// For more information: http://github.com/modeset/teaspoon
//
// Chai
// If you're using Chai, you'll probably want to initialize your preferred assertion style. You can read more about Chai
// at: http://chaijs.com/guide/styles
//
 window.assert = chai.assert;
 window.expect = chai.expect;
 window.should = chai.should;
<|endoftext|>