<commit_before>'use strict'

const pushJenkinsUpdate = require('../lib/push-jenkins-update')
const enabledRepos = ['citgm', 'node']

const jenkinsIpWhitelist = process.env.JENKINS_WORKER_IPS ? process.env.JENKINS_WORKER_IPS.split(',') : []

function isJenkinsIpWhitelisted (req) {
  const ip = req.connection.remoteAddress

  if (jenkinsIpWhitelist.length && !jenkinsIpWhitelist.includes(ip)) {
    req.log.warn({ ip }, 'Ignoring, not allowed to push Jenkins updates')
    return false
  }

  return true
}

module.exports = function (app) {
  app.post('/:repo/jenkins/start', (req, res) => {
    const isValid = pushJenkinsUpdate.validate(req.body)
    const repo = req.params.repo

    if (!isValid) {
      return res.status(400).end('Invalid payload')
    }

    if (!enabledRepos.includes(repo)) {
      return res.status(400).end('Invalid repository')
    }

    if (!isJenkinsIpWhitelisted(req)) {
      return res.status(401).end('Invalid Jenkins IP')
    }

    pushJenkinsUpdate.pushStarted({
      owner: 'nodejs',
      repo,
      logger: req.log
    }, req.body)

    res.status(201).end()
  })

  app.post('/:repo/jenkins/end', (req, res) => {
    const isValid = pushJenkinsUpdate.validate(req.body)
    const repo = req.params.repo

    if (!isValid) {
      return res.status(400).end('Invalid payload')
    }

    if (!enabledRepos.includes(repo)) {
      return res.status(400).end('Invalid repository')
    }

    if (!isJenkinsIpWhitelisted(req)) {
      return res.status(401).end('Invalid Jenkins IP')
    }

    pushJenkinsUpdate.pushEnded({
      owner: 'nodejs',
      repo,
      logger: req.log
    }, req.body)

    res.status(201).end()
  })
}
<commit_msg>jenkins: add support for http-parser jenkins jobs (#154)<commit_after>'use strict'

const pushJenkinsUpdate = require('../lib/push-jenkins-update')
const enabledRepos = ['citgm', 'http-parser', 'node']

const jenkinsIpWhitelist = process.env.JENKINS_WORKER_IPS ? process.env.JENKINS_WORKER_IPS.split(',') : []

function isJenkinsIpWhitelisted (req) {
  const ip = req.connection.remoteAddress

  if (jenkinsIpWhitelist.length && !jenkinsIpWhitelist.includes(ip)) {
    req.log.warn({ ip }, 'Ignoring, not allowed to push Jenkins updates')
    return false
  }

  return true
}

module.exports = function (app) {
  app.post('/:repo/jenkins/start', (req, res) => {
    const isValid = pushJenkinsUpdate.validate(req.body)
    const repo = req.params.repo

    if (!isValid) {
      return res.status(400).end('Invalid payload')
    }

    if (!enabledRepos.includes(repo)) {
      return res.status(400).end('Invalid repository')
    }

    if (!isJenkinsIpWhitelisted(req)) {
      return res.status(401).end('Invalid Jenkins IP')
    }

    pushJenkinsUpdate.pushStarted({
      owner: 'nodejs',
      repo,
      logger: req.log
    }, req.body)

    res.status(201).end()
  })

  app.post('/:repo/jenkins/end', (req, res) => {
    const isValid = pushJenkinsUpdate.validate(req.body)
    const repo = req.params.repo

    if (!isValid) {
      return res.status(400).end('Invalid payload')
    }

    if (!enabledRepos.includes(repo)) {
      return res.status(400).end('Invalid repository')
    }

    if (!isJenkinsIpWhitelisted(req)) {
      return res.status(401).end('Invalid Jenkins IP')
    }

    pushJenkinsUpdate.pushEnded({
      owner: 'nodejs',
      repo,
      logger: req.log
    }, req.body)

    res.status(201).end()
  })
}
<|endoftext|>


<commit_before>/**
 * .reel Unit Tests
 */
(function($){

  module('Animation', { teardown: function teardown(){
    $('.jquery-reel').trigger('teardown');
		$(document).unbind('tick.reel');
  }});

	asyncTest( 'When at least one instance of Reel is present in the DOM a shared ticker is started', function()
	{
		expect(1);

		$(document).bind('tick.reel', tick);

		var
			ticks = 0;

		setTimeout(function(){
			ok( ticks == 0, 'Ticker isn\'t running when no Reel is on');
			start();
		}, 1000);

		function tick(){
			ticks++
		}
	});

	asyncTest( 'Ticker is driven by `leader`\'s data from `$.reel.leader()`', function()
	{
		expect(9);

		$(document).bind('tick.reel', tick);

		var
			ticks = 0,
			$faster = $('#image').reel({ tempo: 20 }),
			$slower = $('#image2').reel({ tempo: 10 });

		setTimeout(function(){
			deepEqual( $.reel.leader(), $faster.data(), 'Leader\'s data are the first (oldest living) instance\'s data')
			equals( $.reel.leader('tempo'), $faster.data('tempo'), 'Timer keeps faster tempo dictated by the leader');

			ok( $faster.trigger('teardown'), 'The older faster instance destroyed (the latter slower instance remains)');

			setTimeout(function(){
				deepEqual( $.reel.leader(), $slower.data(), 'Leader\'s data are the second (now the only) instance\'s data')
				equals( $.reel.leader('tempo'), $slower.data('tempo'), 'Ticker slowed down');

				ok( $slower.trigger('teardown'), 'Slower instance removed too (no instance remains)')
				var
					ticks_copy= ticks;

				setTimeout(function(){
					equals( $.reel.leader(), undefined, 'Without a leader there\'s no data');
					equals( $.reel.leader('tempo'), undefined, 'and no leader\'s tempo');
					equals( ticks_copy, ticks, 'Ticker is stopped.');

					start();
				}, 1000);

			}, 1000);

		}, 1000);

		function tick(){
			ticks++
		}
	});

	// We generate tests for several different tempos ranging from 6 to 48
	$.each([6, 8, 10, 12, 18, 24, 36], function(ix, tempo){

		var
			one_second= 1000,
			lazy_tempo= tempo / ($.reel.lazy? $.reel.def.laziness : 1)

		// We also try both animated and non-animated
		$.each([0, 1], function(ixx, speed){

			asyncTest( 'Ticker timing precision on `tempo: ' + lazy_tempo + '` - measuring 1 second at `speed: ' + speed + '`...', function()
			{
				expect(2);

				var
					ticks= 0,
					sum= 0,
					bang= +new Date(),
					$reel= $('#image').reel({ tempo: tempo, speed: speed })

				$(document).bind('tick.reel', function tick(){
					ticks++;
				});

				setTimeout(function(duration){
					duration= +new Date() - bang;
					ok( duration < 1.2 * one_second, 'Duration of what wannabe one second within 20 % tolerance with slip ' + (duration - one_second) + ' ms');
					ok( ticks < Math.max(1, 1.2 * lazy_tempo), 'Counted ticks within 20 % tolerance with slip ' + (tempo - ticks) + '.');
					start();
				}, one_second);
			});
		});
	});

	asyncTest( 'Running instances have their overall running cost (in ms) exposed as `$.reel.cost`', function()
	{
		expect(4);

		$('#image').reel({ speed: 1 });

		setTimeout(function(){
			var
				cost_of_one

			ok( is('Number', cost_of_one= $.reel.cost), 'Number `$.reel.cost`')
			ok( cost_of_one >= 0, 'Non-zero cost of one instance (' + cost_of_one + ' ms)' )

			$('#image2').reel({ speed: 2 });
			$('#stitched_looping').reel({ speed: 2 });

			setTimeout(function(){
				var
					cost_of_three= $.reel.cost

				ok( cost_of_three > 0, 'Non-zero cost of two instances (' + cost_of_three + ' ms)' )
				ok( cost_of_three > cost_of_one, 'Running cost of three instances is higher then of one' )
				start();

			}, 100);

		}, 100);

	});

})(jQuery);<commit_msg>Refactoring the ticker accuracy test with setting tolerance in variable and optimizing the actual check. Also number of ticks per second isn't verified anymore as we want to measure and stick to the duration of "one second" and basically don't care much about how many ticks had been fired to acomplish the accurate second. Also the tolerance has been lowered again to 10%.<commit_after>/**
 * .reel Unit Tests
 */
(function($){

  module('Animation', { teardown: function teardown(){
    $('.jquery-reel').trigger('teardown');
		$(document).unbind('tick.reel');
  }});

	asyncTest( 'When at least one instance of Reel is present in the DOM a shared ticker is started', function()
	{
		expect(1);

		$(document).bind('tick.reel', tick);

		var
			ticks = 0;

		setTimeout(function(){
			ok( ticks == 0, 'Ticker isn\'t running when no Reel is on');
			start();
		}, 1000);

		function tick(){
			ticks++
		}
	});

	asyncTest( 'Ticker is driven by `leader`\'s data from `$.reel.leader()`', function()
	{
		expect(9);

		$(document).bind('tick.reel', tick);

		var
			ticks = 0,
			$faster = $('#image').reel({ tempo: 20 }),
			$slower = $('#image2').reel({ tempo: 10 });

		setTimeout(function(){
			deepEqual( $.reel.leader(), $faster.data(), 'Leader\'s data are the first (oldest living) instance\'s data')
			equals( $.reel.leader('tempo'), $faster.data('tempo'), 'Timer keeps faster tempo dictated by the leader');

			ok( $faster.trigger('teardown'), 'The older faster instance destroyed (the latter slower instance remains)');

			setTimeout(function(){
				deepEqual( $.reel.leader(), $slower.data(), 'Leader\'s data are the second (now the only) instance\'s data')
				equals( $.reel.leader('tempo'), $slower.data('tempo'), 'Ticker slowed down');

				ok( $slower.trigger('teardown'), 'Slower instance removed too (no instance remains)')
				var
					ticks_copy= ticks;

				setTimeout(function(){
					equals( $.reel.leader(), undefined, 'Without a leader there\'s no data');
					equals( $.reel.leader('tempo'), undefined, 'and no leader\'s tempo');
					equals( ticks_copy, ticks, 'Ticker is stopped.');

					start();
				}, 1000);

			}, 1000);

		}, 1000);

		function tick(){
			ticks++
		}
	});

	// We generate tests for several different tempos ranging from 6 to 48
	$.each([6, 8, 10, 12, 18, 24, 36], function(ix, tempo){

		var
			one_second= 1000,
			lazy_tempo= tempo / ($.reel.lazy? $.reel.def.laziness : 1),
			tolerate= 10, // percents
			tolerance= {
				lo: 1 - tolerate / 100,
				hi: 1 + tolerate / 100
			}

		// We also try both animated and non-animated
		$.each([0, 1], function(ixx, speed){

			asyncTest( 'Measuring 1 second timing accuracy when running ' + (speed ? 'animated' : 'non-animated') + ' instance at `tempo: ' + lazy_tempo + '`', function()
			{
				expect(2);

				var
					ticks= 0,
					sum= 0,
					bang= +new Date(),
					$reel= $('#image').reel({ tempo: tempo, speed: speed })

				$(document).bind('tick.reel', function tick(){
					ticks++;
				});

				setTimeout(function(duration){
					var filled;
					duration= +new Date() - bang;
					ok( (filled= duration / one_second) >= tolerance.lo && filled <= tolerance.hi, duration + ' ms is within the ' + tolerate + ' % tolerance.');
					ok( true, 'Received ' + ticks + ' ticks');
					start();
				}, one_second);
			});
		});
	});

	asyncTest( 'Running instances have their overall running cost (in ms) exposed as `$.reel.cost`', function()
	{
		expect(4);

		$('#image').reel({ speed: 1 });

		setTimeout(function(){
			var
				cost_of_one

			ok( is('Number', cost_of_one= $.reel.cost), 'Number `$.reel.cost`')
			ok( cost_of_one >= 0, 'Non-zero cost of one instance (' + cost_of_one + ' ms)' )

			$('#image2').reel({ speed: 2 });
			$('#stitched_looping').reel({ speed: 2 });

			setTimeout(function(){
				var
					cost_of_three= $.reel.cost

				ok( cost_of_three > 0, 'Non-zero cost of two instances (' + cost_of_three + ' ms)' )
				ok( cost_of_three > cost_of_one, 'Running cost of three instances is higher then of one' )
				start();

			}, 100);

		}, 100);

	});

})(jQuery);<|endoftext|>


<commit_before>/*
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree and available online at
 *
 *     http://duracloud.org/license/
 */

/**
 * A collection of useful jquery extensions
 * @author "Daniel Bernstein (dbernstein@duraspace.org)"
 */

$(function(){
	(function(){
		////////////////////////////////////////////////////////////////////
		//jquery extensions
		///////////////////////////////////////////////////////////////////
	    $.fn.disable = function(/*boolean*/ val){
	        if(!val){
	           return $(this).removeAttr("disabled");
	        }else{
	           return $(this).attr("disabled", "disabled");
	        }
	    };

	    /**
		 * Similar to hide/show jquery functions but toggles the visibility css
		 * attribute instead of the display attribute.
		 */
		$.fn.makeVisible = function(isvisible) {
			return $(this).css("visibility", (isvisible == undefined || isvisible) ? "visible":"hidden");
		};

		$.fn.makeHidden = function() {
			return $(this).makeVisible(false);
		};

		/**
		 * This finds the nearest ancestor of the specified class.  It is just like jQuery.closest(selector) except
		 * that it includes the dom node your are calling the function on.
		 */
		$.fn.nearestOfClass = function(className){
			var nearest = (this.hasClass(className)) ? this : this.closest("." + className);
			return $(nearest);
		};

		$.fn.toggleOpenClosed = function(){
			$(this).nearestOfClass("button")
					.toggleClass("dialog-open")
					.toggleClass("dialog-closed");
		};

		/**
		 * Shorthand for document.createElement
		 * Returns the new element as a jQuery object.
		 */
		$.fn.create = function(tag){
			return $(document.createElement(tag));

		};

		/**
		 * Scrolls the specified dom element to the top of the
		 * viewport (which is the object on which you're calling this function)
		 * if possible. If it can't scroll it to the top of the viewport it at
		 * least scrolls the container so that the element is in view.
		 * @param DOM node or jquery object
		 */
		$.fn.scrollTo = function(element){
			var top = $(element).position().top;
			this.animate({scrollTop: top}, {duration:"slow", easing:"swing", queue:true});
		};

		/**
		 * this method loads the children of the new contents
		 * into the target after emptying the contents
		 * with a fade in / fade out effect
		 */
		$.fn.replaceContents = function(/*the pane whose contents will be swapped in*/ newContents,
										/*the layout for the target*/ layoutOptions){
			var target = this;
			//$(target).fadeOut("fast", function(){
				$(target).empty().prepend($(newContents).children());
				//$(target).fadeIn("fast");
				if(layoutOptions != null && layoutOptions != undefined){
					$(target).layout(layoutOptions);
				}
			//});
			return $(target);
		};

		/**
		 * Closes the dialog when the user clicks off of it.
		 */
		$.fn.closeOnLostFocus = function() { // on the open event
		    // find the dialog element
		    var dialogEl = this;
		    $(document).click(function (e) { // when anywhere in the doc is clicked
		        var clickedOutside = true; // start searching assuming we clicked outside
		        $(e.target).parents().andSelf().each(function () { // search parents and self
		            // if the original dialog selector is the click's target or a parent of the target
		            // we have not clicked outside the box
		            if ($(this).first().attr("id") == $(dialogEl).attr("id")) {
		                clickedOutside = false; // found
		                return false; // stop searching
		            }
		        });
		        if (clickedOutside) {
		            $(dialogEl).dialog("close"); // close the dialog
		            // unbind this listener, we're done with it
		            $(document).unbind('click',arguments.callee);
		        }
		    });
		};

		/**
		 * Binds the enter keyup event to the specified function.
		 */
		$.fn.bindEnterKey = function(func) {
			$(this).bind('keyup', function(e){
				if(e.keyCode==13){
		        	func(e);
			    }
			});

			return this;
		};

		$.fn.busy = function(){
		    $(".dc-busy",this).show("fast");
		    return this;
		};

		$.fn.idle = function(){
            $(".dc-busy",this).hide();
            return this;
        };

    $.fn.busySibling = function(text){
      var busy = $("

");
      if(text){
        busy.html(text);
      }
      busy.insertAfter($(this));
      busy.show("fast");
      return this;
    };

    $.fn.idleSibling = function(){
      $(this).next(".dc-busy-holder").hide("fast").remove();
      return this;
    };

    //adds in missing addBack function for plugins that depend on it (namely jquery dropdown)
    $.fn.addBack = function (selector) {
      return this.add(selector == null ? this.prevObject : this.prevObject.filter(selector));
    };

	})();
});

<commit_msg>Completes https://jira.duraspace.org/browse/DURACLOUD-912<commit_after>/*
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree and available online at
 *
 *     http://duracloud.org/license/
 */

/**
 * A collection of useful jquery extensions
 * @author "Daniel Bernstein (dbernstein@duraspace.org)"
 */

$(function(){
	(function(){
		////////////////////////////////////////////////////////////////////
		//jquery extensions
		///////////////////////////////////////////////////////////////////
	    $.fn.disable = function(/*boolean*/ val){
	        if(!val){
	           return $(this).removeAttr("disabled");
	        }else{
	           return $(this).attr("disabled", "disabled");
	        }
	    };

	    /**
		 * Similar to hide/show jquery functions but toggles the visibility css
		 * attribute instead of the display attribute.
		 */
		$.fn.makeVisible = function(isvisible) {
			return $(this).css("visibility", (isvisible == undefined || isvisible) ? "visible":"hidden");
		};

		$.fn.makeHidden = function() {
			return $(this).makeVisible(false);
		};

		/**
		 * This finds the nearest ancestor of the specified class.  It is just like jQuery.closest(selector) except
		 * that it includes the dom node your are calling the function on.
		 */
		$.fn.nearestOfClass = function(className){
			var nearest = (this.hasClass(className)) ? this : this.closest("." + className);
			return $(nearest);
		};

		$.fn.toggleOpenClosed = function(){
			$(this).nearestOfClass("button")
					.toggleClass("dialog-open")
					.toggleClass("dialog-closed");
		};

		/**
		 * Shorthand for document.createElement
		 * Returns the new element as a jQuery object.
		 */
		$.fn.create = function(tag){
			return $(document.createElement(tag));

		};

		/**
		 * Scrolls the specified dom element to the top of the
		 * viewport (which is the object on which you're calling this function)
		 * if possible. If it can't scroll it to the top of the viewport it at
		 * least scrolls the container so that the element is in view.
		 * @param DOM node or jquery object
		 */
		$.fn.scrollTo = function(element){
			var top = $(element).position().top;
			this.animate({scrollTop: top}, {duration:"slow", easing:"swing", queue:true});
		};

		/**
		 * this method loads the children of the new contents
		 * into the target after emptying the contents
		 * with a fade in / fade out effect
		 */
		$.fn.replaceContents = function(/*the pane whose contents will be swapped in*/ newContents,
										/*the layout for the target*/ layoutOptions){
			var target = this;
			//$(target).fadeOut("fast", function(){
				$(target).empty().prepend($(newContents).children());
				//$(target).fadeIn("fast");
				if(layoutOptions != null && layoutOptions != undefined){
					$(target).layout(layoutOptions);
				}
			//});
			return $(target);
		};

		/**
		 * Closes the dialog when the user clicks off of it.
		 */
		$.fn.closeOnLostFocus = function() { // on the open event
		    // find the dialog element
		    var dialogEl = this;
		    $(document).click(function (e) { // when anywhere in the doc is clicked
		        var clickedOutside = true; // start searching assuming we clicked outside
		        $(e.target).parents().andSelf().each(function () { // search parents and self
		            // if the original dialog selector is the click's target or a parent of the target
		            // we have not clicked outside the box
		            if ($(this).first().attr("id") == $(dialogEl).attr("id")) {
		                clickedOutside = false; // found
		                return false; // stop searching
		            }
		        });
		        if (clickedOutside) {
		            $(dialogEl).dialog("close"); // close the dialog
		            // unbind this listener, we're done with it
		            $(document).unbind('click',arguments.callee);
		        }
		    });
		};

		/**
		 * Binds the enter keyup event to the specified function.
		 */
		$.fn.bindEnterKey = function(func) {
			$(this).bind('keyup', function(e){
				if(e.keyCode==13){
		        	func(e);
			    }
			});

			return this;
		};

		$.fn.busy = function(){
		    $(".dc-busy",this).show("fast");
		    return this;
		};

		$.fn.idle = function(){
            $(".dc-busy",this).hide();
            return this;
        };

    $.fn.busySibling = function(text){
      var busy = $("

");
      if(text){
        busy.html(text);
      }

      busy.insertAfter($(this));
      busy.show("fast");
      return this;
    };

    $.fn.idleSibling = function(){
      $(this).siblings(".dc-busy-holder").hide("fast").remove();
      return this;
    };

    //adds in missing addBack function for plugins that depend on it (namely jquery dropdown)
    $.fn.addBack = function (selector) {
      return this.add(selector == null ? this.prevObject : this.prevObject.filter(selector));
    };

	})();
});

<|endoftext|>


<commit_before>(function(env) {
var quixey_image_domain = "d1z22zla46lb9g.cloudfront.net";

// spice callback function
env.ddg_spice_quixey = function(api_result) {

    var q = api_result.q.replace(/\s/g, '+');

    var category_regexp = new RegExp([
            "action",
            "adventure",
            "arcade",
            "board",
            "business",
            "casino",
            // "calculator",
            "design",
            "developer tools",
            "dice",
            "education",
            "educational",
            "entertainment",
            "family",
            "finance",
            "fitness",
            "graphics and design",
            "graphics",
            "health and fitness",
            "health",
            "kids",
            "lifestyle",
            "map",
            "medical",
            "music",
            "navigation",
            "networking",
            "news",
            "photography",
            "productivity",
            "puzzle",
            "racing",
            "role playing",
            "simulation",
            "social networking",
            "social",
            "sports",
            "strategy",
            "travel",
            "trivia",
            "utilities",
            "video",
            "weather"
        ].join("|"), "i");

    Spice.add({
        id: 'quixey',
        name: 'Apps',

        data: api_result.results,   //relevants,

        meta: {
            // count is now computed by Spice
            // count: relevants.length,
            total: api_result.results.length,
            itemType: 'Apps',
            sourceName: 'Quixey',
            sourceUrl: 'https://www.quixey.com/search?q=' + q,
            sourceIconUrl: DDG.get_asset_path('quixey','quixey_logo.png')
        },

        normalize : function(item) {

            // relevancy pre-filter: skip ones that have less than three reviews
            if (!item.rating_count || item.rating_count < 3)
                return null;

            return {
                'img':           make_icon_url(item),
                'title':         item.name,
                'heading':       item.name,
                'ratingData':    {
                                   stars: item.rating,
                                   reviews: item.rating_count
                               },
                'url_review':    item.dir_url,
                'price':         pricerange(item),
                'abstract':      item.short_desc || "",
                'brand':         (item.developer && item.developer.name) || "",
                'products_buy':  Spice.quixey.quixey_buy,

                // this should be the array of screenshots with captions
                // and check for the existence of them
                'img_m': quixey_image(item.editions[0].screenshots[0].image_url)
            };
        },

        relevancy: {
            type: DDG.get_query().match(category_regexp) ? "category" : "primary",

            skip_words: [
                "android",
                "app",
                "apple app store",
                "apple app",
                "application",
                "applications",
                "apps",
                "best",
                "blackberry",
                "download",
                "downloaded",
                "droid",
                "enhanced",
                "free",
                "fully featured",
                "google play store",
                "google play",
                "ios",
                "ipad",
                "iphone",
                "ipod touch",
                "ipod",
                "most",
                "playbook",
                "popular",
                "release data",
                "release",
                "sale",
                "search",
                "windows mobile",
                "windows phone 8",
                "windows phone"
            ],

            category: [
                { required: 'icon_url' },
                { key: 'short_desc' },
                { key: 'name' },
                { key: 'custom.features.category', match: category_regexp, strict:false }    // strict means this key has to contain a category phrase or we reject
            ],

            primary: [
                { required: 'icon_url' }, // would like to add  alt: 'platforms.0.icon_url'
                { key: 'name' },
                { key: 'short_desc', strict: false }
            ],

            // secondary:  [
            //     { key: 'short_desc' },
            //     { key: 'name' },
            //     { key: 'custom.features.category' },
            //     { required: 'icon_url' }
            // ],

            // field for de-duplication
            // currently single value, could be differentiated by type
            // eg { 'category': 'name', 'primary': 'id' }
            dup: 'name'

        },

        // sort field definition: how this data can be sorted. each field may appear in a UI drop-down.
        sort_fields: {
            'rating': //Spice.rating_comparator('rating', 'rating_count')
                function(a,b) {
                    var rank = function(r,count) {  // will be moved up
                        return r*r*r*count/5;
                    };
                    return rank(a.rating,a.rating_count) > rank(b.rating, b.rating_count) ? -1: 1;
                }
            // 'platform': function(a,b) { } ,
            // 'name':
            // 'price':
        },

        // default sorting- how the data will be initially arranged.
        // depends on the type of search. here only a 'category' search will
        // perform a default initial sort.
        // 'primary' is not here, meaning will remain in api_result order.
        // sort_default: { <sorttype>:<field>, <sorttype>:<field>, ... }
        sort_default: { 'category': 'rating' },

        templates: {
            item: DDG.templates.products,
            item_variant: 'short',
            detail: DDG.templates.products_detail
        }
    });

}

// format a price
// p is expected to be a number
function qprice(p) {
    if (p == 0) {    // == type coercion is ok here
        return "FREE";
    }

    return "$" + (p/100).toFixed(2).toString();
}

// template helper for price formatting
// {{price x}}
Handlebars.registerHelper("qprice", function(obj) {
    return qprice(obj);
});

var quixey_image = function(image_url) {
    return "http://" + quixey_image_domain + image_url.match(/\/image\/.+/)[0];
}

var make_icon_url = function(item) {
    var domain = "d1z22zla46lb9g.cloudfront.net",
        icon_url = item.icon_url;

    if (!icon_url) {
        console.warn("quixey: icon_url is null for %o", item);
        if (item.editions && item.editions[0].icon_url)
            icon_url = item.editions[0].icon_url;
        else
            return "";
    }

    // Get the image server that the icon_url in platforms is pointing to.
    // It's not ideal, but the link to the app's image still has to redirect
    // and it redirects to HTTPS. What we want is an HTTP link (for speed).
    if (item.platforms && item.platforms.length > 0 && item.platforms[0].icon_url) {
        domain = item.platforms[0].icon_url.match(/https?:\/\/([^\/]+)/)[1];
    }

    // Replace the domain in our icon_url to the one that we got from
    // the platforms array.
    // return "/iu/?u=http://" + domain + item.icon_url.match(/\/image\/.+/)[0] + "&f=1";
    return "http://" + domain + icon_url.match(/\/image\/.+/)[0];
};

Handlebars.registerHelper("toHTTP", function(icon_url, platforms) {
    var domain = "d1z22zla46lb9g.cloudfront.net";

    // Get the image server that the icon_url in platforms is pointing to.
    // It's not ideal, but the link to the app's image still has to redirect
    // and it redirects to HTTPS. What we want is an HTTP link (for speed).
    if(platforms && platforms.length > 0 && platforms[0].icon_url) {
    domain = platforms[0].icon_url.match(/https?:\/\/([^\/]+)/)[1];
    }

    // Replace the domain in our icon_url to the one that we got from
    // the platforms array.
    icon_url = icon_url.match(/\/image\/.+/)[0];
    return "http://" + domain + icon_url;
});

// template helper to format a price range
var pricerange = function(item) {

    if (!item || !item.editions)
        return "";

    var low  = item.editions[0].cents;
    var high = item.editions[0].cents;
    var tmp, range, lowp, highp;

    for (var i in item.editions) {
        tmp = item.editions[i].cents;
        if (tmp < low) low = tmp;
        if (tmp > high) high = tmp;
    }

    lowp = qprice(low);

    if (high > low) {
       highp = qprice(high);
       range = lowp + " - " + highp;
       item.hasPricerange = true;
    } else {
        range = lowp;
    }

    return range;
};

Handlebars.registerHelper("pricerange", function() {
    return pricerange(this);
});

// template helper to replace iphone and ipod icons with
// smaller 'Apple' icons
Handlebars.registerHelper("platform_icon", function(icon_url) {
    if (this.id === 2004 || this.id === 2015) {
        return "https://icons.duckduckgo.com/i/itunes.apple.com.ico";
    }

    // return "/iu/?u=" + icon_url + "&f=1";
    return icon_url;
});

// template helper that returns and unifies platform names
Handlebars.registerHelper("platform_name", function() {
    var name;
    var platforms = this.platforms;

    name = platforms[0].name;

    if (platforms.length > 1) {
        switch (platforms[0].name) {
            case "iPhone" :
            case "iPad" :
                name = "iOS";
                break;

            case "Blackberry":
            case "Blackberry 10":
                name = "Blackberry";
                break;
        }
    }

    return name;
});

// template helper to give url for star icon
Handlebars.registerHelper("quixey_star", function() {
    return DDG.get_asset_path("quixey", "star.png").replace("//", "/");
});

})(this);
<commit_msg>quixey: skip when no icon can be found<commit_after>(function(env) {
var quixey_image_domain = "d1z22zla46lb9g.cloudfront.net";

// spice callback function
env.ddg_spice_quixey = function(api_result) {

    var q = api_result.q.replace(/\s/g, '+');

    var category_regexp = new RegExp([
            "action",
            "adventure",
            "arcade",
            "board",
            "business",
            "casino",
            // "calculator",
            "design",
            "developer tools",
            "dice",
            "education",
            "educational",
            "entertainment",
            "family",
            "finance",
            "fitness",
            "graphics and design",
            "graphics",
            "health and fitness",
            "health",
            "kids",
            "lifestyle",
            "map",
            "medical",
            "music",
            "navigation",
            "networking",
            "news",
            "photography",
            "productivity",
            "puzzle",
            "racing",
            "role playing",
            "simulation",
            "social networking",
            "social",
            "sports",
            "strategy",
            "travel",
            "trivia",
            "utilities",
            "video",
            "weather"
        ].join("|"), "i");

    Spice.add({
        id: 'quixey',
        name: 'Apps',

        data: api_result.results,   //relevants,

        meta: {
            // count is now computed by Spice
            // count: relevants.length,
            total: api_result.results.length,
            itemType: 'Apps',
            sourceName: 'Quixey',
            sourceUrl: 'https://www.quixey.com/search?q=' + q,
            sourceIconUrl: DDG.get_asset_path('quixey','quixey_logo.png')
        },

        normalize : function(item) {

            // relevancy pre-filter: skip ones that have less than three reviews
            if (!item.rating_count || item.rating_count < 3)
                return null;

            var icon_url = make_icon_url(item);

            if (!icon_url)
                return null;

            return {
                'img':           icon_url,
                'title':         item.name,
                'heading':       item.name,
                'ratingData':    {
                                   stars: item.rating,
                                   reviews: item.rating_count
                               },
                'url_review':    item.dir_url,
                'price':         pricerange(item),
                'abstract':      item.short_desc || "",
                'brand':         (item.developer && item.developer.name) || "",
                'products_buy':  Spice.quixey.quixey_buy,

                // this should be the array of screenshots with captions
                // and check for the existence of them
                'img_m': quixey_image(item.editions[0].screenshots[0].image_url)
            };
        },

        relevancy: {
            type: DDG.get_query().match(category_regexp) ? "category" : "primary",

            skip_words: [
                "android",
                "app",
                "apple app store",
                "apple app",
                "application",
                "applications",
                "apps",
                "best",
                "blackberry",
                "download",
                "downloaded",
                "droid",
                "enhanced",
                "free",
                "fully featured",
                "google play store",
                "google play",
                "ios",
                "ipad",
                "iphone",
                "ipod touch",
                "ipod",
                "most",
                "playbook",
                "popular",
                "release data",
                "release",
                "sale",
                "search",
                "windows mobile",
                "windows phone 8",
                "windows phone"
            ],

            category: [
                { required: 'icon_url' },
                { key: 'short_desc' },
                { key: 'name' },
                { key: 'custom.features.category', match: category_regexp, strict:false }    // strict means this key has to contain a category phrase or we reject
            ],

            primary: [
                { required: 'icon_url' }, // would like to add  alt: 'platforms.0.icon_url'
                { key: 'name' },
                { key: 'short_desc', strict: false }
            ],

            // secondary:  [
            //     { key: 'short_desc' },
            //     { key: 'name' },
            //     { key: 'custom.features.category' },
            //     { required: 'icon_url' }
            // ],

            // field for de-duplication
            // currently single value, could be differentiated by type
            // eg { 'category': 'name', 'primary': 'id' }
            dup: 'name'

        },

        // sort field definition: how this data can be sorted. each field may appear in a UI drop-down.
        sort_fields: {
            'rating': //Spice.rating_comparator('rating', 'rating_count')
                function(a,b) {
                    var rank = function(r,count) {  // will be moved up
                        return r*r*r*count/5;
                    };
                    return rank(a.rating,a.rating_count) > rank(b.rating, b.rating_count) ? -1: 1;
                }
            // 'platform': function(a,b) { } ,
            // 'name':
            // 'price':
        },

        // default sorting- how the data will be initially arranged.
        // depends on the type of search. here only a 'category' search will
        // perform a default initial sort.
        // 'primary' is not here, meaning will remain in api_result order.
        // sort_default: { <sorttype>:<field>, <sorttype>:<field>, ... }
        sort_default: { 'category': 'rating' },

        templates: {
            item: DDG.templates.products,
            item_variant: 'short',
            detail: DDG.templates.products_detail
        }
    });

}

// format a price
// p is expected to be a number
function qprice(p) {
    if (p == 0) {    // == type coercion is ok here
        return "FREE";
    }

    return "$" + (p/100).toFixed(2).toString();
}

// template helper for price formatting
// {{price x}}
Handlebars.registerHelper("qprice", function(obj) {
    return qprice(obj);
});

var quixey_image = function(image_url) {
    return "http://" + quixey_image_domain + image_url.match(/\/image\/.+/)[0];
}

var make_icon_url = function(item) {
    var domain = "d1z22zla46lb9g.cloudfront.net",
        icon_url = item.icon_url;

    if (!icon_url) {
        // console.warn("quixey: icon_url is null for %o", item);
        if (item.editions && item.editions[0].icon_url)
            icon_url = item.editions[0].icon_url;
        else
            return null;
    }

    // Get the image server that the icon_url in platforms is pointing to.
    // It's not ideal, but the link to the app's image still has to redirect
    // and it redirects to HTTPS. What we want is an HTTP link (for speed).
    if (item.platforms && item.platforms.length > 0 && item.platforms[0].icon_url) {
        domain = item.platforms[0].icon_url.match(/https?:\/\/([^\/]+)/)[1];
    }

    // Replace the domain in our icon_url to the one that we got from
    // the platforms array.
    // return "/iu/?u=http://" + domain + item.icon_url.match(/\/image\/.+/)[0] + "&f=1";
    return "http://" + domain + icon_url.match(/\/image\/.+/)[0];
};

Handlebars.registerHelper("toHTTP", function(icon_url, platforms) {
    var domain = "d1z22zla46lb9g.cloudfront.net";

    // Get the image server that the icon_url in platforms is pointing to.
    // It's not ideal, but the link to the app's image still has to redirect
    // and it redirects to HTTPS. What we want is an HTTP link (for speed).
    if(platforms && platforms.length > 0 && platforms[0].icon_url) {
    domain = platforms[0].icon_url.match(/https?:\/\/([^\/]+)/)[1];
    }

    // Replace the domain in our icon_url to the one that we got from
    // the platforms array.
    icon_url = icon_url.match(/\/image\/.+/)[0];
    return "http://" + domain + icon_url;
});

// template helper to format a price range
var pricerange = function(item) {

    if (!item || !item.editions)
        return "";

    var low  = item.editions[0].cents;
    var high = item.editions[0].cents;
    var tmp, range, lowp, highp;

    for (var i in item.editions) {
        tmp = item.editions[i].cents;
        if (tmp < low) low = tmp;
        if (tmp > high) high = tmp;
    }

    lowp = qprice(low);

    if (high > low) {
       highp = qprice(high);
       range = lowp + " - " + highp;
       item.hasPricerange = true;
    } else {
        range = lowp;
    }

    return range;
};

Handlebars.registerHelper("pricerange", function() {
    return pricerange(this);
});

// template helper to replace iphone and ipod icons with
// smaller 'Apple' icons
Handlebars.registerHelper("platform_icon", function(icon_url) {
    if (this.id === 2004 || this.id === 2015) {
        return "https://icons.duckduckgo.com/i/itunes.apple.com.ico";
    }

    // return "/iu/?u=" + icon_url + "&f=1";
    return icon_url;
});

// template helper that returns and unifies platform names
Handlebars.registerHelper("platform_name", function() {
    var name;
    var platforms = this.platforms;

    name = platforms[0].name;

    if (platforms.length > 1) {
        switch (platforms[0].name) {
            case "iPhone" :
            case "iPad" :
                name = "iOS";
                break;

            case "Blackberry":
            case "Blackberry 10":
                name = "Blackberry";
                break;
        }
    }

    return name;
});

// template helper to give url for star icon
Handlebars.registerHelper("quixey_star", function() {
    return DDG.get_asset_path("quixey", "star.png").replace("//", "/");
});

})(this);
<|endoftext|>


<commit_before>// vendor dependencies
var babel = require('gulp-babel')
var sourcemaps = require('gulp-sourcemaps')

// local dependencies
var logger = require(enduro.enduro_path + '/libs/logger')
// * ———————————————————————————————————————————————————————— * //
// * 	JS Task
// *	Transpile ES6 to JS
// * ———————————————————————————————————————————————————————— * //
var js_handler = function () {}

js_handler.prototype.init = function (gulp, browser_sync) {

	// stores task name
	var js_handler_task_name = 'js';
	gulp.task(js_handler_task_name, function() {
		if (enduro.config.babel) {
			logger.timestamp('JS compiling started', 'enduro_events')
			var babelConfig = enduro.config.babel || {
				presets: ['es2015']
			};
			return gulp.src([enduro.project_path + '/assets/js/*.js',
							'!' + enduro.project_path + '/assets/js/*.min.js',
							'!' + enduro.project_path + '/assets/js/handlebars.js'])
				.pipe(sourcemaps.init())
				.pipe(babel(babelConfig))
				.on('error', function (err) {
					logger.err_blockStart('JS error')
					logger.err(err.message)
					logger.err_blockEnd()
					this.emit('end')
				})
				.pipe(sourcemaps.write())
				.pipe(gulp.dest(enduro.project_path + '/' + enduro.config.build_folder + '/assets/js'))
				.pipe(browser_sync.stream())
				.on('end', () => {
					logger.timestamp('JS compiling finished', 'enduro_events')
				})
		} else {
			logger.timestamp('js compiling not enabled, add babel options to enduro.json to enable')
		}
	})

	return js_handler_task_name;
}

module.exports = new js_handler()
<commit_msg>fix failing test<commit_after>// vendor dependencies
var babel = require('gulp-babel')
var sourcemaps = require('gulp-sourcemaps')
var Promise = require('bluebird')
var fs = Promise.promisifyAll(require('fs-extra'))

// local dependencies
var flat_helpers = require(enduro.enduro_path + '/libs/flat_db/flat_helpers')
var logger = require(enduro.enduro_path + '/libs/logger')
// * ———————————————————————————————————————————————————————— * //
// * 	JS Task
// *	Transpile ES6 to JS
// * ———————————————————————————————————————————————————————— * //
var js_handler = function () {}

js_handler.prototype.init = function (gulp, browser_sync) {

	// stores task name
	var js_handler_task_name = 'js';
	gulp.task(js_handler_task_name, function() {
		if (enduro.config.babel) {
			logger.timestamp('JS compiling started', 'enduro_events')
			var babelConfig = enduro.config.babel || {
				presets: ['es2015']
			};
			return gulp.src([enduro.project_path + '/assets/js/*.js',
							'!' + enduro.project_path + '/assets/js/*.min.js',
							'!' + enduro.project_path + '/assets/js/handlebars.js'])
				.pipe(sourcemaps.init())
				.pipe(babel(babelConfig))
				.on('error', function (err) {
					logger.err_blockStart('JS error')
					logger.err(err.message)
					logger.err_blockEnd()
					this.emit('end')
				})
				.pipe(sourcemaps.write())
				.pipe(gulp.dest(enduro.project_path + '/' + enduro.config.build_folder + '/assets/js'))
				.pipe(browser_sync.stream())
				.on('end', () => {
					logger.timestamp('JS compiling finished', 'enduro_events')
				})
		} else {
			logger.timestamp('js compiling not enabled, add babel options to enduro.json to enable')
			var copy_from = enduro.project_path + '/assets/js'
			var copy_to = enduro.project_path + '/' + enduro.config.build_folder + '/assets/js'
			return flat_helpers.dir_exists(copy_from)
				.then(() => {
					return fs.copyAsync(copy_from, copy_to, { overwrite: true })
				}, () => {})
		}
	})

	return js_handler_task_name;
}

module.exports = new js_handler()
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
({

	browsers:["GOOGLECHROME", "SAFARI"],

	setUp: function(cmp) {

		FORCE = {
			getPrefix: function() {
				return "webkit";
			}
		};

	},

	// verify panel element
	verifyPanelElements: function(cmp) {

        var containerEle = cmp.getElement();
        var ele = cmp.find("panel").getElement();
		var attributes = cmp.attributes;

		$A.test.assertTrue($A.util.hasClass(ele, "panel"), "Element is not rendered with panel class");

		$A.test.assertFalsy(cmp.get('v.detail'), "unexpected attr");
		$A.test.assertFalsy(cmp.get('v.icon'), "unexpected attr");
		$A.test.assertTruthy(ele.querySelector(".body"), "body is not rendered");

		// title bar
		if(!cmp.get("v.removeHeader") && cmp.get("v.title")) {
			$A.test.assertTruthy(ele.querySelector(".titleBar"), "titleBar is not rendered");

			// title
			if(cmp.get("v.title")) {
				$A.test.assertEquals(cmp.get("v.title"), ele.querySelector(".title").textContent, "title is not expected");
			}
			else {
				$A.test.assertFalsy(ele.querySelector(".title")?ele.querySelector(".title").textContent:ele.querySelector(".title"), "title is unexpectedly rendered");
			}
		}
		else {
			$A.test.assertFalsy(ele.querySelector(".titleBar"), "titleBar is unexpectedly rendered");
		}

		// buttons
		if(cmp.get("v.body").length) {
			$A.test.assertTruthy(ele.querySelector(".button_row"), "buttons not rendered");
		}
		else {
			$A.test.assertFalsy(ele.querySelector(".button_row"), "buttons unexpectedly rendered");
		}

		// additional class
		if(cmp.get("v.class")) {
    		$A.test.assertTrue($A.util.hasClass(containerEle, cmp.get("v.class")), "Additional class not added as expected");
    	}
    	else {
    		$A.test.assertTrue($A.util.hasClass(ele, "forceUIPanel"), "Additional class added unexpectedly");
    	}
	},

	/*
	* Panel is rendered
	*/
	testPanelAllAttributes:{
		attributes: {
			isVisible:true,
			title:"test title",
			'class': "testClass",
			isScrollable: true,
			removeHeader: false
		},
	    test : function(cmp){

	    	// Assert
	    	this.verifyPanelElements(cmp);
	    }
	},

	testPanelNoScroller:{
		attributes: {
			isVisible:true,
			title:"test title",
			'class': "testClass",
			isScrollable: false
		},
	    test : function(cmp){

	    	// Assert
	    	this.verifyPanelElements(cmp);
	    }
	},

	testPanelRemoveHeader:{
		attributes: {
			isVisible:true,
			title:"test title",
			'class': "testClass",
			removeHeader: true
		},
	    test : function(cmp){

			// Assert
	    	this.verifyPanelElements(cmp);
	    }
	},

	testPanelSpecialCharecter:{
		attributes: {
			isVisible:true,
			title:"test title!$#%^!^%$^&@FAGFDGWAERGY$#^%&@%#^%$&",
			'class': "testClass",
			isScrollable: true,
			removeHeader: false
		},
	    test : function(cmp){

	    	// Assert
	    	this.verifyPanelElements(cmp);
	    }
	}
})
<commit_msg>Automation for non full screen panel overlay<commit_after>/*
 * Copyright (C) 2013 salesforce.com, inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
({

	browsers:["GOOGLECHROME", "SAFARI"],

	setUp: function(cmp) {

		FORCE = {
			getPrefix: function() {
				return "webkit";
			}
		};

	},

	// verify panel element
	verifyPanelElements: function(cmp) {
		var containerEle = cmp.getElement();
        var ele = cmp.find("panel").getElement();
		var attributes = cmp.attributes;
		$A.test.assertTrue($A.util.hasClass(ele, "panel"), "Element is not rendered with panel class");
		if(!cmp.get("v.isFullScreen") || $A.get("$Browser").isPhone){
			$A.test.assertTrue($A.util.hasClass(containerEle, "notFullScreen"), "Container Element is not rendered with notFullScreen class");
			$A.test.assertTruthy(containerEle.querySelector(".modal-glass"), "modal glass is not rendered");
		}
		else{
			$A.test.assertTrue($A.util.hasClass(containerEle, "fullScreen"), "Container Element is not rendered with notFullScreen class");
		}
		$A.test.assertFalsy(cmp.get('v.detail'), "unexpected attr");
		$A.test.assertFalsy(cmp.get('v.icon'), "unexpected attr");
		$A.test.assertTruthy(ele.querySelector(".body"), "body is not rendered");

		// title bar
		if(!cmp.get("v.removeHeader") && cmp.get("v.title")) {
			$A.test.assertTruthy(ele.querySelector(".titleBar"), "titleBar is not rendered");

			// title
			if(cmp.get("v.title")) {
				$A.test.assertEquals(cmp.get("v.title"), $A.test.getText(ele.querySelector(".title")), "title is not expected");
			}
			else {
				$A.test.assertFalsy(ele.querySelector(".title")?$A.test.getText(ele.querySelector(".title")):ele.querySelector(".title"), "title is unexpectedly rendered");
			}
		}
		else {
			$A.test.assertFalsy(ele.querySelector(".titleBar"), "titleBar is unexpectedly rendered");
		}

		// buttons
		if(cmp.get("v.body").length) {
			$A.test.assertTruthy(ele.querySelector(".button_row"), "buttons not rendered");
		}
		else {
			$A.test.assertFalsy(ele.querySelector(".button_row"), "buttons unexpectedly rendered");
		}

		// additional class
		if(cmp.get("v.class")) {
    		$A.test.assertTrue($A.util.hasClass(containerEle, cmp.get("v.class")), "Additional class not added as expected");
    	}
    	else {
    		$A.test.assertTrue($A.util.hasClass(ele, "forceUIPanel"), "Additional class added unexpectedly");
    	}
	},

	/*
	* Panel is rendered
	*/
	testPanelAllAttributes:{
		attributes: {
			isVisible:true,
			title:"test title",
			'class': "testClass",
			isScrollable: true,
			removeHeader: false,
			isFullScreen: true,
		},
	    test : function(cmp){

	    	// Assert
	    	this.verifyPanelElements(cmp);
	    }
	},

	testPanelNoScroller:{
		attributes: {
			isVisible:true,
			title:"test title",
			'class': "testClass",
			isScrollable: false
		},
	    test : function(cmp){

	    	// Assert
	    	this.verifyPanelElements(cmp);
	    }
	},

	/**
	 * Allow ui:panelOverlay to not take up the full screen on desktop via an attribute
	 * Test case: W-2420802
	 */
	testPanelNoFullScreen:{
		attributes: {
			isVisible:true,
			title:"test title",
			'class': "testClass",
			isFullScreen: false,
		},
	    test : function(cmp){

	    	// Assert
	    	this.verifyPanelElements(cmp);
	    }
	},

	testPanelRemoveHeader:{
		attributes: {
			isVisible:true,
			title:"test title",
			'class': "testClass",
			removeHeader: true
		},
	    test : function(cmp){

			// Assert
	    	this.verifyPanelElements(cmp);
	    }
	},

	testPanelSpecialCharecter:{
		attributes: {
			isVisible:true,
			title:"test title!$#%^!^%$^&@FAGFDGWAERGY$#^%&@%#^%$&",
			'class': "testClass",
			isScrollable: true,
			removeHeader: false
		},
	    test : function(cmp){

	    	// Assert
	    	this.verifyPanelElements(cmp);
	    }
	}
})<|endoftext|>


<commit_before>showChart = function( area, sensor, period, unit ) {
    $( area ).empty();

    var margin = {top: 20, right: 50, bottom: 30, left: 50 },
        width = 700 - margin.left - margin.right,
        height = 250 - margin.top - margin.bottom;

    var parseDate = d3.time.format("%Y-%m-%d %X").parse;

    var x = d3.time.scale()
        .range([0, width]);

    var y = d3.scale.linear()
        .range([height, 0]);

    y.ticks(0.1);

    var xAxis = d3.svg.axis()
        .scale(x)
        .tickFormat( function(d) { return d3.time.format('%H:%M')(d); } )
        .orient("bottom");

    var yAxis = d3.svg.axis()
        .scale(y)
        .tickSize(-width,0,0)
        .tickFormat( d3.format(',.1f') )
        .orient("left");

    var yAxis2 = d3.svg.axis()
        .scale(y)
        .tickFormat( d3.format(',.1f') )
        .orient("right");

    // interpolate 'smoothens' the line
    var line = d3.svg.line()
        .interpolate("cardinal")
        .x(function (d) { return x(d.timestamp); })

    .y(function (d) {
        return y(d.value);
    });

    var svg = d3.select( area ).append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    d3.csv("/sensor-data.php?action=csv_data&id="+sensor+"&period="+period, function (error, data) {
        data.forEach(function (d) {
            d.timestamp = parseDate(d.timestamp);
            d.value = +d.value;
        });

        x.domain(d3.extent(data, function (d) {return d.timestamp; }));
        y.domain( [d3.min(data, function (d) {return d.value; })-0.1,d3.max(data, function (d) {return d.value; })+0.1] ).nice();

        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);

        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis)
            .append("text")
            .attr("transform", "rotate(-90) translate(0,-50)")
            .attr("y", 6)
            .attr("dy", ".71em")
            .style("text-anchor", "end")
            .text(unit);

        svg.append("g")
            .attr("class", "y2 axis")
            .attr("transform", "translate(" + width + " ,0)")
            .call(yAxis2)
            .append("text")
            .attr("transform", "rotate(90) translate(0, -50)")
            .attr("y", 6)
            .attr("dy", ".71em")
            .style("text-anchor", "start")
            .text(unit);

        svg.append("path")
            .datum(data)
            .attr("class", "line")
            .attr("d", line);

        svg.selectAll("dot")
            .data(data)
            .enter().append("circle")
            .style("fill","purple")
            .attr("r", 1.5)
            .attr("cx", function(d) { return x(d.timestamp); })
            .attr("cy", function(d) { return y(d.value); });
    });
};
<commit_msg>Smaller radius for data points<commit_after>showChart = function( area, sensor, period, unit ) {
    $( area ).empty();

    var margin = {top: 20, right: 50, bottom: 30, left: 50 },
        width = 700 - margin.left - margin.right,
        height = 250 - margin.top - margin.bottom;

    var parseDate = d3.time.format("%Y-%m-%d %X").parse;

    var x = d3.time.scale()
        .range([0, width]);

    var y = d3.scale.linear()
        .range([height, 0]);

    y.ticks(0.1);

    var xAxis = d3.svg.axis()
        .scale(x)
        .tickFormat( function(d) { return d3.time.format('%H:%M')(d); } )
        .orient("bottom");

    var yAxis = d3.svg.axis()
        .scale(y)
        .tickSize(-width,0,0)
        .tickFormat( d3.format(',.1f') )
        .orient("left");

    var yAxis2 = d3.svg.axis()
        .scale(y)
        .tickFormat( d3.format(',.1f') )
        .orient("right");

    // interpolate 'smoothens' the line
    var line = d3.svg.line()
        .interpolate("monotone")
        .x(function (d) { return x(d.timestamp); })

    .y(function (d) {
        return y(d.value);
    });

    var svg = d3.select( area ).append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    d3.csv("/sensor-data.php?action=csv_data&id="+sensor+"&period="+period, function (error, data) {
        data.forEach(function (d) {
            d.timestamp = parseDate(d.timestamp);
            d.value = +d.value;
        });

        x.domain(d3.extent(data, function (d) {return d.timestamp; }));
        y.domain( [d3.min(data, function (d) {return d.value; })-0.1,d3.max(data, function (d) {return d.value; })+0.1] ).nice();

        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);

        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis)
            .append("text")
            .attr("transform", "rotate(-90) translate(0,-50)")
            .attr("y", 6)
            .attr("dy", ".71em")
            .style("text-anchor", "end")
            .text(unit);

        svg.append("g")
            .attr("class", "y2 axis")
            .attr("transform", "translate(" + width + " ,0)")
            .call(yAxis2)
            .append("text")
            .attr("transform", "rotate(90) translate(0, -50)")
            .attr("y", 6)
            .attr("dy", ".71em")
            .style("text-anchor", "start")
            .text(unit);

        svg.append("path")
            .datum(data)
            .attr("class", "line")
            .attr("d", line);

        svg.selectAll("dot")
            .data(data)
            .enter().append("circle")
            .style("fill","purple")
            .attr("r", 1.0)
            .attr("cx", function(d) { return x(d.timestamp); })
            .attr("cy", function(d) { return y(d.value); });
    });
};
<|endoftext|>


