<commit_before>$(document).ready(function() {

  // Create a client instance fro ZeroCipboard

  var datepicker = function(){
    // Displays a date/time picker when suggetsion field is focused
    $('input[data-role="primary-suggestion"]').datepicker({
      nextText: "▶",
      prevText: "◀",
      dateFormat: 'D, M dd yy',
      constrainInput: false,
    });

    $('input[data-role="secondary-suggestion"]').timepicker({
      timeFormat: 'hh:mm TT z',
      constrainInput: false,
      ampm: true,
      stepMinute: 5,
      hourGrid: 3,
      minuteGrid: 5,
      hour: 8,
      minute: 0,
      timezone: '',
      showTimezone: true,
      timezoneList: [
        { value: 'UTC-11', label: '(-11h) Pago Pago, Alofi' },
        { value: 'UTC-10', label: '(-10h) Honolulu, Papeete' },
        { value: 'UTC-9', label: '(-9h) Anchorage, Juneau' },
        { value: 'UTC-8', label: '(-8h) San Francisco, Vancouver' },
        { value: 'UTC-7', label: '(-7h) Denver, Edmonton' },
        { value: 'UTC-6', label: '(-6h) Chicago, Mexico City' },
        { value: 'UTC-5', label: '(-5h) New York City, Toronto' },
        { value: 'UTC-4', label: '(-4h) Santiago de Chile, Halifax' },
        { value: 'UTC-3', label: '(-3h) Rio de Janeiro, Buenos Aires' },
        { value: 'UTC-2', label: '(-2h) Fernando de Noronha' },
        { value: 'UTC-1', label: '(-1h) Praia, Ponta Delgada' },
        { value: 'UTC', label: '(UTC) London, Lisbon, Casablanca' },
        { value: '', label: 'Time zone not set' },
        { value: 'UTC+1', label: '(+1h) Madrid, Paris, Berlin, Rome' },
        { value: 'UTC+2', label: '(+2h) Helsinki, Athens, Cairo' },
        { value: 'UTC+3', label: '(+3h) Nairobi, Baghdad, Riyadh' },
        { value: 'UTC+4', label: '(+4h) Dubai, Moscow' },
        { value: 'UTC+5', label: '(+5h) Karachi, Lahore' },
        { value: 'UTC+6', label: '(+6h) Dhaka, Chittagong' },
        { value: 'UTC+7', label: '(+7h) Jakarta, Bangkok' },
        { value: 'UTC+8', label: '(+8h) Beijing, Singapore' },
        { value: 'UTC+9', label: '(+9h) Seoul, Tokyo' },
        { value: 'UTC+10', label: '(+10h) Sydney, Melbourne' },
        { value: 'UTC+11', label: '(+11h) Vladivostok, Noumea' },
        { value: 'UTC+12', label: '(+12h) Auckland, Wellington' },
        ]
    });
  };

  var addRemovalAnimation = function() {
    $('div.primary > div.times > a.remove_fields').click(function(){
      $(this).parents('div.nested-fields').addClass('deleted');
    });
    $('div.secondary a.remove_fields').click(function(){
      $(this).parent('div.nested-fields').addClass('deleted');
    });
  };

  datepicker();
  addRemovalAnimation();

  $.extend($.datepicker,{_checkOffset:function(inst,offset,isFixed){
    var dpHeight = inst.dpDiv.outerHeight();
    var inputHeight = inst.input ? inst.input.outerHeight() : 0;

    offset.top -= dpHeight + inputHeight + 10;
    offset.left -= (window.innerWidth < 430 ? 20 : 0);
    return offset;
  }});

  var forms = $('form[id*=new_event], form[id*="edit_event"]');
  forms.find('div.nested-fields input').removeAttr('maxlength');

  forms.bind('insertion-callback', function(){
    datepicker();
    addRemovalAnimation();

    // Animate new nodes
    var lastNode =  forms.find('div.nested-fields.primary:not(".initial"):last');
    lastNode.addClass('animated');

    $dateTimePickers = forms.find('div.nested-fields input')
    $dateTimePickers.removeAttr('maxlength');
  });

  // Prevent initial primary suggestion fields from animating
  $('div.nested-fields.primary').addClass('initial');

  bind_to_new_time_fields();
  bind_to_changed_primary_fields();

  $('#new_event ol').bind("insertion-callback", function() {
    bind_to_new_time_fields();
    bind_to_changed_primary_fields();
  });

  function bind_to_new_time_fields() {
    $('.nested-fields.primary').bind("insertion-callback", function() {
      var primary_suggestions = $(this).find("[data-role='primary-suggestion']");
      var primary_suggestion_value = primary_suggestions.first().val();
      primary_suggestions.last().val(primary_suggestion_value);
    });
  }

  function bind_to_changed_primary_fields() {
    $("[data-role='primary-suggestion']").change(function() {
      var primary_suggestions = $(this).parents('.nested-fields.primary')
        .first().find("[data-role='primary-suggestion']");
      var primary_suggestion_value = primary_suggestions.first().val();
      primary_suggestions.each(function(index) {
        $(this).val(primary_suggestion_value);
      });
    });
  }

  // Select event URL on click
   $("input#event-url").click(function() {
     $(this).select();
   });

  // Enable dragging in touch devices on tables
  if (Modernizr.touch) {
    $('table.touch-scrollable').addClass("scrollable horizontal")
  }

  // Enable click-to-copy
  var clip = new ZeroClipboard.Client();
  clip.addEventListener( 'mouseDown', function(client) {
    clip.setText( $('input#event-url').val());
    $('input#copy-url').val('URL Copied!');
  });

  clip.addEventListener( 'mouseOver', function(client) {
    $("input#copy-url").tooltip('show');
  });

   clip.addEventListener( 'mouseOut', function(client) {
    $("input#copy-url").tooltip('hide');
  });

  clip.glue( 'copy-url', 'copy-url-container' );

  $(window).resize(function(){
    clip.reposition();
  });

  $('#auto-complete').keyup(function(){
    var inviteButton = $(this).parents("form").find('.add-invitee');
    if($(this).val() != ""){
      inviteButton.show();
    } else {
      inviteButton.hide();
    }
  });

  // Shrink invitee name/email text size if it is too large to fit in the table cell
  $('div#invitees td').each(function(){
    var stringLength = $(this).html().length;
    if (stringLength > 60) {
      $(this).css('font-size','0.8em');
    }
    else if (stringLength > 55) {
      $(this).css('font-size','0.85em');
    }
    else if (stringLength > 50) {
      $(this).css('font-size','0.9em');
    }
  });
});
<commit_msg>Remove stray comment.<commit_after>$(document).ready(function() {

  var datepicker = function(){
    // Displays a date/time picker when suggetsion field is focused
    $('input[data-role="primary-suggestion"]').datepicker({
      nextText: "▶",
      prevText: "◀",
      dateFormat: 'D, M dd yy',
      constrainInput: false,
    });

    $('input[data-role="secondary-suggestion"]').timepicker({
      timeFormat: 'hh:mm TT z',
      constrainInput: false,
      ampm: true,
      stepMinute: 5,
      hourGrid: 3,
      minuteGrid: 5,
      hour: 8,
      minute: 0,
      timezone: '',
      showTimezone: true,
      timezoneList: [
        { value: 'UTC-11', label: '(-11h) Pago Pago, Alofi' },
        { value: 'UTC-10', label: '(-10h) Honolulu, Papeete' },
        { value: 'UTC-9', label: '(-9h) Anchorage, Juneau' },
        { value: 'UTC-8', label: '(-8h) San Francisco, Vancouver' },
        { value: 'UTC-7', label: '(-7h) Denver, Edmonton' },
        { value: 'UTC-6', label: '(-6h) Chicago, Mexico City' },
        { value: 'UTC-5', label: '(-5h) New York City, Toronto' },
        { value: 'UTC-4', label: '(-4h) Santiago de Chile, Halifax' },
        { value: 'UTC-3', label: '(-3h) Rio de Janeiro, Buenos Aires' },
        { value: 'UTC-2', label: '(-2h) Fernando de Noronha' },
        { value: 'UTC-1', label: '(-1h) Praia, Ponta Delgada' },
        { value: 'UTC', label: '(UTC) London, Lisbon, Casablanca' },
        { value: '', label: 'Time zone not set' },
        { value: 'UTC+1', label: '(+1h) Madrid, Paris, Berlin, Rome' },
        { value: 'UTC+2', label: '(+2h) Helsinki, Athens, Cairo' },
        { value: 'UTC+3', label: '(+3h) Nairobi, Baghdad, Riyadh' },
        { value: 'UTC+4', label: '(+4h) Dubai, Moscow' },
        { value: 'UTC+5', label: '(+5h) Karachi, Lahore' },
        { value: 'UTC+6', label: '(+6h) Dhaka, Chittagong' },
        { value: 'UTC+7', label: '(+7h) Jakarta, Bangkok' },
        { value: 'UTC+8', label: '(+8h) Beijing, Singapore' },
        { value: 'UTC+9', label: '(+9h) Seoul, Tokyo' },
        { value: 'UTC+10', label: '(+10h) Sydney, Melbourne' },
        { value: 'UTC+11', label: '(+11h) Vladivostok, Noumea' },
        { value: 'UTC+12', label: '(+12h) Auckland, Wellington' },
        ]
    });
  };

  var addRemovalAnimation = function() {
    $('div.primary > div.times > a.remove_fields').click(function(){
      $(this).parents('div.nested-fields').addClass('deleted');
    });
    $('div.secondary a.remove_fields').click(function(){
      $(this).parent('div.nested-fields').addClass('deleted');
    });
  };

  datepicker();
  addRemovalAnimation();

  $.extend($.datepicker,{_checkOffset:function(inst,offset,isFixed){
    var dpHeight = inst.dpDiv.outerHeight();
    var inputHeight = inst.input ? inst.input.outerHeight() : 0;

    offset.top -= dpHeight + inputHeight + 10;
    offset.left -= (window.innerWidth < 430 ? 20 : 0);
    return offset;
  }});

  var forms = $('form[id*=new_event], form[id*="edit_event"]');
  forms.find('div.nested-fields input').removeAttr('maxlength');

  forms.bind('insertion-callback', function(){
    datepicker();
    addRemovalAnimation();

    // Animate new nodes
    var lastNode =  forms.find('div.nested-fields.primary:not(".initial"):last');
    lastNode.addClass('animated');

    $dateTimePickers = forms.find('div.nested-fields input')
    $dateTimePickers.removeAttr('maxlength');
  });

  // Prevent initial primary suggestion fields from animating
  $('div.nested-fields.primary').addClass('initial');

  bind_to_new_time_fields();
  bind_to_changed_primary_fields();

  $('#new_event ol').bind("insertion-callback", function() {
    bind_to_new_time_fields();
    bind_to_changed_primary_fields();
  });

  function bind_to_new_time_fields() {
    $('.nested-fields.primary').bind("insertion-callback", function() {
      var primary_suggestions = $(this).find("[data-role='primary-suggestion']");
      var primary_suggestion_value = primary_suggestions.first().val();
      primary_suggestions.last().val(primary_suggestion_value);
    });
  }

  function bind_to_changed_primary_fields() {
    $("[data-role='primary-suggestion']").change(function() {
      var primary_suggestions = $(this).parents('.nested-fields.primary')
        .first().find("[data-role='primary-suggestion']");
      var primary_suggestion_value = primary_suggestions.first().val();
      primary_suggestions.each(function(index) {
        $(this).val(primary_suggestion_value);
      });
    });
  }

  // Select event URL on click
   $("input#event-url").click(function() {
     $(this).select();
   });

  // Enable dragging in touch devices on tables
  if (Modernizr.touch) {
    $('table.touch-scrollable').addClass("scrollable horizontal")
  }

  // Enable click-to-copy
  var clip = new ZeroClipboard.Client();
  clip.addEventListener( 'mouseDown', function(client) {
    clip.setText( $('input#event-url').val());
    $('input#copy-url').val('URL Copied!');
  });

  clip.addEventListener( 'mouseOver', function(client) {
    $("input#copy-url").tooltip('show');
  });

   clip.addEventListener( 'mouseOut', function(client) {
    $("input#copy-url").tooltip('hide');
  });

  clip.glue( 'copy-url', 'copy-url-container' );

  $(window).resize(function(){
    clip.reposition();
  });

  $('#auto-complete').keyup(function(){
    var inviteButton = $(this).parents("form").find('.add-invitee');
    if($(this).val() != ""){
      inviteButton.show();
    } else {
      inviteButton.hide();
    }
  });

  // Shrink invitee name/email text size if it is too large to fit in the table cell
  $('div#invitees td').each(function(){
    var stringLength = $(this).html().length;
    if (stringLength > 60) {
      $(this).css('font-size','0.8em');
    }
    else if (stringLength > 55) {
      $(this).css('font-size','0.85em');
    }
    else if (stringLength > 50) {
      $(this).css('font-size','0.9em');
    }
  });
});
<|endoftext|>


