<commit_before>(function(Browser) {

	Browser.Items = Browser.Items || {};
	Browser.Items.Views = Browser.Items || {};

	Browser.Items.Views.Thumb = Backbone.View.extend({

		tagName : 'li',
		events: {

			//'click .jda-delete-item' : this.remove,

		},
		initialize: function () {

			this.el.id = this.model.id;

			if (_.isUndefined(this.options.thumbnail_height)){
				this.options.thumbnail_height = 120;
			}
			if (_.isUndefined(this.options.fancybox)){
				this.options.fancybox = true;
			}
			if(this.options.fancybox||true){
				$(this.el).addClass('thumb-fancymedia');
			}
			if (_.isUndefined(this.options.thumbnail_width)){
				this.options.thumbnail_width = 160;
			}
			if (_.isUndefined(this.options.show_caption)){
				this.options.show_caption = true;
			}

			if (!_.isUndefined(this.options.draggable)){
				this.draggable=this.options.draggable;
			}
			else this.draggable=true;

			this.model.set({thumbnail_width:this.options.thumbnail_width, thumbnail_height:this.options.thumbnail_height});

			//this is for fancy box to know to group these into a gallery
			$(this.el).attr("rel", "group");

		},

		render: function(done)
		{
			var _this = this;

			var template = this.getDefaultTemplate();

			switch( this.model.get('media_type') )
			{

				case 'Tweet':
					template = this.getTweetTemplate();
					break;
				case 'Text':
					template = this.getTestimonialTemplate();
					break;
				case 'Collection':
					template = this.getCollectionTemplate();
					break;

				default:
					template = this.getDefaultTemplate();
			}

			var blanks = this.model.attributes;

			blanks.remove_text = l.jda_collection_remove;
			blanks.delete_text = l.jda_collection_delete;

			if (this.model.get('media_type') == "Tweet" && this.options.show_caption){
				blanks['position_tweet_handle'] = '50%';
			} else if (this.model.get('media_type') == "Tweet" && !this.options.show_caption){
				blanks['position_tweet_handle'] = '75%';
			}

			$(this.el).html( _.template( template, blanks ) );

			//Turn off captions if we don't want them OR if it's an image
			if (!this.options.show_caption || this.model.get('media_type') == "Image"){
				$(this.el).find('.jda-thumbnail-caption').hide();
			}

			//Insert play icon if it's a video
			if (this.model.get('media_type') == "Video"){
				$('').insertBefore($(this.el).find('img'));
			}

			//if no thumbnail or if it's a tweet then just show the grey icon instead of thumb
			/*if (this.model.get('media_type') == 'Tweet' || this.model.get('thumbnail_url') == null || this.model.get('thumbnail_url').length ==0 && !_.isUndefined(this.model.get('media_type')))
			{

				$(this.el).find('img').replaceWith(	'');
			}*/
			if (this.model.get('media_type') == 'Document'){

				$(this.el).find('img').addClass('jda-document-thumbnail');

			}
			if (this.model.get('media_type') == 'Collection')
			{
				this.draggable=false;
				$(this.el).click(function(){ jda.app.goToCollection(_this.model.id); return false;});
				$(this.el).find('.zeega-collection').css({'width':this.options.thumbnail_width, 'height': this.options.thumbnail_height});

			} else{
				//Turning this off because buggy
				//$(this.el).popover({'title':this.model.get('title'), 'content':this.model.get('description'), 'delay':{ show: 2000, hide: 100 },'placement':'bottom'});

			}

			if(this.draggable){
				$(this.el).draggable({

					cursor : 'move',
					cursorAt : {
						top : -5,
						left : -5
					},
					appendTo : 'body',
					opacity : 0.8,

					helper : function(){
						var drag = $(this).find('a').clone().css({'z-index':'101'});
						return drag;
					},

					//init the dragged item variable
					start : function(){
						$(this).draggable('option','revert',true);
						jda.app.draggedItem = _this.model;
					}
				});
				$(this.el).find(".jdicon-small-drag").tooltip({'title':'Drag to add to your collection','placement':'bottom', delay: { show: 600, hide: 100 }});
				$(this.el).find(".label").tooltip({'placement':'bottom', delay: { show: 600, hide: 100 }});
			}

			//Replace broken thumbnail images with the media type icon

			$(this.el).find("img").on("error", function(e) {
                $(e.target).hide();
                $(e.target.parentElement).append(  '');
            });
			return this;
		},

		getCollectionTemplate : function()
		{
			var html =

				''+
				//	''+
				//	''+
				//	''+
					'<img src="<%=thumbnail_url%>" alt="<%=title%>" style="width:<%=thumbnail_width%>px;height:<%=thumbnail_height%>px">'+
					//'<input class="jda-item-checkbox" type="checkbox">'+
					'<button class="btn btn-danger btn-mini jda-delete-item jda-delete-collection">x  <%=delete_text%></button>'+
				'<p class="jda-thumbnail-caption" style="max-width:<%=thumbnail_width%>px;text-align:center;font-size:12px;font-weight:bold"><%=title%>
';

			return html;
		},

		getDefaultTemplate : function()
		{

			var html =

				'<a href="#" class="thumbnail" style="position:relative;width:<%=thumbnail_width%>px;height:<%=thumbnail_height%>px;background-color:white">'+
					'<img src="<%=thumbnail_url%>" alt="<%=title%>" style="width:<%=thumbnail_width%>px;height:<%=thumbnail_height%>px">'+

					'<button class="btn btn-danger btn-mini jda-delete-item">x  <%=remove_text%></button>'+
				'<p class="jda-thumbnail-caption" style="max-width:<%=thumbnail_width%>px;"><%=title%>
';

			return html;

		},
		getTestimonialTemplate : function()
		{

			var html =

				'<a href="#" class="thumbnail" style="position:relative;width:<%=thumbnail_width%>px;height:<%=thumbnail_height%>px;background-color:white">'+
					''+

					'<button class="btn btn-danger btn-mini jda-delete-item">x  <%=remove_text%></button>'+
				'<p class="jda-thumbnail-caption" style="max-width:<%=thumbnail_width%>px"><%=description%>
';

			return html;

		},
		getTweetTemplate : function()
		{

			var html =

				'<a href="#" class="thumbnail" style="width:<%=thumbnail_width%>px;height:<%=thumbnail_height%>px;background-color:white">'+
					''+
					'<span style="position:absolute;top:<%=position_tweet_handle%>;right:9%;max-width:85%;overflow:hidden;line-height:18px;color:#444;font-size:12px">@<%=media_creator_username%>'+

					'<button class="btn btn-danger btn-mini jda-delete-item">x  <%=remove_text%></button>'+
				'<p class="jda-thumbnail-caption" style="max-width:<%=thumbnail_width%>px"><%=description%>
';

			return html;

		}

	});

})(jda.module("browser"));<commit_msg>Added id<commit_after>(function(Browser) {

	Browser.Items = Browser.Items || {};
	Browser.Items.Views = Browser.Items || {};

	Browser.Items.Views.Thumb = Backbone.View.extend({

		tagName : 'li',
		events: {

			//'click .jda-delete-item' : this.remove,

		},
		initialize: function () {

			this.el.id = this.model.id;

			if (_.isUndefined(this.options.thumbnail_height)){
				this.options.thumbnail_height = 120;
			}
			if (_.isUndefined(this.options.fancybox)){
				this.options.fancybox = true;
			}
			if(this.options.fancybox||true){
				$(this.el).addClass('thumb-fancymedia');
			}
			if (_.isUndefined(this.options.thumbnail_width)){
				this.options.thumbnail_width = 160;
			}
			if (_.isUndefined(this.options.show_caption)){
				this.options.show_caption = true;
			}

			if (!_.isUndefined(this.options.draggable)){
				this.draggable=this.options.draggable;
			}
			else this.draggable=true;

			this.model.set({thumbnail_width:this.options.thumbnail_width, thumbnail_height:this.options.thumbnail_height});

			//this is for fancy box to know to group these into a gallery
			$(this.el).attr("rel", "group");

		},

		render: function(done)
		{
			var _this = this;

			var template = this.getDefaultTemplate();

			switch( this.model.get('media_type') )
			{

				case 'Tweet':
					template = this.getTweetTemplate();
					break;
				case 'Text':
					template = this.getTestimonialTemplate();
					break;
				case 'Collection':
					template = this.getCollectionTemplate();
					break;

				default:
					template = this.getDefaultTemplate();
			}

			var blanks = this.model.attributes;

			blanks.remove_text = l.jda_collection_remove;
			blanks.delete_text = l.jda_collection_delete;

			if (this.model.get('media_type') == "Tweet" && this.options.show_caption){
				blanks['position_tweet_handle'] = '50%';
			} else if (this.model.get('media_type') == "Tweet" && !this.options.show_caption){
				blanks['position_tweet_handle'] = '75%';
			}

			$(this.el).html( _.template( template, blanks ) );

			//Turn off captions if we don't want them OR if it's an image
			if (!this.options.show_caption || this.model.get('media_type') == "Image"){
				$(this.el).find('.jda-thumbnail-caption').hide();
			}

			//Insert play icon if it's a video
			if (this.model.get('media_type') == "Video"){
				$('').insertBefore($(this.el).find('img'));
			}

			//if no thumbnail or if it's a tweet then just show the grey icon instead of thumb
			/*if (this.model.get('media_type') == 'Tweet' || this.model.get('thumbnail_url') == null || this.model.get('thumbnail_url').length ==0 && !_.isUndefined(this.model.get('media_type')))
			{

				$(this.el).find('img').replaceWith(	'');
			}*/
			if (this.model.get('media_type') == 'Document'){

				$(this.el).find('img').addClass('jda-document-thumbnail');

			}
			if (this.model.get('media_type') == 'Collection')
			{
				this.draggable=false;
				$(this.el).click(function(){ jda.app.goToCollection(_this.model.id); return false;});
				$(this.el).find('.zeega-collection').css({'width':this.options.thumbnail_width, 'height': this.options.thumbnail_height});

			} else{
				//Turning this off because buggy
				//$(this.el).popover({'title':this.model.get('title'), 'content':this.model.get('description'), 'delay':{ show: 2000, hide: 100 },'placement':'bottom'});

			}

			if(this.draggable){
				$(this.el).draggable({

					cursor : 'move',
					cursorAt : {
						top : -5,
						left : -5
					},
					appendTo : 'body',
					opacity : 0.8,

					helper : function(){
						var drag = $(this).find('a').clone().css({'z-index':'101'});
						return drag;
					},

					//init the dragged item variable
					start : function(){
						$(this).draggable('option','revert',true);
						jda.app.draggedItem = _this.model;
					}
				});
				$(this.el).find(".jdicon-small-drag").tooltip({'title':'Drag to add to your collection','placement':'bottom', delay: { show: 600, hide: 100 }});
				$(this.el).find(".label").tooltip({'placement':'bottom', delay: { show: 600, hide: 100 }});
			}

			//Replace broken thumbnail images with the media type icon

			$(this.el).find("img").on("error", function(e) {
                $(e.target).hide();
                $(e.target.parentElement).append(  '');
            });
			return this;
		},

		getCollectionTemplate : function()
		{
			var html =

				'<a href="#<%=id%>" class="thumbnail zeega-collection rotated-left">'+
				//	''+
				//	''+
				//	''+
					'<img src="<%=thumbnail_url%>" alt="<%=title%>" style="width:<%=thumbnail_width%>px;height:<%=thumbnail_height%>px">'+
					//'<input class="jda-item-checkbox" type="checkbox">'+
					'<button class="btn btn-danger btn-mini jda-delete-item jda-delete-collection">x  <%=delete_text%></button>'+
				'<p class="jda-thumbnail-caption" style="max-width:<%=thumbnail_width%>px;text-align:center;font-size:12px;font-weight:bold"><%=title%>
';

			return html;
		},

		getDefaultTemplate : function()
		{

			var html =

				'<a href="#" class="thumbnail" style="position:relative;width:<%=thumbnail_width%>px;height:<%=thumbnail_height%>px;background-color:white">'+
					'<img src="<%=thumbnail_url%>" alt="<%=title%>" style="width:<%=thumbnail_width%>px;height:<%=thumbnail_height%>px">'+

					'<button class="btn btn-danger btn-mini jda-delete-item">x  <%=remove_text%></button>'+
				'<p class="jda-thumbnail-caption" style="max-width:<%=thumbnail_width%>px;"><%=title%>
';

			return html;

		},
		getTestimonialTemplate : function()
		{

			var html =

				'<a href="#" class="thumbnail" style="position:relative;width:<%=thumbnail_width%>px;height:<%=thumbnail_height%>px;background-color:white">'+
					''+

					'<button class="btn btn-danger btn-mini jda-delete-item">x  <%=remove_text%></button>'+
				'<p class="jda-thumbnail-caption" style="max-width:<%=thumbnail_width%>px"><%=description%>
';

			return html;

		},
		getTweetTemplate : function()
		{

			var html =

				'<a href="#" class="thumbnail" style="width:<%=thumbnail_width%>px;height:<%=thumbnail_height%>px;background-color:white">'+
					''+
					'<span style="position:absolute;top:<%=position_tweet_handle%>;right:9%;max-width:85%;overflow:hidden;line-height:18px;color:#444;font-size:12px">@<%=media_creator_username%>'+

					'<button class="btn btn-danger btn-mini jda-delete-item">x  <%=remove_text%></button>'+
				'<p class="jda-thumbnail-caption" style="max-width:<%=thumbnail_width%>px"><%=description%>
';

			return html;

		}

	});

})(jda.module("browser"));<|endoftext|>