<commit_before>$(document).ready(function()
{
	// Using leaflet.js to pan and zoom a big image.
	// See also: http://kempe.net/blog/2014/06/14/leaflet-pan-zoom-image.html

	// create the slippy map
	var map = L.map('mapid', {
	  minZoom: 1,
	  maxZoom: 4,
	  zoomControl : true,
	  center: [0, 0],
	  zoom: 1,
	  crs: L.CRS.Simple
	});
	var bat = document.getElementById('session').rows[0].cells[0].innerHTML;
			etage = document.getElementById('session').rows[0].cells[1].innerHTML;
	// dimensions of the image
	var w = 1600,
    	h = 1050,
    	url = 'data/etage'+etage+'.png';

	// calculate the edges of the image, in coordinate space
	var southWest = map.unproject([0, h], map.getMaxZoom()-1);
	var northEast = map.unproject([w, 0], map.getMaxZoom()-1);
	var bounds = new L.LatLngBounds(southWest, northEast);

	// add the image overlay,
	// so that it covers the entire map
	//L.marker([-50, 100	]).addTo(map);

	var arrayRows = document.getElementById("points").rows;
	var rowsNb = arrayRows.length;
	var tab_points = [];
	var j = 0;
	for(var i = 0 ; i < rowsNb; i++)
	{
			if(arrayRows[i].cells[5].innerHTML == bat && arrayRows[i].cells[6].innerHTML == etage){
				tab_points[j] = L.marker([-arrayRows[i].cells[1].innerHTML,arrayRows[i].cells[0].innerHTML],{title:arrayRows[i].cells[2].innerHTML}).addTo(map);
				tab_points[j].id = arrayRows[i].cells[2].innerHTML;
				tab_points[j].name = arrayRows[i].cells[3].innerHTML;
				tab_points[j].description = arrayRows[i].cells[4].innerHTML;
				tab_points[j].lat = arrayRows[i].cells[1].innerHTML;
				tab_points[j].lng = arrayRows[i].cells[0].innerHTML;
				j++;
			}
	}

	L.imageOverlay(url, bounds).addTo(map);

	var liaisons = document.getElementById("liaisons").rows;
	var nbliaisons = liaisons.length;
	var tab_liaisons = [];
	for(var k = 0; k<nbliaisons; k++){
		tab_liaisons[k] = new Object();
		for(i = 0; i<tab_points.length;i++){
			if(liaisons[k].cells[0].innerHTML == tab_points[i].id){
				tab_liaisons[k].src = tab_points[i].getLatLng();
			}
		}
		for(i = 0; i<tab_points.length;i++){
			if(liaisons[k].cells[1].innerHTML == tab_points[i].id){
				tab_liaisons[k].dest = tab_points[i].getLatLng();
			}
		}

		var polygon = L.polygon([tab_liaisons[k].src,tab_liaisons[k].dest]).addTo(map);
	}

	// tell leaflet that the map is exactly as big as the image
	map.setMaxBounds(bounds);

    	/*for (var i = 0; i < j; i++)
    	{
				tab_points[i].addTo(map);
    		tab_points[i].on('click',function()
    		{
    			//location.href = "index.php?page=etage&drop=drop"+(this).id;
    			//info_card = document.createElement("div");
    			//container = document.getElementById("container");
    			//container.appendChild(info_card);
					alert(tab_points[i].id);
    		});
    	}*/
var qrcode = new QRCode(document.getElementById('qrcode'));
			for(var k=0;k<tab_points.length;k++){
				tab_points[k].on('click',function(d){
					qrcode.makeCode("?page=etage&location=true&selectedPoint="+this.id);
				});
			}

			//alert(tab_points.length);
});
<commit_msg>résolution bug affichage qrcode<commit_after>$(document).ready(function()
{
	// Using leaflet.js to pan and zoom a big image.
	// See also: http://kempe.net/blog/2014/06/14/leaflet-pan-zoom-image.html

	// create the slippy map
	var map = L.map('mapid', {
	  minZoom: 1,
	  maxZoom: 4,
	  zoomControl : true,
	  center: [0, 0],
	  zoom: 1,
	  crs: L.CRS.Simple
	});
	var bat = document.getElementById('session').rows[0].cells[0].innerHTML;
			etage = document.getElementById('session').rows[0].cells[1].innerHTML;
	// dimensions of the image
	var w = 1600,
    	h = 1050,
    	url = 'data/etage'+etage+'.png';

	// calculate the edges of the image, in coordinate space
	var southWest = map.unproject([0, h], map.getMaxZoom()-1);
	var northEast = map.unproject([w, 0], map.getMaxZoom()-1);
	var bounds = new L.LatLngBounds(southWest, northEast);

	// add the image overlay,
	// so that it covers the entire map
	//L.marker([-50, 100	]).addTo(map);

	var arrayRows = document.getElementById("points").rows;
	var rowsNb = arrayRows.length;
	var tab_points = [];
	var j = 0;
	for(var i = 0 ; i < rowsNb; i++)
	{
			if(arrayRows[i].cells[5].innerHTML == bat && arrayRows[i].cells[6].innerHTML == etage){
				tab_points[j] = L.marker([-arrayRows[i].cells[1].innerHTML,arrayRows[i].cells[0].innerHTML],{title:arrayRows[i].cells[2].innerHTML}).addTo(map);
				tab_points[j].id = arrayRows[i].cells[2].innerHTML;
				tab_points[j].name = arrayRows[i].cells[3].innerHTML;
				tab_points[j].description = arrayRows[i].cells[4].innerHTML;
				tab_points[j].lat = arrayRows[i].cells[1].innerHTML;
				tab_points[j].lng = arrayRows[i].cells[0].innerHTML;
				j++;
			}
	}

	L.imageOverlay(url, bounds).addTo(map);

	var liaisons = document.getElementById("liaisons").rows;
	var nbliaisons = liaisons.length;
	var tab_liaisons = [];
	for(var k = 0; k<nbliaisons; k++){
		tab_liaisons[k] = new Object();
		for(i = 0; i<tab_points.length;i++){
			if(liaisons[k].cells[0].innerHTML == tab_points[i].id){
				tab_liaisons[k].src = tab_points[i].getLatLng();
			}
		}
		for(i = 0; i<tab_points.length;i++){
			if(liaisons[k].cells[1].innerHTML == tab_points[i].id){
				tab_liaisons[k].dest = tab_points[i].getLatLng();
			}
		}
		if(tab_liaisons[k].src != undefined && tab_liaisons[k].dest != undefined){
			var polygon = L.polygon([tab_liaisons[k].src,tab_liaisons[k].dest]).addTo(map);}
	}

	// tell leaflet that the map is exactly as big as the image
	map.setMaxBounds(bounds);

    	/*for (var i = 0; i < j; i++)
    	{
				tab_points[i].addTo(map);
    		tab_points[i].on('click',function()
    		{
    			//location.href = "index.php?page=etage&drop=drop"+(this).id;
    			//info_card = document.createElement("div");
    			//container = document.getElementById("container");
    			//container.appendChild(info_card);
					alert(tab_points[i].id);
    		});
    	}*/
var qrcode = new QRCode(document.getElementById('qrcode'));
			for(var k=0;k<tab_points.length;k++){
				tab_points[k].on('click',function(d){
					qrcode.makeCode("?page=etage&location=true&selectedPoint="+this.id);
				});
			}

			//alert(tab_points.length);
});
<|endoftext|>