<commit_before>require([ "jquery" ], function($) {

  "use strict";

  require([
    "lib/page/swipe",
    "lib/utils/konami",
    "lib/page/scroll_perf",
    "lib/styleguide/charts",
    "lib/components/poi_map",
    "lib/components/poi_list",
    "lib/components/slider",
    "lib/components/toggle_active",
    "lib/components/select_group_manager",
    "lib/components/page_hopper",
    "lib/components/parallax",
    "lib/styleguide/svg",
    "lib/styleguide/copy",
    "lib/styleguide/swipe",
    "pickadate/lib/legacy",
    "pickadate/lib/picker",
    "lib/styleguide/konami",
    "lib/styleguide/colours",
    "lib/components/lightbox",
    "lib/styleguide/lightbox",
    "lib/styleguide/typography",
    "pickadate/lib/picker.date",
    "lib/utils/last_input_device",
    "lib/components/range_slider",
    "lib/styleguide/snippet-expand"
  ], function(Swipe, Konami, ScrollPerf, Charts, POIMap, POIList, Slider, ToggleActive, SelectGroupManager, PageHopper) {

    new ScrollPerf();
    new ToggleActive();
    new Konami();
    new Swipe();
    new POIList(null, new POIMap);
    new Slider({ el: ".js-slider", assetReveal: true });
    new SelectGroupManager();
    new PageHopper();

    var d = new Date();
    $(".input--datepicker").pickadate({
      min: [ d.getFullYear(), (d.getMonth() + 1), d.getDate() ]
    });

  });
});
<commit_msg>Restore line length loveliness to the world<commit_after>require([ "jquery" ], function($) {

  "use strict";

  require([
    "lib/page/swipe",
    "lib/utils/konami",
    "lib/page/scroll_perf",
    "lib/components/slider",
    "lib/styleguide/charts",
    "lib/components/poi_map",
    "lib/components/poi_list",
    "lib/components/page_hopper",
    "lib/components/toggle_active",
    "lib/components/select_group_manager",
    "lib/styleguide/svg",
    "lib/styleguide/copy",
    "lib/styleguide/swipe",
    "pickadate/lib/legacy",
    "pickadate/lib/picker",
    "lib/styleguide/konami",
    "lib/styleguide/colours",
    "lib/components/lightbox",
    "lib/styleguide/lightbox",
    "lib/components/parallax",
    "lib/styleguide/typography",
    "pickadate/lib/picker.date",
    "lib/utils/last_input_device",
    "lib/components/range_slider",
    "lib/styleguide/snippet-expand"
  ], function(Swipe, Konami, ScrollPerf, Slider, Charts, POIMap, POIList, PageHopper, ToggleActive, SelectGroupManager) {

    new ScrollPerf();
    new ToggleActive();
    new Konami();
    new Swipe();
    new POIList(null, new POIMap);
    new Slider({ el: ".js-slider", assetReveal: true });
    new SelectGroupManager();
    new PageHopper();

    var d = new Date();
    $(".input--datepicker").pickadate({
      min: [ d.getFullYear(), (d.getMonth() + 1), d.getDate() ]
    });

  });
});
<|endoftext|>


<commit_before>(function() {
  document.addEventListener('trix-initialize', function(e) {
    trix = e.target;
    toolBar = trix.toolbarElement;

    // Creation of the button
    button = document.createElement("button");
    button.setAttribute("type", "button");
    button.setAttribute("class", "embed");
    button.setAttribute("data-trix-attribute", "insertEmbed");
    button.setAttribute("title", "Insérer une iframe");
    button.innerText = "Insérer une iframe";

    // Attachment of the button to the toolBar
    formulaButton = toolBar.querySelector('.button_group.text_tools').appendChild(button);

    // Creating the dialog
    dialog = document.createElement("div");
    dialog.setAttribute("class", "dialog embed-dialog");
    dialog.setAttribute("data-trix-dialog", "insertEmbed");
    dialog.innerHTML = '

Coller le code iframe
<textarea id="EmbeddedCode" style="width: 100%;"></textarea><button class="btn btn-insert-embed">Insérer

'
    // Attaching the dialog
    toolBar.querySelector('.dialogs').appendChild(dialog);

    // Insert math
    $('a.btn-insert-embed').on('click', function(event) {
      event.preventDefault();
      var element = document.querySelector('trix-editor');
      var embedded = $('#EmbeddedCode').val();
      element.editor.insertAttachment(new Trix.Attachment({content: embedded}));
      element.focus();
    });
  });
}).call(this);
<commit_msg>fix insert embed listener<commit_after>(function() {
  document.addEventListener('trix-initialize', function(e) {
    trix = e.target;
    toolBar = trix.toolbarElement;

    // Creation of the button
    button = document.createElement("button");
    button.setAttribute("type", "button");
    button.setAttribute("class", "embed");
    button.setAttribute("data-trix-attribute", "insertEmbed");
    button.setAttribute("title", "Insérer une iframe");
    button.innerText = "Insérer une iframe";

    // Attachment of the button to the toolBar
    formulaButton = toolBar.querySelector('.button_group.text_tools').appendChild(button);

    // Creating the dialog
    dialog = document.createElement("div");
    dialog.setAttribute("class", "dialog embed-dialog");
    dialog.setAttribute("data-trix-dialog", "insertEmbed");
    dialog.innerHTML = '

Coller le code iframe
<textarea id="EmbeddedCode" style="width: 100%;"></textarea><button class="btn btn-insert-embed">Insérer

'
    // Attaching the dialog
    toolBar.querySelector('.dialogs').appendChild(dialog);

    // Insert math
    $('button.btn-insert-embed').on('click', function(event) {
      event.preventDefault();
      var element = document.querySelector('trix-editor');
      var embedded = $('#EmbeddedCode').val();
      element.editor.insertAttachment(new Trix.Attachment({content: embedded}));
      element.focus();
    });
  });
}).call(this);
<|endoftext|>


<commit_before>var log4js = require('log4js');
var PlurkClient = require('plurk').PlurkClient;
var nconf = require('nconf');
nconf.file('config', __dirname + '/config/config.json')
	.file('keywords', __dirname + '/config/keywords.json');

var filter = require(__dirname + '/lib/contentfilter');
var action = require(__dirname + '/lib/action');

var logging = nconf.get('log').logging;
var log_path = nconf.get('log').log_path;

if (logging) {
	log4js.clearAppenders();
	log4js.loadAppender('file');
	log4js.addAppender(log4js.appenders.file(log_path), 'BOT_LOG');
}

var logger = log4js.getLogger('BOT_LOG');

var consumerKey = nconf.get('token').consume_key;
var consumerSecret = nconf.get('token').consume_secret;
var accessToken = nconf.get('token').access_token;
var accessTokenSecret = nconf.get('token').access_token_secret;

var summon_keywords = nconf.get('summon_keywords').keywords_list;
var keywords = nconf.get('keywords').keywords_list;

var verifiyKeyword = filter.verifiyKeyword;

var client = new PlurkClient(true, consumerKey, consumerSecret, accessToken, accessTokenSecret);

var rec;

rec = checkTL;

client.startComet(function(err, data, cometUrl) {

	if (err) {
		logger.error(err);
		return;
	}

	logger.info('Comet channel started.');

	rec(cometUrl);

});

function checkTL(reqUrl) {

	client.rq('Alerts/addAllAsFriends');

	client.comet(reqUrl, function(err, cometData, newUrl) {
		if (err) {
            logger.error('There are some error ! ', err);
			rec(cometUrl);
			return;
		}

		var msgs = cometData.data;

		if (msgs && Array.isArray(msgs)) {

			msgs.filter(function(data) {
				return (data && (data.type === 'new_plurk'));
			}).forEach(function(data) {

				var content = data.content_raw;

				var response = verifiyKeyword(keywords, content);

				if(response){

					action.respond(client, plurkId, response);
				}
			});
		}
		rec(newUrl);
	});
}
<commit_msg>Will call filter.verifiyKeyword directly<commit_after>var log4js = require('log4js');
var PlurkClient = require('plurk').PlurkClient;
var nconf = require('nconf');
nconf.file('config', __dirname + '/config/config.json')
	.file('keywords', __dirname + '/config/keywords.json');

var filter = require(__dirname + '/lib/contentfilter');
var action = require(__dirname + '/lib/action');

var logging = nconf.get('log').logging;
var log_path = nconf.get('log').log_path;

if (logging) {
	log4js.clearAppenders();
	log4js.loadAppender('file');
	log4js.addAppender(log4js.appenders.file(log_path), 'BOT_LOG');
}

var logger = log4js.getLogger('BOT_LOG');

var consumerKey = nconf.get('token').consume_key;
var consumerSecret = nconf.get('token').consume_secret;
var accessToken = nconf.get('token').access_token;
var accessTokenSecret = nconf.get('token').access_token_secret;

var summon_keywords = nconf.get('summon_keywords').keywords_list;
var keywords = nconf.get('keywords').keywords_list;

var client = new PlurkClient(true, consumerKey, consumerSecret, accessToken, accessTokenSecret);

var rec;

rec = checkTL;

client.startComet(function(err, data, cometUrl) {

	if (err) {
		logger.error(err);
		return;
	}

	logger.info('Comet channel started.');

	rec(cometUrl);

});