<commit_before>(function () {
    'use strict';

    angular
        .module('web')
        .config(routerConfig);

    /** @ngInject */
    function routerConfig($stateProvider, $urlRouterProvider) {
        $stateProvider
            .state('main', {
                url: '/',
                abstract: true,
                templateUrl : 'app/main/main.html',
                controller: 'MainController',
                controllerAs: 'main'
            })
            .state('main.homepage', {
                url: '',
                parent: 'main',
                templateUrl: 'app/templates/homepage.html'
            })
            .state('main.profile', {
                url: 'profile',
                parent: 'main',
                templateUrl: 'app/templates/userProfile/indexUserProfile.html'
            });

        $urlRouterProvider.otherwise('/');
    }

})();
<commit_msg>changed url for profile<commit_after>(function () {
    'use strict';

    angular
        .module('web')
        .config(routerConfig);

    /** @ngInject */
    function routerConfig($stateProvider, $urlRouterProvider) {
        $stateProvider
            .state('main', {
                url: '/',
                abstract: true,
                templateUrl : 'app/main/main.html',
                controller: 'MainController',
                controllerAs: 'main'
            })
            .state('main.homepage', {
                url: '',
                parent: 'main',
                templateUrl: 'app/templates/homepage.html'
            })
            .state('main.profile', {
                url: 'my-profile',
                parent: 'main',
                templateUrl: 'app/templates/userProfile/indexUserProfile.html'
            });

        $urlRouterProvider.otherwise('/');
    }

})();
<|endoftext|>


<commit_before>import R from 'ramda';

const allData = [
  {
    album: 'We Like it Here',
    name: 'Shofukan',
    year: '2014',
    length: '6:33',
    description: 'This is some smooth funkalucious stuff right here',
    uri: 'spotify:track:5v0Q1mWIWd5XYtto97VUZy',
    img: 'http://placehold.it/433x433',
    artist: 'Peter',
    genre: 'Alternative, maybe',
    decade: 1
  },
  {
    album: 'We Like it Here',
    name: 'What About Me?',
    year: '2014',
    length: '6:43',
    description: 'Trey loves this fuckadelic stuff, he tells his grandma about it every sunday',
    uri: 'spotify:track:4YpXSKVrp8jhI7EAPV1xpF',
    img: 'http://placehold.it/433x433',
    artist: 'Peter',
    genre: 'Alternative, maybe',
    decade: 4
  },
  {
    album: 'We Like it Here',
    name: 'Tia Macaco',
    year: '2014',
    length: '5:44',
    description: 'Bring it home with some funktastic sounds',
    uri: 'spotify:track:7DsEr8IEmhZYgAaHHwELwa',
    img: 'http://placehold.it/433x433',
    artist: 'Peter',
    genre: 'Alternative, maybe',
    decade: 8
  },
];

export const getDataFromURIS = currentURIS =>
  R.filter(({ uri }) => R.contains(uri, currentURIS), allData);

export default allData;
<commit_msg>getting new fixes and songData<commit_after>import R from 'ramda';

const allData = [
  {
    album: 'We Like it Here',
    name: 'Shofukan',
    year: '2014',
    length: '6:33',
    description: 'This is some smooth funkalucious stuff right here',
    uri: 'spotify:track:5v0Q1mWIWd5XYtto97VUZy',
    img: 'http://placehold.it/433x433',
    artist: 'Peter',
    genre: 'Alternative, maybe',
    decade: 1
  },
  {
    album: 'We Like it Here',
    name: 'What About Me?',
    year: '2014',
    length: '6:43',
    description: 'Trey loves this fuckadelic stuff, he tells his grandma about it every sunday',
    uri: 'spotify:track:4YpXSKVrp8jhI7EAPV1xpF',
    img: 'http://placehold.it/433x433',
    artist: 'Peter',
    genre: 'Alternative, maybe',
    decade: 4
  },
  {
    album: 'We Like it Here',
    name: 'Tia Macaco',
    year: '2014',
    length: '5:44',
    description: 'Bring it home with some funktastic sounds',
    uri: 'spotify:track:7DsEr8IEmhZYgAaHHwELwa',
    img: 'http://placehold.it/433x433',
    artist: 'Peter',
    genre: 'Alternative, maybe',
    decade: 8
  },
    {
    album:'Plans',
    name:'Soul Meets Body',
    artist:'Death Cab for Cutie',
    year:'2005',
    length:'3:49',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:5yc59J3MR3tVDPTOgwgRI5',
    img:'https://i.scdn.co/image/3e5e3d76c8f50393a6494a1c8bea1a01178a8753',
    decade: '';
    genre:'Alternative';
  },
  {
    album:'How To Dismantle An Atomic Bomb',
    name:'Vertigo',
    artist:'U2',
    year:'2004',
    length:'3:15',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:57ZXcBtCZXSg9TVV5xRdnR',
    img:'https://i.scdn.co/image/1ba80e91c966d08ba4340b4e9f21c55b064a1e21',
    decade: '';
    genre:'Rock';
  },
  {
    album:'Aftermath',
    name:'Paint It Black',
    artist:'Rolling Stones',
    year:'1966',
    length:'3:22',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:63T7DJ1AFDD6Bn8VzG6JE8',
    img:'https://i.scdn.co/image/c09585dd1713b35f8e47393d05ced6b9bcd03607',
    decade: '';
    genre: 'Rock';
  },
  {
    album:'Led Zeppelin IV',
    name:'Stairway To Heaven',
    artist:'Led Zeppelin',
    year:'1971',
    length:'7:58',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:51pQ7vY7WXzxskwloaeqyj',
    img:'https://i.scdn.co/image/c89be3d95870abb652c16deef6e3d3e5174710ff',
    decade: '';
    genre: 'Rock';
  },
  {
    album:'The Wall',
    name:'Another Brick in the Wall, Pt. 2',
    artist:'Pink Floyd',
    year:'1979',
    length:'3:59',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:4gMgiXfqyzZLMhsksGmbQV',
    img:'https://i.scdn.co/image/464f49ec36104a5939ea76cf1597a5311d91f602',
    decade: '';
    genre: 'Rock';
  },
  {
    album:'Paranoid',
    name:'Iron Man',
    artist:'Black Sabbath',
    year:'2005',
    length:'5:55',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:3IOQZRcEkplCXg6LofKqE9',
    img:'https://i.scdn.co/image/851538088475961344e79ae1022d1a0bd0bf53f5',
    decade: '';
    genre: 'Metal';
  },
  {
    album:'Metallica',
    name:'Enter Sandman',
    artist:'Metallica',
    year:'2005',
    length:'3:49',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:1hKdDCpiI9mqz1jVHRKG0E',
    img:'https://i.scdn.co/image/400dee6165a81c49b665d18637e3954213679ee8 ',
    decade: '';
    genre: 'Metal';
  },
  {
    album:'Number of the Beast',
    name:'Run to the Hills',
    artist:'Iron Maiden',
    year:'1982',
    length:'3:49',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:44AxeBXrK9LQlGjXyT2oZQ',
    img:'https://i.scdn.co/image/84747e43820bec289c0d75a3ae2af776f1897900',
    decade: '';
    genre: 'Metal';
  },
  {
    album:'99 Luftballons',
    name:'99 Luftballons',
    artist:'Nena',
    year:'1984',
    length:'3:53',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:6HA97v4wEGQ5TUClRM0XLc',
    img:'https://i.scdn.co/image/7db0e29a743c07c28aba88babc47a460c70fcea5',
    decade: '';
    genre: 'Pop'
  },
  {
    album:'Thriller',
    name:'Thriller',
    artist:'Micheal Jackson',
    year:'1982',
    length:'5:58',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:2LlQb7Uoj1kKyGhlkBf9aC',
    img:'https://i.scdn.co/image/6d1d714f4dcb306d3b3533fea400362974060d2d',
    decade: '';
    genre: 'Pop';
  },
  {
    album:'Solid Gold Hits',
    name:'Intergalactic',
    artist:'Beastie Boys',
    year:'2005',
    length:'3:30',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:7uDir35ufndq1NBOpoL3Ba',
    img:'https://i.scdn.co/image/c7c2d21c4152741210c2eede503a3dceab35b05c',
    decade: '';
    genre: 'Hip-Hop';
  },
    {
    album:'Raising Hell',
    name:"It's Tricky",
    artist:'Run D.M.C',
    year:'2005',
    length:'3:30',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:1zAfj2rXxddGb8Dhnwxue8',
    img:'https://i.scdn.co/image/e1a16b17492b091182a76b3cdb32b69232cdea09',
    decade: '';
    genre: 'Hip-Hop';
  },
  {
    album:'Nevermind',
    name:"Come As Your Are",
    artist:'Nirvana',
    year:'1991',
    length:'3:39',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:4P5KoWXOxwuobLmHXLMobV',
    img:'https://i.scdn.co/image/864bd75b46a575917d795b7a484f7f1fe43d23e9 ',
    decade: '';
    genre: 'Alternative';
  },
  {
    album:'King of Electric Blues',
    name:"Muddy Waters",
    artist:'Mannish Boy',
    year:'1997',
    length:'5:21',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:58PSYdY0GFg0LFb2PxYk4T',
    img:'https://i.scdn.co/image/058c42d38cc9f1b86a9bffb3b512cc986f6952a1',
    decade: '';
    genre: 'Blues';
  },
   {
    album:'The Graduate',
    name:"The Sound of Silence",
    artist:'Simon & Garfunkel',
    year:'1968',
    length:'3:05',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:58PSYdY0GFg0LFb2PxYk4T',
    img:'https://i.scdn.co/image/753d9208d21d332eea5673102a15266c2f08a884',
    decade: '';
    genre: 'Folk';
  },
   {
    album:'The Best of Don McLean',
    name:"American Pie",
    artist:'Don McLean',
    year:'1989',
    length:'8:36',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:2QgWuCtBpNIpl5trmKCxRf',
    img:'https://i.scdn.co/image/5abe5e81fb9858849116e1678d6e595c4ca68c34',
    decade: '';
    genre: 'Folk';
  },
   {
    album:"The Times They Are A'Changing",
    name:"The Times They Are A'Changing",
    artist:'Bob Dylan',
    year:'1964',
    length:'3:12',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:52vA3CYKZqZVdQnzRrdZt6',
    img:'https://i.scdn.co/image/0934c1a0019dd7783d514249680180b39c94100d',
    decade: '';
    genre: 'Folk';
  },
  {
    album:"The Man Who Invented Soul",
    name:"Wonderful World",
    artist:'Sam Cooke',
    year:'2000',
    length:'2:06',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:5SKXlfKfhNUyJ3GkpI0ELJ',
    img:'https://i.scdn.co/image/0400f51d1c2ff1ace99d28c12d8258e73d330b18',
    decade: '';
    genre: 'R&B/Soul';
  },
  {
    album:"Love Songs",
    name:"At Last",
    artist:'Etta James',
    year:'2006',
    length:'3:00',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:1nd9moIZkGvWoHtReFqkRY',
    img:'https://i.scdn.co/image/afe423c99a46d1ed470f3d41bc5850e1288ca771',
    decade: '';
    genre: 'R&B/Soul';
  },
  {
    album:"Ray Charles",
    name:"I've Got A Woman",
    artist:'Ray Charles',
    year:'2003',
    length:'2:51',
    description:'zoopa zoopa pizza peroggi pasta penne',
    uri:'spotify:track:2xar08Fq5xra2KKZs5Bw9j',
    img:'https://i.scdn.co/image/2ad60ab4f04de877f48ca7ae8e62618d38f0e51e',
    decade: '';
    genre:'R&B/Soul';
  },

];