<commit_before>if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') {
	console.error('Class ss.i18n not defined');
} else {
	ss.i18n.addDictionary('pl_PL', {
		'CMSMAIN.WARNINGSAVEPAGESBEFOREADDING' : "Należy najpierw zapisać stronę, aby móc dodać strony podrzędne",
		'CMSMAIN.CANTADDCHILDREN' : "Nie można dodać stron podrzędnych",
		'CMSMAIN.ERRORADDINGPAGE' : 'Błąd przy dodawaniu strony',
		'CMSMAIN.FILTEREDTREE' : 'Drzewo filtrowane pokazujące tylko zmienione strony',
		'CMSMAIN.ERRORFILTERPAGES' : 'Nie można było filtrować drzewa
%s',
		'CMSMAIN.ERRORUNFILTER' : 'Nie można było cofnąć filtrowania drzewa
%s',
		'CMSMAIN.PUBLISHINGPAGES' : 'Publikacja strony...',
		'CMSMAIN.SELECTONEPAGE' : "Proszę wybrać przynajmniej jedną stronę",
		'CMSMAIN.ERRORPUBLISHING' : 'Błąd podczas publikacji stron',
		'CMSMAIN.REALLYDELETEPAGES' : "Czy na pewno zaznaczone strony %s usunąć?",
		'CMSMAIN.DELETINGPAGES' : 'Usuwanie stron...',
		'CMSMAIN.ERRORDELETINGPAGES': 'Błąd podczas usuwania stron',
		'CMSMAIN.PUBLISHING' : 'Publikacja...',
		'CMSMAIN.RESTORING': 'Odzyskiwanie...',
		'CMSMAIN.ERRORREVERTING': 'Błąd podczas powrotu do opublikowanej strony',
		'CMSMAIN.SAVING' : 'Zapisywanie...'
		'CMSMAIN.SELECTMOREPAGES' : "Zaznaczono %s stron.\n\nCzy na pewno chcesz wykonać tę akcje?",
		'CMSMAIN.ALERTCLASSNAME': 'Ta strona zostanie zaktualizowana po jej zapisani'ur,
		'CMSMAIN.URLSEGMENTVALIDATION': 'Adres URL może składać się tylko z liter, cyfr i łączników.',
		'AssetAdmin.BATCHACTIONSDELETECONFIRM': "Czy na pewno usunąć %s folderów?",
		'AssetTableField.REALLYDELETE': 'Czy na pewno usunąć zaznaczone pliki??',
		'AssetTableField.MOVING': 'Przenoszenie %s plików',
		'CMSMAIN.AddSearchCriteria': 'Dodaj kryteria',
		'WidgetAreaEditor.TOOMANY': 'Przepraszam, ale osiągnięto maksymalną ilość widgetów w tym obszarze',
		'AssetAdmin.ConfirmDelete': 'Czy na pewno usunąć ten folder i wszystkie pliki w nim zawarte?',
		'Folder.Name': 'Nazwa folderu',
		'Tree.AddSubPage': 'Dodaj tutaj nową stronę',
		'Tree.EditPage': 'Edytuj',
		'CMSMain.ConfirmRestoreFromLive': "Czy na pewno skopiować opublikowaną treść do strony roboczej?",
		'CMSMain.RollbackToVersion': "Czy na pewno cofnąć do wersji #%s tej strony?",
		'URLSEGMENT.Edit': 'Edytuj',
		'URLSEGMENT.OK': 'OK',
		'URLSEGMENT.Cancel': 'Anuluj'
	});
}
<commit_msg>Update pl_PL.js<commit_after>if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') {
	console.error('Class ss.i18n not defined');
} else {
	ss.i18n.addDictionary('pl_PL', {
		'CMSMAIN.WARNINGSAVEPAGESBEFOREADDING' : "Należy najpierw zapisać stronę, aby móc dodać strony podrzędne",
		'CMSMAIN.CANTADDCHILDREN' : "Nie można dodać stron podrzędnych",
		'CMSMAIN.ERRORADDINGPAGE' : 'Błąd przy dodawaniu strony',
		'CMSMAIN.FILTEREDTREE' : 'Drzewo filtrowane pokazujące tylko zmienione strony',
		'CMSMAIN.ERRORFILTERPAGES' : 'Nie można było filtrować drzewa
%s',
		'CMSMAIN.ERRORUNFILTER' : 'Nie można było cofnąć filtrowania drzewa
%s',
		'CMSMAIN.PUBLISHINGPAGES' : 'Publikacja strony...',
		'CMSMAIN.SELECTONEPAGE' : "Proszę wybrać przynajmniej jedną stronę",
		'CMSMAIN.ERRORPUBLISHING' : 'Błąd podczas publikacji stron',
		'CMSMAIN.REALLYDELETEPAGES' : "Czy na pewno zaznaczone strony %s usunąć?",
		'CMSMAIN.DELETINGPAGES' : 'Usuwanie stron...',
		'CMSMAIN.ERRORDELETINGPAGES': 'Błąd podczas usuwania stron',
		'CMSMAIN.PUBLISHING' : 'Publikacja...',
		'CMSMAIN.RESTORING': 'Odzyskiwanie...',
		'CMSMAIN.ERRORREVERTING': 'Błąd podczas powrotu do opublikowanej strony',
		'CMSMAIN.SAVING' : 'Zapisywanie...',
		'CMSMAIN.SELECTMOREPAGES' : "Zaznaczono %s stron.\n\nCzy na pewno chcesz wykonać tę akcje?",
		'CMSMAIN.ALERTCLASSNAME': 'Ta strona zostanie zaktualizowana po jej zapisani'ur,
		'CMSMAIN.URLSEGMENTVALIDATION': 'Adres URL może składać się tylko z liter, cyfr i łączników.',
		'AssetAdmin.BATCHACTIONSDELETECONFIRM': "Czy na pewno usunąć %s folderów?",
		'AssetTableField.REALLYDELETE': 'Czy na pewno usunąć zaznaczone pliki??',
		'AssetTableField.MOVING': 'Przenoszenie %s plików',
		'CMSMAIN.AddSearchCriteria': 'Dodaj kryteria',
		'WidgetAreaEditor.TOOMANY': 'Przepraszam, ale osiągnięto maksymalną ilość widgetów w tym obszarze',
		'AssetAdmin.ConfirmDelete': 'Czy na pewno usunąć ten folder i wszystkie pliki w nim zawarte?',
		'Folder.Name': 'Nazwa folderu',
		'Tree.AddSubPage': 'Dodaj tutaj nową stronę',
		'Tree.EditPage': 'Edytuj',
		'CMSMain.ConfirmRestoreFromLive': "Czy na pewno skopiować opublikowaną treść do strony roboczej?",
		'CMSMain.RollbackToVersion': "Czy na pewno cofnąć do wersji #%s tej strony?",
		'URLSEGMENT.Edit': 'Edytuj',
		'URLSEGMENT.OK': 'OK',
		'URLSEGMENT.Cancel': 'Anuluj'
	});
}
<|endoftext|>