function checkTL(reqUrl) {

	client.rq('Alerts/addAllAsFriends');

	client.comet(reqUrl, function(err, cometData, newUrl) {
		if (err) {
            logger.error('There are some error ! ', err);
			rec(cometUrl);
			return;
		}

		var msgs = cometData.data;

		if (msgs && Array.isArray(msgs)) {

			msgs.filter(function(data) {
				return (data && (data.type === 'new_plurk'));
			}).forEach(function(data) {

				var content = data.content_raw;

				var response = filter.verifiyKeyword(keywords, content);

				if(response){

					action.respond(client, plurkId, response);
				}
			});
		}
		rec(newUrl);
	});
}
<|endoftext|>


<commit_before>var Backbone = require('backbone');
var ConfigModel = require('builder/data/config-model');
var UserModel = require('builder/data/user-model');
var LayerDefinitionsCollection = require('builder/data/layer-definitions-collection');
var AnalysisDefinitionsCollection = require('builder/data/analysis-definitions-collection');
var AnalysisDefinitionNodesCollection = require('builder/data/analysis-definition-nodes-collection');

describe('builder/data/analysis-definitions-collection', function () {
  beforeEach(function () {
    this.configModel = new ConfigModel({
      base_url: '/u/pepe'
    });

    this.userModel = new UserModel({}, {
      configModel: this.configModel
    });

    this.analysisDefinitionNodesCollection = new AnalysisDefinitionNodesCollection(null, {
      configModel: this.configModel,
      userModel: this.userModel
    });

    this.collection = new AnalysisDefinitionsCollection(null, {
      vizId: 'v-123',
      analysisDefinitionNodesCollection: this.analysisDefinitionNodesCollection,
      configModel: this.configModel
    });

    this.A = this.collection.add({
      id: 'A',
      analysis_definition: {
        id: 'a1',
        type: 'buffer',
        params: {
          radius: 100,
          source: {
            id: 'a0',
            type: 'source',
            params: {
              query: 'SELECT * FROM somewhere'
            }
          }
        }
      }
    });
    this.B = this.collection.add({
      id: 'B',
      analysis_definition: {
        id: 'b1',
        type: 'buffer',
        params: {
          radius: 100,
          source: {
            id: 'a1'
          }
        }
      }
    });
    this.C = this.collection.add({
      id: 'C',
      analysis_definition: {
        id: 'c1',
        type: 'buffer',
        params: {
          source: {
            id: 'b1'
          }
        }
      }
    });

    this.originalAjax = Backbone.ajax;
    Backbone.ajax = function () {
      return {
        always: function (cb) {
          cb();
        }
      };
    };
  });

  afterEach(function () {
    Backbone.ajax = this.originalAjax;
  });

  describe('.url', function () {
    it('should return URL', function () {
      expect(this.collection.url()).toMatch(/\/analyses$/);
    });
  });

  describe('.findAnalysisThatContainsNode', function () {
    describe('when given a node that does not have any analysis', function () {
      it('should return undefined', function () {
        expect(this.collection.findAnalysisThatContainsNode({id: 'x123'})).toBeUndefined();
      });
    });

    describe('when given a node is root', function () {
      it('should return the analysis', function () {
        expect(this.collection.findAnalysisThatContainsNode({id: 'c1'})).toBeDefined();
      });
    });

    describe('when given a node is contained in an analysis', function () {
      it('should return the analysis', function () {
        expect(this.collection.findAnalysisThatContainsNode({id: 'a0'})).toBeDefined();
      });
    });
  });

  describe('.saveAnalysisForLayer', function () {
    beforeEach(function () {
      this.a0 = this.analysisDefinitionNodesCollection.get('a0');
      this.a1 = this.analysisDefinitionNodesCollection.get('a1');
      this.b1 = this.analysisDefinitionNodesCollection.get('b1');
      this.c1 = this.analysisDefinitionNodesCollection.get('c1');

      this.x1 = this.analysisDefinitionNodesCollection.add({
        id: 'x1',
        type: 'buffer',
        params: {
          radius: 100,
          source: {
            id: 'a1'
          }
        }
      });

      this.layerDefinitionsCollection = new LayerDefinitionsCollection(null, {
        configModel: this.configModel,
        userModel: this.userModel,
        analysisDefinitionNodesCollection: this.analysisDefinitionNodesCollection,
        mapId: '123',
        stateDefinitionModel: {}
      });
      this.layerA = this.layerDefinitionsCollection.add({
        id: 'layerA',
        kind: 'carto',
        options: {
          letter: 'a',
          source: 'a1'
        }
      });
      this.layerB = this.layerDefinitionsCollection.add({
        id: 'layerB',
        kind: 'carto',
        options: {
          letter: 'b',
          source: 'b1'
        }
      });
      this.layerC = this.layerDefinitionsCollection.add({
        id: 'layerC',
        kind: 'carto',
        options: {
          letter: 'c',
          source: 'c1'
        }
      });
      this.layerX = this.layerDefinitionsCollection.add({
        id: 'layerX',
        kind: 'carto',
        options: {
          letter: 'x',
          source: 'x1'
        }
      });
      this.beforeSaveSpy = jasmine.createSpy('beforeSave');
      spyOn(this.A, 'save');
      spyOn(this.B, 'save');
      spyOn(this.C, 'save');
      spyOn(this.layerA, 'save');
      spyOn(this.layerB, 'save');
      spyOn(this.layerC, 'save');
    });

    describe('when given a layer with an already persisted analysis', function () {
      it('should save all analysis containing node', function () {
        this.collection.saveAnalysisForLayer(this.layerA);
        expect(this.A.save).toHaveBeenCalled();
        expect(this.B.save).toHaveBeenCalled();
        expect(this.C.save).toHaveBeenCalled();

        this.A.save.calls.reset();
        this.B.save.calls.reset();
        this.collection.saveAnalysisForLayer(this.layerB);
        expect(this.A.save).not.toHaveBeenCalled();
        expect(this.B.save).toHaveBeenCalled();
        expect(this.C.save).toHaveBeenCalled();
      });

      it('should save only the analysis of which is the main node if the "containingAnalysisNode" flag is set to false', function() {
        this.collection.saveAnalysisForLayer(this.layerA, false);
        expect(this.A.save).toHaveBeenCalled();
        expect(this.B.save).not.toHaveBeenCalled();
        expect(this.C.save).not.toHaveBeenCalled();
      });
    });

    describe('when given a layer has a source that is owned by another layer', function () {
      describe('when has a persisted analysis', function () {
        beforeEach(function () {
          this.layerB.set('source', 'a0');
          this.collection.saveAnalysisForLayer(this.layerB);
        });

        it('should destroy analysis that existed for layer', function () {
          expect(this.collection.pluck('node_id')).toEqual(['a1', 'c1']);
        });
      });

      describe('when has no persisted analysis', function () {
        beforeEach(function () {
          this.layerX.set('source', 'a0');
          this.collection.saveAnalysisForLayer(this.layerX);
        });

        it('should not create any analysis since its already persisted for its owning layer', function () {
          expect(this.collection.pluck('node_id')).toEqual(['a1', 'b1', 'c1']);
        });
      });
    });

    describe('when a node is added on a node', function () {
      beforeEach(function () {
        this.analysisDefinitionNodesCollection.add({
          id: 'b2',
          type: 'buffer',
          params: {
            source: {
              id: 'b1'
            }
          }
        });
        this.layerB.set('source', 'b2');
        this.collection.saveAnalysisForLayer(this.layerB);
      });

      it('should update affected analysis', function () {
        expect(this.A.save).not.toHaveBeenCalled();
        expect(this.B.save).toHaveBeenCalled();
        expect(this.C.save).not.toHaveBeenCalled();
      });

      it('should updated analysis', function () {
        expect(this.collection.pluck('node_id').sort()).toEqual(['a1', 'b2', 'c1'], 'should contain x1 in addition to the others');
      });
    });

    describe('when given a layer with a node that is not yet saved', function () {
      beforeEach(function () {
        this.collection.saveAnalysisForLayer(this.layerX);
      });

      it('should save layer after creating node if given a layer', function () {
        expect(this.collection.pluck('node_id').sort()).toEqual(['a1', 'b1', 'c1', 'x1'], 'should contain x1 in addition to the others');
      });
    });
  });

  describe('.newAnalysisForNode', function () {
    beforeEach(function () {
      this.nodeDefModel = new Backbone.Model();
      this.JSON = {
        id: 'x0',
        type: 'source',
        params: {
          query: 'SELECT * FROM a_table'
        }
      };
      spyOn(this.nodeDefModel, 'toJSON').and.returnValue(this.JSON);
      this.model = this.collection.newAnalysisForNode(this.nodeDefModel);
    });

    it('should return a new model', function () {
      expect(this.model).toBeDefined();
    });

    it('should point to the given node id', function () {
      expect(this.model.get('node_id')).toEqual('x0');
    });
  });
});
<commit_msg>Fix linter issues<commit_after>var Backbone = require('backbone');
var ConfigModel = require('builder/data/config-model');
var UserModel = require('builder/data/user-model');
var LayerDefinitionsCollection = require('builder/data/layer-definitions-collection');
var AnalysisDefinitionsCollection = require('builder/data/analysis-definitions-collection');
var AnalysisDefinitionNodesCollection = require('builder/data/analysis-definition-nodes-collection');