export const getDataFromURIS = currentURIS =>
  R.filter(({ uri }) => R.contains(uri, currentURIS), allData);

export default allData;
<|endoftext|>


<commit_before>function $_String(/*{Character*}*/value,size) {
    if (value && value.getT$name && value.getT$name() == 'ceylon.language::String') {
        //if it's already a String just return it
        return value;
    }
    else if (typeof(value) === 'string') {
        var that = new String(value);
        that.codePoints = size;
        return that;
    }
    var that = '';
    var _iter = value.iterator();
    var _c; while ((_c = _iter.next()) !== getFinished()) {
        that += _c.string;
    }
    if (size !== undefined) that.codePoints=size;
    return that;
}
<commit_msg>fix initializer<commit_after>function $_String(/*{Character*}*/value,size) {
    if (value && value.getT$name && value.getT$name() == 'ceylon.language::String') {
        //if it's already a String just return it
        return value;
    }
    else if (typeof(value) === 'string') {
        var that = new String(value);
        that.codePoints = size;
        return that;
    }
    var that = '';
    var _iter = value.iterator();
    var _c; while ((_c = _iter.next()) !== getFinished()) {
        that += _c.string;
    }
    if (size !== undefined) that.codePoints=size;
    return that;
}
<|endoftext|>


<commit_before>/*jshint esversion: 6,node: true,-W041: false */
"use strict";
const request = require('request'),
	converter = require('../util/converter'),
	debug = require('debug')('homebridge-weather-plus');

class WundergroundAPI_new {
    constructor(apiKey, location, units, l, d) {
        this.attribution = 'Powered by Weather Underground';
        this.reportCharacteristics = [
            'ObservationStation',
            'ObservationTime',
            'WindDirection',
            'Humidity',
            'SolarRadiation',
            'UVIndex',
            'Temperature',
            'DewPoint',
            'AirPressure',
            'WindSpeed',
            'WindSpeedMax'
        ];

        /* no example data for forecasts */
        /*
        this.forecastCharacteristics = [
            'Condition',
            'ConditionCategory',
            'ForecastDay',
            'Humidity',
            'RainChance',
            'RainDay',
            'Temperature',
            'TemperatureMin',
            'WindDirection',
            'WindSpeed',
            'WindSpeedMax'
        ];
        this.forecastDays = 4;
        */

        this.debug = d;
        this.log = l;

        this.location = location;
        this.apiKey = apiKey;
        this.units = {	'si': 's',
        				'us': 'e',
        				"uk": 'h',
        				'ca': 'm'}[units];

    }

    update(callback) {
        this.debug("Updating weather with weather underground");

//this.log.error("units:" + this.units);

        const queryUri = "https://api.weather.com/v2/pws/observations/current?apiKey="+this.apiKey+"&stationId="+this.location+"&format=json&units="+ this.units;
        request(encodeURI(queryUri), function (err, response, body) {
            if (!err) {
                // Current weather report
                const jsonObj = JSON.parse(body);
				debug( JSON.stringify(jsonObj, null, 2));

                this.parseReport(jsonObj, callback);
            } else {
                this.log.error("Error retrieving weather report and forecast");
                this.log.error("Error Message: " + err);
                callback(err);
            }
        }.bind(this));
    }

    parseReport(values) {

        let report = {};

        /* EXAMPLE values

		observations
			0
				stationID	"KCASANJO898"
				obsTimeUtc	"2019-09-01T19:03:41Z"
				obsTimeLocal	"2019-09-01 12:03:41"
				neighborhood	"West San Jose - Casa de la Niles"
				softwareType	"WS-1002 V2.4.6"
				country	"US"
				solarRadiation	719.2
				lon	-122.01569366
				realtimeFrequency	null
				epoch	1567364621
				lat	37.30566025
				uv	9
				winddir	326
				humidity	49
				qcStatus	1
				metric_si	# imperial(e) | metric(m) | metric_si(s) | uk_hybrid(h)
					temp	30
					heatIndex	31
					dewpt	18
					windChill	30
					windSpeed	3
					windGust	3
					pressure	1010.16
					precipRate	0
					precipTotal	0
					elev	105
		*/

        try {
        	var observation = values.observations[0]
            var metric;
			debug("Units:" + this.units);
            if (this.units=='s') {
            	metric = observation.metric_si;
            } else if (this.units=='m') {
            	metric = observation.metric;
            } else if (this.units=='e') {
            	metric = observation.imperial;
            } else { // 'h'
            	metric = observation.uk_hybrid;
            };

			debug("Station:" + observation.stationID + " : " + observation.neighborhood);
            report.ObservationStation = observation.stationID + " : " + observation.neighborhood;
            report.ObservationTime = observation.obsTimeUtc.split(' ')[4];

			debug("WindDirection:" + observation.winddir);
			debug("Humidity:" + observation.humidity);
        	report.WindDirection = converter.getWindDirection(isNaN(parseInt(observation.winddir)) ? 0 : parseInt(observation.winddir));
            report.Humidity 		= isNaN(parseInt(observation.humidity)) ? 0 : parseInt(observation.humidity);
            report.SolarRadiation 	= isNaN(parseInt(observation.solarRadiation)) ? 0 : parseInt(observation.solarRadiation);
            report.UVIndex 			= isNaN(parseInt(observation.uv)) ? 0 : parseInt(observation.uv);

 			debug("Temperature:" + metric.temp);
            report.Temperature 		= isNaN(parseInt(metric.temp)) ? 0 : parseInt(metric.temp);
            report.DewPoint 		= isNaN(parseInt(metric.dewpt)) ? 0 : parseInt(metric.dewpt);
            report.AirPressure 		= isNaN(parseInt(metric.pressure)) ? 0 : parseInt(metric.pressure);
            report.WindSpeed 		= isNaN(parseInt(metric.windSpeed)) ? 0 : parseInt(metric.windSpeed);
            report.WindSpeedMax 	= isNaN(parseInt(metric.windGusts)) ? 0 : parseInt(metric.windGusts);
        }
        catch(error) {
            this.log.error("Error retrieving weather report for Weather Underground");
            this.log.error("Error Message: " + error);
        }

        return report;
    }

    parseForecasts(forecastObjs, timezone) {
        let forecasts = [];
        var observation = values.observations[0]

    /* I DON'T HAVE AN EXAMPLE WITH FORECASTS*/
    /*
        for (let i = 0; i < forecastObjs.length; i++) {
            const values = forecastObjs[i];
            const forecast = {};
            forecast.Condition = values.text;
            forecast.ConditionCategory = converter.getConditionCategoryOwm(parseInt(values.code));
            forecast.ForecastDay = moment(values.date, "DD MMM YYYY").tz(timezone).format("dddd");
            forecast.Temperature = values.high;
            forecast.TemperatureMin = values.low;
            forecasts[forecasts.length] = forecast;
        }
    */
        return forecasts;
    }
}

module.exports = {
    WundergroundAPI_new: WundergroundAPI_new
};
<commit_msg>Update weatherunderground_new.js<commit_after>/*jshint esversion: 6,node: true,-W041: false */
"use strict";
const request = require('request'),
	converter = require('../util/converter'),
	debug = require('debug')('homebridge-weather-plus');

class WundergroundAPI_new {
    constructor(apiKey, location, units, l, d) {
        this.attribution = 'Powered by Weather Underground';
        this.reportCharacteristics = [
            'ObservationStation',
            'ObservationTime',
            'WindDirection',
            'Humidity',
            'SolarRadiation',
            'UVIndex',
            'Temperature',
            'DewPoint',
            'AirPressure',
            'WindSpeed',
            'WindSpeedMax'
        ];

        this.debug = d;
        this.log = l;

        this.location = location;
        this.apiKey = apiKey;
        this.units = {	'si': 's',
        				'us': 'e',
        				"uk": 'h',
        				'ca': 'm'}[units];
    }

    update(callback) {
        this.debug("Updating weather with weather underground");
        let weather = {};

        const queryUri = "https://api.weather.com/v2/pws/observations/current?apiKey="+this.apiKey+"&stationId="+this.location+"&format=json&units="+ this.units;
        request(encodeURI(queryUri), function (err, response, body) {
            if (!err) {
                // Current weather report
                const jsonObj = JSON.parse(body);
				debug( JSON.stringify(jsonObj, null, 2));

                weather.report = this.parseReport(jsonObj, callback);
                callback(null, weather);
            } else {
                this.log.error("Error retrieving weather report and forecast");
                this.log.error("Error Message: " + err);
                callback(err);
            }
        }.bind(this));
    }

    parseReport(values) {

        let report = {};

        /* EXAMPLE values

		observations
			0
				stationID	"KCASANJO898"
				obsTimeUtc	"2019-09-01T19:03:41Z"
				obsTimeLocal	"2019-09-01 12:03:41"
				neighborhood	"West San Jose - Casa de la Niles"
				softwareType	"WS-1002 V2.4.6"
				country	"US"
				solarRadiation	719.2
				lon	-122.01569366
				realtimeFrequency	null
				epoch	1567364621
				lat	37.30566025
				uv	9
				winddir	326
				humidity	49
				qcStatus	1
				metric_si	# imperial(e) | metric(m) | metric_si(s) | uk_hybrid(h)
					temp	30
					heatIndex	31
					dewpt	18
					windChill	30
					windSpeed	3
					windGust	3
					pressure	1010.16
					precipRate	0
					precipTotal	0
					elev	105
		*/

        try {
        	var observation = values.observations[0]
            var metric;
			debug("Units:" + this.units);
            if (this.units=='s') {
            	metric = observation.metric_si;
            } else if (this.units=='m') {
            	metric = observation.metric;
            } else if (this.units=='e') {
            	metric = observation.imperial;
            } else { // 'h'
            	metric = observation.uk_hybrid;
            };

			debug("Station:" + observation.stationID + " : " + observation.neighborhood);
            report.ObservationStation = observation.stationID + " : " + observation.neighborhood;
            report.ObservationTime = observation.obsTimeUtc.split(' ')[4];

			debug("WindDirection:" + observation.winddir);
			debug("Humidity:" + observation.humidity);
        	report.WindDirection = converter.getWindDirection(isNaN(parseInt(observation.winddir)) ? 0 : parseInt(observation.winddir));
            report.Humidity 		= isNaN(parseInt(observation.humidity)) ? 0 : parseInt(observation.humidity);
            report.SolarRadiation 	= isNaN(parseInt(observation.solarRadiation)) ? 0 : parseInt(observation.solarRadiation);
            report.UVIndex 			= isNaN(parseInt(observation.uv)) ? 0 : parseInt(observation.uv);

 			debug("Temperature:" + metric.temp);
            report.Temperature 		= isNaN(parseInt(metric.temp)) ? 0 : parseInt(metric.temp);
            report.DewPoint 		= isNaN(parseInt(metric.dewpt)) ? 0 : parseInt(metric.dewpt);
            report.AirPressure 		= isNaN(parseInt(metric.pressure)) ? 0 : parseInt(metric.pressure);
            report.WindSpeed 		= isNaN(parseInt(metric.windSpeed)) ? 0 : parseInt(metric.windSpeed);
            report.WindSpeedMax 	= isNaN(parseInt(metric.windGusts)) ? 0 : parseInt(metric.windGusts);
        }
        catch(error) {
            this.log.error("Error retrieving weather report for Weather Underground");
            this.log.error("Error Message: " + error);
        }

        return report;
    }

    parseForecasts(forecastObjs, timezone) {
        let forecasts = [];
        var observation = values.observations[0]

    /* I DON'T HAVE AN EXAMPLE WITH FORECASTS*/
    /*
        for (let i = 0; i < forecastObjs.length; i++) {
            const values = forecastObjs[i];
            const forecast = {};
            forecast.Condition = values.text;
            forecast.ConditionCategory = converter.getConditionCategoryOwm(parseInt(values.code));
            forecast.ForecastDay = moment(values.date, "DD MMM YYYY").tz(timezone).format("dddd");
            forecast.Temperature = values.high;
            forecast.TemperatureMin = values.low;
            forecasts[forecasts.length] = forecast;
        }
    */
        return forecasts;
    }
}