<commit_before>import { Context } from './context';
import { Travis } from './travis';
import { Readme } from './readme';
import { Package } from './package';
import { Rollup } from './rollup';
import { License } from './license';
import { MergeAndRemoveLineSet } from './merge-and-remove-line-set';
import { MergeLineSet } from './merge-line-set';
import { ReplaceIfEmpty } from './replace-if-empty';
import { Replace } from './replace';
import { JSONFile } from './json-file';
import { JSDoc } from './jsdoc';

const mm = require('micromatch');

const mergers = [
  Rollup,
  Travis,
  Readme,
  Package,
  JSONFile,
  JSDoc,
  Travis,
  MergeAndRemoveLineSet,
  MergeLineSet,
  License,
  ReplaceIfEmpty,
  Replace
];

const defaultMapping = [
  { merger: 'Package', pattern: '**/package.json' },
  { merger: 'Travis', pattern: '.travis.yml' },
  { merger: 'Readme', pattern: '**/README.*' },
  { merger: 'JSDoc', pattern: '**/jsdoc.json' },
  { merger: 'Rollup', pattern: '**/rollup.config.js' },
  { merger: 'License', pattern: 'LICENSE' },
  {
    merger: 'MergeAndRemoveLineSet',
    pattern: '.gitignore',
    options: { message: 'chore(git): update {{path}} from template' }
  },
  {
    merger: 'MergeAndRemoveLineSet',
    pattern: '.npmignore',
    options: { message: 'chore(npm): update {{path}} from template' }
  },
  { merger: 'ReplaceIfEmpty', pattern: '**/*' }
];