describe('builder/data/analysis-definitions-collection', function () {
  beforeEach(function () {
    this.configModel = new ConfigModel({
      base_url: '/u/pepe'
    });

    this.userModel = new UserModel({}, {
      configModel: this.configModel
    });

    this.analysisDefinitionNodesCollection = new AnalysisDefinitionNodesCollection(null, {
      configModel: this.configModel,
      userModel: this.userModel
    });

    this.collection = new AnalysisDefinitionsCollection(null, {
      vizId: 'v-123',
      analysisDefinitionNodesCollection: this.analysisDefinitionNodesCollection,
      configModel: this.configModel
    });

    this.A = this.collection.add({
      id: 'A',
      analysis_definition: {
        id: 'a1',
        type: 'buffer',
        params: {
          radius: 100,
          source: {
            id: 'a0',
            type: 'source',
            params: {
              query: 'SELECT * FROM somewhere'
            }
          }
        }
      }
    });
    this.B = this.collection.add({
      id: 'B',
      analysis_definition: {
        id: 'b1',
        type: 'buffer',
        params: {
          radius: 100,
          source: {
            id: 'a1'
          }
        }
      }
    });
    this.C = this.collection.add({
      id: 'C',
      analysis_definition: {
        id: 'c1',
        type: 'buffer',
        params: {
          source: {
            id: 'b1'
          }
        }
      }
    });

    this.originalAjax = Backbone.ajax;
    Backbone.ajax = function () {
      return {
        always: function (cb) {
          cb();
        }
      };
    };
  });

  afterEach(function () {
    Backbone.ajax = this.originalAjax;
  });

  describe('.url', function () {
    it('should return URL', function () {
      expect(this.collection.url()).toMatch(/\/analyses$/);
    });
  });

  describe('.findAnalysisThatContainsNode', function () {
    describe('when given a node that does not have any analysis', function () {
      it('should return undefined', function () {
        expect(this.collection.findAnalysisThatContainsNode({id: 'x123'})).toBeUndefined();
      });
    });

    describe('when given a node is root', function () {
      it('should return the analysis', function () {
        expect(this.collection.findAnalysisThatContainsNode({id: 'c1'})).toBeDefined();
      });
    });

    describe('when given a node is contained in an analysis', function () {
      it('should return the analysis', function () {
        expect(this.collection.findAnalysisThatContainsNode({id: 'a0'})).toBeDefined();
      });
    });
  });

  describe('.saveAnalysisForLayer', function () {
    beforeEach(function () {
      this.a0 = this.analysisDefinitionNodesCollection.get('a0');
      this.a1 = this.analysisDefinitionNodesCollection.get('a1');
      this.b1 = this.analysisDefinitionNodesCollection.get('b1');
      this.c1 = this.analysisDefinitionNodesCollection.get('c1');

      this.x1 = this.analysisDefinitionNodesCollection.add({
        id: 'x1',
        type: 'buffer',
        params: {
          radius: 100,
          source: {
            id: 'a1'
          }
        }
      });

      this.layerDefinitionsCollection = new LayerDefinitionsCollection(null, {
        configModel: this.configModel,
        userModel: this.userModel,
        analysisDefinitionNodesCollection: this.analysisDefinitionNodesCollection,
        mapId: '123',
        stateDefinitionModel: {}
      });
      this.layerA = this.layerDefinitionsCollection.add({
        id: 'layerA',
        kind: 'carto',
        options: {
          letter: 'a',
          source: 'a1'
        }
      });
      this.layerB = this.layerDefinitionsCollection.add({
        id: 'layerB',
        kind: 'carto',
        options: {
          letter: 'b',
          source: 'b1'
        }
      });
      this.layerC = this.layerDefinitionsCollection.add({
        id: 'layerC',
        kind: 'carto',
        options: {
          letter: 'c',
          source: 'c1'
        }
      });
      this.layerX = this.layerDefinitionsCollection.add({
        id: 'layerX',
        kind: 'carto',
        options: {
          letter: 'x',
          source: 'x1'
        }
      });
      this.beforeSaveSpy = jasmine.createSpy('beforeSave');
      spyOn(this.A, 'save');
      spyOn(this.B, 'save');
      spyOn(this.C, 'save');
      spyOn(this.layerA, 'save');
      spyOn(this.layerB, 'save');
      spyOn(this.layerC, 'save');
    });

    describe('when given a layer with an already persisted analysis', function () {
      it('should save all analysis containing node', function () {
        this.collection.saveAnalysisForLayer(this.layerA);
        expect(this.A.save).toHaveBeenCalled();
        expect(this.B.save).toHaveBeenCalled();
        expect(this.C.save).toHaveBeenCalled();

        this.A.save.calls.reset();
        this.B.save.calls.reset();
        this.collection.saveAnalysisForLayer(this.layerB);
        expect(this.A.save).not.toHaveBeenCalled();
        expect(this.B.save).toHaveBeenCalled();
        expect(this.C.save).toHaveBeenCalled();
      });

      it('should save only the analysis of which is the main node if the "containingAnalysisNode" flag is set to false', function () {
        this.collection.saveAnalysisForLayer(this.layerA, false);
        expect(this.A.save).toHaveBeenCalled();
        expect(this.B.save).not.toHaveBeenCalled();
        expect(this.C.save).not.toHaveBeenCalled();
      });
    });

    describe('when given a layer has a source that is owned by another layer', function () {
      describe('when has a persisted analysis', function () {
        beforeEach(function () {
          this.layerB.set('source', 'a0');
          this.collection.saveAnalysisForLayer(this.layerB);
        });

        it('should destroy analysis that existed for layer', function () {
          expect(this.collection.pluck('node_id')).toEqual(['a1', 'c1']);
        });
      });

      describe('when has no persisted analysis', function () {
        beforeEach(function () {
          this.layerX.set('source', 'a0');
          this.collection.saveAnalysisForLayer(this.layerX);
        });

        it('should not create any analysis since its already persisted for its owning layer', function () {
          expect(this.collection.pluck('node_id')).toEqual(['a1', 'b1', 'c1']);
        });
      });
    });

    describe('when a node is added on a node', function () {
      beforeEach(function () {
        this.analysisDefinitionNodesCollection.add({
          id: 'b2',
          type: 'buffer',
          params: {
            source: {
              id: 'b1'
            }
          }
        });
        this.layerB.set('source', 'b2');
        this.collection.saveAnalysisForLayer(this.layerB);
      });

      it('should update affected analysis', function () {
        expect(this.A.save).not.toHaveBeenCalled();
        expect(this.B.save).toHaveBeenCalled();
        expect(this.C.save).not.toHaveBeenCalled();
      });

      it('should updated analysis', function () {
        expect(this.collection.pluck('node_id').sort()).toEqual(['a1', 'b2', 'c1'], 'should contain x1 in addition to the others');
      });
    });

    describe('when given a layer with a node that is not yet saved', function () {
      beforeEach(function () {
        this.collection.saveAnalysisForLayer(this.layerX);
      });

      it('should save layer after creating node if given a layer', function () {
        expect(this.collection.pluck('node_id').sort()).toEqual(['a1', 'b1', 'c1', 'x1'], 'should contain x1 in addition to the others');
      });
    });
  });

  describe('.newAnalysisForNode', function () {
    beforeEach(function () {
      this.nodeDefModel = new Backbone.Model();
      this.JSON = {
        id: 'x0',
        type: 'source',
        params: {
          query: 'SELECT * FROM a_table'
        }
      };
      spyOn(this.nodeDefModel, 'toJSON').and.returnValue(this.JSON);
      this.model = this.collection.newAnalysisForNode(this.nodeDefModel);
    });

    it('should return a new model', function () {
      expect(this.model).toBeDefined();
    });

    it('should point to the given node id', function () {
      expect(this.model.get('node_id')).toEqual('x0');
    });
  });
});
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var parallel = require('run-parallel');
var EventEmitter = require('events').EventEmitter;
var inherits = require('util').inherits;

var errors = require('./errors');

function TChannelRequest(channel, options) {
    options = options || {};
    if (options.streamed) {
        throw new Error('streaming request federation not supported');
    }
    var self = this;
    EventEmitter.call(self);
    self.channel = channel;
    self.logger = self.channel.logger;
    self.random = self.channel.random;
    self.timers = self.channel.timers;

    self.options = options;

    if (!self.options.retryFlags) {
        self.options.retryFlags = {
            never: false,
            onConnectionError: true,
            onTimeout: false
        };
    }

    self.triedRemoteAddrs = {};
    self.outReqs = [];
    self.timeout = self.options.timeout || TChannelRequest.defaultTimeout;
    self.limit = self.options.retryLimit || TChannelRequest.defaultRetryLimit;
    self.start = 0;
    self.end = 0;
    self.elapsed = 0;
    self.resendSanity = 0;

    self.service = options.service || '';
    self.headers = self.options.headers || {}; // so that as-foo can punch req.headers.X
    self.options.headers = self.headers; // for passing to peer.request(opts) later

    self.arg1 = null;
    self.arg2 = null;
    self.arg3 = null;

    self.err = null;
    self.res = null;
    self.on('error', self.onError);
    self.on('response', self.onResponse);
}

inherits(TChannelRequest, EventEmitter);

TChannelRequest.defaultRetryLimit = 5;
TChannelRequest.defaultTimeout = 5000;

TChannelRequest.prototype.type = 'tchannel.request';

TChannelRequest.prototype.onError = function onError(err) {
    var self = this;
    if (!self.end) self.end = self.timers.now();
    self.err = err;
};

TChannelRequest.prototype.onResponse = function onResponse(res) {
    var self = this;
    if (!self.end) self.end = self.timers.now();
    self.res = res;
};

TChannelRequest.prototype.hookupStreamCallback = function hookupCallback(callback) {
    throw new Error('not implemented');
};

TChannelRequest.prototype.hookupCallback = function hookupCallback(callback) {
    var self = this;
    if (callback.canStream) {
        return self.hookupStreamCallback(callback);
    }
    var called = false;

    self.on('error', onError);
    self.on('response', onResponse);

    function onError(err) {
        if (called) return;
        called = true;
        callback(err, null, null, null);
    }

    function onResponse(res) {
        if (called) return;
        called = true;
        withArg23(res, callback);
    }

    return self;
};

TChannelRequest.prototype.choosePeer = function choosePeer() {
    var self = this;
    return self.channel.peers.choosePeer(self, self.options);
};

TChannelRequest.prototype.send = function send(arg1, arg2, arg3, callback) {
    var self = this;
    self.arg1 = arg1;
    self.arg2 = arg2;
    self.arg3 = arg3;
    if (callback) {
        self.hookupCallback(callback);
    }
    self.start = self.timers.now();
    self.resendSanity = self.limit + 1;
    self.resend();
};

TChannelRequest.prototype.resend = function resend() {
    var self = this;

    if (self.checkTimeout()) return;

    var peer = self.choosePeer();
    if (!peer) {
        if (self.outReqs.length) {
            var lastReq = self.outReqs[self.outReqs.length - 1];
            if (lastReq.err) self.emit('error', lastReq.err);
            else self.emit('response', lastReq.res);
        } else {
            self.emit('error', errors.NoPeerAvailable());
        }
        return;
    }

    if (self.checkTimeout()) return;

    var opts = {};
    var keys = Object.keys(self.options);
    for (var i = 0; i < keys.length; i++) {
        var key = keys[i];
        opts[key] = self.options[key];
    }
    opts.timeout = self.timeout - self.elapsed;
    var outReq = peer.request(opts);
    self.outReqs.push(outReq);

    self.triedRemoteAddrs[outReq.remoteAddr] = (self.triedRemoteAddrs[outReq.remoteAddr] || 0) + 1;
    outReq.on('response', onResponse);
    outReq.on('error', onError);
    outReq.send(self.arg1, self.arg2, self.arg3);

    function onError(err) {
        if (self.checkTimeout(err)) return;
        if (self.shouldRetry(err)) {
            deferResend();
        } else {
            self.emit('error', err);
        }
    }

    function onResponse(res) {
        withArg23(res, function onArg23(err, res, arg2, arg3) {
            if (self.checkTimeout(err, res)) return;
            if (self.shouldRetry(err, res, arg2, arg3)) {
                deferResend();
            } else if (err) {
                self.emit('error', err);
            } else {
                self.emit('response', res);
            }
        });
    }

    function deferResend() {
        if (--self.resendSanity <= 0) {
            throw new Error('TChannelRequest out of resend sanity');
        } else {
            process.nextTick(doResend);
        }
    }

    function doResend() {
        self.resend();
    }
};