module.exports = {
    WundergroundAPI_new: WundergroundAPI_new
};
<|endoftext|>


<commit_before>/* eslint no-unused-vars: ["error", {"varsIgnorePattern": "React|imageForDesign|Button|Glyphicon"}]*/
import React, { Component } from "react";
import {Button,
        Glyphicon} from "react-bootstrap";
import {imageForDesign} from "./Vote/Helpers";

class Vote extends Component {
  constructor(props) {
    super(props);
    this.state = {
      designs: props.designs || [],
      cursor: 0
    };
  }

  render() {
    const state = this.state;
    const currentDesign = (state.cursor >= state.designs.length)
                        ? {description: "", resources: []}
                        : state.designs[state.cursor];
    return (

          <Button ref="searchButton" onClick={this.props.searchButton}>
            <Glyphicon glyph="search"/>
          </Button>
          <Button ref="statisticsButton" onClick={this.props.statisticsButton}>
            <Glyphicon glyph="stats"/>
          </Button>
          <Button ref="voteDownButton" bsStyle="danger"
                  onClick={this.props.voteDownButton}>
            <Glyphicon glyph="chevron-down"/>
          </Button>
          <Button ref="voteUpButton" bsStyle="success"
                  onClick={this.props.voteUpButton}>
            <Glyphicon glyph="chevron-up"/>
          </Button>

    );
  }
}

export default Vote;
<commit_msg>Add method Vote.vote<commit_after>/* eslint no-unused-vars: ["error", {"varsIgnorePattern": "React|imageForDesign|Button|Glyphicon"}]*/
import React, { Component } from "react";
import {Button,
        Glyphicon} from "react-bootstrap";
import {imageForDesign} from "./Vote/Helpers";

class Vote extends Component {
  constructor(props) {
    super(props);
    this.state = {
      designs: props.designs || [],
      cursor: 0
    };
  }

  vote(λ){
    this.setState({cursor: this.state.cursor + 1});
    λ();
  }

  render() {
    const state = this.state;
    const currentDesign = (state.cursor >= state.designs.length)
                        ? {description: "", resources: []}
                        : state.designs[state.cursor];
    return (

          <Button ref="searchButton" onClick={this.props.searchButton}>
            <Glyphicon glyph="search"/>
          </Button>
          <Button ref="statisticsButton" onClick={this.props.statisticsButton}>
            <Glyphicon glyph="stats"/>
          </Button>
          <Button ref="voteDownButton" bsStyle="danger"
                  onClick={() => {this.vote(this.props.voteDownButton);}}>
            <Glyphicon glyph="chevron-down"/>
          </Button>
          <Button ref="voteUpButton" bsStyle="success"
                  onClick={() => {this.vote(this.props.voteUpButton);}}>
            <Glyphicon glyph="chevron-up"/>
          </Button>

    );
  }
}

export default Vote;
<|endoftext|>


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

'use strict';

// MODULES //

var tape = require( 'tape' );
var ordinalize = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof ordinalize, 'function', 'main export is a function' );
	t.end();
});

tape( 'if the first argument is not a string or integer, the function throws an error', function test( t ) {
	var values;
	var i;

	values = [
		null,
		true,
		void 0,
		NaN,
		[],
		{},
		function noop() {},
		3.12
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			ordinalize( value );
		};
	}
});

tape( 'if the first argument is not a string or integer, the function throws an error (options)', function test( t ) {
	var values;
	var i;

	values = [
		null,
		true,
		void 0,
		NaN,
		[],
		{},
		function noop() {},
		3.12
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			ordinalize( value, {} );
		};
	}
});

tape( 'the function throws an error if provided an invalid options argument', function test( t ) {
	var values;
	var i;

	values = [
		'abc',
		5,
		null,
		true,
		void 0,
		NaN,
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function zipper() {
			ordinalize( 8, value );
		};
	}
});

tape( 'the function throws an error if provided an invalid `lang` option', function test( t ) {
	var values;
	var i;

	values = [
		'abc',
		5,
		null,
		[],
		{},
		true,
		void 0,
		NaN,
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function zipper() {
			ordinalize( 8, {
				'lang': value
			});
		};
	}
});

tape( 'the function returns an ordinal string for a provided integer string (default language)', function test( t ) {
	var expected;
	var values;
	var i;

	values = [
		'1',
		'2',
		'21',
		'7',
		'10',
		'11',
		'12',
		'13',
		'14',
		'15',
		'16',
		'21',
		'22',
		'23',
		'24',
		'332',
		'333',
		'999'
	];
	expected = [
		'1st',
		'2nd',
		'21st',
		'7th',
		'10th',
		'11th',
		'12th',
		'13th',
		'14th',
		'15th',
		'16th',
		'21st',
		'22nd',
		'23rd',
		'24th',
		'332nd',
		'333rd',
		'999th'
	];

	for ( i = 0; i < values.length; i++ ) {
		t.equal( ordinalize( values[i] ), expected[i], 'returns expected value' );
	}
	t.end();
});

tape( 'the function returns an ordinal string for a provided integer (default language)', function test( t ) {
	var expected;
	var values;
	var i;

	values = [
		1,
		2,
		21,
		7,
		10,
		11,
		12,
		13,
		14,
		15,
		16,
		21,
		22,
		23,
		24,
		332,
		333,
		999
	];
	expected = [
		'1st',
		'2nd',
		'21st',
		'7th',
		'10th',
		'11th',
		'12th',
		'13th',
		'14th',
		'15th',
		'16th',
		'21st',
		'22nd',
		'23rd',
		'24th',
		'332nd',
		'333rd',
		'999th'
	];

	for ( i = 0; i < values.length; i++ ) {
		t.equal( ordinalize( values[i] ), expected[i], 'returns expected value' );
	}
	t.end();
});

tape( 'the function returns an ordinal string for a provided integer string (lang=fr)', function test( t ) {
	var expected;
	var values;
	var opts;
	var i;

	values = [
		'1',
		'2',
		'21',
		'7',
		'10',
		'11',
		'12',
		'13',
		'14',
		'15',
		'16',
		'21',
		'22',
		'23',
		'24',
		'332',
		'333',
		'999'
	];
	expected = [
		'1er',
		'2e',
		'21e',
		'7e',
		'10e',
		'11e',
		'12e',
		'13e',
		'14e',
		'15e',
		'16e',
		'21e',
		'22e',
		'23e',
		'24e',
		'332e',
		'333e',
		'999e'
	];

	opts = {
		'lang': 'fr'
	};

	for ( i = 0; i < values.length; i++ ) {
		t.equal( ordinalize( values[i], opts ), expected[i], 'returns expected value' );
	}
	t.end();
});

tape( 'the function returns an ordinal string for a provided integer string (lang=de)', function test( t ) {
	var expected;
	var values;
	var opts;
	var i;

	values = [
		'1',
		'2',
		'21',
		'7',
		'10',
		'11',
		'12',
		'13',
		'14',
		'15',
		'16',
		'21',
		'22',
		'23',
		'24',
		'332',
		'333',
		'999'
	];
	expected = [
		'1.',
		'2.',
		'21.',
		'7.',
		'10.',
		'11.',
		'12.',
		'13.',
		'14.',
		'15.',
		'16.',
		'21.',
		'22.',
		'23.',
		'24.',
		'332.',
		'333.',
		'999.'
	];

	opts = {
		'lang': 'de'
	};

	for ( i = 0; i < values.length; i++ ) {
		t.equal( ordinalize( values[i], opts ), expected[i], 'returns expected value' );
	}
	t.end();
});

tape( 'the function returns an ordinal string for a provided integer string (lang=it,gender=masculine)', function test( t ) {
	var expected;
	var values;
	var opts;
	var i;

	values = [
		'1',
		'2',
		'21',
		'7',
		'10',
		'11',
		'12',
		'13',
		'14',
		'15',
		'16',
		'21',
		'22',
		'23',
		'24',
		'332',
		'333',
		'999'
	];
	expected = [
		'1º',
		'2º',
		'21º',
		'7º',
		'10º',
		'11º',
		'12º',
		'13º',
		'14º',
		'15º',
		'16º',
		'21º',
		'22º',
		'23º',
		'24º',
		'332º',
		'333º',
		'999º'
	];

	opts = {
		'lang': 'it',
		'gender': 'masculine'
	};

	for ( i = 0; i < values.length; i++ ) {
		t.equal( ordinalize( values[i], opts ), expected[i], 'returns expected value' );
	}
	t.end();
});

tape( 'the function returns an ordinal string for a provided integer string (lang=it,gender=feminine)', function test( t ) {
	var expected;
	var values;
	var opts;
	var i;

	values = [
		'1',
		'2',
		'21',
		'7',
		'10',
		'11',
		'12',
		'13',
		'14',
		'15',
		'16',
		'21',
		'22',
		'23',
		'24',
		'332',
		'333',
		'999'
	];
	expected = [
		'1ª',
		'2ª',
		'21ª',
		'7ª',
		'10ª',
		'11ª',
		'12ª',
		'13ª',
		'14ª',
		'15ª',
		'16ª',
		'21ª',
		'22ª',
		'23ª',
		'24ª',
		'332ª',
		'333ª',
		'999ª'
	];

	opts = {
		'lang': 'it',
		'gender': 'feminine'
	};

	for ( i = 0; i < values.length; i++ ) {
		t.equal( ordinalize( values[i], opts ), expected[i], 'returns expected value' );
	}
	t.end();
});
<commit_msg>Add tests<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2022 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var tape = require( 'tape' );
var ordinalize = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof ordinalize, 'function', 'main export is a function' );
	t.end();
});

tape( 'if the first argument is not a string or integer, the function throws an error', function test( t ) {
	var values;
	var i;

	values = [
		null,
		true,
		void 0,
		NaN,
		[],
		{},
		function noop() {},
		3.12
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			ordinalize( value );
		};
	}
});

tape( 'if the first argument is not a string or integer, the function throws an error (options)', function test( t ) {
	var values;
	var i;

	values = [
		null,
		true,
		void 0,
		NaN,
		[],
		{},
		function noop() {},
		3.12
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			ordinalize( value, {} );
		};
	}
});

tape( 'the function throws an error if provided an invalid options argument', function test( t ) {
	var values;
	var i;

	values = [
		'abc',
		5,
		null,
		true,
		void 0,
		NaN,
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function zipper() {
			ordinalize( 8, value );
		};
	}
});

tape( 'the function throws an error if provided an invalid `lang` option', function test( t ) {
	var values;
	var i;

	values = [
		'abc',
		5,
		null,
		[],
		{},
		true,
		void 0,
		NaN,
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function zipper() {
			ordinalize( 8, {
				'lang': value
			});
		};
	}
});

tape( 'the function returns an ordinal string for a provided integer string (default language)', function test( t ) {
	var expected;
	var values;
	var i;

	values = [
		'1',
		'2',
		'21',
		'7',
		'10',
		'11',
		'12',
		'13',
		'14',
		'15',
		'16',
		'21',
		'22',
		'23',
		'24',
		'332',
		'333',
		'999'
	];
	expected = [
		'1st',
		'2nd',
		'21st',
		'7th',
		'10th',
		'11th',
		'12th',
		'13th',
		'14th',
		'15th',
		'16th',
		'21st',
		'22nd',
		'23rd',
		'24th',
		'332nd',
		'333rd',
		'999th'
	];

	for ( i = 0; i < values.length; i++ ) {
		t.equal( ordinalize( values[i] ), expected[i], 'returns expected value' );
	}
	t.end();
});

tape( 'the function returns an ordinal string for a provided integer (default language)', function test( t ) {
	var expected;
	var values;
	var i;

	values = [
		1,
		2,
		21,
		7,
		10,
		11,
		12,
		13,
		14,
		15,
		16,
		21,
		22,
		23,
		24,
		332,
		333,
		999
	];
	expected = [
		'1st',
		'2nd',
		'21st',
		'7th',
		'10th',
		'11th',
		'12th',
		'13th',
		'14th',
		'15th',
		'16th',
		'21st',
		'22nd',
		'23rd',
		'24th',
		'332nd',
		'333rd',
		'999th'
	];

	for ( i = 0; i < values.length; i++ ) {
		t.equal( ordinalize( values[i] ), expected[i], 'returns expected value' );
	}
	t.end();
});