export async function createFiles(branch, mapping = defaultMapping) {
  const files = await branch.list();
  let alreadyPresent = new Set();

  return mapping
    .map(m => {
      const found = mm(
        files.filter(f => f.type === 'blob').map(f => f.path),
        m.pattern
      );

      const notAlreadyProcessed = found.filter(f => !alreadyPresent.has(f));

      alreadyPresent = new Set([...Array.from(alreadyPresent), ...found]);

      return notAlreadyProcessed.map(f => {
        const merger =
          mergers.find(merger => merger.name === m.merger) || ReplaceIfEmpty;
        return new merger(f, m.options);
      });
    })
    .reduce((last, current) => Array.from([...last, ...current]), []);
}

/**
 * @param {RepositoryProvider} provider
 * @param {Branch} targetBranch
 * @param {Branch} templateBranch
 * @param {Object} options
 * @return {Promise<PullRequest>}
 */
export async function npmTemplateSync(
  provider,
  targetBranch,
  templateBranch,
  options
) {
  options = Object.assign(
    {
      logger: console,
      dry: false,
      trackUsedByModule: false
    },
    options
  );

  options.spinner.text = targetBranch.fullCondensedName;
  const condensedName = targetBranch.repository.condensedName;

  try {
    const context = new Context(
      targetBranch,
      undefined,
      {
        github: { user: targetBranch.owner, repo: condensedName },
        npm: { name: condensedName, fullName: condensedName },
        name: condensedName,
        user: targetBranch.owner,
        'date.year': new Date().getFullYear(),
        'license.owner': targetBranch.owner
      },
      options
    );

    const pkg = new Package('package.json');

    Object.assign(context.properties, await pkg.properties(context));

    if (templateBranch === undefined) {
      templateBranch = await provider.branch(context.properties.templateRepo);

      if (templateBranch === undefined) {
        throw new Error(
          `Unable to extract template repo url from ${targetBranch.name} ${
            pkg.path
          }`
        );
      }
    }

    context.templateBranch = templateBranch;

    context.logger.debug(
      `Using ${templateBranch.provider.name} as template provider`
    );

    const json = JSON.parse(
      await pkg.templateContent(context, { ignoreMissing: true })
    );

    if (options.trackUsedByModule) {
      const name = targetBranch.fullCondensedName;

      if (json.template === undefined) {
        json.template = {};
      }
      if (!Array.isArray(json.template.usedBy)) {
        json.template.usedBy = [];
      }

      if (!json.template.usedBy.find(n => n === name)) {
        json.template.usedBy.push(name);

        const prBranch = await templateBranch.repository.createBranch(
          'template-add-used-1',
          context.templateBranch
        );
        await prBranch.commit(`fix: add ${name}`, [
          {
            path: 'package.json',
            content: JSON.stringify(json, undefined, 2)
          }
        ]);

        const pullRequest = await templateBranch.createPullRequest(prBranch, {
          title: `add ${name}`,
          body: `add tracking info for ${name}`
        });
      }
    }

    const files = await createFiles(
      context.templateBranch,
      json.template && json.template.files
    );

    files.forEach(f => context.addFile(f));

    context.logger.debug(context.files.values());

    const merges = (await Promise.all(
      files.map(f => f.saveMerge(context))
    )).filter(m => m !== undefined && m.changed);

    if (merges.length === 0) {
      context.spinner.succeed(
        `${targetBranch.fullCondensedName}: nothing changed`
      );
      return;
    }

    context.spinner.text = merges
      .map(m => `${targetBranch.fullCondensedName}: ${m.messages[0]}`)
      .join(',');

    if (context.dry) {
      context.spinner.succeed(`${targetBranch.fullCondensedName}: dry run`);
      return;
    }

    let newPullRequestRequired = false;
    const prBranchName = 'template-sync-1';
    let prBranch = (await targetBranch.repository.branches()).get(prBranchName);

    if (prBranch === undefined) {
      newPullRequestRequired = true;
      prBranch = await targetBranch.repository.createBranch(
        prBranchName,
        targetBranch
      );
    }

    const messages = merges.reduce((result, merge) => {
      merge.messages.forEach(m => result.push(m));
      return result;
    }, []);

    await prBranch.commit(messages.join('\n'), merges);

    if (newPullRequestRequired) {
      try {
        const pullRequest = await targetBranch.createPullRequest(prBranch, {
          title: `merge package template from ${
            context.templateBranch.fullCondensedName
          }`,
          body: merges
            .map(
              m =>
                `${m.path}
---
- ${m.messages.join('\n- ')}
`
            )
            .join('\n')
        });
        context.spinner.succeed(
          `${targetBranch.fullCondensedName}: ${pullRequest.name}`
        );

        return pullRequest;
      } catch (err) {
        context.spinner.fail(err);
      }
    } else {
      const pullRequest = new targetBranch.provider.pullRequestClass(
        targetBranch.repository,
        'old'
      );

      context.spinner.succeed(`${targetBranch.fullCondensedName}: update PR`);
      return pullRequest;
    }
  } catch (err) {
    options.spinner.fail(`${targetBranch.fullCondensedName}: ${err}`);
    throw err;
  }
}
<commit_msg>fix: update branch only if pr for template is already created<commit_after>import { Context } from './context';
import { Travis } from './travis';
import { Readme } from './readme';
import { Package } from './package';
import { Rollup } from './rollup';
import { License } from './license';
import { MergeAndRemoveLineSet } from './merge-and-remove-line-set';
import { MergeLineSet } from './merge-line-set';
import { ReplaceIfEmpty } from './replace-if-empty';
import { Replace } from './replace';
import { JSONFile } from './json-file';
import { JSDoc } from './jsdoc';