TChannelRequest.prototype.checkTimeout = function checkTimeout(err, res) {
    var self = this;
    var now = self.timers.now();
    self.elapsed = now - self.start;
    if (self.elapsed < self.timeout) return false;
    if (err) {
        if (!self.err) {
            self.emit('error', err);
        }
    } else if (res) {
        if (!self.err && !self.res) {
            self.emit('response', res);
        }
    } else if (!self.err) {
        self.emit('error', errors.TimeoutError({
            start: self.start,
            elapsed: self.elapsed,
            timeout: self.timeout
        }));
    }
    return true;
};

TChannelRequest.prototype.shouldRetry = function shouldRetry(err, res, arg2, arg3) {
    var self = this;

    if (self.outReqs.length >= self.limit) {
        return false;
    }

    if (self.options.retryFlags.never) {
        return false;
    }

    if (err) {
        switch (err.type) {
            case 'tchannel.bad-request':
            case 'tchannel.canceled':
                return false;

            case 'tchannel.busy':
            case 'tchannel.declined':
                return true;

            case 'tchannel.timeout':
                return !!self.options.retryFlags.onTimeout;

            case 'tchannel.socket':
            case 'tchannel.protocol':
            case 'tchannel.unexpected':
                return !!self.options.retryFlags.onConnectionError;

            default:
                self.logger.error('unknown error type in request retry', {
                    error: err
                });
                return true;
        }
    }

    if (!res.ok && self.options.shouldApplicationRetry) {
        return self.options.shouldApplicationRetry(self, res, arg2, arg3);
    }

    return false;
};

module.exports = TChannelRequest;

function withArg23(res, callback) {
    if (!res.streamed) {
        callback(null, res, res.arg2, res.arg3);
        return;
    }
    parallel({
        arg2: res.arg2.onValueReady,
        arg3: res.arg3.onValueReady
    }, compatCall);
    function compatCall(err, args) {
        callback(err, res, args.arg2, args.arg3);
    }
}
<commit_msg>Request: emit rather than throw insanity<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var parallel = require('run-parallel');
var EventEmitter = require('events').EventEmitter;
var inherits = require('util').inherits;

var errors = require('./errors');

function TChannelRequest(channel, options) {
    options = options || {};
    if (options.streamed) {
        throw new Error('streaming request federation not supported');
    }
    var self = this;
    EventEmitter.call(self);
    self.channel = channel;
    self.logger = self.channel.logger;
    self.random = self.channel.random;
    self.timers = self.channel.timers;

    self.options = options;

    if (!self.options.retryFlags) {
        self.options.retryFlags = {
            never: false,
            onConnectionError: true,
            onTimeout: false
        };
    }

    self.triedRemoteAddrs = {};
    self.outReqs = [];
    self.timeout = self.options.timeout || TChannelRequest.defaultTimeout;
    self.limit = self.options.retryLimit || TChannelRequest.defaultRetryLimit;
    self.start = 0;
    self.end = 0;
    self.elapsed = 0;
    self.resendSanity = 0;

    self.service = options.service || '';
    self.headers = self.options.headers || {}; // so that as-foo can punch req.headers.X
    self.options.headers = self.headers; // for passing to peer.request(opts) later

    self.arg1 = null;
    self.arg2 = null;
    self.arg3 = null;

    self.err = null;
    self.res = null;
    self.on('error', self.onError);
    self.on('response', self.onResponse);
}

inherits(TChannelRequest, EventEmitter);

TChannelRequest.defaultRetryLimit = 5;
TChannelRequest.defaultTimeout = 5000;

TChannelRequest.prototype.type = 'tchannel.request';

TChannelRequest.prototype.onError = function onError(err) {
    var self = this;
    if (!self.end) self.end = self.timers.now();
    self.err = err;
};

TChannelRequest.prototype.onResponse = function onResponse(res) {
    var self = this;
    if (!self.end) self.end = self.timers.now();
    self.res = res;
};

TChannelRequest.prototype.hookupStreamCallback = function hookupCallback(callback) {
    throw new Error('not implemented');
};

TChannelRequest.prototype.hookupCallback = function hookupCallback(callback) {
    var self = this;
    if (callback.canStream) {
        return self.hookupStreamCallback(callback);
    }
    var called = false;

    self.on('error', onError);
    self.on('response', onResponse);

    function onError(err) {
        if (called) return;
        called = true;
        callback(err, null, null, null);
    }

    function onResponse(res) {
        if (called) return;
        called = true;
        withArg23(res, callback);
    }

    return self;
};

TChannelRequest.prototype.choosePeer = function choosePeer() {
    var self = this;
    return self.channel.peers.choosePeer(self, self.options);
};

TChannelRequest.prototype.send = function send(arg1, arg2, arg3, callback) {
    var self = this;
    self.arg1 = arg1;
    self.arg2 = arg2;
    self.arg3 = arg3;
    if (callback) {
        self.hookupCallback(callback);
    }
    self.start = self.timers.now();
    self.resendSanity = self.limit + 1;
    self.resend();
};

TChannelRequest.prototype.resend = function resend() {
    var self = this;

    if (self.checkTimeout()) return;

    var peer = self.choosePeer();
    if (!peer) {
        if (self.outReqs.length) {
            var lastReq = self.outReqs[self.outReqs.length - 1];
            if (lastReq.err) self.emit('error', lastReq.err);
            else self.emit('response', lastReq.res);
        } else {
            self.emit('error', errors.NoPeerAvailable());
        }
        return;
    }

    if (self.checkTimeout()) return;

    var opts = {};
    var keys = Object.keys(self.options);
    for (var i = 0; i < keys.length; i++) {
        var key = keys[i];
        opts[key] = self.options[key];
    }
    opts.timeout = self.timeout - self.elapsed;
    var outReq = peer.request(opts);
    self.outReqs.push(outReq);

    self.triedRemoteAddrs[outReq.remoteAddr] = (self.triedRemoteAddrs[outReq.remoteAddr] || 0) + 1;
    outReq.on('response', onResponse);
    outReq.on('error', onError);
    outReq.send(self.arg1, self.arg2, self.arg3);

    function onError(err) {
        if (self.checkTimeout(err)) return;
        if (self.shouldRetry(err)) {
            deferResend();
        } else {
            self.emit('error', err);
        }
    }

    function onResponse(res) {
        withArg23(res, function onArg23(err, res, arg2, arg3) {
            if (self.checkTimeout(err, res)) return;
            if (self.shouldRetry(err, res, arg2, arg3)) {
                deferResend();
            } else if (err) {
                self.emit('error', err);
            } else {
                self.emit('response', res);
            }
        });
    }

    function deferResend() {
        if (--self.resendSanity <= 0) {
            self.emit('error', new Error('TChannelRequest out of resend sanity'));
        } else {
            process.nextTick(doResend);
        }
    }

    function doResend() {
        self.resend();
    }
};

TChannelRequest.prototype.checkTimeout = function checkTimeout(err, res) {
    var self = this;
    var now = self.timers.now();
    self.elapsed = now - self.start;
    if (self.elapsed < self.timeout) return false;
    if (err) {
        if (!self.err) {
            self.emit('error', err);
        }
    } else if (res) {
        if (!self.err && !self.res) {
            self.emit('response', res);
        }
    } else if (!self.err) {
        self.emit('error', errors.TimeoutError({
            start: self.start,
            elapsed: self.elapsed,
            timeout: self.timeout
        }));
    }
    return true;
};

TChannelRequest.prototype.shouldRetry = function shouldRetry(err, res, arg2, arg3) {
    var self = this;

    if (self.outReqs.length >= self.limit) {
        return false;
    }

    if (self.options.retryFlags.never) {
        return false;
    }

    if (err) {
        switch (err.type) {
            case 'tchannel.bad-request':
            case 'tchannel.canceled':
                return false;

            case 'tchannel.busy':
            case 'tchannel.declined':
                return true;

            case 'tchannel.timeout':
                return !!self.options.retryFlags.onTimeout;

            case 'tchannel.socket':
            case 'tchannel.protocol':
            case 'tchannel.unexpected':
                return !!self.options.retryFlags.onConnectionError;

            default:
                self.logger.error('unknown error type in request retry', {
                    error: err
                });
                return true;
        }
    }

    if (!res.ok && self.options.shouldApplicationRetry) {
        return self.options.shouldApplicationRetry(self, res, arg2, arg3);
    }

    return false;
};

module.exports = TChannelRequest;

function withArg23(res, callback) {
    if (!res.streamed) {
        callback(null, res, res.arg2, res.arg3);
        return;
    }
    parallel({
        arg2: res.arg2.onValueReady,
        arg3: res.arg3.onValueReady
    }, compatCall);
    function compatCall(err, args) {
        callback(err, res, args.arg2, args.arg3);
    }
}
<|endoftext|>


<commit_before>(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    define(factory);
  } else if (typeof exports === 'object') {
    module.exports = factory;
  } else {
    root.request = factory(root);
  }
})(this, function (root) {

	'use strict';

	var exports = {},
		utils = {},
		xhr;

	utils.parse = function(req){
		var result;
	    try {
			result = JSON.parse(req.responseText);
	    } catch (e) {
			result = req.responseText;
	    }
	    return [result, req];
	}

	utils.toQuery = function(q){
		var key,
	      	params = [];
	    for(key in q){
			params.push(key+'='+q[key]);
	    }
	    return params.join('&');
	}

	xhr = function(method, url, data, query){
		var methods = {
				success: function(){},
				error: function(){},
				always: function(){}
			},
			request = null,
			callbacks = {};

		if(window.XDomainRequest){
			request = new XDomainRequest();
		}else if(window.ActiveXObject){
			request = new ActiveXObject('Microsoft.XMLHTTP');
		}else if(window.XMLHttpRequest){
			request = new XMLHttpRequest();
		}

		if(request){
			if(query) url += '?' + utils.toQuery(query);
			request.open(method, url, true);
			request.onload = function(){
				methods.success.apply(methods, utils.parse(request));
				methods.always.apply();
			};
			request.onerror = function(){
				methods.error.apply(methods, utils.parse(request));
				methods.always.apply();
			};
			if(method === 'POST'){
				request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
				data = utils.toQuery(data);
			}
			if(method === 'GET'){
				data = null;
			}
			setTimeout(function(){
				request.send(data);
			},0);
		}

		callbacks = {
			success: function(callback){
				methods.success = callback;
				return callbacks;
			},
			error: function(callback){
				methods.error = callback;
				return callbacks;
			},
			always: function(callback){
				methods.always = callback;
				return callbacks;
			}
	    };

		return callbacks;
	}

	exports['get'] = function (url, query) {
		return xhr('GET', url, {}, query);
	};

	exports['put'] = function (url, data, query) {
		return xhr('PUT', url, data, query);
	};

	exports['post'] = function (url, data, query) {
		return xhr('POST', url, data, query);
	};

	exports['delete'] = function (url, query) {
		return xhr('DELETE', url, {}, query);
	};

	return exports;
});<commit_msg>using spaces<commit_after>(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    define(factory);
  } else if (typeof exports === 'object') {
    module.exports = factory;
  } else {
    root.request = factory(root);
  }
})(this, function (root) {

  'use strict';

  var exports = {},
    utils = {},
    xhr;

  utils.parse = function(req){
    var result;
      try {
      result = JSON.parse(req.responseText);
      } catch (e) {
      result = req.responseText;
      }
      return [result, req];
  }

  utils.toQuery = function(q){
    var key,
          params = [];
      for(key in q){
      params.push(key+'='+q[key]);
      }
      return params.join('&');
  }

  xhr = function(method, url, data, query){
    var methods = {
        success: function(){},
        error: function(){},
        always: function(){}
      },
      request = null,
      callbacks = {};

    if(window.XDomainRequest){
      request = new XDomainRequest();
    }else if(window.ActiveXObject){
      request = new ActiveXObject('Microsoft.XMLHTTP');
    }else if(window.XMLHttpRequest){
      request = new XMLHttpRequest();
    }

    if(request){
      if(query) url += '?' + utils.toQuery(query);
      request.open(method, url, true);
      request.onload = function(){
        methods.success.apply(methods, utils.parse(request));
        methods.always.apply();
      };
      request.onerror = function(){
        methods.error.apply(methods, utils.parse(request));
        methods.always.apply();
      };
      if(method === 'POST'){
        request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        data = utils.toQuery(data);
      }
      if(method === 'GET'){
        data = null;
      }
      setTimeout(function(){
        request.send(data);
      },0);
    }

    callbacks = {
      success: function(callback){
        methods.success = callback;
        return callbacks;
      },
      error: function(callback){
        methods.error = callback;
        return callbacks;
      },
      always: function(callback){
        methods.always = callback;
        return callbacks;
      }
      };

    return callbacks;
  }

  exports['get'] = function (url, query) {
    return xhr('GET', url, {}, query);
  };

  exports['put'] = function (url, data, query) {
    return xhr('PUT', url, data, query);
  };

  exports['post'] = function (url, data, query) {
    return xhr('POST', url, data, query);
  };

  exports['delete'] = function (url, query) {
    return xhr('DELETE', url, {}, query);
  };

  return exports;
});<|endoftext|>