tape( 'the function returns an ordinal string for a provided integer string (lang=en)', function test( t ) {
	var expected;
	var values;
	var opts;
	var i;

	values = [
		'1',
		'2',
		'21',
		'7',
		'10',
		'11',
		'12',
		'13',
		'14',
		'15',
		'16',
		'21',
		'22',
		'23',
		'24',
		'332',
		'333',
		'999'
	];
	expected = [
		'1st',
		'2nd',
		'21st',
		'7th',
		'10th',
		'11th',
		'12th',
		'13th',
		'14th',
		'15th',
		'16th',
		'21st',
		'22nd',
		'23rd',
		'24th',
		'332nd',
		'333rd',
		'999th'
	];

	opts = {
		'lang': 'en'
	};

	for ( i = 0; i < values.length; i++ ) {
		t.equal( ordinalize( values[i], opts ), expected[i], 'returns expected value' );
	}
	t.end();
});

tape( 'the function returns an ordinal string for a provided integer (lang=en)', function test( t ) {
	var expected;
	var values;
	var opts;
	var i;

	values = [
		1,
		2,
		21,
		7,
		10,
		11,
		12,
		13,
		14,
		15,
		16,
		21,
		22,
		23,
		24,
		332,
		333,
		999
	];
	expected = [
		'1st',
		'2nd',
		'21st',
		'7th',
		'10th',
		'11th',
		'12th',
		'13th',
		'14th',
		'15th',
		'16th',
		'21st',
		'22nd',
		'23rd',
		'24th',
		'332nd',
		'333rd',
		'999th'
	];

	opts = {
		'lang': 'en'
	};

	for ( i = 0; i < values.length; i++ ) {
		t.equal( ordinalize( values[i], opts ), expected[i], 'returns expected value' );
	}
	t.end();
});

tape( 'the function returns an ordinal string for a provided integer string (lang=fr)', function test( t ) {
	var expected;
	var values;
	var opts;
	var i;

	values = [
		'1',
		'2',
		'21',
		'7',
		'10',
		'11',
		'12',
		'13',
		'14',
		'15',
		'16',
		'21',
		'22',
		'23',
		'24',
		'332',
		'333',
		'999'
	];
	expected = [
		'1er',
		'2e',
		'21e',
		'7e',
		'10e',
		'11e',
		'12e',
		'13e',
		'14e',
		'15e',
		'16e',
		'21e',
		'22e',
		'23e',
		'24e',
		'332e',
		'333e',
		'999e'
	];

	opts = {
		'lang': 'fr'
	};

	for ( i = 0; i < values.length; i++ ) {
		t.equal( ordinalize( values[i], opts ), expected[i], 'returns expected value' );
	}
	t.end();
});

tape( 'the function returns an ordinal string for a provided integer string (lang=de)', function test( t ) {
	var expected;
	var values;
	var opts;
	var i;

	values = [
		'1',
		'2',
		'21',
		'7',
		'10',
		'11',
		'12',
		'13',
		'14',
		'15',
		'16',
		'21',
		'22',
		'23',
		'24',
		'332',
		'333',
		'999'
	];
	expected = [
		'1.',
		'2.',
		'21.',
		'7.',
		'10.',
		'11.',
		'12.',
		'13.',
		'14.',
		'15.',
		'16.',
		'21.',
		'22.',
		'23.',
		'24.',
		'332.',
		'333.',
		'999.'
	];

	opts = {
		'lang': 'de'
	};

	for ( i = 0; i < values.length; i++ ) {
		t.equal( ordinalize( values[i], opts ), expected[i], 'returns expected value' );
	}
	t.end();
});

tape( 'the function returns an ordinal string for a provided integer string (lang=it,gender=masculine)', function test( t ) {
	var expected;
	var values;
	var opts;
	var i;

	values = [
		'1',
		'2',
		'21',
		'7',
		'10',
		'11',
		'12',
		'13',
		'14',
		'15',
		'16',
		'21',
		'22',
		'23',
		'24',
		'332',
		'333',
		'999'
	];
	expected = [
		'1º',
		'2º',
		'21º',
		'7º',
		'10º',
		'11º',
		'12º',
		'13º',
		'14º',
		'15º',
		'16º',
		'21º',
		'22º',
		'23º',
		'24º',
		'332º',
		'333º',
		'999º'
	];

	opts = {
		'lang': 'it',
		'gender': 'masculine'
	};

	for ( i = 0; i < values.length; i++ ) {
		t.equal( ordinalize( values[i], opts ), expected[i], 'returns expected value' );
	}
	t.end();
});

tape( 'the function returns an ordinal string for a provided integer string (lang=it,gender=feminine)', function test( t ) {
	var expected;
	var values;
	var opts;
	var i;

	values = [
		'1',
		'2',
		'21',
		'7',
		'10',
		'11',
		'12',
		'13',
		'14',
		'15',
		'16',
		'21',
		'22',
		'23',
		'24',
		'332',
		'333',
		'999'
	];
	expected = [
		'1ª',
		'2ª',
		'21ª',
		'7ª',
		'10ª',
		'11ª',
		'12ª',
		'13ª',
		'14ª',
		'15ª',
		'16ª',
		'21ª',
		'22ª',
		'23ª',
		'24ª',
		'332ª',
		'333ª',
		'999ª'
	];

	opts = {
		'lang': 'it',
		'gender': 'feminine'
	};

	for ( i = 0; i < values.length; i++ ) {
		t.equal( ordinalize( values[i], opts ), expected[i], 'returns expected value' );
	}
	t.end();
});
<|endoftext|>


<commit_before>module.exports = function (config) {
  config.set({
    // global config of your BrowserStack account
    browserStack: {
      username: process.env.BROWSERSTACK_USERNAME,
      accessKey: process.env.BROWSERSTACK_ACCESSKEY
    },

    // define browsers
    customLaunchers: {
      bstack_chrome_windows: {
        base: 'BrowserStack',
        browser: 'chrome',
        browser_version: '72.0',
        os: 'Windows',
        os_version: '10'
      },
      bstack_firefox_windows: {
        base: 'BrowserStack',
        browser: 'firefox',
        browser_version: '98.0',
        os: 'Windows',
        os_version: '10'
      },
      //dropped support for IE 10
      bstack_ie10_windows: {
        base: 'BrowserStack',
        browser: 'ie',
        browser_version: '10',
        os: 'Windows',
        os_version: '7'
      },
      //dropped support for IE 10
      bstack_ie11_windows: {
        base: 'BrowserStack',
        browser: 'ie',
        browser_version: '11',
        os: 'Windows',
        os_version: '10'
      },
      bstack_iphoneX: {
        base: 'BrowserStack',
        browser: 'safari',
        device: 'iPhone X',
        os: 'ios',
        real_mobile: true,
        os_version: '11.0'
      }
    },

    browsers: ['bstack_chrome_windows', 'bstack_firefox_windows', 'bstack_ie11_windows', 'bstack_iphoneX'],
    frameworks: ['mocha', 'chai'],
    reporters: ['dots', 'BrowserStack'],
    files: [
      { pattern: '.build/showdown.js'},
      { pattern: 'src/options.js'},
      // tests
      { pattern: 'test/unit/showdown*.js' },
      { pattern: 'test/functional/showdown*.js' },
    ],
    singleRun: true,
    concurrency: Infinity
  });
};
<commit_msg>test: add project name and build to browserstack<commit_after>module.exports = function (config) {
  config.set({
    // global config of your BrowserStack account
    browserStack: {
      username: process.env.BROWSERSTACK_USERNAME,
      accessKey: process.env.BROWSERSTACK_ACCESSKEY,
      project: 'showdown',
      build: require('./package.json').version
    },

    // define browsers
    customLaunchers: {
      bstack_chrome_windows: {
        base: 'BrowserStack',
        browser: 'chrome',
        browser_version: '72.0',
        os: 'Windows',
        os_version: '10'
      },
      bstack_firefox_windows: {
        base: 'BrowserStack',
        browser: 'firefox',
        browser_version: '98.0',
        os: 'Windows',
        os_version: '10'
      },
      //dropped support for IE 10
      bstack_ie10_windows: {
        base: 'BrowserStack',
        browser: 'ie',
        browser_version: '10',
        os: 'Windows',
        os_version: '7'
      },
      //dropped support for IE 10
      bstack_ie11_windows: {
        base: 'BrowserStack',
        browser: 'ie',
        browser_version: '11',
        os: 'Windows',
        os_version: '10'
      },
      bstack_iphoneX: {
        base: 'BrowserStack',
        browser: 'safari',
        device: 'iPhone X',
        os: 'ios',
        real_mobile: true,
        os_version: '11.0'
      }
    },

    browsers: ['bstack_chrome_windows', 'bstack_firefox_windows', 'bstack_ie11_windows', 'bstack_iphoneX'],
    frameworks: ['mocha', 'chai'],
    reporters: ['dots', 'BrowserStack'],
    files: [
      { pattern: '.build/showdown.js'},
      { pattern: 'src/options.js'},
      // tests
      { pattern: 'test/unit/showdown*.js' },
      { pattern: 'test/functional/showdown*.js' },
    ],
    singleRun: true,
    concurrency: Infinity
  });
};
<|endoftext|>


<commit_before>var summaryTemplate = null;
var singleResultTemplate = null;
var multiResultTemplate = null;
var resultStatsTemplate = null;

$(function() {
    summaryTemplate = _.template($("#summary-template").html());
    singleResultTemplate = _.template($("#single-result-template").html());
    multiResultTemplate = _.template($("#multi-result-template").html());
    resultStatsTemplate = _.template($("#result-stats-sidebar").html());
    $('.example-search').click(function() {
        $('#search-input').val($(this).text());
        $('#search-submit').click();
        return false;
    });
    buildDateUI();
});

var appendResult = function(obj) {
    var statusClass;
    switch (obj.docs[0].matter.status){
        case 'Adopted':
        case 'Approved':
        case 'Passed':
        case 'Recommended for Passage':
            statusClass = 'success';
            break;

        case 'Deferred and Published':
        case 'Direct Introduction':
        case 'In Committee':
        case 'Introduced':
        case 'Placed on File':
        case 'Recommended for Re-referral':
        case 'Re-referred':
            statusClass = 'warning';
            break;

        case 'Failed to Pass':
        case 'Recommended Do Not Pass':
        case 'Tabled':
        case 'Vetoed':
        case 'Void':
        case 'Withdrawn':
            statusClass = 'alert';
            break;
    }
    if(obj.docs.length > 1) {
        $(multiResultTemplate({docs: obj.docs, statusClass: statusClass})).appendTo('#search-results');
    } else {
        $(singleResultTemplate({doc: obj.docs[0], statusClass: statusClass})).appendTo('#search-results');
    }
};

//Need to store the results of the AJAX call somewhere so we can sort without hitting the database
var resultData = {
  'documents': [],
  'dateGroups': {},
  'rankGroups': {},
  'sidebarData': {}, //statsData
  'query': '',
  'dateRangeType': '',
  'ignoreRoutine': true,
  'queryQualifier': '',
  'isRanked': false,
  'truncated': false,
  'fullCount': ''
}

function populateResults(sortType){
    typeKeys = Object.keys(resultData[sortType]);
    if (sortType == "dateGroups"){
      typeKeys.sort(function(a,b) { return (b < a) ? -1 : 1 });
    } //Do we also need to sort ranks?
    for (i=0; i<typeKeys.length; i++) {
        var resultGroups = resultData[sortType][typeKeys[i]];
        $.each(resultGroups, function(j, g) {
            appendResult(g);
        });
    }
    //setTimeout(function() { hideNonPages(); }, 3000);
    $(".sort[data-grouptype='" + sortType + "']").children('.option').addClass('active');
    $(".sort[data-grouptype='" + sortType + "']").siblings().children().removeClass('active');
}

