<commit_before>/**
	@name Alphageo V2
	@description Methods to handle geolocation across gov.uk
	@requires core.js
*/
var AlphaGeo = {

	location: false,
	full_location: false,

	initialize: function() {
		// look for cookie
		var cookie = AlphaGeo.read_and_parse_json_cookie('govukgeo');
		if (cookie.current_location) {
			AlphaGeo.location = { lat: cookie.current_location.lat, lon: cookie.current_location.lon };
			AlphaGeo.full_location = cookie;
		}

		if (AlphaGeo.location) {
			// get full location
			if (AlphaGeo.full_location) {
				$(AlphaGeo).trigger('location-completed', AlphaGeo.full_location);
			} else {
				AlphaGeo.lookup_full_location( function() {
					$(AlphaGeo).trigger('location-completed', AlphaGeo.full_location);
				});
			}
		}

		$(AlphaGeo).bind('location-completed', function(e, location){
			AlphaGeo.save_location_to_cookie(location);
		});
	},

	read_and_parse_json_cookie: function(name) {
		var cookie = Alphagov.read_cookie(name);
		if (cookie) {
			var json_cookie = $.base64Decode(cookie);
			var geo_json = jQuery.parseJSON(json_cookie);
      		return geo_json;
    	}
    	return false;
	},

	lookup_full_location: function(callback) {
		$.getJSON('/locator.json', AlphaGeo.location, function(data){
			if (data.location_error || data.current_location.locality == false) {
				$(AlphaGeo).trigger('location-failed');
				return false;
			} else {
				AlphaGeo.full_location = data;
				callback();
			}
		});
	},

	locate: function(postcode) {
		AlphaGeo.location = { 'postcode': postcode }
		AlphaGeo.lookup_full_location( function() {
			$(AlphaGeo).trigger('location-completed', AlphaGeo.full_location);
		});
	},

	notify: function() {
		if (AlphaGeo.full_location) {
			$(AlphaGeo).trigger('location-completed', AlphaGeo.full_location);
		}
	},

	geolocate: function() {
		if (navigator.geolocation) {
			$(AlphaGeo).trigger('geolocation-started');
			AlphaGeo.browser_geolocate();
			$(AlphaGeo).bind('geolocation-completed', function(e, position) {
				AlphaGeo.location = position;
				AlphaGeo.lookup_full_location( function() {
					$(AlphaGeo).trigger('location-completed', AlphaGeo.full_location);
				});
			});
		} else {
			$(AlphaGeo).trigger('geolocation-failed');
		}
	},

	browser_geolocate: function() {
		navigator.geolocation.getCurrentPosition(
      function(position) {
      	coordinates = {lat: position.coords.latitude, lon: position.coords.longitude};
        $(AlphaGeo).trigger('geolocation-completed', coordinates);
      },
      function() {
      	$(AlphaGeo).trigger('geolocation-failed');
      }
    );
	},

	save_location_to_cookie: function() {
		var cookie = $.base64Encode(JSON.stringify(AlphaGeo.full_location));
		Alphagov.write_cookie('govukgeo', cookie);
	},

	remove: function() {
		Alphagov.delete_cookie('govukgeo');
		AlphaGeo.location = false;
		AlphaGeo.full_location = false;

		$(AlphaGeo).trigger('location-removed');
	}

}