const mm = require('micromatch');

const mergers = [
  Rollup,
  Travis,
  Readme,
  Package,
  JSONFile,
  JSDoc,
  Travis,
  MergeAndRemoveLineSet,
  MergeLineSet,
  License,
  ReplaceIfEmpty,
  Replace
];

const defaultMapping = [
  { merger: 'Package', pattern: '**/package.json' },
  { merger: 'Travis', pattern: '.travis.yml' },
  { merger: 'Readme', pattern: '**/README.*' },
  { merger: 'JSDoc', pattern: '**/jsdoc.json' },
  { merger: 'Rollup', pattern: '**/rollup.config.js' },
  { merger: 'License', pattern: 'LICENSE' },
  {
    merger: 'MergeAndRemoveLineSet',
    pattern: '.gitignore',
    options: { message: 'chore(git): update {{path}} from template' }
  },
  {
    merger: 'MergeAndRemoveLineSet',
    pattern: '.npmignore',
    options: { message: 'chore(npm): update {{path}} from template' }
  },
  { merger: 'ReplaceIfEmpty', pattern: '**/*' }
];

export async function createFiles(branch, mapping = defaultMapping) {
  const files = await branch.list();
  let alreadyPresent = new Set();

  return mapping
    .map(m => {
      const found = mm(
        files.filter(f => f.type === 'blob').map(f => f.path),
        m.pattern
      );

      const notAlreadyProcessed = found.filter(f => !alreadyPresent.has(f));

      alreadyPresent = new Set([...Array.from(alreadyPresent), ...found]);

      return notAlreadyProcessed.map(f => {
        const merger =
          mergers.find(merger => merger.name === m.merger) || ReplaceIfEmpty;
        return new merger(f, m.options);
      });
    })
    .reduce((last, current) => Array.from([...last, ...current]), []);
}