function appendSummaryAndStats(total, qualifier, statsData, truncatedFlag, fullCount){
    var query = $('#search-input').val();
    // if ($('#search-input').val() != '') {
    //   query = 'matching ' + $('#search-input').val() + '';
    // }
    $('#results-summary').html($(summaryTemplate({
        total: total,
        query: query,
        qualifier: qualifier,
        truncated: truncatedFlag,
        fullCount: fullCount
    })));
    /* not using the sidebar right now */
    //$('#results-stats').empty();
    //if (total > 0) {
        //$('#results-stats').html(resultStatsTemplate({statsData: statsData}));
    //}
}

var doSearch = function(searchUrl, subscribeUrl) {
    showLoadingState();
    resultData = {
      'documents': [],
      'dateGroups': {},
      'rankGroups': {},
      'sidebarData': {}, //statsData
      'query': $('#search-input').val(),
      'dateRangeType': $('#date-range-type input[type="radio"]:checked').val(),
      'ignoreRoutine': $('#ignore-routine').is(':checked'),
      'queryQualifier': '',
      'isRanked': false,
      'truncated': false,
      'fullCount':''
    }
    // only rank if there is a search term
    if (resultData.query != "") {
      resultData.isRanked = true;
    }

    //build up summary stats for sidebar
    function buildResultStats(doc, statsData){
        var statTypes = {
            'Statuses': 'status',
            'Matter Types': 'type'
        };
        $.each(statTypes, function(key, matter_field) {
            if (!(key in statsData)){
                statsData[key] = {};
            }
            if(doc.matter[matter_field] in statsData[key]) {
                statsData[key][doc.matter[matter_field]] += 1;
            } else {
                statsData[key][doc.matter[matter_field]] = 1;
            }
        });
        return statsData;
    };

    // group documents with their related matters
    function buildDateResults(data){
        if(data.documents.length > 0) {
            var dates = [];
            //TODO: create statsData global so we don't have to rebuild sidebar on sort-by-rank?
            $.each(data.documents, function(i, doc) {
                // dt is datetime
                var dt = doc.sort_date;
                // if the datetime hasn't already been added to the dates array
                if(dates.indexOf(dt) < 0) {
                    dates.push(dt);
                    resultData.dateGroups[dt] = {};
                }
                // if the datetime already exists in `groups`, it means the matter has multiple documents: add docs to existing matter
                // otherwise just create the `docs` property
                if(doc.matter.id in resultData.dateGroups[dt]) {
                    resultData.dateGroups[dt][doc.matter.id]['docs'].push(doc);
                } else {
                    resultData.dateGroups[dt][doc.matter.id] = {
                        'docs': [doc]
                    };
                }
                buildResultStats(doc, resultData.sidebarData);
            });
        }
    }

    function buildRankResults(data){
        if(data.documents.length > 0) {
            var ranks = [];
            $.each(data.documents, function(i, doc) {
                var rank = doc.rank;
                if(ranks.indexOf(rank) < 0) {
                    ranks.push(rank);
                    resultData.rankGroups[rank] = {};
                }
                if(doc.matter.id in resultData.rankGroups[rank]) {
                    resultData.rankGroups[rank][doc.matter.id]['docs'].push(doc);
                } else {
                    resultData.rankGroups[rank][doc.matter.id] = {
                        'docs': [doc]
                    };
                }
            });
        }
    }

    function showEmailForm(){
      $('#search-subscribe-form').show();
      $('#search-subscribe-form').submit(function(event) {
          handle_subscribe(event, subscribeUrl);
          return false;
      });
    }

    function showSortButtons(){
      $('#sort-by').show();
    }

    //used to determine language to display and time period to return
    var preposition = ' from '; // just a little nuance to the qualifier language
    if (resultData.query) {
      preposition = ' in ';
    }
    switch (resultData.dateRangeType) {
        case 'past-year':
            resultData.queryQualifier = preposition + 'the past year';
            break;

        case 'past-month':
            resultData.queryQualifier = preposition + 'the last 30 days';
            break;

        case 'any':
            break;
    }

    $.ajax({
        url: searchUrl,
        data: {
            query: resultData.query,
            date_range: resultData.dateRangeType,
            ignore_routine: resultData.ignoreRoutine,
            is_ranked: resultData.isRanked,
            resultData: resultData.truncated,
            fullCount: resultData.fullCount
        }
    })
    .success(function(data) {
        resultData.truncated = data.truncated;
        resultData.fullCount = data.full_count;
        resultData.documents = data.documents;
        buildDateResults(data);
        appendSummaryAndStats(resultData.documents.length, resultData.queryQualifier, resultData.sidebarData, resultData.truncated, resultData.fullCount);
        if (data.is_ranked) {
          //NOTE: are results in ranked order already? If so, we just need to create meta.
          buildRankResults(data);
          populateResults("rankGroups");
        } else {
          populateResults("dateGroups");
        }

        if (resultData.query != '') {
          // don't let people subscribe to queries without keywords
          showEmailForm(subscribeUrl);
        }
        if (resultData.documents.length > 0 && resultData.isRanked) {
          showSortButtons();
        }
        $("#search-results").foundation('reveal', 'reflow');

    })
    .error(function(xhr, status, errMsg) {
        alert(errMsg);
    })
    .complete(function(xhr, status) {
        hideLoadingState();
    });
}; // doSearch

$('#sort-by .sort').on('click', function(){
  if (resultData.documents.length > 0){
    $('#search-results').empty();
    populateResults($(this).data('grouptype'));
  }
});
<commit_msg>Removed buggy addition of truncated and fullcount to AJAX query object that gets sent to server from the backend.<commit_after>var summaryTemplate = null;
var singleResultTemplate = null;
var multiResultTemplate = null;
var resultStatsTemplate = null;

$(function() {
    summaryTemplate = _.template($("#summary-template").html());
    singleResultTemplate = _.template($("#single-result-template").html());
    multiResultTemplate = _.template($("#multi-result-template").html());
    resultStatsTemplate = _.template($("#result-stats-sidebar").html());
    $('.example-search').click(function() {
        $('#search-input').val($(this).text());
        $('#search-submit').click();
        return false;
    });
    buildDateUI();
});

var appendResult = function(obj) {
    var statusClass;
    switch (obj.docs[0].matter.status){
        case 'Adopted':
        case 'Approved':
        case 'Passed':
        case 'Recommended for Passage':
            statusClass = 'success';
            break;

        case 'Deferred and Published':
        case 'Direct Introduction':
        case 'In Committee':
        case 'Introduced':
        case 'Placed on File':
        case 'Recommended for Re-referral':
        case 'Re-referred':
            statusClass = 'warning';
            break;

        case 'Failed to Pass':
        case 'Recommended Do Not Pass':
        case 'Tabled':
        case 'Vetoed':
        case 'Void':
        case 'Withdrawn':
            statusClass = 'alert';
            break;
    }
    if(obj.docs.length > 1) {
        $(multiResultTemplate({docs: obj.docs, statusClass: statusClass})).appendTo('#search-results');
    } else {
        $(singleResultTemplate({doc: obj.docs[0], statusClass: statusClass})).appendTo('#search-results');
    }
};

//Need to store the results of the AJAX call somewhere so we can sort without hitting the database
var resultData = {
  'documents': [],
  'dateGroups': {},
  'rankGroups': {},
  'sidebarData': {}, //statsData
  'query': '',
  'dateRangeType': '',
  'ignoreRoutine': true,
  'queryQualifier': '',
  'isRanked': false,
  'truncated': false,
  'fullCount': ''
}

function populateResults(sortType){
    typeKeys = Object.keys(resultData[sortType]);
    if (sortType == "dateGroups"){
      typeKeys.sort(function(a,b) { return (b < a) ? -1 : 1 });
    } //Do we also need to sort ranks?
    for (i=0; i<typeKeys.length; i++) {
        var resultGroups = resultData[sortType][typeKeys[i]];
        $.each(resultGroups, function(j, g) {
            appendResult(g);
        });
    }
    //setTimeout(function() { hideNonPages(); }, 3000);
    $(".sort[data-grouptype='" + sortType + "']").children('.option').addClass('active');
    $(".sort[data-grouptype='" + sortType + "']").siblings().children().removeClass('active');
}

function appendSummaryAndStats(total, qualifier, statsData, truncatedFlag, fullCount){
    var query = $('#search-input').val();
    // if ($('#search-input').val() != '') {
    //   query = 'matching ' + $('#search-input').val() + '';
    // }
    $('#results-summary').html($(summaryTemplate({
        total: total,
        query: query,
        qualifier: qualifier,
        truncated: truncatedFlag,
        fullCount: fullCount
    })));
    /* not using the sidebar right now */
    //$('#results-stats').empty();
    //if (total > 0) {
        //$('#results-stats').html(resultStatsTemplate({statsData: statsData}));
    //}
}

var doSearch = function(searchUrl, subscribeUrl) {
    showLoadingState();
    resultData = {
      'documents': [],
      'dateGroups': {},
      'rankGroups': {},
      'sidebarData': {}, //statsData
      'query': $('#search-input').val(),
      'dateRangeType': $('#date-range-type input[type="radio"]:checked').val(),
      'ignoreRoutine': $('#ignore-routine').is(':checked'),
      'queryQualifier': '',
      'isRanked': false,
      'truncated': false,
      'fullCount':''
    }
    // only rank if there is a search term
    if (resultData.query != "") {
      resultData.isRanked = true;
    }

    //build up summary stats for sidebar
    function buildResultStats(doc, statsData){
        var statTypes = {
            'Statuses': 'status',
            'Matter Types': 'type'
        };
        $.each(statTypes, function(key, matter_field) {
            if (!(key in statsData)){
                statsData[key] = {};
            }
            if(doc.matter[matter_field] in statsData[key]) {
                statsData[key][doc.matter[matter_field]] += 1;
            } else {
                statsData[key][doc.matter[matter_field]] = 1;
            }
        });
        return statsData;
    };

    // group documents with their related matters
    function buildDateResults(data){
        if(data.documents.length > 0) {
            var dates = [];
            //TODO: create statsData global so we don't have to rebuild sidebar on sort-by-rank?
            $.each(data.documents, function(i, doc) {
                // dt is datetime
                var dt = doc.sort_date;
                // if the datetime hasn't already been added to the dates array
                if(dates.indexOf(dt) < 0) {
                    dates.push(dt);
                    resultData.dateGroups[dt] = {};
                }
                // if the datetime already exists in `groups`, it means the matter has multiple documents: add docs to existing matter
                // otherwise just create the `docs` property
                if(doc.matter.id in resultData.dateGroups[dt]) {
                    resultData.dateGroups[dt][doc.matter.id]['docs'].push(doc);
                } else {
                    resultData.dateGroups[dt][doc.matter.id] = {
                        'docs': [doc]
                    };
                }
                buildResultStats(doc, resultData.sidebarData);
            });
        }
    }

    function buildRankResults(data){
        if(data.documents.length > 0) {
            var ranks = [];
            $.each(data.documents, function(i, doc) {
                var rank = doc.rank;
                if(ranks.indexOf(rank) < 0) {
                    ranks.push(rank);
                    resultData.rankGroups[rank] = {};
                }
                if(doc.matter.id in resultData.rankGroups[rank]) {
                    resultData.rankGroups[rank][doc.matter.id]['docs'].push(doc);
                } else {
                    resultData.rankGroups[rank][doc.matter.id] = {
                        'docs': [doc]
                    };
                }
            });
        }
    }

    function showEmailForm(){
      $('#search-subscribe-form').show();
      $('#search-subscribe-form').submit(function(event) {
          handle_subscribe(event, subscribeUrl);
          return false;
      });
    }

    function showSortButtons(){
      $('#sort-by').show();
    }

    //used to determine language to display and time period to return
    var preposition = ' from '; // just a little nuance to the qualifier language
    if (resultData.query) {
      preposition = ' in ';
    }
    switch (resultData.dateRangeType) {
        case 'past-year':
            resultData.queryQualifier = preposition + 'the past year';
            break;

        case 'past-month':
            resultData.queryQualifier = preposition + 'the last 30 days';
            break;

        case 'any':
            break;
    }

    $.ajax({
        url: searchUrl,
        data: {
            query: resultData.query,
            date_range: resultData.dateRangeType,
            ignore_routine: resultData.ignoreRoutine,
            is_ranked: resultData.isRanked
        }
    })
    .success(function(data) {
        resultData.truncated = data.truncated;
        resultData.fullCount = data.full_count;
        resultData.documents = data.documents;
        buildDateResults(data);
        appendSummaryAndStats(resultData.documents.length, resultData.queryQualifier, resultData.sidebarData, resultData.truncated, resultData.fullCount);
        if (data.is_ranked) {
          //NOTE: are results in ranked order already? If so, we just need to create meta.
          buildRankResults(data);
          populateResults("rankGroups");
        } else {
          populateResults("dateGroups");
        }

        if (resultData.query != '') {
          // don't let people subscribe to queries without keywords
          showEmailForm(subscribeUrl);
        }
        if (resultData.documents.length > 0 && resultData.isRanked) {
          showSortButtons();
        }
        $("#search-results").foundation('reveal', 'reflow');

    })
    .error(function(xhr, status, errMsg) {
        alert(errMsg);
    })
    .complete(function(xhr, status) {
        hideLoadingState();
    });
}; // doSearch