<commit_before>import React from 'react';
import FontAwesome from 'react-fontawesome';
import _ from 'lodash';

import ContextPopup from '../ContextPopup';
import TrackRow from '../TrackRow';

import Spacer from '../Spacer';
import artPlaceholder from '../../../resources/media/art_placeholder.png';

import styles from './styles.scss';

class PlaylistView extends React.Component {
  constructor(props) {
    super(props);
  }

  addPlaylistToQueue (
    musicSources,
    playlist,
    addTracks,
    selectSong,
    startPlayback
  ) {
    addTracks(musicSources, playlist.tracks);
    selectSong(0);
    startPlayback();
  }

  renderOptions (trigger, playlist) {
    return (
      <ContextPopup
        trigger={trigger}
        artist={null}
        title={playlist.name}
        thumb={_.get(playlist, 'tracks[0].thumbnail', artPlaceholder)}
      >

      </ContextPopup>
    );
  }

  renderPlayButton () {
    let {
      playlist,
      addTracks,
      musicSources,
      selectSong,
      startPlayback
    } = this.props;
    return (

          this.addPlaylistToQueue(
            musicSources,
            playlist,
            addTracks,
            selectSong,
            startPlayback
          )
        }
      >
        <FontAwesome name='play' /> Play

    );
  }

  renderPlaylistInfo () {
    let { playlist } = this.props;
    let popupTrigger = (

        <FontAwesome name='ellipsis-h' />

    );
    return (

{playlist.name}

          <Spacer />

            {this.renderPlayButton()}
            {this.renderOptions(popupTrigger, playlist)}

    );
  }

  renderPlaylistTracksHeader () {
    return (

            <FontAwesome name='photo' />

          Artist
          Title

);
  }

  render () {
    let { playlist } = this.props;
    return (

          {this.renderPlaylistInfo()}

              {this.renderPlaylistTracksHeader()}

                {playlist.tracks.map((track, index) => {
                  const newTrack = _.cloneDeep(track);
                  _.set(newTrack, 'artist.name', newTrack.artist);
                  _.set(newTrack, 'image[0][\'#text\']', newTrack.thumbnail);
                  return (< TrackRow
                    key={'playlist-track-row-' + index}
                    track={newTrack}
                    index={'playlist-track-' + index}
                    clearQueue={this.props.clearQueue}
                    addToQueue={this.props.addToQueue}
                    startPlayback={this.props.startPlayback}
                    selectSong={this.props.selectSong}
                    musicSources={this.props.musicSources}
                    displayCover
                    displayArtist
                  />
                  );
                })
                }

    );
  }
}

export default PlaylistView;
<commit_msg>Simplified PlaylistView render<commit_after>import React from 'react';
import FontAwesome from 'react-fontawesome';
import _ from 'lodash';

import ContextPopup from '../ContextPopup';
import TrackRow from '../TrackRow';

import Spacer from '../Spacer';
import artPlaceholder from '../../../resources/media/art_placeholder.png';

import styles from './styles.scss';

class PlaylistView extends React.Component {
  constructor(props) {
    super(props);
  }

  addPlaylistToQueue (
    musicSources,
    playlist,
    addTracks,
    selectSong,
    startPlayback
  ) {
    addTracks(musicSources, playlist.tracks);
    selectSong(0);
    startPlayback();
  }

  renderOptions (trigger, playlist) {
    return (
      <ContextPopup
        trigger={trigger}
        artist={null}
        title={playlist.name}
        thumb={_.get(playlist, 'tracks[0].thumbnail', artPlaceholder)}
      >

      </ContextPopup>
    );
  }

  renderPlayButton () {
    let {
      playlist,
      addTracks,
      musicSources,
      selectSong,
      startPlayback
    } = this.props;
    return (

          this.addPlaylistToQueue(
            musicSources,
            playlist,
            addTracks,
            selectSong,
            startPlayback
          )
        }
      >
        <FontAwesome name='play' /> Play

    );
  }

  renderPlaylistInfo () {
    let { playlist } = this.props;
    let popupTrigger = (

        <FontAwesome name='ellipsis-h' />

    );
    return (

{playlist.name}

          <Spacer />

            {this.renderPlayButton()}
            {this.renderOptions(popupTrigger, playlist)}

    );
  }

  renderPlaylistTracksHeader () {
    return (

            <FontAwesome name='photo' />

          Artist
          Title

);
  }

  renderTrack (track, index) {
    const newTrack = _.cloneDeep(track);
    _.set(newTrack, 'artist.name', newTrack.artist);
    _.set(newTrack, 'image[0][\'#text\']', newTrack.thumbnail);
    return (< TrackRow
      key={'playlist-track-row-' + index}
      track={newTrack}
      index={'playlist-track-' + index}
      clearQueue={this.props.clearQueue}
      addToQueue={this.props.addToQueue}
      startPlayback={this.props.startPlayback}
      selectSong={this.props.selectSong}
      musicSources={this.props.musicSources}
      displayCover
      displayArtist
    />
    );
  }

  render () {
    let { playlist } = this.props;
    return (

          {this.renderPlaylistInfo()}

              {this.renderPlaylistTracksHeader()}

                {playlist.tracks.map((track, index) => this.renderTrack(track, index))}

    );
  }
}

export default PlaylistView;
<|endoftext|>