/**
 * @param {RepositoryProvider} provider
 * @param {Branch} targetBranch
 * @param {Branch} templateBranch
 * @param {Object} options
 * @return {Promise<PullRequest>}
 */
export async function npmTemplateSync(
  provider,
  targetBranch,
  templateBranch,
  options
) {
  options = Object.assign(
    {
      logger: console,
      dry: false,
      trackUsedByModule: false
    },
    options
  );

  options.spinner.text = targetBranch.fullCondensedName;
  const condensedName = targetBranch.repository.condensedName;

  try {
    const context = new Context(
      targetBranch,
      undefined,
      {
        github: { user: targetBranch.owner, repo: condensedName },
        npm: { name: condensedName, fullName: condensedName },
        name: condensedName,
        user: targetBranch.owner,
        'date.year': new Date().getFullYear(),
        'license.owner': targetBranch.owner
      },
      options
    );

    const pkg = new Package('package.json');

    Object.assign(context.properties, await pkg.properties(context));

    if (templateBranch === undefined) {
      templateBranch = await provider.branch(context.properties.templateRepo);

      if (templateBranch === undefined) {
        throw new Error(
          `Unable to extract template repo url from ${targetBranch.name} ${
            pkg.path
          }`
        );
      }
    }

    context.templateBranch = templateBranch;

    context.logger.debug(
      `Using ${templateBranch.provider.name} as template provider`
    );

    const json = JSON.parse(
      await pkg.templateContent(context, { ignoreMissing: true })
    );

    if (options.trackUsedByModule) {
      const name = targetBranch.fullCondensedName;

      if (json.template === undefined) {
        json.template = {};
      }
      if (!Array.isArray(json.template.usedBy)) {
        json.template.usedBy = [];
      }

      if (!json.template.usedBy.find(n => n === name)) {
        json.template.usedBy.push(name);
        json.template.usedBy = json.template.usedBy.sort();

        let newPullRequest = false;
        let prBranch = await templateBranch.repository.branch(
          'template-add-used-1'
        );

        if (prBranch === undefined) {
          prBranch = await templateBranch.repository.createBranch(
            'template-add-used-1',
            context.templateBranch
          );
          newPullRequest = true;
        }

        await prBranch.commit(`fix: add ${name}`, [
          {
            path: 'package.json',
            content: JSON.stringify(json, undefined, 2)
          }
        ]);

        if (newPullRequest) {
          const pullRequest = await templateBranch.createPullRequest(prBranch, {
            title: `add ${name}`,
            body: `add tracking info for ${name}`
          });
        }
      }
    }

    const files = await createFiles(
      context.templateBranch,
      json.template && json.template.files
    );

    files.forEach(f => context.addFile(f));

    context.logger.debug(context.files.values());

    const merges = (await Promise.all(
      files.map(f => f.saveMerge(context))
    )).filter(m => m !== undefined && m.changed);

    if (merges.length === 0) {
      context.spinner.succeed(
        `${targetBranch.fullCondensedName}: nothing changed`
      );
      return;
    }

    context.spinner.text = merges
      .map(m => `${targetBranch.fullCondensedName}: ${m.messages[0]}`)
      .join(',');

    if (context.dry) {
      context.spinner.succeed(`${targetBranch.fullCondensedName}: dry run`);
      return;
    }

    let newPullRequestRequired = false;
    const prBranchName = 'template-sync-1';
    let prBranch = (await targetBranch.repository.branches()).get(prBranchName);

    if (prBranch === undefined) {
      newPullRequestRequired = true;
      prBranch = await targetBranch.repository.createBranch(
        prBranchName,
        targetBranch
      );
    }

    const messages = merges.reduce((result, merge) => {
      merge.messages.forEach(m => result.push(m));
      return result;
    }, []);

    await prBranch.commit(messages.join('\n'), merges);

    if (newPullRequestRequired) {
      try {
        const pullRequest = await targetBranch.createPullRequest(prBranch, {
          title: `merge package template from ${
            context.templateBranch.fullCondensedName
          }`,
          body: merges
            .map(
              m =>
                `${m.path}
---
- ${m.messages.join('\n- ')}
`
            )
            .join('\n')
        });
        context.spinner.succeed(
          `${targetBranch.fullCondensedName}: ${pullRequest.name}`
        );

        return pullRequest;
      } catch (err) {
        context.spinner.fail(err);
      }
    } else {
      const pullRequest = new targetBranch.provider.pullRequestClass(
        targetBranch.repository,
        'old'
      );

      context.spinner.succeed(`${targetBranch.fullCondensedName}: update PR`);
      return pullRequest;
    }
  } catch (err) {
    options.spinner.fail(`${targetBranch.fullCondensedName}: ${err}`);
    throw err;
  }
}
<|endoftext|>