$('#sort-by .sort').on('click', function(){
  if (resultData.documents.length > 0){
    $('#search-results').empty();
    populateResults($(this).data('grouptype'));
  }
});
<|endoftext|>


<commit_before>var Utils = require("util");
var File = require("fs");
var JSONSaver = require("../jsonsaver");

var FactoidServer = module.exports = function(filename) {
	this.filename = filename;
	this.changed = false;
	this.loaded = false;
	this.db = new JSONSaver(filename);
};

FactoidServer.prototype.learn = function(key, value) {

	var db = this.db.object.factoids;

	var popularity = 0;
	key = key.toLowerCase();

	if (typeof db[key] !== "undefined") {
		if (typeof db[key].alias !== "undefined") {
			return this.learn(db[key].alias, value);
		}
		popularity = db[key].popularity;
	}

	db[key] = {value: value, popularity: popularity};
	this.db.activity();
};

FactoidServer.prototype.alias = function(alias, key) {
	key = key.toLowerCase();
	alias = alias.toLowerCase();

	var db = this.db.object.factoids;

	if (typeof db[key] === "undefined") throw new Error("Factoid `"+key+"` doesn't exist.");

	if (typeof db[key].alias !== "undefined") {
		return this.alias(alias, db[key].alias);
	}

	if (alias === key) throw new Error("Cannot alias yourself.");

	db[alias] = {alias: key};
	this.db.activity();
	return key;
};

FactoidServer.prototype.find = function(key, incpop) {
	key = key.toLowerCase();
	var db = this.db.object.factoids;

	if (typeof db[key] === "undefined") {
		throw new Error("Factoid `"+key+"` was not found.");
	}

	if (typeof db[key].alias !== "undefined") {
		return this.find(db[key].alias);
	}

	var thing = db[key];
	if (incpop) thing.popularity++;
	this.db.activity();

	return thing.value;
};

FactoidServer.prototype.search = function(pattern, num) {
	if (typeof num !== "number") num = 5;
	var found = [], cat, db = this.db.object.factoids;

	for (var i in db) {
		if (db.hasOwnProperty(i)) {
			if (typeof db[i].value === "undefined") break;

			cat = (i+" "+db[i].value).toLowerCase();
			if (~cat.indexOf(pattern.toLowerCase())) {
				found.push(i);
			}
		}
	}

	found.sort(function(a, b) { return db[b].popularity - db[a].popularity; });
	return found.slice(0, num);
};

FactoidServer.prototype.forget = function(key) {
	key = key.toLowerCase();
	var db = this.db.object.factoids;

	if (typeof db[key] === "undefined") {
		throw new Error("`"+key+"` was not a factoid.");
	}
	delete db[key];
	this.db.activity();
	return true;
};

FactoidServer.prototype.clean = function() {
	var db = this.db.object.factoids, j, i;
	for (i in db) {
		if (db.hasOwnProperty(i)) {
			if (typeof db[i].alias !== "undefined") {
				for (j in db[i]) {
					if (db[i].hasOwnProperty(j)) {
						if (j !== "alias") delete db[i][j];
					}
				}
				continue;
			}
			if (typeof db[i].value !== "undefined") {
				for (j in db[i]) {
					if (db[i].hasOwnProperty(j)) {
						if (j !== "value" && j !== "popularity") delete db[i][j];
					}
				}
				continue;
			}
			delete db[i];
		}
	}
	this.db.activity();
};
<commit_msg>Remove popularity handling code in factoids<commit_after>var Utils = require("util");
var File = require("fs");
var JSONSaver = require("../jsonsaver");

var FactoidServer = module.exports = function(filename) {
	this.filename = filename;
	this.changed = false;
	this.loaded = false;
	this.db = new JSONSaver(filename);
};

FactoidServer.prototype.learn = function(key, value) {

	var db = this.db.object.factoids;

	//var popularity = 0;
	key = key.toLowerCase();

	if (typeof db[key] !== "undefined") {
		if (typeof db[key].alias !== "undefined") {
			return this.learn(db[key].alias, value);
		}
		//popularity = db[key].popularity;
	}

	//db[key] = {value: value, popularity: popularity};
	db[key] = {value: value};
	this.db.activity();
};

FactoidServer.prototype.alias = function(alias, key) {
	key = key.toLowerCase();
	alias = alias.toLowerCase();

	var db = this.db.object.factoids;

	if (typeof db[key] === "undefined") throw new Error("Factoid `"+key+"` doesn't exist.");

	if (typeof db[key].alias !== "undefined") {
		return this.alias(alias, db[key].alias);
	}

	if (alias === key) throw new Error("Cannot alias yourself.");

	db[alias] = {alias: key};
	this.db.activity();
	return key;
};

FactoidServer.prototype.find = function(key, incpop) {
	key = key.toLowerCase();
	var db = this.db.object.factoids;

	if (typeof db[key] === "undefined") {
		throw new Error("Factoid `"+key+"` was not found.");
	}

	if (typeof db[key].alias !== "undefined") {
		return this.find(db[key].alias);
	}

	var thing = db[key];
	//if (incpop) thing.popularity++;
	this.db.activity();

	return thing.value;
};

FactoidServer.prototype.search = function(pattern, num) {
	if (typeof num !== "number") num = 5;
	var found = [], cat, db = this.db.object.factoids;

	for (var i in db) {
		if (db.hasOwnProperty(i)) {
			if (typeof db[i].value === "undefined") break;

			cat = (i+" "+db[i].value).toLowerCase();
			if (~cat.indexOf(pattern.toLowerCase())) {
				found.push(i);
			}
		}
	}

	//found.sort(function(a, b) { return db[b].popularity - db[a].popularity; });
	return found.slice(0, num);
};

FactoidServer.prototype.forget = function(key) {
	key = key.toLowerCase();
	var db = this.db.object.factoids;

	if (typeof db[key] === "undefined") {
		throw new Error("`"+key+"` was not a factoid.");
	}
	delete db[key];
	this.db.activity();
	return true;
};

FactoidServer.prototype.clean = function() {
	var db = this.db.object.factoids, j, i;
	for (i in db) {
		if (db.hasOwnProperty(i)) {
			if (typeof db[i].alias !== "undefined") {
				for (j in db[i]) {
					if (db[i].hasOwnProperty(j)) {
						if (j !== "alias") delete db[i][j];
					}
				}
				continue;
			}
			if (typeof db[i].value !== "undefined") {
				for (j in db[i]) {
					if (db[i].hasOwnProperty(j)) {
						//if (j !== "value" && j !== "popularity") delete db[i][j];
						if (j !== "value") delete db[i][j];
					}
				}
				continue;
			}
			delete db[i];
		}
	}
	this.db.activity();
};
<|endoftext|>