<commit_before>[
{"id":"layer_new","title":"New Layer"},
{"id":"layer_delete","title":"Delete Layer"},
{"id":"layer_rename","title":"Rename Layer"},
{"id":"layer_up","title":"Move Layer Up"},
{"id":"layer_down","title":"Move Layer Down"},
{"id":"tool_clear","title":"New Image [N]"},
{"id":"tool_open","title":"Open Image [O]"},
{"id":"tool_save","title":"Save Image [S]"},
{"id":"tool_docprops","title":"Document Properties [I]"},
{"id":"tool_source","title":"Edit Source [U]"},
{"id":"tool_undo","title":"Undo [Z]"},
{"id":"tool_redo","title":"Redo [Y]"},
{"id":"tool_clone","title":"Clone Element [C]"},
{"id":"tool_delete","title":"Delete Element [Delete/Backspace]"},
{"id":"tool_move_top","title":"Move to Top [Shift+Up]"},
{"id":"tool_move_bottom","title":"Move to Bottom [Shift+Down]"},
{"id":"group_opacity","title":"Change selected item opacity"},
{"id":"angle","title":"Change rotation angle"},
{"id":"tool_clone_multi","title":"Clone Elements [C]"},
{"id":"tool_delete_multi","title":"Delete Selected Elements [Delete/Backspace]"},
{"id":"tool_alignleft","title":"Align Left"},
{"id":"tool_aligncenter","title":"Align Center"},
{"id":"tool_alignright","title":"Align Right"},
{"id":"tool_aligntop","title":"Align Top"},
{"id":"tool_alignmiddle","title":"Align Middle"},
{"id":"tool_alignbottom","title":"Align Bottom"},
{"id":"align_relative_to","title":"Align relative to ..."},
{"id":"tool_group","title":"Group Elements [G]"},
{"id":"tool_ungroup","title":"Ungroup Elements [G]"},
{"id":"rect_width","title":"Change rectangle width"},
{"id":"rect_height","title":"Change rectangle height"},
{"id":"rect_rx","title":"Change Rectangle Corner Radius"},
{"id":"image_width","title":"Change image width"},
{"id":"image_height","title":"Change image height"},
{"id":"image_url","title":"Change URL"},
{"id":"circle_cx" ,"title":"Change circle's cx coordinate"},
{"id":"circle_cy" ,"title":"Change circle's cy coordinate"},
{"id":"circle_r","title":"Change circle's radius"},
{"id":"ellipse_cx","title":"Change ellipse's cx coordinate"},
{"id":"ellipse_cy","title":"Change ellipse's cy coordinate"},
{"id":"ellipse_rx","title":"Change ellipse's x radius"},
{"id":"ellipse_ry","title":"Change ellipse's y radius"},
{"id":"line_x1","title":"Change line's starting x coordinate"},
{"id":"line_y1","title":"Change line's starting y coordinate"},
{"id":"line_x2","title":"Change line's ending x coordinate"},
{"id":"line_y2","title":"Change line's ending y coordinate"},
{"id":"tool_bold","title":"Bold Text [B]"},
{"id":"tool_italic","title":"Italic Text [I]"},
{"id":"font_family","title":"Change Font Family"},
{"id":"font_size","title":"Change Font Size"},
{"id":"text","title":"Change text contents"},
{"id":"tool_select","title":"Select Tool [1]"},
{"id":"tool_fhpath","title":"Pencil Tool [2]"},
{"id":"tool_line","title":"Line Tool [3]"},
{"id":"tools_rect_show","title":"Square/Rect Tool [4/Shift+4]"},
{"id":"tools_ellipse_show","title":"Ellipse/Circle Tool [5/Shift+5]"},
{"id":"tool_text","title":"Text Tool [6]"},
{"id":"tool_path","title":"Path Tool [7]"},
{"id":"tool_image","title":"Image Tool [8]"},
{"id":"tool_zoom","title":"Zoom Tool [Ctrl+Up/Down]"},
{"id":"zoom","title":"Change zoom level"},
{"id":"fill_color","title":"Change fill color"},
{"id":"stroke_color","title":"Change stroke color"},
{"id":"stroke_width","title":"Change stroke width"},
{"id":"stroke_style","title":"Change stroke dash style"},
{"id":"palette","title":"Click to change fill color, shift-click to change stroke color"},
{"id":"tool_square","title":"Square"},
{"id":"tool_rect","title":"Rectangle"},
{"id":"tool_fhrect","title":"Free-Hand Rectangle"},
{"id":"tool_circle","title":"Circle"},
{"id":"tool_ellipse","title":"Ellipse"},
{"id":"tool_fhellipse","title":"Free-Hand Ellipse"},
{"id":"bkgnd_color","title":"Change background color/opacity"},
{"id":"rwidthLabel","textContent":"width:"},
{"id":"rheightLabel","textContent":"height:"},
{"id":"cornerRadiusLabel","textContent":"Corner Radius:"},
{"id":"iwidthLabel","textContent":"width:"},
{"id":"iheightLabel","textContent":"height:"},
{"id":"svginfo_width","textContent":"Width:" },
{"id":"svginfo_height","textContent":"Height:" },
{"id":"angleLabel","textContent":"angle:"},
{"id":"relativeToLabel","textContent":"relative to:"},
{"id":"zoomLabel","textContent":"zoom:"},
{"id":"svginfo_change_background","textContent":"Canvas Background"},
{"id":"layersLable","textContent":"Layers:"},
{"id":"selectedPredefined","textContent":"Select predefined:"},
{"id":"fitToContent","textContent":"Fit to Content"},
{"id":"tool_source_save","textContent":"Apply Changes"},
{"id":"tool_docprops_save","textContent":"OK"},
{"id":"tool_docprops_cancel","textContent":"Cancel"},
{"id":"tool_source_cancel","textContent":"Cancel"},
{"id":"fit_to_all","textContent":"Fit to all content"},
{"id":"fit_to_layer_content" ,"textContent":"Fit to layer content"},
{"id":"fit_to_sel","textContent":"Fit to selection"},
{"id":"fit_to_canvas","textContent":"Fit to canvas"},
{"id":"selected_objects","textContent":"selected objects"},
{"id":"largest_object","textContent":"largest object"},
{"id":"smallest_object","textContent":"smallest object"},
{"id":"page","textContent":"page"},
{"id":"fill_tool_bottom","textContent":"fill:"},
{"id":"stroke_tool_bottom","textContent":"stroke:"},
{"id":"svginfo_dim","textContent":"Canvas Dimensions"},
{"id":"path_node_x","title":"Change node's x coordinate"},
{"id":"path_node_y","title":"Change node's y coordinate"},
{"id":"seg_type","title":"Change Segment type"},
{"id":"straight_segments","textContent":"Straight"},
{"id":"curve_segments","textContent":"Curve"},
{"id":"tool_node_clone","title":"Clone Node"},
{"id":"tool_node_delete","title":"Delete Node"},
{"id":"selLayerLabel","textContent":"Move elements to:"},
{"id":"selLayerNames","title":"Move selected elements to a different layer"},
{"id":"sidepanel_handle","title":"Drag left/right to resize side panel [X]","textContent":"L a y e r s"},
{"id":"tool_wireframe","title":"Wireframe Mode [F]"},
{"id":"svginfo_image_props","textContent":"Image Properties"},
{"id":"svginfo_title","textContent":"Title"},
{"id":"svginfo_dim","textContent":"Canvas Dimensions"},
{"id":"includedImages","textContent":"Included Images"},
{"id":"image_opt_embed","textContent":"Embed data (local files)"},
{"id":"image_opt_ref","textContent":"Use file reference"},
{"id":"svginfo_editor_prefs","textContent":"Editor Preferences"},
{"id":"svginfo_lang","textContent":"Language"},
{"id":"svginfo_change_background","textContent":"Editor Background"},
{"id":"svginfo_bg_note","textContent":"Note: Background will not be saved with image."},
{"id":"icon_small","textContent":"Small"},
{"id":"icon_medium","textContent":"Medium"},
{"id":"icon_large","textContent":"Large"},
{"id":"icon_xlarge","textContent":"Extra Large"},
{"id":"selected_x","title":"Change X coordinate"},
{"id":"selected_y","title":"Change Y coordinate"},
{"id":"tool_topath","title":"Convert to Path"},
{"id":"tool_reorient","title":"Reorient path"},
{"id":"tool_node_link","title":"Link Control Points"},
{"js_strings": {
	"invalidAttrValGiven":"Invalid value given",
	"noContentToFitTo":"No content to fit to",
	'layer':"Layer",
	"dupeLayerName":"There is already a layer named that!",
	"enterUniqueLayerName":"Please enter a unique layer name",
	"enterNewLayerName":"Please enter the new layer name",
	"layerHasThatName":"Layer already has that name",
	"QmoveElemsToLayer":"Move selected elements to layer '%s'?",
	"QwantToClear":"Do you want to clear the drawing?\nThis will also erase your undo history!",
	"QerrorsRevertToSource":"There were parsing errors in your SVG source.\nRevert back to original SVG source?",
	"QignoreSourceChanges":"Ignore changes made to SVG source?",
	"featNotSupported":"Feature not supported",
	"enterNewImgURL":"Enter the new image URL",
	"ok":"OK",
	"cancel":"Cancel"
	}
}
];
<commit_msg>Updated lang.en.js<commit_after>[
{"id":"layer_new","title":"New Layer"},
{"id":"layer_delete","title":"Delete Layer"},
{"id":"layer_rename","title":"Rename Layer"},
{"id":"layer_up","title":"Move Layer Up"},
{"id":"layer_down","title":"Move Layer Down"},
{"id":"tool_clear","title":"New Image [N]"},
{"id":"tool_open","title":"Open Image [O]"},
{"id":"tool_save","title":"Save Image [S]"},
{"id":"tool_docprops","title":"Document Properties [I]"},
{"id":"tool_source","title":"Edit Source [U]"},
{"id":"tool_undo","title":"Undo [Z]"},
{"id":"tool_redo","title":"Redo [Y]"},
{"id":"tool_clone","title":"Clone Element [C]"},
{"id":"tool_delete","title":"Delete Element [Delete/Backspace]"},
{"id":"tool_move_top","title":"Move to Top [Shift+Up]"},
{"id":"tool_move_bottom","title":"Move to Bottom [Shift+Down]"},
{"id":"group_opacity","title":"Change selected item opacity"},
{"id":"angle","title":"Change rotation angle"},
{"id":"tool_clone_multi","title":"Clone Elements [C]"},
{"id":"tool_delete_multi","title":"Delete Selected Elements [Delete/Backspace]"},
{"id":"tool_alignleft","title":"Align Left"},
{"id":"tool_aligncenter","title":"Align Center"},
{"id":"tool_alignright","title":"Align Right"},
{"id":"tool_aligntop","title":"Align Top"},
{"id":"tool_alignmiddle","title":"Align Middle"},
{"id":"tool_alignbottom","title":"Align Bottom"},
{"id":"align_relative_to","title":"Align relative to ..."},
{"id":"tool_group","title":"Group Elements [G]"},
{"id":"tool_ungroup","title":"Ungroup Elements [G]"},
{"id":"rect_width","title":"Change rectangle width"},
{"id":"rect_height","title":"Change rectangle height"},
{"id":"rect_rx","title":"Change Rectangle Corner Radius"},
{"id":"image_width","title":"Change image width"},
{"id":"image_height","title":"Change image height"},
{"id":"image_url","title":"Change URL"},
{"id":"circle_cx" ,"title":"Change circle's cx coordinate"},
{"id":"circle_cy" ,"title":"Change circle's cy coordinate"},
{"id":"circle_r","title":"Change circle's radius"},
{"id":"ellipse_cx","title":"Change ellipse's cx coordinate"},
{"id":"ellipse_cy","title":"Change ellipse's cy coordinate"},
{"id":"ellipse_rx","title":"Change ellipse's x radius"},
{"id":"ellipse_ry","title":"Change ellipse's y radius"},
{"id":"line_x1","title":"Change line's starting x coordinate"},
{"id":"line_y1","title":"Change line's starting y coordinate"},
{"id":"line_x2","title":"Change line's ending x coordinate"},
{"id":"line_y2","title":"Change line's ending y coordinate"},
{"id":"tool_bold","title":"Bold Text [B]"},
{"id":"tool_italic","title":"Italic Text [I]"},
{"id":"font_family","title":"Change Font Family"},
{"id":"font_size","title":"Change Font Size"},
{"id":"text","title":"Change text contents"},
{"id":"tool_select","title":"Select Tool [1]"},
{"id":"tool_fhpath","title":"Pencil Tool [2]"},
{"id":"tool_line","title":"Line Tool [3]"},
{"id":"tools_rect_show","title":"Square/Rect Tool [4/Shift+4]"},
{"id":"tools_ellipse_show","title":"Ellipse/Circle Tool [5/Shift+5]"},
{"id":"tool_text","title":"Text Tool [6]"},
{"id":"tool_path","title":"Path Tool [7]"},
{"id":"tool_image","title":"Image Tool [8]"},
{"id":"tool_zoom","title":"Zoom Tool [Ctrl+Up/Down]"},
{"id":"zoom","title":"Change zoom level"},
{"id":"fill_color","title":"Change fill color"},
{"id":"stroke_color","title":"Change stroke color"},
{"id":"stroke_width","title":"Change stroke width"},
{"id":"stroke_style","title":"Change stroke dash style"},
{"id":"palette","title":"Click to change fill color, shift-click to change stroke color"},
{"id":"tool_square","title":"Square"},
{"id":"tool_rect","title":"Rectangle"},
{"id":"tool_fhrect","title":"Free-Hand Rectangle"},
{"id":"tool_circle","title":"Circle"},
{"id":"tool_ellipse","title":"Ellipse"},
{"id":"tool_fhellipse","title":"Free-Hand Ellipse"},
{"id":"bkgnd_color","title":"Change background color/opacity"},
{"id":"rwidthLabel","textContent":"width:"},
{"id":"rheightLabel","textContent":"height:"},
{"id":"cornerRadiusLabel","textContent":"Corner Radius:"},
{"id":"iwidthLabel","textContent":"width:"},
{"id":"iheightLabel","textContent":"height:"},
{"id":"svginfo_width","textContent":"Width:" },
{"id":"svginfo_height","textContent":"Height:" },
{"id":"angleLabel","textContent":"angle:"},
{"id":"relativeToLabel","textContent":"relative to:"},
{"id":"zoomLabel","textContent":"zoom:"},
{"id":"svginfo_change_background","textContent":"Canvas Background"},
{"id":"layersLable","textContent":"Layers:"},
{"id":"selectedPredefined","textContent":"Select predefined:"},
{"id":"fitToContent","textContent":"Fit to Content"},
{"id":"tool_source_save","textContent":"Apply Changes"},
{"id":"tool_docprops_save","textContent":"OK"},
{"id":"tool_docprops_cancel","textContent":"Cancel"},
{"id":"tool_source_cancel","textContent":"Cancel"},
{"id":"fit_to_all","textContent":"Fit to all content"},
{"id":"fit_to_layer_content" ,"textContent":"Fit to layer content"},
{"id":"fit_to_sel","textContent":"Fit to selection"},
{"id":"fit_to_canvas","textContent":"Fit to canvas"},
{"id":"selected_objects","textContent":"selected objects"},
{"id":"largest_object","textContent":"largest object"},
{"id":"smallest_object","textContent":"smallest object"},
{"id":"page","textContent":"page"},
{"id":"fill_tool_bottom","textContent":"fill:"},
{"id":"stroke_tool_bottom","textContent":"stroke:"},
{"id":"svginfo_dim","textContent":"Canvas Dimensions"},
{"id":"path_node_x","title":"Change node's x coordinate"},
{"id":"path_node_y","title":"Change node's y coordinate"},
{"id":"seg_type","title":"Change Segment type"},
{"id":"straight_segments","textContent":"Straight"},
{"id":"curve_segments","textContent":"Curve"},
{"id":"tool_node_clone","title":"Clone Node"},
{"id":"tool_node_delete","title":"Delete Node"},
{"id":"selLayerLabel","textContent":"Move elements to:"},
{"id":"selLayerNames","title":"Move selected elements to a different layer"},
{"id":"sidepanel_handle","title":"Drag left/right to resize side panel [X]","textContent":"L a y e r s"},
{"id":"tool_wireframe","title":"Wireframe Mode [F]"},
{"id":"svginfo_image_props","textContent":"Image Properties"},
{"id":"svginfo_title","textContent":"Title"},
{"id":"svginfo_dim","textContent":"Canvas Dimensions"},
{"id":"includedImages","textContent":"Included Images"},
{"id":"image_opt_embed","textContent":"Embed data (local files)"},
{"id":"image_opt_ref","textContent":"Use file reference"},
{"id":"svginfo_editor_prefs","textContent":"Editor Preferences"},
{"id":"svginfo_lang","textContent":"Language"},
{"id":"svginfo_change_background","textContent":"Editor Background"},
{"id":"svginfo_bg_note","textContent":"Note: Background will not be saved with image."},
{"id":"svginfo_icons","textContent":"Icon size"},
{"id":"icon_small","textContent":"Small"},
{"id":"icon_medium","textContent":"Medium"},
{"id":"icon_large","textContent":"Large"},
{"id":"icon_xlarge","textContent":"Extra Large"},
{"id":"selected_x","title":"Change X coordinate"},
{"id":"selected_y","title":"Change Y coordinate"},
{"id":"tool_topath","title":"Convert to Path"},
{"id":"tool_reorient","title":"Reorient path"},
{"id":"tool_node_link","title":"Link Control Points"},
{"js_strings": {
	"invalidAttrValGiven":"Invalid value given",
	"noContentToFitTo":"No content to fit to",
	'layer':"Layer",
	"dupeLayerName":"There is already a layer named that!",
	"enterUniqueLayerName":"Please enter a unique layer name",
	"enterNewLayerName":"Please enter the new layer name",
	"layerHasThatName":"Layer already has that name",
	"QmoveElemsToLayer":"Move selected elements to layer '%s'?",
	"QwantToClear":"Do you want to clear the drawing?\nThis will also erase your undo history!",
	"QerrorsRevertToSource":"There were parsing errors in your SVG source.\nRevert back to original SVG source?",
	"QignoreSourceChanges":"Ignore changes made to SVG source?",
	"featNotSupported":"Feature not supported",
	"enterNewImgURL":"Enter the new image URL",
	"ok":"OK",
	"cancel":"Cancel",
	"pathNodeTooltip":"Drag node to move it. Double-click node to change segment type",
	"pathCtrlPtTooltip":"Drag control point to adjust curve properties"
	}
}
];
<|endoftext|>