<commit_before>'use strict';

const browsers = [
  'last 1 Chrome versions',
  'last 1 Firefox versions',
  'last 1 Safari versions',
];

const isCI = Boolean(process.env.CI);
const isProduction = process.env.EMBER_ENV === 'production';

if (isCI || isProduction) {
  browsers.push('ie 11');
}

module.exports = {
  browsers,
};
<commit_msg>testing without ie11<commit_after>'use strict';

const browsers = [
  'last 1 Chrome versions',
  'last 1 Firefox versions',
  'last 1 Safari versions',
];

const isCI = Boolean(process.env.CI);
const isProduction = process.env.EMBER_ENV === 'production';

if (isCI || isProduction) {
  //browsers.push('ie 11');
}

module.exports = {
  browsers,
};
<|endoftext|>


<commit_before>if (typeof define !== 'function') { var define = require('amdefine')(module) }
define(function (require) {

var SelectionCollection = require('es_client/models/selection_collection');
var Sheet = require('es_client/models/sheet');
var config = require('es_client/config');
var expect = require('chai').expect;
var should = require('chai').should();
var Backbone = require('backbone');
var SheetCollection = require('es_client/models/sheet_collection');

// stub out server calls
Backbone.sync = function(){};

describe('Selection', function(){
  var selection, sheet, col_id,row_id, events;

  var initializeSelection = function(){
    events = [];

    sheets = new SheetCollection();
    sheet = new Sheet();
    sheets.add(sheet);

    selections = new SelectionCollection([],{sheet_collection:sheets});
    selections.createLocal();
    selection = selections.getLocal();

    col_id = sheet.colAt(0);
    row_id = sheet.rowAt(0);
    selection.on('all',function(){
      events.push({
        name: arguments[0],
        args: Array.prototype.slice.call(arguments,1)
      });
    });
  };

  var clearEvents = function(){
    events = [];
  };

  describe('clear selection', function(){
    before(function(){
      initializeSelection();
      selection.addCell(sheet.id,row_id,col_id);
      selection.clear();
    });

    it('should be empty', function(){
      selection.getCells().length.should.equal(0);
    });
  });

  describe('add cell',function(){
    before(function(){
      initializeSelection();
      selection.addCell(sheet.id,row_id,col_id);
    });

    it('should increase the size of the selection',function(){
      selection.getCells().length.should.equal(1);
    });

    it('should add a cell to the selection',function(){
      var cell = selection.getCells()[0];
      cell.sheet_id.should.equal(sheet.id);
      cell.col_id.should.equal(col_id);
      cell.row_id.should.equal(row_id);
    });

    it('should emit an add_cell event', function(){
      events.length.should.equal(2);
      events[0].name.should.equal('add_cell');
      var cell = events[0].args[0];
      cell.sheet_id.should.equal(sheet.id);
      cell.col_id.should.equal(col_id);
      cell.row_id.should.equal(row_id);
    });
  });

  describe('update cell', function(){
    before(function(){
      initializeSelection();
      selection.addCell(sheet.id,row_id,col_id);
      clearEvents();
      sheet.updateCell(row_id,col_id,10)
    });

    it('should emit change when a cell changes value',function(){
      events.length.should.equal(1);
      events[0].name.should.equal('change');
    })
  });

  describe('remove cell', function(){
    beforeEach(function(){
      initializeSelection();
      selection.addCell(sheet.id,row_id,col_id);
      clearEvents();
    });

    it('should emit change when it\'s column is removed',function(){
      sheet.deleteCol(col_id);
      events.length.should.equal(1);
      events[0].name.should.equal('change');
    });

    it('should emit change when it\'s row is removed',function(){
      sheet.deleteRow(row_id);
      events.length.should.equal(1);
      events[0].name.should.equal('change');
    });

    it('should emit change when it\'s sheet is removed',function(){
      sheet.destroy();
      events.length.should.equal(3);
      events[0].name.should.equal('change');
    });
  });

  describe('Replication',function(){
    describe('requestReplication',function(){
      it('should send a copy of the local selection',function(done){
        initializeSelection();
        selection.addCell(sheet.id,'123','abc');
        var test_msg = {
          type: 'selection',
          action: 'replicateSelection',
          params:[selection.getData()]
        }
        selections.on('send',function(msg){
          expect(msg).to.deep.equal(test_msg);
          done();
        });
        selections.requestReplication();

      });
    })

    describe('replicateSelection',function(){
      var rep_data, rep_selection;

      beforeEach(function(){
        initializeSelection();
        rep_data = {id:'test_selection',color:'000000'};
        selections.replicateSelection(rep_data);
        rep_selection = selections.get('test_selection')
      });

      it('should create a copy of the selection',function(){
        expect(rep_selection.id).to.equal(rep_data.id);
      });

      it('replicated data should be correct',function(){
        rep_selection.getColor().should.equal('000000');
      });

    });
  });
});

});
<commit_msg>writing tests for some features that I spiked<commit_after>if (typeof define !== 'function') { var define = require('amdefine')(module) }
define(function (require) {

var SelectionCollection = require('es_client/models/selection_collection');
var Sheet = require('es_client/models/sheet');
var config = require('es_client/config');
var expect = require('chai').expect;
var should = require('chai').should();
var Backbone = require('backbone');
var SheetCollection = require('es_client/models/sheet_collection');

// stub out server calls
Backbone.sync = function(){};

describe('Selection', function(){
  var selection, sheet, col_id,row_id, events;

  var initializeSelection = function(){
    events = [];

    sheets = new SheetCollection();
    sheet = new Sheet();
    sheets.add(sheet);

    selections = new SelectionCollection([],{sheet_collection:sheets});
    selections.createLocal();
    selection = selections.getLocal();

    col_id = sheet.colAt(0);
    row_id = sheet.rowAt(0);
    selection.on('all',function(){
      events.push({
        name: arguments[0],
        args: Array.prototype.slice.call(arguments,1)
      });
    });
  };

  var clearEvents = function(){
    events = [];
  };

  describe('clear selection', function(){
    before(function(){
      initializeSelection();
      selection.addCell(sheet.id,row_id,col_id);
      clearEvents();
      selection.clear();
    });

    it('should be empty', function(){
      selection.getCells().length.should.equal(0);
    });

    it('should trigger a send event', function(){
      events[2].name.should.equal('send');
      events[2].args[0].action.should.equal('clear');
    });
  });

  describe('add cell',function(){
    before(function(){
      initializeSelection();
      selection.addCell(sheet.id,row_id,col_id);
    });

    it('should increase the size of the selection',function(){
      selection.getCells().length.should.equal(1);
    });

    it('should add a cell to the selection',function(){
      var cell = selection.getCells()[0];
      cell.sheet_id.should.equal(sheet.id);
      cell.col_id.should.equal(col_id);
      cell.row_id.should.equal(row_id);
    });

    it('should emit an add_cell event', function(){
      events.length.should.equal(2);
      events[0].name.should.equal('add_cell');
      var cell = events[0].args[0];
      cell.sheet_id.should.equal(sheet.id);
      cell.col_id.should.equal(col_id);
      cell.row_id.should.equal(row_id);
    });

    it('should trigger a send event', function(){
      events[1].name.should.equal('send');
      events[1].args[0].params[0].should.equal(sheet.id);
      events[1].args[0].params[1].should.equal(row_id);
      events[1].args[0].params[2].should.equal(col_id);
    });

  });

  describe('update cell', function(){
    before(function(){
      initializeSelection();
      selection.addCell(sheet.id,row_id,col_id);
      clearEvents();
      sheet.updateCell(row_id,col_id,10)
    });

    it('should emit change when a cell changes value',function(){
      events.length.should.equal(1);
      events[0].name.should.equal('change');
    })
  });

  describe('remove cell', function(){
    beforeEach(function(){
      initializeSelection();
      selection.addCell(sheet.id,row_id,col_id);
      clearEvents();
    });

    it('should emit change when it\'s column is removed',function(){
      sheet.deleteCol(col_id);
      events.length.should.equal(1);
      events[0].name.should.equal('change');
    });

    it('should emit change when it\'s row is removed',function(){
      sheet.deleteRow(row_id);
      events.length.should.equal(1);
      events[0].name.should.equal('change');
    });

    it('should emit change when it\'s sheet is removed',function(){
      sheet.destroy();
      events.length.should.equal(3);
      events[0].name.should.equal('change');
    });
  });

  describe('Replication',function(){
    describe('requestReplication',function(){
      it('should send a copy of the local selection',function(done){
        initializeSelection();
        selection.addCell(sheet.id,'123','abc');
        var test_msg = {
          type: 'selection',
          action: 'replicateSelection',
          params:[selection.getData()]
        }
        selections.on('send',function(msg){
          expect(msg).to.deep.equal(test_msg);
          done();
        });
        selections.requestReplication();

      });
    })

    describe('replicateSelection',function(){
      var rep_data, rep_selection;

      beforeEach(function(){
        initializeSelection();
        rep_data = {id:'test_selection',color:'000000', cells:[{sheet_id:sheet.id,row_id:'foo',col_id:'foo'}]};
        selections.replicateSelection(rep_data);
        rep_selection = selections.get('test_selection')
      });

      it('should create a copy of the selection',function(){
        expect(rep_selection.id).to.equal(rep_data.id);
      });

      it('replicated data should be correct',function(){
        rep_selection.getColor().should.equal('000000');
      });

      it('should call add cell for for each cell in the replication', function(){
        rep_selection.getCells().should.not.be.empty
      });
    });
  });
});

});
<|endoftext|>