<commit_before>/*************************************************************
 *
 *  MathJax/extension/v1.0-warning.js
 *
 *  This extension file is loaded when no jax are configured
 *  as a backward-compatible measure to help people convert to the
 *  new configuration process.
 *
 *  ---------------------------------------------------------------------
 *
 *  Copyright (c) 2011 Design Science, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

(function (HUB,HTML) {
  var VERSION = "1.1";

  var CONFIG = {
    style: {
      position:"fixed", bottom:"4em", left:"3em", width:"40em",
      border: "3px solid #880000", "background-color": "#E0E0E0",
      padding: "1em", "font-size":"small", "white-space":"normal",

      "border-radius": ".75em",                     // Opera 10.5 and IE9
      "-webkit-border-radius": ".75em",             // Safari and Chrome
      "-moz-border-radius": ".75em",                // Firefox
      "-khtml-border-radius": ".75em",              // Konqueror

      "box-shadow": "4px 4px 10px #AAAAAA",         // Opera 10.5 and IE9
      "-webkit-box-shadow": "4px 4px 10px #AAAAAA", // Safari 3 and Chrome
      "-moz-box-shadow": "4px 4px 10px #AAAAAA",    // Forefox 3.5
      "-khtml-box-shadow": "4px 4px 10px #AAAAAA",  // Konqueror
      filter: "progid:DXImageTransform.Microsoft.dropshadow(OffX=3, OffY=3, Color='gray', Positive='true')" // IE
    }
  };
  if (HUB.Browser.isIE9 && document.documentMode >= 9) {delete CONFIG.style.filter}

  var DIV;

  HUB.Register.StartupHook("onLoad",function () {
    var frame = document.body;
    if (HUB.Browser.isMSIE) {
      MathJax.Message.Init();  // make sure MathJax_MSIE_frame exists
      frame = document.getElementById("MathJax_MSIE_frame") || frame; // in IE8 and 9 it may not anyway
      CONFIG.style.position = "absolute";
    } else {delete CONFIG.style.filter}
    CONFIG.style.maxWidth = (document.body.clientWidth-75) + "px";
    DIV = HTML.addElement(frame,"div",{id:"MathJax_ConfigWarning",style:CONFIG.style},[
      [
        "div",{
          style: {
            position:"absolute", overflow:"hidden", top:".1em", right:".1em",
            border: "1px outset", width:"1em", height:"1em",
            "text-align": "center", cursor: "pointer",
            "background-color": "#EEEEEE", color:"#606060",

            "border-radius": ".5em",           // Opera 10.5
            "-webkit-border-radius": ".5em",   // Safari and Chrome
            "-moz-border-radius": ".5em",      // Firefox
            "-khtml-border-radius": ".5em"     // Konqueror
          },
          onclick: function () {DIV.style.display = "none"}
        },
        [["span",{style:{position:"relative", bottom:".2em"}},["x"]]]
      ],
      "MathJax no longer loads a default configuration file; " +
      "you must specify such files explicitly. " +
      "This page seems to use the older default ",["code",{},["config/MathJax.js"]],
      " file, and so needs to be updated.  This is explained further at",
      ["p",{style:{"text-align":"center"}},[
        ["a",
          {href:"http://www.mathjax.org/help/configuration"},
          ["http://www.mathjax.org/help/configuration"]
        ]
      ]]
    ]);
  });

})(MathJax.Hub,MathJax.HTML);

MathJax.Ajax.loadComplete("[MathJax]/extensions/v1.0-warning.js");
<commit_msg>Fix a typo in the comments<commit_after>/*************************************************************
 *
 *  MathJax/extensions/v1.0-warning.js
 *
 *  This extension file is loaded when no jax are configured
 *  as a backward-compatible measure to help people convert to the
 *  new configuration process.
 *
 *  ---------------------------------------------------------------------
 *
 *  Copyright (c) 2011 Design Science, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

(function (HUB,HTML) {
  var VERSION = "1.1";

  var CONFIG = {
    style: {
      position:"fixed", bottom:"4em", left:"3em", width:"40em",
      border: "3px solid #880000", "background-color": "#E0E0E0",
      padding: "1em", "font-size":"small", "white-space":"normal",

      "border-radius": ".75em",                     // Opera 10.5 and IE9
      "-webkit-border-radius": ".75em",             // Safari and Chrome
      "-moz-border-radius": ".75em",                // Firefox
      "-khtml-border-radius": ".75em",              // Konqueror

      "box-shadow": "4px 4px 10px #AAAAAA",         // Opera 10.5 and IE9
      "-webkit-box-shadow": "4px 4px 10px #AAAAAA", // Safari 3 and Chrome
      "-moz-box-shadow": "4px 4px 10px #AAAAAA",    // Forefox 3.5
      "-khtml-box-shadow": "4px 4px 10px #AAAAAA",  // Konqueror
      filter: "progid:DXImageTransform.Microsoft.dropshadow(OffX=3, OffY=3, Color='gray', Positive='true')" // IE
    }
  };
  if (HUB.Browser.isIE9 && document.documentMode >= 9) {delete CONFIG.style.filter}

  var DIV;

  HUB.Register.StartupHook("onLoad",function () {
    var frame = document.body;
    if (HUB.Browser.isMSIE) {
      MathJax.Message.Init();  // make sure MathJax_MSIE_frame exists
      frame = document.getElementById("MathJax_MSIE_frame") || frame; // in IE8 and 9 it may not anyway
      CONFIG.style.position = "absolute";
    } else {delete CONFIG.style.filter}
    CONFIG.style.maxWidth = (document.body.clientWidth-75) + "px";
    DIV = HTML.addElement(frame,"div",{id:"MathJax_ConfigWarning",style:CONFIG.style},[
      [
        "div",{
          style: {
            position:"absolute", overflow:"hidden", top:".1em", right:".1em",
            border: "1px outset", width:"1em", height:"1em",
            "text-align": "center", cursor: "pointer",
            "background-color": "#EEEEEE", color:"#606060",

            "border-radius": ".5em",           // Opera 10.5
            "-webkit-border-radius": ".5em",   // Safari and Chrome
            "-moz-border-radius": ".5em",      // Firefox
            "-khtml-border-radius": ".5em"     // Konqueror
          },
          onclick: function () {DIV.style.display = "none"}
        },
        [["span",{style:{position:"relative", bottom:".2em"}},["x"]]]
      ],
      "MathJax no longer loads a default configuration file; " +
      "you must specify such files explicitly. " +
      "This page seems to use the older default ",["code",{},["config/MathJax.js"]],
      " file, and so needs to be updated.  This is explained further at",
      ["p",{style:{"text-align":"center"}},[
        ["a",
          {href:"http://www.mathjax.org/help/configuration"},
          ["http://www.mathjax.org/help/configuration"]
        ]
      ]]
    ]);
  });

})(MathJax.Hub,MathJax.HTML);

MathJax.Ajax.loadComplete("[MathJax]/extensions/v1.0-warning.js");
<|endoftext|>


<commit_before>// @flow

import * as React from 'react'
import {ActionSheetIOS, Clipboard} from 'react-native'
import glamorous from 'glamorous-native'
import openUrl from '../open-url'

import * as c from '../colors'

export const LinkText = glamorous.text({
	textDecorationLine: 'underline',
	textDecorationStyle: 'solid',
	color: c.infoBlue,
})

type Props = {
	href: string,
	title?: string,
	children: React.ChildrenArray<string>,
}

type Callback = ({title?: string, href: string}) => any

export class Link extends React.Component<Props> {
	options: Array<[string, Callback]> = [
		['Open', ({href}: {href: string}) => openUrl(href)],
		[
			'Copy',
			({title, href}: {href: string, title?: string}) =>
				Clipboard.setString(`${href}${title ? ' ' + title : ''}`),
		],
		[
			'Share…',
			({href}: {href: string}) =>
				ActionSheetIOS.showShareActionSheetWithOptions(
					{url: href},
					this.onShareFailure,
					this.onShareSuccess,
				),
		],
		['Cancel', () => {}],
	]

	onPress = () => {
		return openUrl(this.props.href)
	}

	onLongPress = () => {
		return ActionSheetIOS.showActionSheetWithOptions(
			{
				options: this.options.map(([name]) => name),
				title: this.props.title,
				message: this.props.href,
				cancelButtonIndex: this.options.length - 1,
			},
			this.onLongPressEnd,
		)
	}

	onLongPressEnd = (pressedOptionIndex: number) => {
		// eslint-disable-next-line no-unused-vars
		const [name, action] = this.options[pressedOptionIndex]
		return action(this.props)
	}

	onShareFailure = () => {}
	onShareSuccess = () => {}

	render() {
		return (
			<LinkText onLongPress={this.onLongPress} onPress={this.onPress}>
				{this.props.children}
			</LinkText>
		)
	}
}
<commit_msg>clean up types in markdown/Link<commit_after>// @flow

import * as React from 'react'
import {ActionSheetIOS, Clipboard} from 'react-native'
import glamorous from 'glamorous-native'
import openUrl from '../open-url'

import * as c from '../colors'

export const LinkText = glamorous.text({
	textDecorationLine: 'underline',
	textDecorationStyle: 'solid',
	color: c.infoBlue,
})

type Props = {
	href: string,
	title?: string,
	children: React.ChildrenArray<string>,
}

type Callback = ({title?: string, href: string}) => any

export class Link extends React.Component<Props> {
	options: Array<[string, Callback]> = [
		['Open', ({href}) => openUrl(href)],
		[
			'Copy',
			({title, href}) =>
				Clipboard.setString(`${href}${title ? ' ' + title : ''}`),
		],
		[
			'Share…',
			({href}) =>
				ActionSheetIOS.showShareActionSheetWithOptions(
					{url: href},
					this.onShareFailure,
					this.onShareSuccess,
				),
		],
		['Cancel', () => {}],
	]

	onPress = () => {
		return openUrl(this.props.href)
	}

	onLongPress = () => {
		return ActionSheetIOS.showActionSheetWithOptions(
			{
				options: this.options.map(([name]) => name),
				title: this.props.title,
				message: this.props.href,
				cancelButtonIndex: this.options.length - 1,
			},
			this.onLongPressEnd,
		)
	}

	onLongPressEnd = (pressedOptionIndex: number) => {
		// eslint-disable-next-line no-unused-vars
		const [name, action] = this.options[pressedOptionIndex]
		return action(this.props)
	}

	onShareFailure = () => {}
	onShareSuccess = () => {}

	render() {
		return (
			<LinkText onLongPress={this.onLongPress} onPress={this.onPress}>
				{this.props.children}
			</LinkText>
		)
	}
}
<|endoftext|>


<commit_before>import {
	dirname,
	resolve
} from 'path';
import {
	merge
} from 'lodash';
import findRoot from 'find-root';
import exists from 'path-exists';

import load from '../../../library/utilities/configuration';

export default {
	after: ['application:before'],

	defaults: {
		path: './configuration',
		filter: /(.*).(js|json)$/
	},

	async configure(application) {
		application.configuration = {};
		this.configuration = merge(
			{},
			this.defaults,
			{
				path: resolve(application.runtime.base, this.defaults.path)
			}
		);
		return this;
	},

	async start(application) {
		// Load boilerplate-server core configuration
		const core = load(
			resolve(
				findRoot(__dirname),
				this.configuration.path
			),
			this.configuration.filter,
			application.runtime.env
		);

		// Load package.jsons
		const corePkgPath = resolve(application.runtime.base, 'package.json');
		const pkgPath = resolve(application.runtime.cwd, 'package.json');

		const corePkg = require(corePkgPath);
		const userPkg = require(pkgPath);
		const pkg = merge({}, corePkg, pkg, userPkg);

		// Allow user to override core behaviour via cli and *rc files
		merge(core, {pkg}, application.runtime.api);

		// Set application runtime cwds
		application.runtime.cwds = [
			...new Set([
				application.runtime.cwd,
				process.cwd()
			])
		];

		// Check which user config paths exist
		let existingConfigPaths = [];
		for (const configPath of core.paths.configuration) {
			for (const cwd of application.runtime.cwds) {
				for (const suffix of ['', userPkg.name]) {
					const userPath = resolve(cwd, configPath, suffix);
					console.log(userPath);
					if (await exists(userPath)) {
						existingConfigPaths.push(userPath);
					}
				}
			}
		}

		// Load most specific paths only
		// Check if paths have siblings that contain them completely, thus are sub directories / more specific configuration folders
		existingConfigPaths = existingConfigPaths.filter(configPath => {
			const match = existingConfigPaths.filter(subConfigPath =>
				subConfigPath.includes(configPath) && subConfigPath !== configPath
			);
			return match.length === 0;
		});

		// Load dem configs from filtered paths
		let user = {};
		for (const userPath of existingConfigPaths) {
			this.log.info(`Loading configuration from '${userPath}'`);

			try {
				const userPathConfig = load(userPath, this.configuration.filter, application.runtime.env);
				user = merge(user, userPathConfig);
			} catch (err) {
				this.log.error(`Error while reading configuration from ${userPath}.`);
				this.log.error(err);
				err.message = 'Failed loading configuration from ${userPath}';
				throw err;
			}
		}

		merge(application.configuration, core, user, application.runtime.api, (a, b) => {
			if (Array.isArray(b) && typeof a === 'string') {
				return b;
			}
		});

		application.runtime.prefix = application.runtime.prefix || '/';
		application.runtime.mode = application.runtime.mode || 'server';
		return this;
	}
};
<commit_msg>fix: restore former npm tree walking lookups<commit_after>import {
	dirname,
	resolve
} from 'path';
import {
	merge
} from 'lodash';
import findRoot from 'find-root';
import exists from 'path-exists';

import load from '../../../library/utilities/configuration';

export default {
	after: ['application:before'],

	defaults: {
		path: './configuration',
		filter: /(.*).(js|json)$/
	},

	async configure(application) {
		application.configuration = {};
		this.configuration = merge(
			{},
			this.defaults,
			{
				path: resolve(application.runtime.base, this.defaults.path)
			}
		);
		return this;
	},

	async start(application) {
		// Load boilerplate-server core configuration
		const core = load(
			resolve(
				findRoot(__dirname),
				this.configuration.path
			),
			this.configuration.filter,
			application.runtime.env
		);

		// Load package.jsons
		const corePkgPath = resolve(application.runtime.base, 'package.json');
		const pkgPath = resolve(application.runtime.cwd, 'package.json');

		const corePkg = require(corePkgPath);
		const userPkg = require(pkgPath);
		const pkg = merge({}, corePkg, pkg, userPkg);

		// Allow user to override core behaviour via cli and *rc files
		merge(core, {pkg}, application.runtime.api);

		// Find all node modules on the way from here to the top
		let modulePaths = [dirname(module.filename)];
		let moduleRoot = module;
		while (moduleRoot.parent) {
			moduleRoot = moduleRoot.parent;
			modulePaths.push(dirname(moduleRoot.filename));
		}

		modulePaths = [...new Set(modulePaths)];
		modulePaths = modulePaths.filter(modulePath => !modulePath.includes(findRoot(__dirname)));

		const existingModulePaths = [];

		console.log('modulePaths', modulePaths);

		for (let modulePath of modulePaths) { // eslint-disable-line
			let moduleRoot = modulePath;
			while (await exists(resolve(moduleRoot, 'package.json')) === false) {
				console.log('root', moduleRoot);
				moduleRoot = dirname(moduleRoot);
			}
			existingModulePaths.push(moduleRoot);
		}

		// Set application runtime cwds
		application.runtime.cwds = [
			...new Set([
				application.runtime.cwd,
				...existingModulePaths,
				process.cwd()
			])
		];

		// Check which user config paths exist
		let existingConfigPaths = [];
		for (const configPath of core.paths.configuration) {
			for (const cwd of application.runtime.cwds) {
				for (const suffix of ['', userPkg.name]) {
					const userPath = resolve(cwd, configPath, suffix);
					console.log(userPath);
					if (await exists(userPath)) {
						existingConfigPaths.push(userPath);
					}
				}
			}
		}

		// Load most specific paths only
		// Check if paths have siblings that contain them completely, thus are sub directories / more specific configuration folders
		existingConfigPaths = existingConfigPaths.filter(configPath => {
			const match = existingConfigPaths.filter(subConfigPath =>
				subConfigPath.includes(configPath) && subConfigPath !== configPath
			);
			return match.length === 0;
		});

		// Load dem configs from filtered paths
		let user = {};
		for (const userPath of existingConfigPaths) {
			this.log.info(`Loading configuration from '${userPath}'`);

			try {
				const userPathConfig = load(userPath, this.configuration.filter, application.runtime.env);
				user = merge(user, userPathConfig);
			} catch (err) {
				this.log.error(`Error while reading configuration from ${userPath}.`);
				this.log.error(err);
				err.message = 'Failed loading configuration from ${userPath}';
				throw err;
			}
		}

		merge(application.configuration, core, user, application.runtime.api, (a, b) => {
			if (Array.isArray(b) && typeof a === 'string') {
				return b;
			}
		});

		application.runtime.prefix = application.runtime.prefix || '/';
		application.runtime.mode = application.runtime.mode || 'server';
		return this;
	}
};
<|endoftext|>