<commit_before>/*
 *
 * FirebaseChat
 *
 */

import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';
import { createStructuredSelector } from 'reselect';

// Styled Components
import StyledFirebaseChat from 'containers/FirebaseChat/StyledFirebaseChat';

// App Containers
import Messages from 'containers/FirebaseChatMessages';

// Actions
import { checkAuthentication, authenticateUser, getMessages, addUser, handleChange, processSubmit } from './actions';

import { makeSelectIsAuthenticated, makeSelectUserId, makeSelectUser, makeSelectMessage, makeSelectMessages } from './selectors';
import messages from './messages';

export class FirebaseChat extends React.Component { // eslint-disable-line react/prefer-stateless-function
  componentDidMount() {
    this.props.checkAuthentication();
    this.messageInput.focus();
  }

  shouldComponentUpdate(nextProps) {
    // No Firebase Authentication Found
    if (this.props.isAuthenticated === null && nextProps.isAuthenticated === false) {
      return true;
    }

    return true;
  }

  componentWillUpdate(nextProps) {
    // No Firebase Authentication Found
    if (this.props.isAuthenticated === null && nextProps.isAuthenticated === false) {
      this.props.authenticateUser();
    }

    // Firebase Authentication Found
    if (this.props.isAuthenticated === null && nextProps.isAuthenticated === true) {
      // TODO: this.props.loadUser()
    }

    // User Authenticated
    if (this.props.isAuthenticated === false && !this.props.userId && nextProps.userId) {
      this.addUser();
    }

    // Load Chat History
    if (!this.props.isAuthenticated && nextProps.isAuthenticated) {
      this.props.loadMessages();
    }
  }

  addUser = () => {
    let user = this.props.user ? this.props.user : prompt('Hello! What is your name?'); // eslint-disable-line
    user = user === null || user === '' ? `user${Math.floor(Math.random() * 9000) + 1000}` : user;
    this.props.addUser(user);
  }

  handleSubmit = (e) => {
    const type = e.type;
    const key = e.key;
    const onKeyEnter = type === 'keydown' && key === 'Enter' && this.props.message;
    const onClick = type === 'click' && this.props.message;
    if (onKeyEnter || onClick) {
      this.props.processSubmit();
    }
  }

  render() {
    const user = this.props.user ? `@${this.props.user}` : '';
    const buttonSend = <FormattedMessage {...messages.buttonSend} />;

    return (

    );
  }
}

FirebaseChat.propTypes = {
  user: PropTypes.string,
  message: PropTypes.string,
  messages: PropTypes.oneOfType([
    PropTypes.object,
    PropTypes.array,
  ]),
  isAuthenticated: PropTypes.bool,
  userId: PropTypes.string,
  checkAuthentication: PropTypes.func.isRequired,
  authenticateUser: PropTypes.func.isRequired,
  loadMessages: PropTypes.func.isRequired,
  // loadUser: PropTypes.func.isRequired,
  addUser: PropTypes.func.isRequired,
  handleChange: PropTypes.func.isRequired,
  processSubmit: PropTypes.func.isRequired,
};

const mapStateToProps = createStructuredSelector({
  isAuthenticated: makeSelectIsAuthenticated(),
  userId: makeSelectUserId(),
  user: makeSelectUser(),
  message: makeSelectMessage(),
  messages: makeSelectMessages(),
});

function mapDispatchToProps(dispatch) {
  return {
    checkAuthentication: () => dispatch(checkAuthentication.request()),
    authenticateUser: () => dispatch(authenticateUser.request()),
    loadMessages: () => dispatch(getMessages.request()),
    addUser: (user) => dispatch(addUser(user)),
    handleChange: (e) => dispatch(handleChange(e.target.value)),
    processSubmit: () => dispatch(processSubmit.request()),
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(FirebaseChat);
<commit_msg>Fixed Messages PropType<commit_after>/*
 *
 * FirebaseChat
 *
 */

import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';
import { createStructuredSelector } from 'reselect';

// Styled Components
import StyledFirebaseChat from 'containers/FirebaseChat/StyledFirebaseChat';

// App Containers
import Messages from 'containers/FirebaseChatMessages';

// Actions
import { checkAuthentication, authenticateUser, getMessages, addUser, handleChange, processSubmit } from './actions';

import { makeSelectIsAuthenticated, makeSelectUserId, makeSelectUser, makeSelectMessage, makeSelectMessages } from './selectors';
import messages from './messages';

export class FirebaseChat extends React.Component { // eslint-disable-line react/prefer-stateless-function
  componentDidMount() {
    this.props.checkAuthentication();
    this.messageInput.focus();
  }

  shouldComponentUpdate(nextProps) {
    // No Firebase Authentication Found
    if (this.props.isAuthenticated === null && nextProps.isAuthenticated === false) {
      return true;
    }

    return true;
  }

  componentWillUpdate(nextProps) {
    // No Firebase Authentication Found
    if (this.props.isAuthenticated === null && nextProps.isAuthenticated === false) {
      this.props.authenticateUser();
    }

    // Firebase Authentication Found
    if (this.props.isAuthenticated === null && nextProps.isAuthenticated === true) {
      // TODO: this.props.loadUser()
    }

    // User Authenticated
    if (this.props.isAuthenticated === false && !this.props.userId && nextProps.userId) {
      this.addUser();
    }

    // Load Chat History
    if (!this.props.isAuthenticated && nextProps.isAuthenticated) {
      this.props.loadMessages();
    }
  }

  addUser = () => {
    let user = this.props.user ? this.props.user : prompt('Hello! What is your name?'); // eslint-disable-line
    user = user === null || user === '' ? `user${Math.floor(Math.random() * 9000) + 1000}` : user;
    this.props.addUser(user);
  }

  handleSubmit = (e) => {
    const type = e.type;
    const key = e.key;
    const onKeyEnter = type === 'keydown' && key === 'Enter' && this.props.message;
    const onClick = type === 'click' && this.props.message;
    if (onKeyEnter || onClick) {
      this.props.processSubmit();
    }
  }

  render() {
    const user = this.props.user ? `@${this.props.user}` : '';
    const buttonSend = <FormattedMessage {...messages.buttonSend} />;

    return (

    );
  }
}

FirebaseChat.propTypes = {
  user: PropTypes.string,
  message: PropTypes.string,
  messages: PropTypes.array,
  isAuthenticated: PropTypes.bool,
  userId: PropTypes.string,
  checkAuthentication: PropTypes.func.isRequired,
  authenticateUser: PropTypes.func.isRequired,
  loadMessages: PropTypes.func.isRequired,
  // loadUser: PropTypes.func.isRequired,
  addUser: PropTypes.func.isRequired,
  handleChange: PropTypes.func.isRequired,
  processSubmit: PropTypes.func.isRequired,
};

const mapStateToProps = createStructuredSelector({
  isAuthenticated: makeSelectIsAuthenticated(),
  userId: makeSelectUserId(),
  user: makeSelectUser(),
  message: makeSelectMessage(),
  messages: makeSelectMessages(),
});

function mapDispatchToProps(dispatch) {
  return {
    checkAuthentication: () => dispatch(checkAuthentication.request()),
    authenticateUser: () => dispatch(authenticateUser.request()),
    loadMessages: () => dispatch(getMessages.request()),
    addUser: (user) => dispatch(addUser(user)),
    handleChange: (e) => dispatch(handleChange(e.target.value)),
    processSubmit: () => dispatch(processSubmit.request()),
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(FirebaseChat);
<|endoftext|>