var AlphaGeoForm = function(selector) {

	var form 				= $(selector);
	var ask_ui 			= form.find('.ask_location');
	var finding_ui 	= form.find('.finding_location');
	var found_ui 		= form.find('.found_location');
	var all_ui			= [ask_ui, finding_ui, found_ui];

	form.find('.location_error').addClass('hidden').text('');
	if (AlphaGeo.full_location) {
  	found_ui.find('strong, a span.friendly-name').text(AlphaGeo.full_location.current_location.locality);
  	show_ui(found_ui);
	} else {
		show_ui(ask_ui);
	}

	function show_ui(selector) {
		$(all_ui).each(function(k, item){
			item.hide().css('visibility','hidden');
		});
		selector.show().css('visibility','visible');
	}

	function append_cookie_notice() {
		$('
Sets a cookie
').appendTo(ask_ui);
	}

	if (navigator.geolocation) {
    $('
or locate me automatically
').appendTo(ask_ui);
		//append_cookie_notice();

	  $(".geolocate-me a").live('click', function(e){
	    e.preventDefault();
	    AlphaGeo.geolocate();
	  });

	  $(AlphaGeo).bind("geolocation-started", function() {
	  	form.find('.location_error').addClass('hidden').text('');
	  	show_ui(finding_ui);
		});

	  $(AlphaGeo).bind("geolocation-failed", function() {
	  	show_ui(ask_ui);
		});
	} else {
		append_cookie_notice();
	}

	$('a.change-location').live('click', function(e){
		e.preventDefault();
		AlphaGeo.remove();
	});

	$(AlphaGeo).bind("location-completed", function(e, location) {
		form.find('.location_error').addClass('hidden').text('');
  	found_ui.find('strong, a span.friendly-name').text(location.current_location.locality);
  	ask_ui.find('input[type=submit]').removeAttr('disabled');
  	show_ui(found_ui);
	});

	$(AlphaGeo).bind("location-failed", function(e, location) {
		form.find('.location_error').text('Please enter a valid postcode.').removeClass('hidden');
		ask_ui.find('input[type=submit]').removeAttr('disabled');
  	show_ui(ask_ui);
	});

	$(AlphaGeo).bind("location-removed", function(e, location) {
  	found_ui.find('strong, a span.friendly-name').text('');
  	ask_ui.find('input.postcode').val('');
  	show_ui(ask_ui);
	});

  form.live('submit', function(e) {
  	e.preventDefault();
  	form.find('input[type=submit]').attr('disabled','disabled');
  	AlphaGeo.locate( form.find('input.postcode').val() );
  });

}

$(document).ready( function() {
	AlphaGeo.initialize();
});<commit_msg>Make a POST request so that identifying information is not logged.<commit_after>/**
	@name Alphageo V2
	@description Methods to handle geolocation across gov.uk
	@requires core.js
*/
var AlphaGeo = {

	location: false,
	full_location: false,

	initialize: function() {
		// look for cookie
		var cookie = AlphaGeo.read_and_parse_json_cookie('govukgeo');
		if (cookie.current_location) {
			AlphaGeo.location = { lat: cookie.current_location.lat, lon: cookie.current_location.lon };
			AlphaGeo.full_location = cookie;
		}

		if (AlphaGeo.location) {
			// get full location
			if (AlphaGeo.full_location) {
				$(AlphaGeo).trigger('location-completed', AlphaGeo.full_location);
			} else {
				AlphaGeo.lookup_full_location( function() {
					$(AlphaGeo).trigger('location-completed', AlphaGeo.full_location);
				});
			}
		}

		$(AlphaGeo).bind('location-completed', function(e, location){
			AlphaGeo.save_location_to_cookie(location);
		});
	},

	read_and_parse_json_cookie: function(name) {
		var cookie = Alphagov.read_cookie(name);
		if (cookie) {
			var json_cookie = $.base64Decode(cookie);
			var geo_json = jQuery.parseJSON(json_cookie);
      		return geo_json;
    	}
    	return false;
	},

	lookup_full_location: function(callback) {
    $.ajax({
      url: '/locator.json',
      dataType: 'json',
      data: AlphaGeo.location,
      type: 'POST',
      success: function(data){
        if (data.location_error || data.current_location.locality == false) {
          $(AlphaGeo).trigger('location-failed');
          return false;
        } else {
          AlphaGeo.full_location = data;
          callback();
        }
      }
    });
	},

	locate: function(postcode) {
		AlphaGeo.location = { 'postcode': postcode }
		AlphaGeo.lookup_full_location( function() {
			$(AlphaGeo).trigger('location-completed', AlphaGeo.full_location);
		});
	},

	notify: function() {
		if (AlphaGeo.full_location) {
			$(AlphaGeo).trigger('location-completed', AlphaGeo.full_location);
		}
	},

	geolocate: function() {
		if (navigator.geolocation) {
			$(AlphaGeo).trigger('geolocation-started');
			AlphaGeo.browser_geolocate();
			$(AlphaGeo).bind('geolocation-completed', function(e, position) {
				AlphaGeo.location = position;
				AlphaGeo.lookup_full_location( function() {
					$(AlphaGeo).trigger('location-completed', AlphaGeo.full_location);
				});
			});
		} else {
			$(AlphaGeo).trigger('geolocation-failed');
		}
	},

	browser_geolocate: function() {
		navigator.geolocation.getCurrentPosition(
      function(position) {
      	coordinates = {lat: position.coords.latitude, lon: position.coords.longitude};
        $(AlphaGeo).trigger('geolocation-completed', coordinates);
      },
      function() {
      	$(AlphaGeo).trigger('geolocation-failed');
      }
    );
	},

	save_location_to_cookie: function() {
		var cookie = $.base64Encode(JSON.stringify(AlphaGeo.full_location));
		Alphagov.write_cookie('govukgeo', cookie);
	},

	remove: function() {
		Alphagov.delete_cookie('govukgeo');
		AlphaGeo.location = false;
		AlphaGeo.full_location = false;

		$(AlphaGeo).trigger('location-removed');
	}

}

var AlphaGeoForm = function(selector) {

	var form 				= $(selector);
	var ask_ui 			= form.find('.ask_location');
	var finding_ui 	= form.find('.finding_location');
	var found_ui 		= form.find('.found_location');
	var all_ui			= [ask_ui, finding_ui, found_ui];

	form.find('.location_error').addClass('hidden').text('');
	if (AlphaGeo.full_location) {
  	found_ui.find('strong, a span.friendly-name').text(AlphaGeo.full_location.current_location.locality);
  	show_ui(found_ui);
	} else {
		show_ui(ask_ui);
	}

	function show_ui(selector) {
		$(all_ui).each(function(k, item){
			item.hide().css('visibility','hidden');
		});
		selector.show().css('visibility','visible');
	}

	function append_cookie_notice() {
		$('
Sets a cookie
').appendTo(ask_ui);
	}

	if (navigator.geolocation) {
    $('
or locate me automatically
').appendTo(ask_ui);
		//append_cookie_notice();

	  $(".geolocate-me a").live('click', function(e){
	    e.preventDefault();
	    AlphaGeo.geolocate();
	  });

	  $(AlphaGeo).bind("geolocation-started", function() {
	  	form.find('.location_error').addClass('hidden').text('');
	  	show_ui(finding_ui);
		});

	  $(AlphaGeo).bind("geolocation-failed", function() {
	  	show_ui(ask_ui);
		});
	} else {
		append_cookie_notice();
	}

	$('a.change-location').live('click', function(e){
		e.preventDefault();
		AlphaGeo.remove();
	});

	$(AlphaGeo).bind("location-completed", function(e, location) {
		form.find('.location_error').addClass('hidden').text('');
  	found_ui.find('strong, a span.friendly-name').text(location.current_location.locality);
  	ask_ui.find('input[type=submit]').removeAttr('disabled');
  	show_ui(found_ui);
	});

	$(AlphaGeo).bind("location-failed", function(e, location) {
		form.find('.location_error').text('Please enter a valid postcode.').removeClass('hidden');
		ask_ui.find('input[type=submit]').removeAttr('disabled');
  	show_ui(ask_ui);
	});

	$(AlphaGeo).bind("location-removed", function(e, location) {
  	found_ui.find('strong, a span.friendly-name').text('');
  	ask_ui.find('input.postcode').val('');
  	show_ui(ask_ui);
	});

  form.live('submit', function(e) {
  	e.preventDefault();
  	form.find('input[type=submit]').attr('disabled','disabled');
  	AlphaGeo.locate( form.find('input.postcode').val() );
  });

}

$(document).ready( function() {
	AlphaGeo.initialize();
});
<|endoftext|>


<commit_before>//
// Copyright (c) 2012-2015 Dropmysite.com <https://dropmyemail.com>
// Copyright (c) 2015 Webhippie <http://www.webhippie.de>
//
// 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.
//

//= require gettext/jed
//= require_self

(function() {
  var locales = locales || {};
  var locale = document.getElementsByTagName('html')[0].lang;

  if(!locale) {
    console.warn('No locale found as an html attribute, using default.');
    return;
  }

  var i18n = new Jed(locales[locale] || {});

  window.__ = function() {
    return i18n.gettext.apply(i18n, arguments);
  };

  window.n__ = function() {
    return i18n.ngettext.apply(i18n, arguments);
  };

  window.s__ = function(key) {
    return window.__(key).split('|').pop();
  }

  window.gettext = window.__;
  window.ngettext = window.n__;
  window.sgettext = window.s__;

  window.i18n = i18n;
})();
<commit_msg>Added missing colon to all.js<commit_after>//
// Copyright (c) 2012-2015 Dropmysite.com <https://dropmyemail.com>
// Copyright (c) 2015 Webhippie <http://www.webhippie.de>
//
// 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.
//

//= require gettext/jed
//= require_self

(function() {
  var locales = locales || {};
  var locale = document.getElementsByTagName('html')[0].lang;

  if(!locale) {
    console.warn('No locale found as an html attribute, using default.');
    return;
  }

  var i18n = new Jed(locales[locale] || {});

  window.__ = function() {
    return i18n.gettext.apply(i18n, arguments);
  };

  window.n__ = function() {
    return i18n.ngettext.apply(i18n, arguments);
  };

  window.s__ = function(key) {
    return window.__(key).split('|').pop();
  };

  window.gettext = window.__;
  window.ngettext = window.n__;
  window.sgettext = window.s__;

  window.i18n = i18n;
})();
<|endoftext|>


<commit_before>// Inspired by the implementation upstream in https://github.com/evereq/bootstrap-wysihtml5
// that has not made it to the Rails version.
(function(wysi) {
  "use strict";

  function exec(composer) {
    var pre = this.state(composer);

    if (pre) {
      // caret is already within a
...

      composer.selection.executeAndRestore(function () {
        var codeSelector = pre.querySelector("code");
        wysi.dom.replaceWithChildNodes(pre);
        if (codeSelector) {
          wysi.dom.replaceWithChildNodes(pre);
        }
      });
    } else {
      // Wrap in ...
      var range = composer.selection.getRange();
      if (!range) {
        return false;
      }

      var selectedNodes = range.extractContents(),
          code = composer.doc.createElement("code");

      code.appendChild(selectedNodes);
      code.className = 'coursemology-code';
      range.insertNode(code);
      composer.selection.selectNode(code);
    }
  }

  function state(composer) {
    var selectedNode = composer.selection.getSelectedNode();
    return wysi.dom.getParentElement(selectedNode, { nodeName: "CODE" });
  }

  wysi.commands.createCode = {
    exec: exec,
    state: state
  };
})(wysihtml5);

$(document).ready(function() {
  // setup html editor
  var imgUploadHtml = $('#html-editor-image-upload-tab').html();

  var options = $.extend(true, {}, $.fn.wysihtml5.defaultOptions);
  options.toolbar = {
    code: '
' +
            '
' +
            '' +
            '
' +
          '
'
  };
  options.parserRules.classes['coursemology-code'] = 1;

  options.customTemplates = {};

  if (imgUploadHtml) {
    options.html = true;
    options.customTemplates = {
      image: function(locale) {
        return imgUploadHtml;
      }
    };
  }

  // FontAwesome's semantics are wrong >_<. This fix removes the default
  // indent/outdent tools and insert our modified indent and outdent buttons.
  // See https://github.com/jhollingworth/bootstrap-wysihtml5/pull/253
  options.lists = false;
  var modifiedListHtml = function(locale) {
      return "
" +
             "
" +
             "" +
             "" +
             "" +
             "" +
             "
" +
             "
";
  };
  options.customTemplates.html = modifiedListHtml;

  var handler = function() {
    var $this = $(this);
    if ($this.data('wysihtml5')) {
      // We need to reinitialise the component; otherwise the iframe is as good as dead
      // see https://github.com/xing/wysihtml5/issues/148
      $this.css('display', 'block');
      var input = $this.val();
      $this.siblings('.wysihtml5-sandbox, .wysihtml5-toolbar, input[name="_wysihtml5_mode"]').remove();
    }

    $(this).wysihtml5(options);
  };

  $(document).on('DOMNodeInserted', function(e) {
    $('textarea.html-editor', e.target).each(handler);
  });
});
<commit_msg>Put back edit html button<commit_after>// Inspired by the implementation upstream in https://github.com/evereq/bootstrap-wysihtml5
// that has not made it to the Rails version.
(function(wysi) {
  "use strict";

  function exec(composer) {
    var pre = this.state(composer);

    if (pre) {
      // caret is already within a
...

      composer.selection.executeAndRestore(function () {
        var codeSelector = pre.querySelector("code");
        wysi.dom.replaceWithChildNodes(pre);
        if (codeSelector) {
          wysi.dom.replaceWithChildNodes(pre);
        }
      });
    } else {
      // Wrap in ...
      var range = composer.selection.getRange();
      if (!range) {
        return false;
      }

      var selectedNodes = range.extractContents(),
          code = composer.doc.createElement("code");

      code.appendChild(selectedNodes);
      code.className = 'coursemology-code';
      range.insertNode(code);
      composer.selection.selectNode(code);
    }
  }

  function state(composer) {
    var selectedNode = composer.selection.getSelectedNode();
    return wysi.dom.getParentElement(selectedNode, { nodeName: "CODE" });
  }

  wysi.commands.createCode = {
    exec: exec,
    state: state
  };
})(wysihtml5);

$(document).ready(function() {
  // setup html editor
  var imgUploadHtml = $('#html-editor-image-upload-tab').html();

  var options = $.extend(true, {}, $.fn.wysihtml5.defaultOptions);
  options.toolbar = {
    code: '
' +
            '
' +
            '' +
            '
' +
          '
'
  };
  options.parserRules.classes['coursemology-code'] = 1;

  options.customTemplates = {};

  options.html = true;

  if (imgUploadHtml) {
    options.customTemplates = {
      image: function(locale) {
        return imgUploadHtml;
      }
    };
  }

  // FontAwesome's semantics are wrong >_<. This fix removes the default
  // indent/outdent tools and insert our modified indent and outdent buttons.
  options.lists = true;
  var modifiedListHtml = function(locale) {
      return "
" +
             "
" +
             "" +
             "" +
             "" +
             "" +
             "
" +
             "
";
  };
  options.customTemplates.lists = modifiedListHtml;

  var handler = function() {
    var $this = $(this);
    if ($this.data('wysihtml5')) {
      // We need to reinitialise the component; otherwise the iframe is as good as dead
      // see https://github.com/xing/wysihtml5/issues/148
      $this.css('display', 'block');
      var input = $this.val();
      $this.siblings('.wysihtml5-sandbox, .wysihtml5-toolbar, input[name="_wysihtml5_mode"]').remove();
    }

    $(this).wysihtml5(options);
  };

  $(document).on('DOMNodeInserted', function(e) {
    $('textarea.html-editor', e.target).each(handler);
  });
});
<|endoftext|>


<commit_before>/*global jQuery, HDO, Handlebars */

(function ($, HDO, Handlebars) {
  HDO.issueEditor = {
    create: function (opts) {
      var instance = Object.create(this);
      instance.root = $(opts.root);
      instance.url = opts.url;
      instance.issueId = opts.id;

      return instance;
    },

    init: function () {
      this.setupTemplates();
      this.renderForm();

      HDO.markdownEditor();

      this.form                  = $('form.edit_issue, form.new_issue');
      this.saveButton            = this.root.find('button[name=save]');
      this.editorSelect          = this.root.find('select#issue_editor_id');
      this.categorySelect        = this.root.find('select#issue_category_ids');
      this.positionPartySelects  = this.root.find('select.position-parties');
      this.newPositionButton     = this.root.find('#new-position');
      this.newPartyCommentButton = this.root.find('#new-party-comment');
      this.tagList               = this.root.find('input[name=tags]');
      this.promiseSearchTab      = this.root.find('#promise-search-tab');
      this.promiseSpinner        = this.root.find("#promise-spinner");
      this.propositionConnectTab = this.root.find("#proposition-connections-tab");
      this.propositionSearchTab  = this.root.find('#proposition-search-tab');
      this.propositionSpinner    = this.root.find("#proposition-spinner");
      this.errorElement          = this.root.find('.error-message');

      this.saveButton.click(this.save.bind(this));
      this.newPositionButton.click(this.newPosition.bind(this));
      this.newPartyCommentButton.click(this.notImplemented.bind(this));
      this.root.delegate('[data-expands]', 'click', this.toggleRow.bind(this));

      this.editorSelect.chosen();
      this.categorySelect.chosen();
      this.positionPartySelects.chosen();
      this.root.find('.position-form').hide();
      this.root.delegate('.position-remove', 'click', this.removePosition.bind(this));

      this.setupTagList();
      this.setupCarts();

      this.facetSearch({
        baseUrl:  '/promises',
        root:     this.promiseSearchTab,
        spinner:  this.promiseSpinner,
        template: this.templates['promise-search-template'],
        cart:     this.promiseCart,
        issueId:  this.issueId
      });

      this.facetSearch({
        baseUrl:  '/propositions',
        root:     this.propositionSearchTab,
        spinner:  this.propositionSpinner,
        template: this.templates['proposition-search-template'],
        cart:     this.propositionCart,
        issueId:  this.issueId
      });
    },

    save: function (e) {
      e.preventDefault();
      this.toggleSpin();

      var self, currentSection;

      self = this;
      currentSection = this.root.find('.in').data('key');

      $.ajax({
        url: this.url,
        method: 'POST',
        data: this.form.serialize(),
        success: function (data) {
          // trololol
          window.location.href = currentSection ?
              data.location + ('?section=' + encodeURIComponent(currentSection)) : data.location;
        },
        error: function (xhr) {
          self.toggleSpin();
          self.errorElement.html(xhr.responseText).show();
        }
      });
    },

    toggleSpin: function () {
      this.root.find('.accordion-group').toggle();
      $('#spinner').toggle();
    },

    newPosition: function (e) {
      var position, created, template;

      e.preventDefault();

      position = { id: 0, party_ids: [], priority: 0 };
      template = this.templates['position-template'];

      created = $(template(position)).prependTo('.positions');
      created.addClass('new');
      created.find('.expandable, .expanded').toggleClass('expandable expanded');

      created.find('.position-parties').chosen();
      HDO.markdownEditor({root: created});
    },

    removePosition: function (e) {
      e.preventDefault();

      var target = $(e.target),
        id = target.data('id'),
        parties = target.data('parties'),
        title = target.data('title'),
        container = target.closest('.position');

      container.html('' + parties + '' + title + '' + '');
      container.append(
        $('<input/>')
          .attr('type', 'hidden')
          .attr('name', 'positions[' + id + '][deleted]')
          .val('true')
      );
    },

    setupTagList: function () {
      var el = this.tagList;
      el.tagsManager({
        prefilled: el.data('current-tags').split(","),
        preventSubmitOnEnter: true,
        typeahead: true,
        typeaheadSource: el.data('all-tags').split(","),
        hiddenTagListName: 'issue[tag_list]'
      });
    },

    setupTemplates: function () {
      var templates;
      this.templates = templates = {};

      $("script[type='text/x-handlebars-template']").each(function () {
        var el, name, partialName;

        el = $(this);
        name = el.data('name');
        partialName = name.match(/^(\w+?)-partial$/);
        partialName = partialName && partialName[1];

        if (partialName) {
          Handlebars.registerPartial(partialName, el.html());
        } else {
          templates[name] = Handlebars.compile(el.html());
        }
      });

      Handlebars.registerHelper('selectedIfEqual', function (a, b) {
        return a === b && 'selected';
      });

      Handlebars.registerHelper('selectedIfInclude', function (a, b) {
        if (b.indexOf(a) !== -1) {
          return 'selected';
        }
      });
    },

    // TODO: get rid of all the duplication
    setupCarts: function () {
      var toggleRow, promiseTemplate, propositionTemplate;

      this.promiseCart = this.createCart($('.cart[data-type=promises]'));
      this.propositionCart = this.createCart($('.cart[data-type=propositions]'));

      toggleRow = this.toggleRow;
      promiseTemplate = this.templates['promise-connection-template'];
      propositionTemplate = this.templates['proposition-connection-template'];

      this.promiseCart.on('use', function (items) {
        if (items.length === 0) {
          return;
        }

        $('a[href=#promise-connections-tab]').click();

        $.ajax({
          url: '/admin/issues/promises/' + items.join(','),
          dataType: 'json',
          success: function (data) {
            $.each(data, function () {
              var created = $(promiseTemplate(this)).prependTo('#promise-connections-tab');
              created.addClass('new');
            });
          },
          error: function (xhr) {
            window.alert('Uffda, noe gikk helt galt ' + xhr.status);
          },
          complete: function () {
            // TODO: spinner
          }
        });
      });

      this.propositionCart.on('use', function (items) {
        if (items.length === 0) {
          return;
        }

        $('a[href=#proposition-connections-tab]').click();

        $.ajax({
          url: '/admin/issues/propositions/' + items.join(','),
          dataType: 'json',
          success: function (data) {
            $.each(data, function () {
              var created = $(propositionTemplate(this)).prependTo('#proposition-connections-tab');
              created.addClass('new');
              HDO.markdownEditor({root: created});
            });
          },
          error: function (xhr) {
            window.alert('Uffda, noe gikk helt galt ' + xhr.status);
          },
          complete: function () {
            // TODO: spinner
          }
        });
      });
    },

    toggleRow: function (e) {
      var target, el;

      target = $(e.target);

      if (target.hasClass('permalink') || e.originalEvent.defaultPrevented) {
        return;
      }

      el = target.parents('.row-fluid:first');
      el.find('.expandable, .expanded').toggleClass('expandable expanded');
      $(el.data('expands')).slideToggle('fast');
    },

    notImplemented: function (e) {
      e.preventDefault();
      window.alert('ikke enda');
    },

    renderForm: function () {
      function render(template, i, e) {
        var el = $(e);
        el.html(template(el.data('context')));
      }

      $(".proposition-connection").each(render.bind(null, this.templates['proposition-connection-template']));
      $(".promise-connection").each(render.bind(null, this.templates['promise-connection-template']));
      $(".position").each(render.bind(null, this.templates['position-template']));
    },

    facetSearch: function (opts) {
      var baseUrl, root, template, spinner, query, cart, filter, issueId;

      baseUrl  = opts.baseUrl;
      root     = opts.root;
      template = opts.template;
      spinner  = opts.spinner || $("#spinner");
      query    = opts.root.find('input[name=q]');
      cart     = opts.cart;
      issueId  = opts.issueId;

      function prepareData(data) {
        $.each(data.results, function (i, e) {
          e.selected = cart.isSelected(Number(e.id));
          e.connected = e.issue_ids.indexOf(issueId) !== -1;
        });

        return data;
      }

      function render(url) {
        spinner.toggleClass('hidden');

        $.ajax({
          url: url || baseUrl,
          dataType: 'json',
          success: function (data) { root.html(template(prepareData(data))); },
          error: function (xhr) { window.alert('Uffda, noe gikk helt galt ' + xhr.status); },
          complete: function () { spinner.toggleClass('hidden'); }
        });
      }

      function filterHandler(e) {
        e.preventDefault();
        render(e.target.href);
      }

      function queryHandler(e) {
        if (e.which === 13) {
          e.preventDefault();

          var target = $(this),
            url = decodeURI(target.data('url-template'));

          url = url.replace('{query}', encodeURIComponent(target.val()));
          render(url);
        }
      }

      function toggleResult(e) {
        var el = $(this), id;

        if (el.hasClass('connected')) {
          return;
        }

        id = el.data('id');
        el.toggleClass('selected');

        if (el.hasClass('selected')) {
          cart.add(id);
        } else {
          cart.remove(id);
        }
      }

      cart.on('clear', function () {
        root.find('.search-result.selected').removeClass('selected');
      });

      root.delegate('.navigators a, a[data-xhr]', 'click', filterHandler);
      root.delegate('input[name=q]', 'keypress', queryHandler);
      root.delegate('.search-result', 'click', toggleResult);

      render();
    },

    createCart: function (el) {
      var items, template, callbacks;

      items = [];
      template = this.templates['shopping-cart-template'];
      callbacks = {clear: [], use: []};

      function invokeCallbacks(type) {
        $(callbacks[type]).each(function (i, cb) {
          cb(items);
        });
      }

      function render() {
        el.html(template({items: items}));
      }

      function isSelected(id) {
        return items.indexOf(id) !== -1;
      }

      function add(id) {
        items.push(id);
        render();
      }

      function remove(id) {
        var idx = items.indexOf(id);
        if (idx > -1) {
          items.splice(idx, 1);
          render();
        }
      }

      function clear() {
        items = [];
        invokeCallbacks('clear');
        render();
      }

      function use() {
        invokeCallbacks('use');
        clear();
      }

      function addCallback(type, cb) {
        if (typeof cb !== 'function') {
          throw new TypeError('expected function, got ' + typeof cb);
        }

        if (Object.keys(callbacks).indexOf(type) === -1) {
          throw new Error('invalid callback type ' + type);
        }

        callbacks[type].push(cb);
      }

      el.delegate('a[data-action=use]', 'click', function (e) {
        e.preventDefault();
        use();
      });

      el.delegate('a[data-action=clear]', 'click', function (e) {
        e.preventDefault();
        clear();
      });

      render();

      return {
        isSelected: isSelected,
        add: add,
        remove: remove,
        on: addCallback
      };
    }

  };
}(jQuery, HDO, Handlebars));
<commit_msg>issue editor: fix saving more than one position in one save<commit_after>/*global jQuery, HDO, Handlebars */

(function ($, HDO, Handlebars) {
  HDO.issueEditor = {
    create: function (opts) {
      var instance = Object.create(this);
      instance.root = $(opts.root);
      instance.url = opts.url;
      instance.issueId = opts.id;

      return instance;
    },

    init: function () {
      this.setupTemplates();
      this.renderForm();

      HDO.markdownEditor();

      this.form                  = $('form.edit_issue, form.new_issue');
      this.saveButton            = this.root.find('button[name=save]');
      this.editorSelect          = this.root.find('select#issue_editor_id');
      this.categorySelect        = this.root.find('select#issue_category_ids');
      this.positionPartySelects  = this.root.find('select.position-parties');
      this.newPositionButton     = this.root.find('#new-position');
      this.newPartyCommentButton = this.root.find('#new-party-comment');
      this.tagList               = this.root.find('input[name=tags]');
      this.promiseSearchTab      = this.root.find('#promise-search-tab');
      this.promiseSpinner        = this.root.find("#promise-spinner");
      this.propositionConnectTab = this.root.find("#proposition-connections-tab");
      this.propositionSearchTab  = this.root.find('#proposition-search-tab');
      this.propositionSpinner    = this.root.find("#proposition-spinner");
      this.errorElement          = this.root.find('.error-message');

      this.saveButton.click(this.save.bind(this));
      this.newPositionButton.click(this.newPosition.bind(this));
      this.newPartyCommentButton.click(this.notImplemented.bind(this));
      this.root.delegate('[data-expands]', 'click', this.toggleRow.bind(this));

      this.editorSelect.chosen();
      this.categorySelect.chosen();
      this.positionPartySelects.chosen();
      this.root.find('.position-form').hide();
      this.root.delegate('.position-remove', 'click', this.removePosition.bind(this));

      this.setupTagList();
      this.setupCarts();

      this.facetSearch({
        baseUrl:  '/promises',
        root:     this.promiseSearchTab,
        spinner:  this.promiseSpinner,
        template: this.templates['promise-search-template'],
        cart:     this.promiseCart,
        issueId:  this.issueId
      });

      this.facetSearch({
        baseUrl:  '/propositions',
        root:     this.propositionSearchTab,
        spinner:  this.propositionSpinner,
        template: this.templates['proposition-search-template'],
        cart:     this.propositionCart,
        issueId:  this.issueId
      });
    },

    save: function (e) {
      e.preventDefault();
      this.toggleSpin();

      var self, currentSection;

      self = this;
      currentSection = this.root.find('.in').data('key');

      $.ajax({
        url: this.url,
        method: 'POST',
        data: this.form.serialize(),
        success: function (data) {
          // trololol
          window.location.href = currentSection ?
              data.location + ('?section=' + encodeURIComponent(currentSection)) : data.location;
        },
        error: function (xhr) {
          self.toggleSpin();
          self.errorElement.html(xhr.responseText).show();
        }
      });
    },

    toggleSpin: function () {
      this.root.find('.accordion-group').toggle();
      $('#spinner').toggle();
    },

    newPosition: function (e) {
      var position, created, template;
      this.newPositionId = this.newPositionId || 0;

      e.preventDefault();

      position = {
        id: --this.newPositionId,
        party_ids: [],
        priority: 0
      };

      template = this.templates['position-template'];

      created = $(template(position)).prependTo('.positions');
      created.addClass('new');
      created.find('.expandable, .expanded').toggleClass('expandable expanded');

      created.find('.position-parties').chosen();
      HDO.markdownEditor({root: created});
    },

    removePosition: function (e) {
      e.preventDefault();

      var target = $(e.target),
        id = target.data('id'),
        parties = target.data('parties'),
        title = target.data('title'),
        container = target.closest('.position');

      container.html('' + parties + '' + title + '' + '');
      container.append(
        $('<input/>')
          .attr('type', 'hidden')
          .attr('name', 'positions[' + id + '][deleted]')
          .val('true')
      );
    },

    setupTagList: function () {
      var el = this.tagList;
      el.tagsManager({
        prefilled: el.data('current-tags').split(","),
        preventSubmitOnEnter: true,
        typeahead: true,
        typeaheadSource: el.data('all-tags').split(","),
        hiddenTagListName: 'issue[tag_list]'
      });
    },

    setupTemplates: function () {
      var templates;
      this.templates = templates = {};

      $("script[type='text/x-handlebars-template']").each(function () {
        var el, name, partialName;

        el = $(this);
        name = el.data('name');
        partialName = name.match(/^(\w+?)-partial$/);
        partialName = partialName && partialName[1];

        if (partialName) {
          Handlebars.registerPartial(partialName, el.html());
        } else {
          templates[name] = Handlebars.compile(el.html());
        }
      });

      Handlebars.registerHelper('selectedIfEqual', function (a, b) {
        return a === b && 'selected';
      });

      Handlebars.registerHelper('selectedIfInclude', function (a, b) {
        if (b.indexOf(a) !== -1) {
          return 'selected';
        }
      });
    },

    // TODO: get rid of all the duplication
    setupCarts: function () {
      var toggleRow, promiseTemplate, propositionTemplate;

      this.promiseCart = this.createCart($('.cart[data-type=promises]'));
      this.propositionCart = this.createCart($('.cart[data-type=propositions]'));

      toggleRow = this.toggleRow;
      promiseTemplate = this.templates['promise-connection-template'];
      propositionTemplate = this.templates['proposition-connection-template'];

      this.promiseCart.on('use', function (items) {
        if (items.length === 0) {
          return;
        }

        $('a[href=#promise-connections-tab]').click();

        $.ajax({
          url: '/admin/issues/promises/' + items.join(','),
          dataType: 'json',
          success: function (data) {
            $.each(data, function () {
              var created = $(promiseTemplate(this)).prependTo('#promise-connections-tab');
              created.addClass('new');
            });
          },
          error: function (xhr) {
            window.alert('Uffda, noe gikk helt galt ' + xhr.status);
          },
          complete: function () {
            // TODO: spinner
          }
        });
      });

      this.propositionCart.on('use', function (items) {
        if (items.length === 0) {
          return;
        }

        $('a[href=#proposition-connections-tab]').click();

        $.ajax({
          url: '/admin/issues/propositions/' + items.join(','),
          dataType: 'json',
          success: function (data) {
            $.each(data, function () {
              var created = $(propositionTemplate(this)).prependTo('#proposition-connections-tab');
              created.addClass('new');
              HDO.markdownEditor({root: created});
            });
          },
          error: function (xhr) {
            window.alert('Uffda, noe gikk helt galt ' + xhr.status);
          },
          complete: function () {
            // TODO: spinner
          }
        });
      });
    },

    toggleRow: function (e) {
      var target, el;

      target = $(e.target);

      if (target.hasClass('permalink') || e.originalEvent.defaultPrevented) {
        return;
      }

      el = target.parents('.row-fluid:first');
      el.find('.expandable, .expanded').toggleClass('expandable expanded');
      $(el.data('expands')).slideToggle('fast');
    },

    notImplemented: function (e) {
      e.preventDefault();
      window.alert('ikke enda');
    },

    renderForm: function () {
      function render(template, i, e) {
        var el = $(e);
        el.html(template(el.data('context')));
      }

      $(".proposition-connection").each(render.bind(null, this.templates['proposition-connection-template']));
      $(".promise-connection").each(render.bind(null, this.templates['promise-connection-template']));
      $(".position").each(render.bind(null, this.templates['position-template']));
    },

    facetSearch: function (opts) {
      var baseUrl, root, template, spinner, query, cart, filter, issueId;

      baseUrl  = opts.baseUrl;
      root     = opts.root;
      template = opts.template;
      spinner  = opts.spinner || $("#spinner");
      query    = opts.root.find('input[name=q]');
      cart     = opts.cart;
      issueId  = opts.issueId;

      function prepareData(data) {
        $.each(data.results, function (i, e) {
          e.selected = cart.isSelected(Number(e.id));
          e.connected = e.issue_ids.indexOf(issueId) !== -1;
        });

        return data;
      }

      function render(url) {
        spinner.toggleClass('hidden');

        $.ajax({
          url: url || baseUrl,
          dataType: 'json',
          success: function (data) { root.html(template(prepareData(data))); },
          error: function (xhr) { window.alert('Uffda, noe gikk helt galt ' + xhr.status); },
          complete: function () { spinner.toggleClass('hidden'); }
        });
      }

      function filterHandler(e) {
        e.preventDefault();
        render(e.target.href);
      }

      function queryHandler(e) {
        if (e.which === 13) {
          e.preventDefault();

          var target = $(this),
            url = decodeURI(target.data('url-template'));

          url = url.replace('{query}', encodeURIComponent(target.val()));
          render(url);
        }
      }

      function toggleResult(e) {
        var el = $(this), id;

        if (el.hasClass('connected')) {
          return;
        }

        id = el.data('id');
        el.toggleClass('selected');

        if (el.hasClass('selected')) {
          cart.add(id);
        } else {
          cart.remove(id);
        }
      }

      cart.on('clear', function () {
        root.find('.search-result.selected').removeClass('selected');
      });

      root.delegate('.navigators a, a[data-xhr]', 'click', filterHandler);
      root.delegate('input[name=q]', 'keypress', queryHandler);
      root.delegate('.search-result', 'click', toggleResult);

      render();
    },

    createCart: function (el) {
      var items, template, callbacks;

      items = [];
      template = this.templates['shopping-cart-template'];
      callbacks = {clear: [], use: []};

      function invokeCallbacks(type) {
        $(callbacks[type]).each(function (i, cb) {
          cb(items);
        });
      }

      function render() {
        el.html(template({items: items}));
      }

      function isSelected(id) {
        return items.indexOf(id) !== -1;
      }

      function add(id) {
        items.push(id);
        render();
      }

      function remove(id) {
        var idx = items.indexOf(id);
        if (idx > -1) {
          items.splice(idx, 1);
          render();
        }
      }

      function clear() {
        items = [];
        invokeCallbacks('clear');
        render();
      }

      function use() {
        invokeCallbacks('use');
        clear();
      }

      function addCallback(type, cb) {
        if (typeof cb !== 'function') {
          throw new TypeError('expected function, got ' + typeof cb);
        }

        if (Object.keys(callbacks).indexOf(type) === -1) {
          throw new Error('invalid callback type ' + type);
        }

        callbacks[type].push(cb);
      }

      el.delegate('a[data-action=use]', 'click', function (e) {
        e.preventDefault();
        use();
      });

      el.delegate('a[data-action=clear]', 'click', function (e) {
        e.preventDefault();
        clear();
      });

      render();

      return {
        isSelected: isSelected,
        add: add,
        remove: remove,
        on: addCallback
      };
    }

  };
}(jQuery, HDO, Handlebars));
<|endoftext|>


<commit_before>var calculator = require('./calculator.js');

describe('Calculator Tests', function() {
  it('should add two', function() {
    expect(calculator.addTwo(2)).toEqual(4);
    expect(calculator.addTwo(4)).toEqual(6);
    expect(calculator.addTwo(8)).toEqual(10);
  });

  it('should add three', function() {
    expect(calculator.addThree(2)).toEqual(5);
    expect(calculator.addThree(4)).toEqual(7);
    expect(calculator.addThree(8)).toEqual(11);
  });

  it('should add four', function() {
    expect(calculator.addFour(2)).toEqual(6);
    expect(calculator.addFour(4)).toEqual(8);
    expect(calculator.addFour(8)).toEqual(14);
  });
});<commit_msg>fix a test<commit_after>var calculator = require('./calculator.js');

describe('Calculator Tests', function() {
  it('should add two', function() {
    expect(calculator.addTwo(2)).toEqual(4);
    expect(calculator.addTwo(4)).toEqual(6);
    expect(calculator.addTwo(8)).toEqual(10);
  });

  it('should add three', function() {
    expect(calculator.addThree(2)).toEqual(5);
    expect(calculator.addThree(4)).toEqual(7);
    expect(calculator.addThree(8)).toEqual(11);
  });

  it('should add four', function() {
    expect(calculator.addFour(2)).toEqual(6);
    expect(calculator.addFour(4)).toEqual(8);
    expect(calculator.addFour(8)).toEqual(12);
  });
});<|endoftext|>


<commit_before>((w) => {
  w.gl = w.gl || {};

  class Members {
    constructor() {
      this.removeListeners();
      this.addListeners();
    }

    removeListeners() {
      $('.project_member, .group_member').off('ajax:success');
      $('.js-member-update-control').off('change');
      $('.js-edit-member-form').off('ajax:success');
    }

    addListeners() {
      $('.project_member, .group_member').on('ajax:success', this.removeRow);
      $('.js-member-update-control').on('change', this.formSubmit);
      $('.js-edit-member-form').on('ajax:success', this.formSuccess);
    }

    removeRow(e) {
      const $target = $(e.target);

      if ($target.hasClass('btn-remove')) {
        $target.closest('.member')
          .fadeOut(function () {
            $(this).remove();
          });
      }
    }

    formSubmit() {
      $(this).closest('form').trigger("submit.rails").end().disable();
    }

    formSuccess() {
      $(this).find('.js-member-update-control').enable();
    }
  }

  gl.Members = Members;
})(window);
<commit_msg>Moved how we remove event listeners<commit_after>((w) => {
  w.gl = w.gl || {};

  class Members {
    constructor() {
      this.addListeners();
    }

    addListeners() {
      $('.project_member, .group_member').off('ajax:success').on('ajax:success', this.removeRow);
      $('.js-member-update-control').off('change').on('change', this.formSubmit);
      $('.js-edit-member-form').off('ajax:success').on('ajax:success', this.formSuccess);
    }

    removeRow(e) {
      const $target = $(e.target);

      if ($target.hasClass('btn-remove')) {
        $target.closest('.member')
          .fadeOut(function () {
            $(this).remove();
          });
      }
    }

    formSubmit() {
      $(this).closest('form').trigger("submit.rails").end().disable();
    }

    formSuccess() {
      $(this).find('.js-member-update-control').enable();
    }
  }

  gl.Members = Members;
})(window);
<|endoftext|>


<commit_before>Teikei.module('User', function(User, App, Backbone, Marionette, $, _) {

  User.Model = Backbone.Model.extend({

    urlRoot: "/api/v1/sessions/",

    parse: function(data) {
      this.setAuthToken(data.auth_token);
      this.setUserName(data.user.name);
      return data.user;
    },

    setUserName: function(userName) {
      this.set("userName", userName);
    },

    setAuthToken:function(authToken) {
      this.set("loggedIn", true);
      var headerData = { auth_token: authToken };
      $.ajaxSetup({ headers: headerData });
    },

    signUp: function(signUpData, callback) {
      this.save(signUpData, {
        url: "/api/v1/users",
        success: callback.success,
        error: callback.error
      });
    }

  });
});
<commit_msg>Store user credentials in cookie.<commit_after>Teikei.module('User', function(User, App, Backbone, Marionette, $, _) {

  User.Model = Backbone.Model.extend({

    urlRoot: "/api/v1/sessions/",

    initialize: function() {
      if ($.cookie('auth_token')) {
        this.setAuthToken($.cookie('auth_token'));
        this.setUserName($.cookie('username'));
      }
    },

    parse: function(data) {
      $.cookie('username', data.user.name);
      $.cookie('auth_token', data.auth_token);
      this.setAuthToken(data.auth_token);
      this.setUserName(data.user.name);
      return data.user;
    },

    setUserName: function(userName) {
      this.set("userName", userName);
    },

    setAuthToken:function(authToken) {
      this.set("loggedIn", true);
      var headerData = { auth_token: authToken };
      $.ajaxSetup({ headers: headerData });
    },

    signUp: function(signUpData, callback) {
      this.save(signUpData, {
        url: "/api/v1/users",
        success: callback.success,
        error: callback.error
      });
    },

    destroy: function() {
      $.removeCookie('username');
      $.removeCookie('auth_token');
      return Backbone.Model.prototype.destroy.apply(this, arguments);
    }

  });
});
<|endoftext|>


<commit_before>module.exports = {
    directory: __dirname,
    prefix: 'isbd',
    fields: {
        titleproper: {
            type: 'text',
            label: 'Title proper',
            css: 'font-weight: bold; font-size: 120%;'
        },
        titleremainder: {
            type: 'text',
            label: 'Remainder of title',
            css: 'font-weight: bold;'
        },
        edition: {
            type: 'text',
            label: 'Edition',
            css: ''
        },
        source: {
            type: 'text',
            label: 'Source'
        },
        publisher: {
            type: 'text',
            label: 'Publisher'
        },
        titlevariant: {
            type: 'text',
            label: 'Other title'
        },
        titletranslated: {
            type: 'text',
            label: 'Translated title'
        },
        uri: {
            type: 'property',
            unique: false,
            multivalue: true,
            datatype: 'String',
            label: 'URI'
        },
        note: {
            type: 'text',
            label: 'Note'
        },
        author: {
            type: 'text',
            label: 'Author'
        },
        host: {
            type: 'text',
            label: 'Host item'
        },
        subject: {
            type: 'text',
            label: 'Subject'
        },
        place: {
            type: 'text',
            label: 'Place of publication'
        },
        callnum: {
            type: 'text',
            label: 'Call number'
        },
        year: {
            type: 'property',
            datatype: 'Integer',
            label: 'Publication date'
        },
        barcode: {
            type: 'property',
            datatype: 'String',
            label: 'Barcode'
        },
        series: {
            type: 'text',
            label: 'Series'
        },
        adate: {
            type: 'property',
            datatype: 'String',
            label: 'Auction date'
        },
        author_e: {
            type: 'edge',
            unidirected: false,
            label: 'Author (edge)'
        },
        subject_e: {
            type: 'edge',
            unidirected: false,
            label: 'Subject (edge)'
        },
        place_e: {
            type: 'edge',
            unidirected: false,
            label: 'Place (edge)'
        },
        year_e: {
            type: 'edge',
            unidirected: false,
            label: 'Year (edge)'
        },
        series_e: {
            type: 'edge',
            unidirected: false,
            label: 'Series (edge)'
        },
    },
    facets: {
        author_e: {
            outlabel: 'By',
            inlabel: 'Wrote',
            facetlabel: 'Author',
            field: 'author_e'
        },
        subject_e: {
            outlabel: 'About',
            inlabel: 'Topic of',
            facetlabel: 'Subject',
            field: 'subject_e'
        },
        place_e: {
            outlabel: 'Published in',
            inlabel: 'Place of',
            facetlabel: 'Place of publication',
            field: 'place_e'
        },
        year_e: {
            outlabel: 'Published in',
            inlabel: 'Year of',
            facetlabel: 'Date of publication',
            field: 'year_e'
        },
        series_e: {
            outlabel: 'Part of series',
            inlabel: 'Series of',
            facetlabel: 'Series',
            field: 'series_e'
        }
    },
    formats: {
        marc: {
            biblio: {
                indexes: [
                    { tag: '008', index: 'year', subfields: '07-10', datatype: 'Integer' },
                    { tag: '033', index: 'adate', subfields: 'a' },
                    { tag: '072', index: 'subjectclass', subfields: 'x' },
                    { tag: '[17](00|10|11)', index: 'author', subfields: 'abcdfghijklmnopqrstu' },
                    { tag: '24.', index: 'title', subfields: 'abcdfghijklmnopqrstuvwxyz' },
                    { tag: '245', index: 'titleproper', subfields: 'a' },
                    { tag: '245', index: 'titleremainder', subfields: 'bcdfghijklmnopqrstuvwxyz' },
                    { tag: '246', index: 'titlevariant', subfields: 'abcdfghijklmnopqrstuvwxyz' },
                    { tag: '250', index: 'edition', subfields: 'abcdfghijklmnopqrstuvwxyz' },
                    { tag: '260', index: 'place', subfields: 'a' },
                    { tag: '260', index: 'publisher', subfields: 'b' },
                    { tag: '(4[49]0|830)', index: 'series', subfields: 'abcdefghijklmnopqrstuvwxyz' },
                    { tag: '5..', index: 'note', subfields: 'abcdfghijklmnopqrstuvwxyz' },
                    { tag: '6..', index: 'subject', subfields: 'abcdfghijklmnopqrstuvwxyz' },
                    { tag: '773', index: 'host', subfields: 'abcdfghijklmnopqrstuvwxyz' }
                ],
                links: [
                    { re: '008', label: 'year_e', subfields: '07-10', type: 'authstub' },
                    { re: '072', label: 'subjectclass_e', subfields: 'x', type: 'authstub', marker: true },
                    { re: '[17](00|10|11)', label: 'author_e', subfields: 'abcdfghijklmnopqrstu', type: 'authstub', marker: true },
                    { re: '(440|830)', label: 'series_e', subfields: 'a', type: 'authstub', marker: true },
                    { re: '6..', label: 'subject_e', subfields: 'abcdfghijklmnopqrstuvwxyz', type: 'authstub', marker: true },
                    { re: '6(00|10|11)', label: 'subject_e', subfields: 'abcdfghijklmnopqrstuw', type: 'authstub', marker: true }
                ]
            },
            auth: {
            }
        }
    },
    static_relevance_bumps: {
        recordclass: {
            biblio: 1,
            auth: 0.5
        }
    },
    templates: [
        'marc21_biblio'
    ]
};

<commit_msg>Add host link to ISBD schema<commit_after>module.exports = {
    directory: __dirname,
    prefix: 'isbd',
    fields: {
        titleproper: {
            type: 'text',
            label: 'Title proper',
            css: 'font-weight: bold; font-size: 120%;'
        },
        titleremainder: {
            type: 'text',
            label: 'Remainder of title',
            css: 'font-weight: bold;'
        },
        edition: {
            type: 'text',
            label: 'Edition',
            css: ''
        },
        source: {
            type: 'text',
            label: 'Source'
        },
        publisher: {
            type: 'text',
            label: 'Publisher'
        },
        titlevariant: {
            type: 'text',
            label: 'Other title'
        },
        titletranslated: {
            type: 'text',
            label: 'Translated title'
        },
        uri: {
            type: 'property',
            unique: false,
            multivalue: true,
            datatype: 'String',
            label: 'URI'
        },
        note: {
            type: 'text',
            label: 'Note'
        },
        author: {
            type: 'text',
            label: 'Author'
        },
        host: {
            type: 'text',
            label: 'Host item'
        },
        subject: {
            type: 'text',
            label: 'Subject'
        },
        place: {
            type: 'text',
            label: 'Place of publication'
        },
        callnum: {
            type: 'text',
            label: 'Call number'
        },
        year: {
            type: 'property',
            datatype: 'Integer',
            label: 'Publication date'
        },
        barcode: {
            type: 'property',
            datatype: 'String',
            label: 'Barcode'
        },
        series: {
            type: 'text',
            label: 'Series'
        },
        adate: {
            type: 'property',
            datatype: 'String',
            label: 'Auction date'
        },
        author_e: {
            type: 'edge',
            unidirected: false,
            label: 'Author (edge)'
        },
        subject_e: {
            type: 'edge',
            unidirected: false,
            label: 'Subject (edge)'
        },
        place_e: {
            type: 'edge',
            unidirected: false,
            label: 'Place (edge)'
        },
        year_e: {
            type: 'edge',
            unidirected: false,
            label: 'Year (edge)'
        },
        series_e: {
            type: 'edge',
            unidirected: false,
            label: 'Series (edge)'
        },
        host_e: {
            type: 'edge',
            unidirected: false,
            label: 'Host (edge)'
        },
    },
    facets: {
        author_e: {
            outlabel: 'By',
            inlabel: 'Wrote',
            facetlabel: 'Author',
            field: 'author_e'
        },
        subject_e: {
            outlabel: 'About',
            inlabel: 'Topic of',
            facetlabel: 'Subject',
            field: 'subject_e'
        },
        place_e: {
            outlabel: 'Published in',
            inlabel: 'Place of',
            facetlabel: 'Place of publication',
            field: 'place_e'
        },
        year_e: {
            outlabel: 'Published in',
            inlabel: 'Year of',
            facetlabel: 'Date of publication',
            field: 'year_e'
        },
        series_e: {
            outlabel: 'Part of series',
            inlabel: 'Series of',
            facetlabel: 'Series',
            field: 'series_e'
        }
    },
    formats: {
        marc: {
            biblio: {
                indexes: [
                    { tag: '008', index: 'year', subfields: '07-10', datatype: 'Integer' },
                    { tag: '033', index: 'adate', subfields: 'a' },
                    { tag: '072', index: 'subjectclass', subfields: 'x' },
                    { tag: '[17](00|10|11)', index: 'author', subfields: 'abcdfghijklmnopqrstu' },
                    { tag: '24.', index: 'title', subfields: 'abcdfghijklmnopqrstuvwxyz' },
                    { tag: '245', index: 'titleproper', subfields: 'a' },
                    { tag: '245', index: 'titleremainder', subfields: 'bcdfghijklmnopqrstuvwxyz' },
                    { tag: '246', index: 'titlevariant', subfields: 'abcdfghijklmnopqrstuvwxyz' },
                    { tag: '250', index: 'edition', subfields: 'abcdfghijklmnopqrstuvwxyz' },
                    { tag: '260', index: 'place', subfields: 'a' },
                    { tag: '260', index: 'publisher', subfields: 'b' },
                    { tag: '(4[49]0|830)', index: 'series', subfields: 'abcdefghijklmnopqrstuvwxyz' },
                    { tag: '5..', index: 'note', subfields: 'abcdfghijklmnopqrstuvwxyz' },
                    { tag: '6..', index: 'subject', subfields: 'abcdfghijklmnopqrstuvwxyz' },
                    { tag: '773', index: 'host', subfields: 'abcdfghijklmnopqrstuvwxyz' }
                ],
                links: [
                    { re: '008', label: 'year_e', subfields: '07-10', type: 'authstub' },
                    { re: '072', label: 'subjectclass_e', subfields: 'x', type: 'authstub', marker: true },
                    { re: '[17](00|10|11)', label: 'author_e', subfields: 'abcdfghijklmnopqrstu', type: 'authstub', marker: true },
                    { re: '(440|830)', label: 'series_e', subfields: 'a', type: 'authstub', marker: true },
                    { re: '6..', label: 'subject_e', subfields: 'abcdfghijklmnopqrstuvwxyz', type: 'authstub', marker: true },
                    { re: '6(00|10|11)', label: 'subject_e', subfields: 'abcdfghijklmnopqrstuw', type: 'authstub', marker: true }
                ]
            },
            auth: {
            }
        }
    },
    static_relevance_bumps: {
        recordclass: {
            biblio: 1,
            auth: 0.5
        }
    },
    templates: [
        'marc21_biblio'
    ]
};

<|endoftext|>


<commit_before>import React from 'react'
import styled, { keyframes, css } from 'styled-components'
import onClickOutside from 'react-onclickoutside'
import { bind, choose } from '../../.utils/react/react-utils'
import { wave } from '../animation'
import { uniq } from 'lodash'

const record = require('mousetrap-record')
const mousetrap = record(require('mousetrap'))

const Dots = styled(props => (

))`
    position: absolute;
    top: 50%;
    left: 50%;
    margin: 0 0 0 -15px;
    display: flex;

    & > span {
        position: relative;
        width: 6px;
        height: 6px;
        margin: 0 2px 0;
        border-radius: 100%;
        background: rgba(255, 255, 255, 0.6);
        display: inline-block;
        animation: ${wave} 1.4s linear infinite;
        animation-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);

        &:nth-child(2) {
            animation-delay: 0.35s;
        }
        &:nth-child(3) {
            animation-delay: 0.7s;
        }
    }
`

class ShortcutsItem extends React.PureComponent {
    constructor(props) {
        super(props)
        bind(this, ['handleClick'])
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.active === false) {
            return
        }
        mousetrap.record(code => {
            this.props.onClick()
            this.props.onAssign(
                this.props.data.name,
                code
            )
            return false
        })
    }

    handleClick() {
        this.props.onClick(this.props.data.name)
        mousetrap.record(() => false)
    }

    handleClickOutside(e) {
        if (this.props.active && !this.isItem(e)) {
            this.handleClick()
        }
    }

    isItem(e) {
        return !this.props.className.indexOf(
            e.target.classList[0]
        )
    }

    toValue() {
        let value = this.props.value
        if (value == null) {
            return ''
        }
        return uniq(value
            .split(/[\+\s]/))
            .join('+')
    }

    render() {
        let { className, data, active } = this.props
        return (

{data.label}

{this.toValue()}

                {active && <Dots />}

        )
    }
}

export default styled(onClickOutside(ShortcutsItem))`
    position: relative;
    padding: 0.75em;
    border-top: 1px dashed #dddfe2;
    display: flex;
    justify-content: space-between;

    &:first-child {
        border-top: 0;
    }
    &:hover {
        background: #eaedf0;
        cursor: pointer;
    }
    ${choose('active', {
        true: css`
            &,
            &:hover {
                color: #fff;
                background: #009ff1;
                border-top-color: #009ff1;
                border-top-style: solid;
            }
            & + * {
                border-top: 1px solid #009ff1;
            }`
    })};
`
<commit_msg>Delete shortcuts-item.js<commit_after><|endoftext|>


<commit_before>import styled from 'styled-components';
import ContentBlock from 'components/ContentBlock';

export default styled(ContentBlock)`
  width: 50%;
  margin-${p=>p.lang==='ar'?'right':'left'}: 50%;
  transform: translateX(${p=>p.lang==='ar'?'50%':'-50%'});
  padding: 0 40px;
  text-align: center;

  @media(max-width: 700px) {
    width: 100%;
  }
`;
<commit_msg>Fix for https://3.basecamp.com/3161453/buckets/3412210/todos/626098030<commit_after>import styled from 'styled-components';
import ContentBlock from 'components/ContentBlock';

export default styled(ContentBlock)`
  width: 50%;
  margin-${p=>p.lang==='ar'?'right':'left'}: 50%;
  transform: translateX(${p=>p.lang==='ar'?'50%':'-50%'});
  padding: 0 40px;
  text-align: center;

  @media(max-width: 700px) {
    width: 100%;
    text-align: center;
    transform: none;
    margin-left: auto;
  }
`;
<|endoftext|>


<commit_before>import {
  a,
  button,
  div,
  span,
  li,
  ul,
  h1,
  h2,
  svg,
  path,
} from '../../utils/elements';
import ScoreBoard from '../ScoreBoard/ScoreBoard';
import { EVENTS } from '../../utils/constants';
import swapNodes from '../../utils/swapNodes';

import store from '../../data/store';

if (process.env.IMPORT_SCSS) require(`./InfoModal.scss`); // eslint-disable-line global-require

const InfoModal = () => {
  let el;

  const render = () => {
    // classList.toggle doesn't work in IE11
    if (store.isModalVisible) {
      document.body.classList.add(`block-scroll`);
    } else {
      document.body.classList.remove(`block-scroll`);
    }

    if (!store.isModalVisible) return div();

    const unknownItems = store.getUnknowns();

    const unknownItemsDom = unknownItems.map(item => (
      li({ className: `info-modal__unknown-item` },
        span({ className: `info-modal__unknown-item-text` }, item.path),
        a(
          {
            className: `info-modal__unknown-item-link`,
            href: item.url,
            rel: `noopen norefferer`,
            target: `_blank`,
          },
          svg({ width: 20, height: 20, viewBox: `0 0 1024 1024` },
            path({ d: `M992.262 871.396l-242.552-206.294c-25.074-22.566-51.89-32.926-73.552-31.926 57.256-67.068 91.842-154.078 91.842-249.176 0-212.078-171.922-384-384-384-212.076 0-384 171.922-384 384s171.922 384 384 384c95.098 0 182.108-34.586 249.176-91.844-1 21.662 9.36 48.478 31.926 73.552l206.294 242.552c35.322 39.246 93.022 42.554 128.22 7.356s31.892-92.898-7.354-128.22zM384 640c-141.384 0-256-114.616-256-256s114.616-256 256-256 256 114.616 256 256-114.614 256-256 256z` }), // eslint-disable-line max-len
          ),
        ),
      )
    ));

    return div(
      {
        className: `info-modal__background`,
        onclick: (e) => {
          // direct hits only
          if (e.eventPhase === Event.AT_TARGET) store.closeModal();
        },
      },
      div({ className: `info-modal` },
        div({ className: `info-modal__header` },
          h1({ className: `info-modal__title` },
            `Info`,
          ),
          button(
            {
              className: `info-modal__close`,
              onclick: () => {
                store.closeModal();
              },
            },
            `✕`,
          ),
        ),
        div({ className: `info-modal__body` },
          a(
            {
              className: `info-modal__info-link`,
              href: `https://hackernoon.com/what-you-dont-know-about-web-development-d7d631f5d468#.ex2yp6d64`,
              rel: `noopener noreferrer`,
              target: `_blank`,
            },
            `A blog post about know it all`,
          ),

          a(
            {
              className: `info-modal__info-link`,
              href: `https://github.com/davidgilbertson/know-it-all/issues`,
              rel: `noopener noreferrer`,
              target: `_blank`,
            },
            `Log an issue, make a suggestion`,
          ),

          h2({ className: `info-modal__section-title` },
            `Scores`,
          ),

          ScoreBoard(),

          h2({ className: `info-modal__section-title` },
            `Things you don't know`,
          ),

          ul({ className: `info-modal__unknown-items` },
            unknownItemsDom,
          ),
        ),
      ),
    );
  };

  store.listen(EVENTS.MODAL_VISIBILITY_CHANGED, () => {
    el = swapNodes(el, render());
  });

  el = render();

  return el;
};

export default InfoModal;
<commit_msg>Link to new blog post<commit_after>import {
  a,
  button,
  div,
  span,
  li,
  ul,
  h1,
  h2,
  svg,
  path,
} from '../../utils/elements';
import ScoreBoard from '../ScoreBoard/ScoreBoard';
import { EVENTS } from '../../utils/constants';
import swapNodes from '../../utils/swapNodes';

import store from '../../data/store';

if (process.env.IMPORT_SCSS) require(`./InfoModal.scss`); // eslint-disable-line global-require

const InfoModal = () => {
  let el;

  const render = () => {
    // classList.toggle doesn't work in IE11
    if (store.isModalVisible) {
      document.body.classList.add(`block-scroll`);
    } else {
      document.body.classList.remove(`block-scroll`);
    }

    if (!store.isModalVisible) return div();

    const unknownItems = store.getUnknowns();

    const unknownItemsDom = unknownItems.map(item => (
      li({ className: `info-modal__unknown-item` },
        span({ className: `info-modal__unknown-item-text` }, item.path),
        a(
          {
            className: `info-modal__unknown-item-link`,
            href: item.url,
            rel: `noopen norefferer`,
            target: `_blank`,
          },
          svg({ width: 20, height: 20, viewBox: `0 0 1024 1024` },
            path({ d: `M992.262 871.396l-242.552-206.294c-25.074-22.566-51.89-32.926-73.552-31.926 57.256-67.068 91.842-154.078 91.842-249.176 0-212.078-171.922-384-384-384-212.076 0-384 171.922-384 384s171.922 384 384 384c95.098 0 182.108-34.586 249.176-91.844-1 21.662 9.36 48.478 31.926 73.552l206.294 242.552c35.322 39.246 93.022 42.554 128.22 7.356s31.892-92.898-7.354-128.22zM384 640c-141.384 0-256-114.616-256-256s114.616-256 256-256 256 114.616 256 256-114.614 256-256 256z` }), // eslint-disable-line max-len
          ),
        ),
      )
    ));

    return div(
      {
        className: `info-modal__background`,
        onclick: (e) => {
          // direct hits only
          if (e.eventPhase === Event.AT_TARGET) store.closeModal();
        },
      },
      div({ className: `info-modal` },
        div({ className: `info-modal__header` },
          h1({ className: `info-modal__title` },
            `Info`,
          ),
          button(
            {
              className: `info-modal__close`,
              onclick: () => {
                store.closeModal();
              },
            },
            `✕`,
          ),
        ),
        div({ className: `info-modal__body` },
          a(
            {
              className: `info-modal__info-link`,
              href: `https://medium.com/@david.gilbertson/master-web-development-with-these-9-985-weird-tricks-77c71d1d96f3#.6fz456o44`, // eslint-disable-line max-len
              rel: `noopener noreferrer`,
              target: `_blank`,
            },
            `A blog post about know it all`,
          ),

          a(
            {
              className: `info-modal__info-link`,
              href: `https://github.com/davidgilbertson/know-it-all/issues`,
              rel: `noopener noreferrer`,
              target: `_blank`,
            },
            `Log an issue, make a suggestion`,
          ),

          h2({ className: `info-modal__section-title` },
            `Scores`,
          ),

          ScoreBoard(),

          h2({ className: `info-modal__section-title` },
            `Things you don't know`,
          ),

          ul({ className: `info-modal__unknown-items` },
            unknownItemsDom,
          ),
        ),
      ),
    );
  };

  store.listen(EVENTS.MODAL_VISIBILITY_CHANGED, () => {
    el = swapNodes(el, render());
  });

  el = render();

  return el;
};

export default InfoModal;
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import ImmutablePropTypes from 'react-immutable-proptypes'
import LanguageProvider from 'containers/LanguageProvider'
// Import i18n messages
import { translationMessages } from '../../i18n'
import Avatar from 'material-ui/Avatar'
import PropTypes from 'prop-types'
import { FormattedMessage } from 'react-intl'
import jp from 'jsonpath'
import Chip from 'material-ui/Chip'
import removeDiacritics from 'components/SearchField/removeDiacritics'
import { lightGreen400 } from 'material-ui/styles/colors'
import SearchIcon from 'material-ui/svg-icons/action/search'
import stopWords from 'utils/stopWords'
import messages from './messages'

const styles = {
  chip: {
    margin: '4px',
  },
}

const baseTags = [
  'traffic',
  'feeding',
  'augmentative communication',
  'language',
  'mass media',
  'signaling system',
  'education',
  'work',
  'sport',
  'traditional game',
  'toy',
  'game',
  'show',
  'hobby',
  'outdoor activity',
  'place',
  'scenic art',
  'music',
  'visual art',
  'environmental science',
  'health',
  'astronomy',
  'biology',
  'geography',
  'meteorology',
  'oceanography',
  'paleontology',
  'physics',
  'chemistry',
  'geology',
  'law',
  'economy',
  'history',
  'psychology',
  'sociology',
  'speech therapy',
  'engineering',
  'architecture',
  'agriculture',
  'computing',
  'veterinary medicine',
  'mathematics',
  'literature',
  'library science',
  'religion',
  'person',
  'routine',
  'human body',
  'animal',
  'plant',
  'event',
  'time',
  'chronological device',
  'object',
  'document',
  'place',
  'categorization',
]

/* we must render:
  none: if searchText is empty or not a category
  pictogram tags that belong to the category otherwise not present in 100% pictos + selectedTags
*/

const importantTags = [
  'professional',
  'place',
  'verb',
  'document',
  'person',
  'building',
  'room',
  'facility',
]

const getTags = (searchText, categoryTree, locale) => {
  const tree = categoryTree.toJSON()
  const nodes = jp.nodes(tree, '$..keywords')
  const categories = nodes
    .filter((node) =>
      node.value.some(
        (keyword) =>
          removeDiacritics(stopWords(keyword, locale)).toLowerCase() ===
          searchText
      )
    )
    .map((node) => node.path[1])

  if (categories.length) {
    const tags = []
    categories.forEach((categoryItem) => {
      const partialData = jp.value(tree, `$..["${categoryItem}"]`)
      const newTags = getSubcategoryTags(partialData, partialData.tags)
      newTags.forEach((element) => tags.push(element))
    })
    return tags.concat(importantTags)
  }
  return []
}

const getSubcategoryTags = (tree, tags) => {
  if (tree.children && Object.keys(tree.children).length !== 0) {
    return Object.entries(tree.children).reduce((accumulator, currentValue) => {
      if (currentValue[0])
        currentValue[1].tags.forEach((tag) => {
          if (tags.indexOf(tag) === -1) tags.push(tag)
        })
      return getSubcategoryTags(currentValue[1], tags)
    }, [])
  }
  return tags
}

const getKeywords = (pictoCategories, categoryTree) => {
  const tree = categoryTree.toJSON()
  const nodes = jp.nodes(tree, '$..keywords')
  const keywords = pictoCategories.reduce((accumulator, currentValue) => {
    const keywords = nodes
      .filter((node) => node.path[node.path.length - 2] === currentValue)
      .map((node) => node.value)
    return keywords[0] && keywords[0].length
      ? [...accumulator, keywords[0][0]]
      : accumulator
  }, [])
  return keywords
}

const PictogramTags = ({
  searchText,
  selectedTags,
  categories,
  locale,
  pictograms,
  onUpdateTags,
  onCategoryClick,
}) => {
  const searchCategory = removeDiacritics(
    stopWords(searchText, locale)
  ).toLowerCase()
  const tags = pictograms.length
    ? getTags(searchCategory, categories, locale)
    : null
  let renderTags

  if (tags.length) {
    /*  if search is a category, tags wont' be empty and we use tags as filter, in other  case
    we wet categories of first pictogram to give suggestions */
    const pictoTags = new Set()
    /* we just show pictoTags present in the tree and not available  in all pictograms */
    pictograms.forEach((pictogram) =>
      pictogram.tags.forEach((tag) => {
        if (tags.indexOf(tag) !== -1) pictoTags.add(tag)
      })
    )
    /*  if tag is available in  all pictograms, we just remove it, we also delete selectedTags as we
    will sort them in first place */
    pictoTags.forEach((tag) => {
      if (
        pictograms.every((pictogram) => pictogram.tags.indexOf(tag) !== -1) ||
        selectedTags.has(tag)
      )
        pictoTags.delete(tag)
    })

    /* we  order then by frequency */
    const countOccurrences = (item) => (accumulator, currentValue) => {
      if (currentValue.tags.indexOf(item) !== -1) return accumulator + 1
      return accumulator + 0
    }
    const tmpPictoTagsOrdered = [...pictoTags].sort((a, b) => {
      const weightA = pictograms.reduce(countOccurrences(a), 0)
      const weightB = pictograms.reduce(countOccurrences(b), 0)
      return weightB - weightA
    })

    let pictoTagsOrdered = [...selectedTags, ...tmpPictoTagsOrdered]
    const concurrences = pictoTagsOrdered.reduce(
      (acc, curVal) => (baseTags.indexOf(curVal) !== -1 ? acc + 1 : acc),
      0
    )
    // core vocabulary,  show only main filters:
    if (concurrences > 5) {
      pictoTagsOrdered = [...selectedTags, ...tmpPictoTagsOrdered].filter(
        (item) => baseTags.indexOf(item) !== -1
      )
    }

    const handleClick = (tag) => onUpdateTags(tag)

    /* we add already selected tags */

    renderTags = pictoTagsOrdered.map((tag) =>
      selectedTags.has(tag) ? (
        <Chip
          backgroundColor={lightGreen400}
          style={styles.chip}
          key={tag}
          onClick={() => handleClick(tag)}
        >
          {<FormattedMessage {...messages[tag]} />}
        </Chip>
      ) : (
        <Chip style={styles.chip} key={tag} onClick={() => handleClick(tag)}>
          {<FormattedMessage {...messages[tag]} />}
        </Chip>
      )
    )
  } else {
    const pictoCategories = pictograms
      .filter((pictogram) =>
        pictogram.keywords.some(
          (keyword) =>
            searchCategory ===
            removeDiacritics(stopWords(keyword.keyword, locale)).toLowerCase()
        )
      )
      .map((pictogram) => pictogram.categories)
    const mergedCategories = [].concat.apply([], pictoCategories)
    const keywords = getKeywords(mergedCategories, categories)
    renderTags = keywords.map((keyword) => (
      <Chip
        style={styles.chip}
        key={keyword}
        onClick={() => onCategoryClick(keyword)}
      >
        <Avatar icon={<SearchIcon />} />
        {keyword}
      </Chip>
    ))
  }

  return (
    <LanguageProvider messages={translationMessages} paramLocale={locale}>

{renderTags}

    </LanguageProvider>
  )
}

PictogramTags.propTypes = {
  searchText: PropTypes.string,
  selectedTags: ImmutablePropTypes.set.isRequired,
  categories: PropTypes.object.isRequired,
  locale: PropTypes.string.isRequired,
  pictograms: PropTypes.array,
}

export default PictogramTags
<commit_msg>remove warning  duplicate  key<commit_after>import React, { Component } from 'react'
import ImmutablePropTypes from 'react-immutable-proptypes'
import LanguageProvider from 'containers/LanguageProvider'
// Import i18n messages
import { translationMessages } from '../../i18n'
import Avatar from 'material-ui/Avatar'
import PropTypes from 'prop-types'
import { FormattedMessage } from 'react-intl'
import jp from 'jsonpath'
import Chip from 'material-ui/Chip'
import removeDiacritics from 'components/SearchField/removeDiacritics'
import { lightGreen400 } from 'material-ui/styles/colors'
import SearchIcon from 'material-ui/svg-icons/action/search'
import stopWords from 'utils/stopWords'
import messages from './messages'

const styles = {
  chip: {
    margin: '4px',
  },
}

const baseTags = [
  'traffic',
  'feeding',
  'augmentative communication',
  'language',
  'mass media',
  'signaling system',
  'education',
  'work',
  'sport',
  'traditional game',
  'toy',
  'game',
  'show',
  'hobby',
  'outdoor activity',
  'place',
  'scenic art',
  'music',
  'visual art',
  'environmental science',
  'health',
  'astronomy',
  'biology',
  'geography',
  'meteorology',
  'oceanography',
  'paleontology',
  'physics',
  'chemistry',
  'geology',
  'law',
  'economy',
  'history',
  'psychology',
  'sociology',
  'speech therapy',
  'engineering',
  'architecture',
  'agriculture',
  'computing',
  'veterinary medicine',
  'mathematics',
  'literature',
  'library science',
  'religion',
  'person',
  'routine',
  'human body',
  'animal',
  'plant',
  'event',
  'time',
  'chronological device',
  'object',
  'document',
  'place',
  'categorization',
]

/* we must render:
  none: if searchText is empty or not a category
  pictogram tags that belong to the category otherwise not present in 100% pictos + selectedTags
*/

const importantTags = [
  'professional',
  'place',
  'verb',
  'document',
  'person',
  'building',
  'room',
  'facility',
]

const getTags = (searchText, categoryTree, locale) => {
  const tree = categoryTree.toJSON()
  const nodes = jp.nodes(tree, '$..keywords')
  const categories = nodes
    .filter((node) =>
      node.value.some(
        (keyword) =>
          removeDiacritics(stopWords(keyword, locale)).toLowerCase() ===
          searchText
      )
    )
    .map((node) => node.path[1])

  if (categories.length) {
    const tags = []
    categories.forEach((categoryItem) => {
      const partialData = jp.value(tree, `$..["${categoryItem}"]`)
      const newTags = getSubcategoryTags(partialData, partialData.tags)
      newTags.forEach((element) => tags.push(element))
    })
    return [...new Set(tags.concat(importantTags))]
  }
  return []
}

const getSubcategoryTags = (tree, tags) => {
  if (tree.children && Object.keys(tree.children).length !== 0) {
    return Object.entries(tree.children).reduce((accumulator, currentValue) => {
      if (currentValue[0])
        currentValue[1].tags.forEach((tag) => {
          if (tags.indexOf(tag) === -1) tags.push(tag)
        })
      return getSubcategoryTags(currentValue[1], tags)
    }, [])
  }
  return tags
}

const getKeywords = (pictoCategories, categoryTree) => {
  const tree = categoryTree.toJSON()
  const nodes = jp.nodes(tree, '$..keywords')
  const keywords = pictoCategories.reduce((accumulator, currentValue) => {
    const keywords = nodes
      .filter((node) => node.path[node.path.length - 2] === currentValue)
      .map((node) => node.value)
    return keywords[0] && keywords[0].length
      ? [...accumulator, keywords[0][0]]
      : accumulator
  }, [])
  return [...new Set(keywords)]
}

const PictogramTags = ({
  searchText,
  selectedTags,
  categories,
  locale,
  pictograms,
  onUpdateTags,
  onCategoryClick,
}) => {
  const searchCategory = removeDiacritics(
    stopWords(searchText, locale)
  ).toLowerCase()
  const tags = pictograms.length
    ? getTags(searchCategory, categories, locale)
    : null
  let renderTags

  if (tags.length) {
    /*  if search is a category, tags wont' be empty and we use tags as filter, in other  case
    we wet categories of first pictogram to give suggestions */
    const pictoTags = new Set()
    /* we just show pictoTags present in the tree and not available  in all pictograms */
    pictograms.forEach((pictogram) =>
      pictogram.tags.forEach((tag) => {
        if (tags.indexOf(tag) !== -1) pictoTags.add(tag)
      })
    )
    /*  if tag is available in  all pictograms, we just remove it, we also delete selectedTags as we
    will sort them in first place */
    pictoTags.forEach((tag) => {
      if (
        pictograms.every((pictogram) => pictogram.tags.indexOf(tag) !== -1) ||
        selectedTags.has(tag)
      )
        pictoTags.delete(tag)
    })

    /* we  order then by frequency */
    const countOccurrences = (item) => (accumulator, currentValue) => {
      if (currentValue.tags.indexOf(item) !== -1) return accumulator + 1
      return accumulator + 0
    }
    const tmpPictoTagsOrdered = [...pictoTags].sort((a, b) => {
      const weightA = pictograms.reduce(countOccurrences(a), 0)
      const weightB = pictograms.reduce(countOccurrences(b), 0)
      return weightB - weightA
    })

    let pictoTagsOrdered = [...selectedTags, ...tmpPictoTagsOrdered]
    const concurrences = pictoTagsOrdered.reduce(
      (acc, curVal) => (baseTags.indexOf(curVal) !== -1 ? acc + 1 : acc),
      0
    )
    // core vocabulary,  show only main filters:
    if (concurrences > 5) {
      pictoTagsOrdered = [...selectedTags, ...tmpPictoTagsOrdered].filter(
        (item) => baseTags.indexOf(item) !== -1
      )
    }

    const handleClick = (tag) => onUpdateTags(tag)

    /* we add already selected tags */

    renderTags = pictoTagsOrdered.map((tag) =>
      selectedTags.has(tag) ? (
        <Chip
          backgroundColor={lightGreen400}
          style={styles.chip}
          key={tag}
          onClick={() => handleClick(tag)}
        >
          {<FormattedMessage {...messages[tag]} />}
        </Chip>
      ) : (
        <Chip style={styles.chip} key={tag} onClick={() => handleClick(tag)}>
          {<FormattedMessage {...messages[tag]} />}
        </Chip>
      )
    )
  } else {
    const pictoCategories = pictograms
      .filter((pictogram) =>
        pictogram.keywords.some(
          (keyword) =>
            searchCategory ===
            removeDiacritics(stopWords(keyword.keyword, locale)).toLowerCase()
        )
      )
      .map((pictogram) => pictogram.categories)
    const mergedCategories = [].concat.apply([], pictoCategories)
    const keywords = getKeywords(mergedCategories, categories)
    renderTags = keywords.map((keyword) => (
      <Chip
        style={styles.chip}
        key={keyword}
        onClick={() => onCategoryClick(keyword)}
      >
        <Avatar icon={<SearchIcon />} />
        {keyword}
      </Chip>
    ))
  }

  return (
    <LanguageProvider messages={translationMessages} paramLocale={locale}>

{renderTags}

    </LanguageProvider>
  )
}

PictogramTags.propTypes = {
  searchText: PropTypes.string,
  selectedTags: ImmutablePropTypes.set.isRequired,
  categories: PropTypes.object.isRequired,
  locale: PropTypes.string.isRequired,
  pictograms: PropTypes.array,
}

export default PictogramTags
<|endoftext|>