<commit_before>
App.page.home = function(force) {

	if (!force && !App.loc.loaded) {
		// if we arent forcing and theres no pos, then this was a home request. we need to wait a second
		console.log('QUE HOME PAGE')
		App.loc.bind('location-loaded', function() {
			App.page.home(force);
		});
		App.loc.bind('location-detected', function() {
			App.page.home(force);
		});

		return;
	}
	console.log('HOME PAGE')

	var homeSuccess = function() {
		$('.nav-back').removeClass('nav-back-show');
		$('.config-icon').addClass('config-icon-mobile-hide');
		$('.content').addClass('short-meal-list');

		App.showPage({
			page: 'home',
			title: 'Crunchbutton',
			data: {
				topCommunities: App.topCommunities,
				yourArea: App.loc.city() || 'your area',
				autofocus: $(window).width() >= 768 ? ' autofocus="autofocus"' : ''
			}
		});

		// @todo: put these in the css. @hacks
		if (navigator.userAgent.toLowerCase().indexOf('safari') > -1 && navigator.userAgent.toLowerCase().indexOf('mobile') == -1 && navigator.userAgent.toLowerCase().indexOf('chrome') == -1) {
			// safari desktop
			$('.location-detect').css({
				'margin-top': '2px',
				'height': '50px'
			});
		} else if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
			// firefox desktop
			$('.location-detect').css({
				'margin-top': '0px',
				'height': '52px'
			});
		}

		// @todo: why is this here??
		if (App.showReset){
			App.signin.passwordHelp.reset.init();
		}
	};

	if (!force && App.loc.address() && App.restaurants.list === false) {
		// we have an address, but no restaurants
console.log('LOCATION NO REST')
		App.page.foodDelivery();

		return;

	} else {
		homeSuccess();
	}

	if (!force && App.loc.address() && App.restaurants.list && App.restaurants.list.length == 0) {
		App.loc.log();

		$('.home-greeting, .enter-location, .button-letseat-form').hide();
		$('.error-location').show();
console.log('LOCATION ERROR')
		App.track('Location Error', {
			lat: App.loc.pos().lat,
			lon: App.loc.pos().lon,
			address: App.loc.address()
		});

	} else {
console.log('JUST HOME')
		$('.location-address').val('');
		$('.error-location').hide();
		$('.home-greeting, .enter-location, .button-letseat-form').show();

	}
};

App.page.restaurant = function(id) {

	$('.config-icon').addClass('config-icon-mobile-hide');
	$('.nav-back').addClass('nav-back-show');

	App.cartHighlightEnabled = false;

	$('.content').removeClass('smaller-width');
	$('.content').removeClass('short-meal-list');

	App.cache('Restaurant', id, function() {
		if (App.restaurant && App.restaurant.permalink != id) {
			App.cart.resetOrder();
		}

		App.restaurant = this;
		var community = App.getCommunityById(App.restaurant.id_community);

		var lastOrderDelivery = false;
		var lastPayCash = false;

		if( App.config && App.config.user && App.config.user.presets && App.config.user.presets[App.restaurant.id_restaurant] ){
			// Check if the last user's order at this restaurant was a delivery type
			lastOrderDelivery = App.config.user.presets[App.restaurant.id_restaurant].delivery_type;
			// Check if the last user's order at this restaurant was cash type
			lastPayCash = App.config.user.presets[App.restaurant.id_restaurant].pay_type;
		}

		App.showPage({
			tracking: {
				title: 'Restaurant page loaded',
				data: {
					restaurant: App.restaurant.name
				}
			},
			page: 'restaurant',
			title: App.restaurant.name + ' | Food Delivery | Order from ' + ( community.name  ? community.name  : 'Local') + ' Restaurants | Crunchbutton',
			data: {
				restaurant: App.restaurant,
				presets: App.config.user.presets,
				lastOrderDelivery: lastOrderDelivery,
				user: App.config.user,
				community: community,
				form: {
					tip: App.order.tip,
					name: App.config.user.name,
					phone: App.phone.format(App.config.user.phone),
					address: App.config.user.address || App.loc.address(),
					notes: (App.config.user && App.config.user.presets && App.config.user.presets[App.restaurant.id_restaurant]) ? App.config.user.presets[App.restaurant.id_restaurant].notes : '',
					card: {
						number: App.config.user.card,
						month: App.config.user.card_exp_month,
						year: App.config.user.card_exp_year
					}
				}
			}
		});

		if (App.config.user.presets) {
			$('.payment-form').hide();
		}

		if (App.cart.hasItems()) {
			App.cart.reloadOrder();
		} else if (App.config.user && App.config.user.presets && App.config.user.presets[App.restaurant.id_restaurant]) {
			try {
				App.cart.loadOrder(App.config.user.presets[App.restaurant.id_restaurant]);
			} catch (e) {
				App.cart.loadOrder(App.restaurant.preset());
			}
		} else {
			App.cart.loadOrder(App.restaurant.preset());
		}

		// As the div restaurant-items has position:absolute this line will make sure the footer will not go up.
		$('.body').css({
			'min-height': $('.restaurant-items').height()
		});

		setTimeout(function() {
			var total = App.cart.updateTotal();
		},200);

		App.cartHighlightEnabled = false;

		if ( App.order['pay_type'] == 'cash' || lastPayCash == 'cash' ) {
			App.trigger.cash();
		} else {
			App.trigger.credit();
		}

		if( lastPayCash == 'cash' ){
			App.trigger.cash();
		} else if ( lastPayCash == 'card' ){
			App.trigger.credit();
		}

		// Rules at #669
		if( ( lastOrderDelivery == 'delivery' && App.restaurant.delivery == '1' ) ||
				( App.order['delivery_type'] == 'delivery' && App.restaurant.delivery == '1' ) ||
				( !App.config.user.delivery_type && App.restaurant.delivery == '1' ) ){
				App.trigger.delivery();
		}

		if( App.order['delivery_type'] == 'takeout' || App.restaurant.delivery != '1') {
			App.trigger.takeout();
		}

		$( '.restaurant-gift' ).hide();

		App.credit.getCredit( function(){
			App.credit.show();
			App.cart.updateTotal();
		} );

		if (!App.config.user.id_user) {
			App.config.user.address = App.loc.enteredLoc;
			App.loc.enteredLoc = '';
		}

	});

};

/**
 * Order page. displayed after order, or at order history
 */
App.page.order = function(id) {

	$( '.config-icon' ).addClass( 'config-icon-mobile-hide' );
	$( '.nav-back' ).addClass( 'nav-back-show' );

	if (App.justCompleted) {
		App.justCompleted = false;
	}

	$('.content').addClass('smaller-width');
	$('.main-content').css('width','auto');

	// Just to make sure the user button will be shown
	App.signin.checkUser();

	App.cache('Order', id, function() {
		var order = this;

		if (!order.uuid) {
			History.replaceState({},'Crunchbutton','/orders');
			return;
		}

		App._order_uuid = id;

		App.facebook.preLoadOrderStatus();

		App.cache('Restaurant',order.id_restaurant, function() {
			var restaurant = this;

			App.showPage({
				title: 'Crunchbutton - Your Order',
				page: 'order',
				data: {
					order: order,
					restaurant: restaurant,
					user: App.config.user.has_auth
				}
			});

		});
	});
};

/**
 * Legal page. loaded from xhr.
 */
App.page.legal = function() {
	App.currentPage = 'legal';
	$.getJSON('/api/legal',function(json) {
		$('.main-content').html(json.data);
		App.refreshLayout();
	});
};

/**
 * Help page. loaded from xhr.
 */
App.page.help = function() {
	App.currentPage = 'help';
	$.getJSON('/api/help',function(json) {
		$('.main-content').html(json.data);
		App.refreshLayout();
	});
};

/**
 * Order page. only avaiable after a user has placed an order or signed up.
 * @todo: change to account page
 */
App.page.orders = function() {
	if (!App.config.user.id_user) {
		History.pushState({}, 'Crunchbutton', '/');
		return;
	}

	$( '.config-icon' ).addClass( 'config-icon-mobile-hide' );
	$( '.nav-back' ).addClass( 'nav-back-show' );

	$.getJSON('/api/user/orders',function(json) {
		App.showPage({
			title: 'Your Account',
			page: 'orders',
			data: {
				orders: json,
				user: App.user
			}
		});
	});

	App.refreshLayout();
};

/**
 * FoodDelivery's methods
 */
App.foodDelivery = {};

// before we change the url we need to make sure that there are restaurants at the typed place.
App.foodDelivery.getRestaurants = function(success, error) {
	if (!App.loc.pos()) {
		error();
		return;
	}

	var url = App.service + 'restaurants?lat=' + App.loc.pos().lat + '&lon=' + App.loc.pos().lon + '&range=' + ( App.loc.range || App.defaultRange );
	App.restaurants.list = false;

	$.getJSON(url, function(json) {
		App.restaurants.list = [];

		// There is no restaurant near to the user. Go home and show the error.
		if (typeof json['restaurants'] == 'undefined' || json['restaurants'].length == 0) {
			error();

		} else {

			for (var x in json.restaurants) {
				var res = new Restaurant(json.restaurants[x]);
				res.open();
				App.restaurants.list[App.restaurants.list.length] = res;
			};
			success();
		}
	});
}

App.foodDelivery.localizedContent = function(){
	// set the slogan and tagline
	try {
		var slogan = App.slogan.slogan;
		var sloganReplace = App.loc.prep() + ' ' + App.loc.city();

		sloganReplace = $.trim(sloganReplace);
		var tagline = App.tagline.tagline.replace('%s', sloganReplace);
		slogan = slogan.replace('%s', sloganReplace);

	} catch (e) {
		console.log('Failed to load dynamic text', App.slogan, App.tagline);
		var slogan = '';
		var tagline = '';
	}

	// set title
	var title = App.loc.city() + ' Food Delivery | Order Food from ' + (App.loc.city() || 'Local') + ' Restaurants | Crunchbutton';
	document.title = title;

	return {
		slogan: slogan,
		tagline: tagline,
		title: title
	};
}
/**
 * food delivery page
 */
App.page.foodDelivery = function(refresh) {
	if (refresh) {
		App.restaurants.list = false;
	}

	//App.loc.reverseGeocode(App.loc.pos().lat, App.loc.pos().lon, success, error);

	console.log('FOOD DELIVERY')
	var success = function() {
		// if we have a success and
		var loc = '/' + App.restaurants.permalink;
		if (loc != location.pathname) {
			History.pushState({}, 'Crunchbutton', '/' + App.restaurants.permalink);
			return;
		}

		$( '.config-icon' ).removeClass( 'config-icon-mobile-hide' );
		$( '.nav-back' ).removeClass( 'nav-back-show' );

		if (App.restaurants.list.length == 4) {
			$('.content').addClass('short-meal-list');
		} else {
			$('.content').removeClass('short-meal-list');
		}
		$('.content').removeClass('smaller-width');

		App.currentPage = 'food-delivery';

		var titles = App.foodDelivery.localizedContent();

		// sort the list by open or not
		App.restaurants.list.sort(sort_by(
			{
				name: '_open',
				reverse: true
			},
			{
				name: '_weight',
				primer: parseInt,
				reverse: true
			}
		));

		App.showPage({
			page: 'restaurants',
			data: {
				slogan: titles.slogan,
				tagline: titles.tagline,
				restaurants: App.restaurants.list
			}
		});
	};

	// we dont have any restaurants
	var error = function() {
		App.loadHome();
	};

	if (App.restaurants.list === false) {
		// we have not checked for restaurants. do that now.
		App.foodDelivery.getRestaurants(success, error);

	} else if (App.restaurants.list === []) {
		// there are no restaurants for this area. go back home
		error();

	} else {
		// we already have a restaurant list. display the restaurant page
		success();
	}
}
/**
 * Gift card page
 */
App.page.giftCard = function(){
	App.giftcard.show();
}<commit_msg>partial #893 - debugging<commit_after>
App.page.home = function(force) {

	if (!force && !App.loc.loaded) {
		// if we arent forcing and theres no pos, then this was a home request. we need to wait a second
		console.log('QUE HOME PAGE')
		App.loc.bind('location-loaded', function() {
			App.page.home(force);
		});
		App.loc.bind('location-detected', function() {
			App.page.home(force);
		});

		return;
	}
	console.log('HOME PAGE')

	var homeSuccess = function() {
		$('.nav-back').removeClass('nav-back-show');
		$('.config-icon').addClass('config-icon-mobile-hide');
		$('.content').addClass('short-meal-list');

		App.showPage({
			page: 'home',
			title: 'Crunchbutton',
			data: {
				topCommunities: App.topCommunities,
				yourArea: App.loc.city() || 'your area',
				autofocus: $(window).width() >= 768 ? ' autofocus="autofocus"' : ''
			}
		});

		// @todo: put these in the css. @hacks
		if (navigator.userAgent.toLowerCase().indexOf('safari') > -1 && navigator.userAgent.toLowerCase().indexOf('mobile') == -1 && navigator.userAgent.toLowerCase().indexOf('chrome') == -1) {
			// safari desktop
			$('.location-detect').css({
				'margin-top': '2px',
				'height': '50px'
			});
		} else if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
			// firefox desktop
			$('.location-detect').css({
				'margin-top': '0px',
				'height': '52px'
			});
		}

		// @todo: why is this here??
		if (App.showReset){
			App.signin.passwordHelp.reset.init();
		}
	};

	if (!force && App.loc.address() && App.restaurants.list === false) {
		// we have an address, but no restaurants
console.log('LOCATION NO REST')
		App.page.foodDelivery();

		return;

	} else {
		homeSuccess();
	}

	if (!force && App.loc.address() && App.restaurants.list && App.restaurants.list.length == 0) {
		App.loc.log();

		$('.home-greeting, .enter-location, .button-letseat-form').hide();
		$('.error-location').show();
console.log('LOCATION ERROR')
		App.track('Location Error', {
			lat: App.loc.pos().lat,
			lon: App.loc.pos().lon,
			address: App.loc.address()
		});

	} else {
console.log('JUST HOME')
		$('.location-address').val('');
		$('.error-location').hide();
		$('.home-greeting, .enter-location, .button-letseat-form').show();

	}
};

App.page.restaurant = function(id) {

	$('.config-icon').addClass('config-icon-mobile-hide');
	$('.nav-back').addClass('nav-back-show');

	App.cartHighlightEnabled = false;

	$('.content').removeClass('smaller-width');
	$('.content').removeClass('short-meal-list');

	App.cache('Restaurant', id, function() {
		if (App.restaurant && App.restaurant.permalink != id) {
			App.cart.resetOrder();
		}

		App.restaurant = this;
		var community = App.getCommunityById(App.restaurant.id_community);

		var lastOrderDelivery = false;
		var lastPayCash = false;

		if( App.config && App.config.user && App.config.user.presets && App.config.user.presets[App.restaurant.id_restaurant] ){
			// Check if the last user's order at this restaurant was a delivery type
			lastOrderDelivery = App.config.user.presets[App.restaurant.id_restaurant].delivery_type;
			// Check if the last user's order at this restaurant was cash type
			lastPayCash = App.config.user.presets[App.restaurant.id_restaurant].pay_type;
		}
			console.log('lastOrderDelivery',lastOrderDelivery);
			console.log('lastPayCash',lastPayCash);

		App.showPage({
			tracking: {
				title: 'Restaurant page loaded',
				data: {
					restaurant: App.restaurant.name
				}
			},
			page: 'restaurant',
			title: App.restaurant.name + ' | Food Delivery | Order from ' + ( community.name  ? community.name  : 'Local') + ' Restaurants | Crunchbutton',
			data: {
				restaurant: App.restaurant,
				presets: App.config.user.presets,
				lastOrderDelivery: lastOrderDelivery,
				user: App.config.user,
				community: community,
				form: {
					tip: App.order.tip,
					name: App.config.user.name,
					phone: App.phone.format(App.config.user.phone),
					address: App.config.user.address || App.loc.address(),
					notes: (App.config.user && App.config.user.presets && App.config.user.presets[App.restaurant.id_restaurant]) ? App.config.user.presets[App.restaurant.id_restaurant].notes : '',
					card: {
						number: App.config.user.card,
						month: App.config.user.card_exp_month,
						year: App.config.user.card_exp_year
					}
				}
			}
		});

		if (App.config.user.presets) {
			$('.payment-form').hide();
		}

		if (App.cart.hasItems()) {
			App.cart.reloadOrder();
		} else if (App.config.user && App.config.user.presets && App.config.user.presets[App.restaurant.id_restaurant]) {
			try {
				App.cart.loadOrder(App.config.user.presets[App.restaurant.id_restaurant]);
			} catch (e) {
				App.cart.loadOrder(App.restaurant.preset());
			}
		} else {
			App.cart.loadOrder(App.restaurant.preset());
		}

		// As the div restaurant-items has position:absolute this line will make sure the footer will not go up.
		$('.body').css({
			'min-height': $('.restaurant-items').height()
		});

		setTimeout(function() {
			var total = App.cart.updateTotal();
		},200);

		App.cartHighlightEnabled = false;

		if ( App.order['pay_type'] == 'cash' || lastPayCash == 'cash' ) {
			App.trigger.cash();
		} else {
			App.trigger.credit();
		}

		if( lastPayCash == 'cash' ){
			App.trigger.cash();
		} else if ( lastPayCash == 'card' ){
			App.trigger.credit();
		}

		// Rules at #669
		if( ( lastOrderDelivery == 'delivery' && App.restaurant.delivery == '1' ) ||
				( App.order['delivery_type'] == 'delivery' && App.restaurant.delivery == '1' ) ||
				( !App.config.user.delivery_type && App.restaurant.delivery == '1' ) ){
				App.trigger.delivery();
		}

		if( App.order['delivery_type'] == 'takeout' || App.restaurant.delivery != '1') {
			App.trigger.takeout();
		}

		$( '.restaurant-gift' ).hide();

		App.credit.getCredit( function(){
			App.credit.show();
			App.cart.updateTotal();
		} );

		if (!App.config.user.id_user) {
			App.config.user.address = App.loc.enteredLoc;
			App.loc.enteredLoc = '';
		}

	});

};

/**
 * Order page. displayed after order, or at order history
 */
App.page.order = function(id) {

	$( '.config-icon' ).addClass( 'config-icon-mobile-hide' );
	$( '.nav-back' ).addClass( 'nav-back-show' );

	if (App.justCompleted) {
		App.justCompleted = false;
	}

	$('.content').addClass('smaller-width');
	$('.main-content').css('width','auto');

	// Just to make sure the user button will be shown
	App.signin.checkUser();

	App.cache('Order', id, function() {
		var order = this;

		if (!order.uuid) {
			History.replaceState({},'Crunchbutton','/orders');
			return;
		}

		App._order_uuid = id;

		App.facebook.preLoadOrderStatus();

		App.cache('Restaurant',order.id_restaurant, function() {
			var restaurant = this;

			App.showPage({
				title: 'Crunchbutton - Your Order',
				page: 'order',
				data: {
					order: order,
					restaurant: restaurant,
					user: App.config.user.has_auth
				}
			});

		});
	});
};

/**
 * Legal page. loaded from xhr.
 */
App.page.legal = function() {
	App.currentPage = 'legal';
	$.getJSON('/api/legal',function(json) {
		$('.main-content').html(json.data);
		App.refreshLayout();
	});
};

/**
 * Help page. loaded from xhr.
 */
App.page.help = function() {
	App.currentPage = 'help';
	$.getJSON('/api/help',function(json) {
		$('.main-content').html(json.data);
		App.refreshLayout();
	});
};

/**
 * Order page. only avaiable after a user has placed an order or signed up.
 * @todo: change to account page
 */
App.page.orders = function() {
	if (!App.config.user.id_user) {
		History.pushState({}, 'Crunchbutton', '/');
		return;
	}

	$( '.config-icon' ).addClass( 'config-icon-mobile-hide' );
	$( '.nav-back' ).addClass( 'nav-back-show' );

	$.getJSON('/api/user/orders',function(json) {
		App.showPage({
			title: 'Your Account',
			page: 'orders',
			data: {
				orders: json,
				user: App.user
			}
		});
	});

	App.refreshLayout();
};

/**
 * FoodDelivery's methods
 */
App.foodDelivery = {};

// before we change the url we need to make sure that there are restaurants at the typed place.
App.foodDelivery.getRestaurants = function(success, error) {
	if (!App.loc.pos()) {
		error();
		return;
	}

	var url = App.service + 'restaurants?lat=' + App.loc.pos().lat + '&lon=' + App.loc.pos().lon + '&range=' + ( App.loc.range || App.defaultRange );
	App.restaurants.list = false;

	$.getJSON(url, function(json) {
		App.restaurants.list = [];

		// There is no restaurant near to the user. Go home and show the error.
		if (typeof json['restaurants'] == 'undefined' || json['restaurants'].length == 0) {
			error();

		} else {

			for (var x in json.restaurants) {
				var res = new Restaurant(json.restaurants[x]);
				res.open();
				App.restaurants.list[App.restaurants.list.length] = res;
			};
			success();
		}
	});
}

App.foodDelivery.localizedContent = function(){
	// set the slogan and tagline
	try {
		var slogan = App.slogan.slogan;
		var sloganReplace = App.loc.prep() + ' ' + App.loc.city();

		sloganReplace = $.trim(sloganReplace);
		var tagline = App.tagline.tagline.replace('%s', sloganReplace);
		slogan = slogan.replace('%s', sloganReplace);

	} catch (e) {
		console.log('Failed to load dynamic text', App.slogan, App.tagline);
		var slogan = '';
		var tagline = '';
	}

	// set title
	var title = App.loc.city() + ' Food Delivery | Order Food from ' + (App.loc.city() || 'Local') + ' Restaurants | Crunchbutton';
	document.title = title;

	return {
		slogan: slogan,
		tagline: tagline,
		title: title
	};
}
/**
 * food delivery page
 */
App.page.foodDelivery = function(refresh) {
	if (refresh) {
		App.restaurants.list = false;
	}

	//App.loc.reverseGeocode(App.loc.pos().lat, App.loc.pos().lon, success, error);

	console.log('FOOD DELIVERY')
	var success = function() {
		// if we have a success and
		var loc = '/' + App.restaurants.permalink;
		if (loc != location.pathname) {
			History.pushState({}, 'Crunchbutton', '/' + App.restaurants.permalink);
			return;
		}

		$( '.config-icon' ).removeClass( 'config-icon-mobile-hide' );
		$( '.nav-back' ).removeClass( 'nav-back-show' );

		if (App.restaurants.list.length == 4) {
			$('.content').addClass('short-meal-list');
		} else {
			$('.content').removeClass('short-meal-list');
		}
		$('.content').removeClass('smaller-width');

		App.currentPage = 'food-delivery';

		var titles = App.foodDelivery.localizedContent();

		// sort the list by open or not
		App.restaurants.list.sort(sort_by(
			{
				name: '_open',
				reverse: true
			},
			{
				name: '_weight',
				primer: parseInt,
				reverse: true
			}
		));

		App.showPage({
			page: 'restaurants',
			data: {
				slogan: titles.slogan,
				tagline: titles.tagline,
				restaurants: App.restaurants.list
			}
		});
	};

	// we dont have any restaurants
	var error = function() {
		App.loadHome();
	};

	if (App.restaurants.list === false) {
		// we have not checked for restaurants. do that now.
		App.foodDelivery.getRestaurants(success, error);

	} else if (App.restaurants.list === []) {
		// there are no restaurants for this area. go back home
		error();

	} else {
		// we already have a restaurant list. display the restaurant page
		success();
	}
}
/**
 * Gift card page
 */
App.page.giftCard = function(){
	App.giftcard.show();
}<|endoftext|>


<commit_before>import React from 'react';
import {Route, IndexRoute} from 'react-router';
import App from './components/App';
import HomePage from './components/home/HomePage';
import OAuthReturner from './components/oauth/OAuthReturner';
import BranchPage from './components/repos/branches/BranchesPage';
import CommitsPage from './components/repos/branches/commits/CommitsPage';
import CombinedStatusPage from './components/repos/combinedStatus/CombinedStatusPage';

import CurrentStatusesPage from './components/repos/currentStatuses/CurrentStatusesPage';

export default (
    <Route path="/" component={App}>
        <IndexRoute component={HomePage}/>
        <Route path="oauthreturn" component={OAuthReturner}/>
        <Route path="repobranches/:id" component={BranchPage}/>
        <Route path="repobranches/:id/commits/:branchName" component={CommitsPage}/>
        <Route path="combinedStatus/repo/:repoId/branch/:branchName" component={CombinedStatusPage}/>

        <Route path="currentStatuses" component={CurrentStatusesPage}/>
    </Route>
);
<commit_msg>Reformat code in routes.js<commit_after>import React from 'react';
import {Route, IndexRoute} from 'react-router';
import App from './components/App';
import HomePage from './components/home/HomePage';
import OAuthReturner from './components/oauth/OAuthReturner';
import BranchPage from './components/repos/branches/BranchesPage';
import CommitsPage from './components/repos/branches/commits/CommitsPage';
import CombinedStatusPage from './components/repos/combinedStatus/CombinedStatusPage';

import CurrentStatusesPage from './components/repos/currentStatuses/CurrentStatusesPage';

export default (
  <Route path="/" component={App}>
    <IndexRoute component={HomePage}/>
    <Route path="oauthreturn" component={OAuthReturner}/>
    <Route path="repobranches/:id" component={BranchPage}/>
    <Route path="repobranches/:id/commits/:branchName" component={CommitsPage}/>
    <Route path="combinedStatus/repo/:repoId/branch/:branchName" component={CombinedStatusPage}/>

    <Route path="currentStatuses" component={CurrentStatusesPage}/>
  </Route>
);
<|endoftext|>


<commit_before>define(['underscore', 'zepto', 'backbone'], function(_, $, Backbone){

	var CardView = Backbone.View.extend({
		template : _.template($('#cardView').html()),

		events : {
			'click .content' : '_onContentClick',
			'click .header .back-button' : '_onBack',
			'click .header .menu-button' : '_onShowMenu',
			'click .header .title .selected' : '_onToggleSelected'
		},
		initialize : function(options){
			this.card = options.card;
		},
		render : function(){
			$(this.el).empty();
			$(this.el).append(this.template({
				card : this.card,
			}));
			var height = $(window).height();
			var headerHeight = this.$('.header').height();
			var contentHeight = height - headerHeight;
			var $content = this.$('.content');
			var $cardSide = this.$('.content .card-side');
			var linesHeight = $cardSide.height();
			$content.height(contentHeight);
			$cardSide.css({
				'padding-top' : ((contentHeight - linesHeight) / 2) + 'px'
			});

		},
		setCard : function(card){
			this.card = card;
		},
		_onBack : function(){
			this.trigger('back', {});
		},
		_onShowMenu : function(){
			this.trigger('show:menu', {});
		},

		_onContentClick : function(evt){
			var width = $(window).width();
			if(evt.offsetX > width * 0.9){
				return this.trigger('card:show-next');
			}
			if(evt.offsetX < width * 0.1){
				return this.trigger('card:show-prev');
			}
			return this.trigger('card:flip');
		},
		_onToggleSelected : function(){
			var $selected = this.$('.header .title .selected');
			$selected.toggleClass('fa-square-o');
			$selected.toggleClass('fa-check-square-o');
			this.trigger('card:toggle-select', $selected.hasClass('fa-check-square-o'));
		}
	});
	return CardView;
});<commit_msg>fixed click location calculation in FF<commit_after>define(['underscore', 'zepto', 'backbone'], function(_, $, Backbone){

	var CardView = Backbone.View.extend({
		template : _.template($('#cardView').html()),

		events : {
			'click .content' : '_onContentClick',
			'click .header .back-button' : '_onBack',
			'click .header .menu-button' : '_onShowMenu',
			'click .header .title .selected' : '_onToggleSelected'
		},
		initialize : function(options){
			this.card = options.card;
		},
		render : function(){
			$(this.el).empty();
			$(this.el).append(this.template({
				card : this.card,
			}));
			var height = $(window).height();
			var headerHeight = this.$('.header').height();
			var contentHeight = height - headerHeight;
			var $content = this.$('.content');
			var $cardSide = this.$('.content .card-side');
			var linesHeight = $cardSide.height();
			$content.height(contentHeight);
			$cardSide.css({
				'padding-top' : ((contentHeight - linesHeight) / 2) + 'px'
			});

		},
		setCard : function(card){
			this.card = card;
		},
		_onBack : function(){
			this.trigger('back', {});
		},
		_onShowMenu : function(){
			this.trigger('show:menu', {});
		},

		_onContentClick : function(evt){
			var width = $(window).width();
			if(evt.clientX > width * 0.9){
				return this.trigger('card:show-next');
			}
			if(evt.clientX < width * 0.1){
				return this.trigger('card:show-prev');
			}
			return this.trigger('card:flip');
		},
		_onToggleSelected : function(){
			var $selected = this.$('.header .title .selected');
			$selected.toggleClass('fa-square-o');
			$selected.toggleClass('fa-check-square-o');
			this.trigger('card:toggle-select', $selected.hasClass('fa-check-square-o'));
		}
	});
	return CardView;
});<|endoftext|>


<commit_before>/*

npm outdated [pkg]

Does the following:

1. check for a new version of pkg

If no packages are specified, then run for all installed
packages.

--parseable creates output like this:
<fullpath>:<name@wanted>:<name@installed>:<name@latest>

*/

module.exports = outdated

outdated.usage = "npm outdated [<pkg> [<pkg> ...]]"

outdated.completion = require("./utils/completion/installed-deep.js")

var path = require("path")
  , readJson = require("read-package-json")
  , cache = require("./cache.js")
  , asyncMap = require("slide").asyncMap
  , npm = require("./npm.js")
  , url = require("url")
  , color = require("ansicolors")
  , styles = require("ansistyles")
  , table = require("text-table")
  , semver = require("semver")
  , os = require("os")
  , mapToRegistry = require("./utils/map-to-registry.js")
  , npa = require("npm-package-arg")
  , readInstalled = require("read-installed")
  , long = npm.config.get("long")
  , log = require("npmlog")

function outdated (args, silent, cb) {
  if (typeof cb !== "function") cb = silent, silent = false
  var dir = path.resolve(npm.dir, "..")

  // default depth for `outdated` is 0 (cf. `ls`)
  if (npm.config.get("depth") === Infinity) npm.config.set("depth", 0)

  outdated_(args, dir, {}, 0, function (er, list) {
    if (!list) list = []
    if (er || silent || list.length === 0) return cb(er, list)
    list.sort(function(a, b) {
      var aa = a[1].toLowerCase()
        , bb = b[1].toLowerCase()
      return aa === bb ? 0
           : aa < bb ? -1 : 1
    })
    if (npm.config.get("json")) {
      console.log(makeJSON(list))
    } else if (npm.config.get("parseable")) {
      console.log(makeParseable(list))
    } else {
      var outList = list.map(makePretty)
      var outHead = [ "Package"
                    , "Current"
                    , "Wanted"
                    , "Latest"
                    , "Location"
                    ]
      if (long) outHead.push("Package Type")
      var outTable = [outHead].concat(outList)

      if (npm.color) {
        outTable[0] = outTable[0].map(function(heading) {
          return styles.underline(heading)
        })
      }

      var tableOpts = { align: ["l", "r", "r", "r", "l"]
                      , stringLength: function(s) { return ansiTrim(s).length }
                      }
      console.log(table(outTable, tableOpts))
    }
    cb(null, list)
  })
}

// [[ dir, dep, has, want, latest, type ]]
function makePretty (p) {
  var dep = p[1]
    , dir = path.resolve(p[0], "node_modules", dep)
    , has = p[2]
    , want = p[3]
    , latest = p[4]
    , type = p[6]

  if (!npm.config.get("global")) {
    dir = path.relative(process.cwd(), dir)
  }

  var columns = [ dep
                , has || "MISSING"
                , want
                , latest
                , dirToPrettyLocation(dir)
                ]
  if (long) columns[5] = type

  if (npm.color) {
    columns[0] = color[has === want ? "yellow" : "red"](columns[0]) // dep
    columns[2] = color.green(columns[2]) // want
    columns[3] = color.magenta(columns[3]) // latest
    columns[4] = color.brightBlack(columns[4]) // dir
    if (long) columns[5] = color.brightBlack(columns[5]) // type
  }

  return columns
}

function ansiTrim (str) {
  var r = new RegExp("\x1b(?:\\[(?:\\d+[ABCDEFGJKSTm]|\\d+;\\d+[Hfm]|" +
        "\\d+;\\d+;\\d+m|6n|s|u|\\?25[lh])|\\w)", "g")
  return str.replace(r, "")
}

function dirToPrettyLocation (dir) {
  return dir.replace(/^node_modules[/\\]/, "")
            .replace(/[[/\\]node_modules[/\\]/g, " > ")
}

function makeParseable (list) {
  return list.map(function (p) {

    var dep = p[1]
      , dir = path.resolve(p[0], "node_modules", dep)
      , has = p[2]
      , want = p[3]
      , latest = p[4]
      , type = p[6]

    var out = [ dir
           , dep + "@" + want
           , (has ? (dep + "@" + has) : "MISSING")
           , dep + "@" + latest
           ]
   if (long) out.push(type)

   return out.join(":")
  }).join(os.EOL)
}

function makeJSON (list) {
  var out = {}
  list.forEach(function (p) {
    var dir = path.resolve(p[0], "node_modules", p[1])
    if (!npm.config.get("global")) {
      dir = path.relative(process.cwd(), dir)
    }
    out[p[1]] = { current: p[2]
                , wanted: p[3]
                , latest: p[4]
                , location: dir
                }
    if (long) out[p[1]].type = p[6]
  })
  return JSON.stringify(out, null, 2)
}

function outdated_ (args, dir, parentHas, depth, cb) {
  // get the deps from package.json, or {<dir/node_modules/*>:"*"}
  // asyncMap over deps:
  //   shouldHave = cache.add(dep, req).version
  //   if has === shouldHave then
  //     return outdated(args, dir/node_modules/dep, parentHas + has)
  //   else if dep in args or args is empty
  //     return [dir, dep, has, shouldHave]

  if (depth > npm.config.get("depth")) {
    return cb(null, [])
  }
  var deps = null
  var types = {}
  readJson(path.resolve(dir, "package.json"), function (er, d) {
    d = d || {}
    if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
    deps = (er) ? true : (d.dependencies || {})
    if (!er) {
      Object.keys(deps).forEach(function (k) {
        types[k] = "dependencies"
      })
    }

    if (npm.config.get("save-dev")) {
      deps = d.devDependencies || {}
      Object.keys(deps).forEach(function (k) {
        types[k] = "devDependencies"
      })

      return next()
    }

    if (npm.config.get("save")) {
      // remove optional dependencies from dependencies during --save.
      Object.keys(d.optionalDependencies || {}).forEach(function (k) {
        delete deps[k]
      })
      return next()
    }

    if (npm.config.get("save-optional")) {
      deps = d.optionalDependencies || {}
      Object.keys(deps).forEach(function (k) {
        types[k] = "optionalDependencies"
      })
      return next()
    }

    var doUpdate = npm.config.get("dev") ||
                    (!npm.config.get("production") &&
                    !Object.keys(parentHas).length &&
                    !npm.config.get("global"))

    if (!er && d && doUpdate) {
      Object.keys(d.devDependencies || {}).forEach(function (k) {
        if (!(k in parentHas)) {
          deps[k] = d.devDependencies[k]
          types[k] = "devDependencies"
        }
      })
    }
    return next()
  })

  var has = null
  readInstalled(path.resolve(dir), { dev : true }, function (er, data) {
    if (er) {
      has = Object.create(parentHas)
      return next()
    }
    var pkgs = Object.keys(data.dependencies)
    pkgs = pkgs.filter(function (p) {
      return !p.match(/^[\._-]/)
    })
    asyncMap(pkgs, function (pkg, cb) {
      var jsonFile = path.resolve(dir, "node_modules", pkg, "package.json")
      readJson(jsonFile, function (er, d) {
        if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
        if (d && d.name && d.private) delete deps[d.name]
        cb(null, er ? [] : [[d.name, d.version, d._from]])
      })
    }, function (er, pvs) {
      if (er) return cb(er)
      has = Object.create(parentHas)
      pvs.forEach(function (pv) {
        has[pv[0]] = {
          version: pv[1],
          from: pv[2]
        }
      })

      next()
    })
  })

  function next () {
    if (!has || !deps) return
    if (deps === true) {
      deps = Object.keys(has).reduce(function (l, r) {
        l[r] = "latest"
        return l
      }, {})
    }

    // now get what we should have, based on the dep.
    // if has[dep] !== shouldHave[dep], then cb with the data
    // otherwise dive into the folder
    asyncMap(Object.keys(deps), function (dep, cb) {
      if (!long) return shouldUpdate(args, dir, dep, has, deps[dep], depth, cb)

      shouldUpdate(args, dir, dep, has, deps[dep], depth, cb, types[dep])
    }, cb)
  }
}

function shouldUpdate (args, dir, dep, has, req, depth, cb, type) {
  // look up the most recent version.
  // if that's what we already have, or if it's not on the args list,
  // then dive into it.  Otherwise, cb() with the data.

  // { version: , from: }
  var curr = has[dep]

  function skip (er) {
    // show user that no viable version can be found
    if (er) return cb(er)
    outdated_( args
             , path.resolve(dir, "node_modules", dep)
             , has
             , depth + 1
             , cb )
  }

  function doIt (wanted, latest) {
    if (!long) {
      return cb(null, [[ dir, dep, curr && curr.version, wanted, latest, req]])
    }
    cb(null, [[ dir, dep, curr && curr.version, wanted, latest, req, type]])
  }

  if (args.length && args.indexOf(dep) === -1) return skip()
  var parsed = npa(dep + '@' + req)
  if (parsed.type === "git" || (parsed.hosted && parsed.hosted.type === "github")) {
    return doIt("git", "git")
  }

  // search for the latest package
  mapToRegistry(dep, npm.config, function (er, uri, auth) {
    if (er) return cb(er)

    npm.registry.get(uri, { auth : auth }, updateDeps)
  })

  function updateLocalDeps (latestRegistryVersion) {
    readJson(path.resolve(parsed.spec, 'package.json'), function (er, localDependency) {
      if (er) return cb()

      var wanted = localDependency.version
      var latest = localDependency.version

      if (latestRegistryVersion) {
        latest = latestRegistryVersion
        if (semver.lt(wanted, latestRegistryVersion)) {
          wanted = latestRegistryVersion
          req = dep + '@' + latest
        }
      }

      if (curr.version !== wanted) {
        doIt(wanted, latest)
      } else {
        skip()
      }
    })
  }

  function updateDeps (er, d) {
    if (er) {
      if (parsed.type !== 'local') return cb(er)
      return updateLocalDeps()
    }

    if (!d || !d["dist-tags"] || !d.versions) return cb()
    var l = d.versions[d["dist-tags"].latest]
    if (!l) return cb()

    var r = req
    if (d["dist-tags"][req])
      r = d["dist-tags"][req]

    if (semver.validRange(r, true)) {
      // some kind of semver range.
      // see if it's in the doc.
      var vers = Object.keys(d.versions)
      var v = semver.maxSatisfying(vers, r, true)
      if (v) {
        return onCacheAdd(null, d.versions[v])
      }
    }

    // We didn't find the version in the doc.  See if cache can find it.
    cache.add(dep, req, null, false, onCacheAdd)

    function onCacheAdd(er, d) {
      // if this fails, then it means we can't update this thing.
      // it's probably a thing that isn't published.
      if (er) {
        if (er.code && er.code === "ETARGET") {
          // no viable version found
          return skip(er)
        }
        return skip()
      }

      // check that the url origin hasn't changed (#1727) and that
      // there is no newer version available
      var dFromUrl = d._from && url.parse(d._from).protocol
      var cFromUrl = curr && curr.from && url.parse(curr.from).protocol

      if (!curr || dFromUrl && cFromUrl && d._from !== curr.from
          || d.version !== curr.version
          || d.version !== l.version) {
        if (parsed.type === 'local') return updateLocalDeps(l.version)

        doIt(d.version, l.version)
      }
      else {
        skip()
      }
    }
  }
}
<commit_msg>Support new hosted type returned by npm-package-arg<commit_after>/*

npm outdated [pkg]

Does the following:

1. check for a new version of pkg

If no packages are specified, then run for all installed
packages.

--parseable creates output like this:
<fullpath>:<name@wanted>:<name@installed>:<name@latest>

*/

module.exports = outdated

outdated.usage = "npm outdated [<pkg> [<pkg> ...]]"

outdated.completion = require("./utils/completion/installed-deep.js")

var path = require("path")
  , readJson = require("read-package-json")
  , cache = require("./cache.js")
  , asyncMap = require("slide").asyncMap
  , npm = require("./npm.js")
  , url = require("url")
  , color = require("ansicolors")
  , styles = require("ansistyles")
  , table = require("text-table")
  , semver = require("semver")
  , os = require("os")
  , mapToRegistry = require("./utils/map-to-registry.js")
  , npa = require("npm-package-arg")
  , readInstalled = require("read-installed")
  , long = npm.config.get("long")
  , log = require("npmlog")

function outdated (args, silent, cb) {
  if (typeof cb !== "function") cb = silent, silent = false
  var dir = path.resolve(npm.dir, "..")

  // default depth for `outdated` is 0 (cf. `ls`)
  if (npm.config.get("depth") === Infinity) npm.config.set("depth", 0)

  outdated_(args, dir, {}, 0, function (er, list) {
    if (!list) list = []
    if (er || silent || list.length === 0) return cb(er, list)
    list.sort(function(a, b) {
      var aa = a[1].toLowerCase()
        , bb = b[1].toLowerCase()
      return aa === bb ? 0
           : aa < bb ? -1 : 1
    })
    if (npm.config.get("json")) {
      console.log(makeJSON(list))
    } else if (npm.config.get("parseable")) {
      console.log(makeParseable(list))
    } else {
      var outList = list.map(makePretty)
      var outHead = [ "Package"
                    , "Current"
                    , "Wanted"
                    , "Latest"
                    , "Location"
                    ]
      if (long) outHead.push("Package Type")
      var outTable = [outHead].concat(outList)

      if (npm.color) {
        outTable[0] = outTable[0].map(function(heading) {
          return styles.underline(heading)
        })
      }

      var tableOpts = { align: ["l", "r", "r", "r", "l"]
                      , stringLength: function(s) { return ansiTrim(s).length }
                      }
      console.log(table(outTable, tableOpts))
    }
    cb(null, list)
  })
}

// [[ dir, dep, has, want, latest, type ]]
function makePretty (p) {
  var dep = p[1]
    , dir = path.resolve(p[0], "node_modules", dep)
    , has = p[2]
    , want = p[3]
    , latest = p[4]
    , type = p[6]

  if (!npm.config.get("global")) {
    dir = path.relative(process.cwd(), dir)
  }

  var columns = [ dep
                , has || "MISSING"
                , want
                , latest
                , dirToPrettyLocation(dir)
                ]
  if (long) columns[5] = type

  if (npm.color) {
    columns[0] = color[has === want ? "yellow" : "red"](columns[0]) // dep
    columns[2] = color.green(columns[2]) // want
    columns[3] = color.magenta(columns[3]) // latest
    columns[4] = color.brightBlack(columns[4]) // dir
    if (long) columns[5] = color.brightBlack(columns[5]) // type
  }

  return columns
}

function ansiTrim (str) {
  var r = new RegExp("\x1b(?:\\[(?:\\d+[ABCDEFGJKSTm]|\\d+;\\d+[Hfm]|" +
        "\\d+;\\d+;\\d+m|6n|s|u|\\?25[lh])|\\w)", "g")
  return str.replace(r, "")
}

function dirToPrettyLocation (dir) {
  return dir.replace(/^node_modules[/\\]/, "")
            .replace(/[[/\\]node_modules[/\\]/g, " > ")
}

function makeParseable (list) {
  return list.map(function (p) {

    var dep = p[1]
      , dir = path.resolve(p[0], "node_modules", dep)
      , has = p[2]
      , want = p[3]
      , latest = p[4]
      , type = p[6]

    var out = [ dir
           , dep + "@" + want
           , (has ? (dep + "@" + has) : "MISSING")
           , dep + "@" + latest
           ]
   if (long) out.push(type)

   return out.join(":")
  }).join(os.EOL)
}

function makeJSON (list) {
  var out = {}
  list.forEach(function (p) {
    var dir = path.resolve(p[0], "node_modules", p[1])
    if (!npm.config.get("global")) {
      dir = path.relative(process.cwd(), dir)
    }
    out[p[1]] = { current: p[2]
                , wanted: p[3]
                , latest: p[4]
                , location: dir
                }
    if (long) out[p[1]].type = p[6]
  })
  return JSON.stringify(out, null, 2)
}

function outdated_ (args, dir, parentHas, depth, cb) {
  // get the deps from package.json, or {<dir/node_modules/*>:"*"}
  // asyncMap over deps:
  //   shouldHave = cache.add(dep, req).version
  //   if has === shouldHave then
  //     return outdated(args, dir/node_modules/dep, parentHas + has)
  //   else if dep in args or args is empty
  //     return [dir, dep, has, shouldHave]

  if (depth > npm.config.get("depth")) {
    return cb(null, [])
  }
  var deps = null
  var types = {}
  readJson(path.resolve(dir, "package.json"), function (er, d) {
    d = d || {}
    if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
    deps = (er) ? true : (d.dependencies || {})
    if (!er) {
      Object.keys(deps).forEach(function (k) {
        types[k] = "dependencies"
      })
    }

    if (npm.config.get("save-dev")) {
      deps = d.devDependencies || {}
      Object.keys(deps).forEach(function (k) {
        types[k] = "devDependencies"
      })

      return next()
    }

    if (npm.config.get("save")) {
      // remove optional dependencies from dependencies during --save.
      Object.keys(d.optionalDependencies || {}).forEach(function (k) {
        delete deps[k]
      })
      return next()
    }

    if (npm.config.get("save-optional")) {
      deps = d.optionalDependencies || {}
      Object.keys(deps).forEach(function (k) {
        types[k] = "optionalDependencies"
      })
      return next()
    }

    var doUpdate = npm.config.get("dev") ||
                    (!npm.config.get("production") &&
                    !Object.keys(parentHas).length &&
                    !npm.config.get("global"))

    if (!er && d && doUpdate) {
      Object.keys(d.devDependencies || {}).forEach(function (k) {
        if (!(k in parentHas)) {
          deps[k] = d.devDependencies[k]
          types[k] = "devDependencies"
        }
      })
    }
    return next()
  })

  var has = null
  readInstalled(path.resolve(dir), { dev : true }, function (er, data) {
    if (er) {
      has = Object.create(parentHas)
      return next()
    }
    var pkgs = Object.keys(data.dependencies)
    pkgs = pkgs.filter(function (p) {
      return !p.match(/^[\._-]/)
    })
    asyncMap(pkgs, function (pkg, cb) {
      var jsonFile = path.resolve(dir, "node_modules", pkg, "package.json")
      readJson(jsonFile, function (er, d) {
        if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
        if (d && d.name && d.private) delete deps[d.name]
        cb(null, er ? [] : [[d.name, d.version, d._from]])
      })
    }, function (er, pvs) {
      if (er) return cb(er)
      has = Object.create(parentHas)
      pvs.forEach(function (pv) {
        has[pv[0]] = {
          version: pv[1],
          from: pv[2]
        }
      })

      next()
    })
  })

  function next () {
    if (!has || !deps) return
    if (deps === true) {
      deps = Object.keys(has).reduce(function (l, r) {
        l[r] = "latest"
        return l
      }, {})
    }

    // now get what we should have, based on the dep.
    // if has[dep] !== shouldHave[dep], then cb with the data
    // otherwise dive into the folder
    asyncMap(Object.keys(deps), function (dep, cb) {
      if (!long) return shouldUpdate(args, dir, dep, has, deps[dep], depth, cb)

      shouldUpdate(args, dir, dep, has, deps[dep], depth, cb, types[dep])
    }, cb)
  }
}

function shouldUpdate (args, dir, dep, has, req, depth, cb, type) {
  // look up the most recent version.
  // if that's what we already have, or if it's not on the args list,
  // then dive into it.  Otherwise, cb() with the data.

  // { version: , from: }
  var curr = has[dep]

  function skip (er) {
    // show user that no viable version can be found
    if (er) return cb(er)
    outdated_( args
             , path.resolve(dir, "node_modules", dep)
             , has
             , depth + 1
             , cb )
  }

  function doIt (wanted, latest) {
    if (!long) {
      return cb(null, [[ dir, dep, curr && curr.version, wanted, latest, req]])
    }
    cb(null, [[ dir, dep, curr && curr.version, wanted, latest, req, type]])
  }

  if (args.length && args.indexOf(dep) === -1) return skip()
  var parsed = npa(dep + '@' + req)
  if (parsed.type === "git" || parsed.type == "hosted") {
    return doIt("git", "git")
  }

  // search for the latest package
  mapToRegistry(dep, npm.config, function (er, uri, auth) {
    if (er) return cb(er)

    npm.registry.get(uri, { auth : auth }, updateDeps)
  })

  function updateLocalDeps (latestRegistryVersion) {
    readJson(path.resolve(parsed.spec, 'package.json'), function (er, localDependency) {
      if (er) return cb()

      var wanted = localDependency.version
      var latest = localDependency.version

      if (latestRegistryVersion) {
        latest = latestRegistryVersion
        if (semver.lt(wanted, latestRegistryVersion)) {
          wanted = latestRegistryVersion
          req = dep + '@' + latest
        }
      }

      if (curr.version !== wanted) {
        doIt(wanted, latest)
      } else {
        skip()
      }
    })
  }

  function updateDeps (er, d) {
    if (er) {
      if (parsed.type !== 'local') return cb(er)
      return updateLocalDeps()
    }

    if (!d || !d["dist-tags"] || !d.versions) return cb()
    var l = d.versions[d["dist-tags"].latest]
    if (!l) return cb()

    var r = req
    if (d["dist-tags"][req])
      r = d["dist-tags"][req]

    if (semver.validRange(r, true)) {
      // some kind of semver range.
      // see if it's in the doc.
      var vers = Object.keys(d.versions)
      var v = semver.maxSatisfying(vers, r, true)
      if (v) {
        return onCacheAdd(null, d.versions[v])
      }
    }

    // We didn't find the version in the doc.  See if cache can find it.
    cache.add(dep, req, null, false, onCacheAdd)

    function onCacheAdd(er, d) {
      // if this fails, then it means we can't update this thing.
      // it's probably a thing that isn't published.
      if (er) {
        if (er.code && er.code === "ETARGET") {
          // no viable version found
          return skip(er)
        }
        return skip()
      }

      // check that the url origin hasn't changed (#1727) and that
      // there is no newer version available
      var dFromUrl = d._from && url.parse(d._from).protocol
      var cFromUrl = curr && curr.from && url.parse(curr.from).protocol

      if (!curr || dFromUrl && cFromUrl && d._from !== curr.from
          || d.version !== curr.version
          || d.version !== l.version) {
        if (parsed.type === 'local') return updateLocalDeps(l.version)

        doIt(d.version, l.version)
      }
      else {
        skip()
      }
    }
  }
}
<|endoftext|>


<commit_before>'use strict';
angular.module('Trendicity')

/**
 * MapService is a simple wrapping service around
 * all Google Maps logic in order to make the choice
 * for Google Maps interchangable for any other map
 * solution.
 */
.service('MapService', function($log, GeolocationService, uiGmapMapScriptLoader) {
    var that = this,
        defaultPosition = GeolocationService.getDefaultPosition();

    /**
     * Markers container
     * @type {Array}
     */
    this.markers = [];

    this.getDefaultOptions = function () {
        return {
            zoom: 4,
            center: defaultPosition
        };
    };

    this.addMarker = function (marker) {
        // Add show / hide logic for each marker individually
        if (!marker.showPopup) {
            marker.show = false;
            marker.showPopup = function () {
                marker.show = !marker.show;
            };
        }
        this.markers.push(marker);
    };

    this.removeMarker = function (marker) {
        var i,
            markerLength = this.markers.length;

        for (i = 0; i < markerLength; i++) {
            if (this.markers[i].id === marker.id) {
                delete this.markers[i];
            }
        }
    };

    this.getCurrentPositionMarker = function () {
        var i,
            markerLength = this.markers.length,
            objReturn = null;

        for (i = 0; i < markerLength; i++) {
            if (this.markers[i] && this.markers[i].id === 'currentPosition') {
                objReturn = this.markers[i];
            }
        }

        return objReturn;
    };

    this.clearMarkers = function (blnRemoveCurrentPosition) {
        if (!!blnRemoveCurrentPosition) {
            // Clear all markers, including current position
            this.markers = [];
            return;
        }

        // Store the current position marker
        var currentPositionMarker = this.getCurrentPositionMarker();
        // Clear marker storage
        this.markers = [];
        // Re-add current position marker
        this.markers.push(currentPositionMarker);

    };

    this.getMarkers = function () {
        return this.markers;
    };

    this.addMarkersFromPosts = function (posts) {
        // Clear markers before potentially adding new ones
        this.clearMarkers();

        if (!posts || posts.length == 0) return;

        var i, post, marker;

        for (i = 0; i < posts.length; i++) {
            post = posts[i];

            marker = {
                coords: post.location,
                id: post.id,
                postData: post
            };

            $log.debug('Adding marker', marker);

            this.addMarker(marker);
        }

        this.updateMarkerBounds();
    };

    this.getMarkerBounds = function () {
        return this.markerBounds;
    };

    this.updateMarkerBounds = function () {
        // Check if the global google object is available to do some native Google Maps API coding.
        uiGmapMapScriptLoader.load().then(calculateMarkerBounds);

        function calculateMarkerBounds(googleMaps) {
            var bounds = new googleMaps.LatLngBounds(),
                markersLength = that.markers.length,
                i, marker;

            for (i = 0; i <= markersLength; i++) {
                marker = that.markers[i];

                if (marker && marker.coords && marker.coords.latitude && marker.coords.longitude) {
                    bounds.extend(
                        new googleMaps.LatLng(
                            marker.coords.latitude,
                            marker.coords.longitude
                        )
                    );
                }
            }

            $log.debug('Figured out correct map bounds', bounds);
        }
    };

    return this;
});
<commit_msg>Use uiGmapGoogleMapApi service instead of uiGmapMapScriptLoader<commit_after>'use strict';
angular.module('Trendicity')

/**
 * MapService is a simple wrapping service around
 * all Google Maps logic in order to make the choice
 * for Google Maps interchangable for any other map
 * solution.
 */
.service('MapService', function($log, GeolocationService, uiGmapGoogleMapApi) {
    var that = this,
        defaultPosition = GeolocationService.getDefaultPosition();

    /**
     * Markers container
     * @type {Array}
     */
    this.markers = [];

    this.getDefaultOptions = function () {
        return {
            zoom: 4,
            center: defaultPosition
        };
    };

    this.addMarker = function (marker) {
        // Add show / hide logic for each marker individually
        if (!marker.showPopup) {
            marker.show = false;
            marker.showPopup = function () {
                marker.show = !marker.show;
            };
        }
        this.markers.push(marker);
    };

    this.removeMarker = function (marker) {
        var i,
            markerLength = this.markers.length;

        for (i = 0; i < markerLength; i++) {
            if (this.markers[i].id === marker.id) {
                delete this.markers[i];
            }
        }
    };

    this.getCurrentPositionMarker = function () {
        var i,
            markerLength = this.markers.length,
            objReturn = null;

        for (i = 0; i < markerLength; i++) {
            if (this.markers[i] && this.markers[i].id === 'currentPosition') {
                objReturn = this.markers[i];
            }
        }

        return objReturn;
    };

    this.clearMarkers = function (blnRemoveCurrentPosition) {
        if (!!blnRemoveCurrentPosition) {
            // Clear all markers, including current position
            this.markers = [];
            return;
        }

        // Store the current position marker
        var currentPositionMarker = this.getCurrentPositionMarker();
        // Clear marker storage
        this.markers = [];
        // Re-add current position marker
        this.markers.push(currentPositionMarker);

    };

    this.getMarkers = function () {
        return this.markers;
    };

    this.addMarkersFromPosts = function (posts) {
        // Clear markers before potentially adding new ones
        this.clearMarkers();

        if (!posts || posts.length == 0) return;

        var i, post, marker;

        for (i = 0; i < posts.length; i++) {
            post = posts[i];

            marker = {
                coords: post.location,
                id: post.id,
                postData: post
            };

            $log.debug('Adding marker', marker);

            this.addMarker(marker);
        }

        this.updateMarkerBounds();
    };

    this.getMarkerBounds = function () {
        return this.markerBounds;
    };

    this.updateMarkerBounds = function () {
        // Check if the global google object is available to do some native Google Maps API coding.
        uiGmapGoogleMapApi.then(function (googleMaps) {
            var bounds = new googleMaps.LatLngBounds(),
                markersLength = that.markers.length,
                i, marker;

            for (i = 0; i <= markersLength; i++) {
                marker = that.markers[i];

                if (marker && marker.coords && marker.coords.latitude && marker.coords.longitude) {
                    bounds.extend(
                        new googleMaps.LatLng(
                            marker.coords.latitude,
                            marker.coords.longitude
                        )
                    );
                }
            }

            $log.debug('Figured out correct map bounds', bounds);
        });
    };

    return this;
});
<|endoftext|>


<commit_before>var validate = require('./validate');
var Runner = require('screener-runner');
var cloneDeep = require('lodash/cloneDeep');
var omit = require('lodash/omit');
var url = require('url');

// transform storybook object into screener states
var transformToStates = function(storybook, baseUrl) {
  // clean baseUrl. remove query/hash/trailing-slash
  var urlObj = url.parse(baseUrl);
  urlObj = omit(urlObj, 'hash', 'search', 'query');
  urlObj.pathname = urlObj.pathname.replace(/\/$/, '');
  baseUrl = url.format(urlObj);
  // transform into states
  var states = [];
  storybook.forEach(function(component) {
    component.stories.forEach(function(story) {
      var iframeUrl = baseUrl + '/iframe.html?dataId=0&selectedKind=' + encodeURIComponent(component.kind) + '&selectedStory=' + encodeURIComponent(story.name);
      var state = {
        url: iframeUrl,
        name: component.kind + ': ' + story.name
      };
      if (story.steps) {
        state.steps = story.steps;
      }
      states.push(state);
    });
  });
  return states;
};

exports.run = function(config, options) {
  // create copy of config
  config = cloneDeep(config);
  return validate.storybookConfig(config)
    .then(function() {
      var host = 'localhost:' + config.storybookPort;
      var localUrl = 'http://' + host;
      // add tunnel details
      config.tunnel = {
        host: host,
        gzip: true,
        cache: true
      };
      // generate config format expected by screener-runner
      config.states = transformToStates(config.storybook, localUrl);
      // remove storybook-specific fields
      config = omit(config, ['storybook', 'storybookConfigDir', 'storybookStaticDir', 'storybookPort', 'nodeModulesPath']);
      if (options && options.debug) {
        console.log('DEBUG: config', JSON.stringify(config, null, 2));
      }
      // send storybook states to screener-runner
      return Runner.run(config);
    });
};
<commit_msg>omit new storybook options<commit_after>var validate = require('./validate');
var Runner = require('screener-runner');
var cloneDeep = require('lodash/cloneDeep');
var omit = require('lodash/omit');
var url = require('url');

// transform storybook object into screener states
var transformToStates = function(storybook, baseUrl) {
  // clean baseUrl. remove query/hash/trailing-slash
  var urlObj = url.parse(baseUrl);
  urlObj = omit(urlObj, 'hash', 'search', 'query');
  urlObj.pathname = urlObj.pathname.replace(/\/$/, '');
  baseUrl = url.format(urlObj);
  // transform into states
  var states = [];
  storybook.forEach(function(component) {
    component.stories.forEach(function(story) {
      var iframeUrl = baseUrl + '/iframe.html?dataId=0&selectedKind=' + encodeURIComponent(component.kind) + '&selectedStory=' + encodeURIComponent(story.name);
      var state = {
        url: iframeUrl,
        name: component.kind + ': ' + story.name
      };
      if (story.steps) {
        state.steps = story.steps;
      }
      states.push(state);
    });
  });
  return states;
};

exports.run = function(config, options) {
  // create copy of config
  config = cloneDeep(config);
  return validate.storybookConfig(config)
    .then(function() {
      var host = 'localhost:' + config.storybookPort;
      var localUrl = 'http://' + host;
      // add tunnel details
      config.tunnel = {
        host: host,
        gzip: true,
        cache: true
      };
      // generate config format expected by screener-runner
      config.states = transformToStates(config.storybook, localUrl);
      // remove storybook-specific fields
      config = omit(config, ['storybook', 'storybookConfigDir', 'storybookStaticDir', 'storybookPort', 'storybookVersion', 'storybookBinPath']);
      if (options && options.debug) {
        console.log('DEBUG: config', JSON.stringify(config, null, 2));
      }
      // send storybook states to screener-runner
      return Runner.run(config);
    });
};
<|endoftext|>


<commit_before>// This sample is meant to illustrate how to create business services,
// custom commands, and rules, and to showcase how they interact with
// each other.  In a real world application, you would most likely keep
// each business service, command, and rule in its own file, or at least
// similar actors in the same files.

"use strict";

var Rule = require('./peasy').Rule;
var BusinessService = require('./peasy').BusinessService;
var Command = require('./peasy').Command;

// CREATE RULES

var AgeRule = Rule.extend({
  association: "age",
  params: ['birthdate'],
  functions: {
    _onValidate: function(done) {
      if (new Date().getFullYear() - this.birthdate.getFullYear() < 50) {
        this._invalidate("You are too young");
      }
      var time = Math.floor((Math.random() * 3000) + 1);
      setTimeout(() => done(), time); // simulate latency
    }
  }
});

var NameRule = Rule.extend({
  association: "name",
  params: ['name'],
  functions: {
    _onValidate: function(done) {
      if (this.name === "Jimi") {
        this._invalidate("Name cannot be Jimi");
      }
      var time = Math.floor((Math.random() * 3000) + 1);
      setTimeout(() => done(), time); // simulate latency
    }
  }
});

var FieldRequiredRule = Rule.extend({
  params: ['field', 'data'],
  functions: {
    _onValidate: function(done) {
      if (!this.data[this.field]) {
        this.association = this.field;
        this._invalidate(this.field + " is required");
      }
      var time = Math.floor((Math.random() * 3000) + 1);
      setTimeout(() => done(), time); // simulate latency
    }
  }
});

var CustomerAuthorizationRule = Rule.extend({
  params: ['roles'],
  functions: {
    _onValidate: function(done) {
      var validRoles = ['super admin', 'admin'];
      this.roles.forEach(function(role) {
        if (validRoles.indexOf(role) > 0) {
          return done();
        }
      });
      this._invalidate("You do not have sufficient priviledges to access national security information");
      done();
    }
  }
});

// CREATE SERVICES, CUSTOM COMMANDS, AND WIRE UP VALIDATION AND BUSINESS RULES

// ROLES SERVICE
var RolesService = BusinessService.extend({
  params: ['userId', 'dataProxy'],
  functions: {
    _getAll: function(context, done) {
      this.dataProxy.getById(this.userId, function(err, roles) {
        done(null, roles);
      });
    }
  }
}).service;

// CUSTOMER SERVICE
var CustomerService = BusinessService
  .extend({
    params: ['dataProxy', 'rolesService'],
    functions: {
      _getRulesForInsert: getRulesForInsert
    }
  })
  .createCommand({
    name: 'getNationalSecurityCommand',
    params: ['id'],
    functions:
    {
      getRules: function(context, done) {
        var getRolesForCurrentUserCommand = this.rolesService.getAllCommand();
        getRolesForCurrentUserCommand.execute(function(err, result) {
          if (err) return done(err);
          if (!result.success) return done(null, result.errors);
          var roles = result.value;
          done(null, new CustomerAuthorizationRule(roles));
        });
      },
      onValidationSuccess: function(context, done) {
        this.dataProxy.getNationalSecurityData(this.id, function(err, data) {
          done(null, data);
        });
      }
    }
  })
  .service;

function getRulesForInsert(customer, context, done) {

  //done([
      //new AgeRule(customer.age),
      //new NameRule(customer.name),
      //new FieldRequiredRule("address", customer)
  //]);

  done(null, new AgeRule(customer.age)
             .ifValidThenExecute(() => console.log("Age succeeded"))
             .ifInvalidThenExecute(() => console.log("Age failed"))
             .ifValidThenValidate(new NameRule(customer.name)
                                        .ifValidThenExecute(() => console.log("Name succeeded"))
                                        .ifInvalidThenExecute(() => console.log("Name failed"))
                                        .ifValidThenValidate(new FieldRequiredRule("address", customer)
                                                                   .ifValidThenExecute(() => console.log("Address succeeded"))
                                                                   .ifInvalidThenExecute(() => console.log("Address failed"))
                                                             )));
}

// CREATE IN-MEMORY DATA PROXIES (these could be a duck typed angular resources, react stores, mongo db implementations, http proxies, etc.)

var customerDataProxy = (function() {
  var state = [
    { id: 1, name: "James Hendrix" },
    { id: 2, name: "James Page" },
    { id: 3, name: "David Gilmour" },
  ];

  return {
    insert: insert,
    getAll: getAll,
    getNationalSecurityData: getNationalSecurityData
  };

  function insert(data, done) {
    var nextId = state.length + 1;
    data.id = nextId;
    state.push(Object.assign({}, data));
    done(null, data);
  }

  function getAll(done) {
    var data = state.map(function(customer) {
      return Object.assign({}, customer);
    });
    done(null, data);
  }

  function getNationalSecurityData(id, done) {
    done(null, { id: id, nsd: "12345678"});
  }
})();

var rolesDataProxy = {
  getById: function(id, done) {
    // add/remove roles to manipulate execution of getNationalSecurityCommand
    done(null, ['admin', 'user']);
  }
}

// CREATE INSTANCE OF A CUSTOMER SERVICE WITH THE REQUIRED DATA PROXY

var currentUserId = 12345; // this id would likely come from some authentication service
var rolesService = new RolesService(currentUserId, rolesDataProxy);
var customerService = new CustomerService(customerDataProxy, rolesService);

// EXECUTE CUSTOM COMMAND
var customerId = 123;
customerService.getNationalSecurityCommand(customerId).execute(function(err, result) {
  console.log("getNationalSecurityCommand execution complete!", result)
});

// CREATE AN ARRAY OF INSERT COMMANDS
var commands = [
  customerService.insertCommand({name: "Jimi", age: new Date('2/3/1975')}),
  customerService.insertCommand({name: "James", age: new Date('2/3/1975'), address: 'aa'}),
  customerService.insertCommand({name: "Jimi", age: new Date('2/3/1925'), address: 'aa'}),
  customerService.insertCommand({name: "James", age: new Date('2/3/1925')}),
  customerService.insertCommand({name: "James", age: new Date('2/3/1925'), address: 'aaa'})
];

// LOOP THROUGH EACH COMMAND AND EXECUTE IT

commands.forEach(function(command, index) {
  command.execute((err, result) => {
    console.log('\n---------------');
    console.log(result);

    if (index == commands.length - 1) {
      console.log('\n---------------');
      customerService.getAllCommand().execute(function(err, result) {
        console.log("End Result", result.value);
      });
    }
  });
});

module.exports = customerService;
<commit_msg>update sample<commit_after>// This sample is meant to illustrate how to create business services,
// custom commands, and rules, and to showcase how they interact with
// each other.  In a real world application, you would most likely keep
// each business service, command, and rule in its own file, or at least
// similar actors in the same files.

"use strict";

var peasy = require('./peasy');
var Rule = peasy.Rule;
var BusinessService = peasy.BusinessService;
var Command = peasy.Command;

// CREATE RULES

var AgeRule = Rule.extend({
  association: "age",
  params: ['birthdate'],
  functions: {
    _onValidate: function(done) {
      if (new Date().getFullYear() - this.birthdate.getFullYear() < 50) {
        this._invalidate("You are too young");
      }
      var time = Math.floor((Math.random() * 3000) + 1);
      setTimeout(() => done(), time); // simulate latency
    }
  }
});

var NameRule = Rule.extend({
  association: "name",
  params: ['name'],
  functions: {
    _onValidate: function(done) {
      if (this.name === "Jimi") {
        this._invalidate("Name cannot be Jimi");
      }
      var time = Math.floor((Math.random() * 3000) + 1);
      setTimeout(() => done(), time); // simulate latency
    }
  }
});

var FieldRequiredRule = Rule.extend({
  params: ['field', 'data'],
  functions: {
    _onValidate: function(done) {
      if (!this.data[this.field]) {
        this.association = this.field;
        this._invalidate(this.field + " is required");
      }
      var time = Math.floor((Math.random() * 3000) + 1);
      setTimeout(() => done(), time); // simulate latency
    }
  }
});

var CustomerAuthorizationRule = Rule.extend({
  params: ['roles'],
  functions: {
    _onValidate: function(done) {
      var validRoles = ['super admin', 'admin'];
      this.roles.forEach(function(role) {
        if (validRoles.indexOf(role) > 0) {
          return done();
        }
      });
      this._invalidate("You do not have sufficient priviledges to access national security information");
      done();
    }
  }
});

// CREATE SERVICES, CUSTOM COMMANDS, AND WIRE UP VALIDATION AND BUSINESS RULES

// ROLES SERVICE

var RolesService = BusinessService.extend({
  params: ['userId', 'dataProxy'],
  functions: {
    _getAll: function(context, done) {
      this.dataProxy.getById(this.userId, function(err, roles) {
        done(null, roles);
      });
    }
  }
}).service;

// CUSTOMER SERVICE

var CustomerService = BusinessService
  .extend({
    params: ['dataProxy', 'rolesService'],
    functions: {
      _getRulesForInsert: getRulesForInsert
    }
  })
  .createCommand({
    name: 'getNationalSecurityCommand',
    params: ['id'],
    functions:
    {
      getRules: function(context, done) {
        var getRolesForCurrentUserCommand = this.rolesService.getAllCommand();
        getRolesForCurrentUserCommand.execute(function(err, result) {
          if (err) return done(err);
          if (!result.success) return done(null, result.errors);
          var roles = result.value;
          done(null, new CustomerAuthorizationRule(roles));
        });
      },
      onValidationSuccess: function(context, done) {
        this.dataProxy.getNationalSecurityData(this.id, function(err, data) {
          done(null, data);
        });
      }
    }
  })
  .service;

function getRulesForInsert(customer, context, done) {

  // these will all execute
  //done([
      //new AgeRule(customer.age),
      //new NameRule(customer.name),
      //new FieldRequiredRule("address", customer)
  //]);

  // chained rules - rules will only execute upon successful validation of predecessor
  done(null, new AgeRule(customer.age)
             .ifValidThenExecute(() => console.log("Age succeeded"))
             .ifInvalidThenExecute(() => console.log("Age failed"))
             .ifValidThenValidate(new NameRule(customer.name)
                                        .ifValidThenExecute(() => console.log("Name succeeded"))
                                        .ifInvalidThenExecute(() => console.log("Name failed"))
                                        .ifValidThenValidate(new FieldRequiredRule("address", customer)
                                                                   .ifValidThenExecute(() => console.log("Address succeeded"))
                                                                   .ifInvalidThenExecute(() => console.log("Address failed"))
                                                             )));
}

// CREATE IN-MEMORY DATA PROXIES (these could be a duck typed angular resources, react stores, mongo db implementations, http proxies, etc.)

var customerDataProxy = (function() {
  var state = [
    { id: 1, name: "James Hendrix" },
    { id: 2, name: "James Page" },
    { id: 3, name: "David Gilmour" },
  ];

  return {
    insert: insert,
    getAll: getAll,
    getNationalSecurityData: getNationalSecurityData
  };

  function insert(data, done) {
    var nextId = state.length + 1;
    data.id = nextId;
    state.push(Object.assign({}, data));
    done(null, data);
  }

  function getAll(done) {
    var data = state.map(function(customer) {
      return Object.assign({}, customer);
    });
    done(null, data);
  }

  function getNationalSecurityData(id, done) {
    done(null, { id: id, nsd: "12345678"});
  }
})();

var rolesDataProxy = {
  getById: function(id, done) {
    // add/remove roles to manipulate execution of getNationalSecurityCommand
    done(null, ['admin', 'user']);
  }
}

// CREATE INSTANCE OF A CUSTOMER SERVICE WITH THE REQUIRED DATA PROXY

var currentUserId = 12345; // this id would likely come from some authentication service
var rolesService = new RolesService(currentUserId, rolesDataProxy);
var customerService = new CustomerService(customerDataProxy, rolesService);

// EXECUTE CUSTOM COMMAND

var customerId = 123;
customerService.getNationalSecurityCommand(customerId).execute(function(err, result) {
  console.log("getNationalSecurityCommand execution complete!", result)
});

// CREATE AN ARRAY OF INSERT COMMANDS

var commands = [
  customerService.insertCommand({name: "Jimi", age: new Date('2/3/1975')}),
  customerService.insertCommand({name: "James", age: new Date('2/3/1975'), address: 'aa'}),
  customerService.insertCommand({name: "Jimi", age: new Date('2/3/1925'), address: 'aa'}),
  customerService.insertCommand({name: "James", age: new Date('2/3/1925')}),
  customerService.insertCommand({name: "James", age: new Date('2/3/1925'), address: 'aaa'})
];

// LOOP THROUGH EACH COMMAND AND EXECUTE IT

commands.forEach(function(command, index) {
  command.execute((err, result) => {
    console.log('\n---------------');
    console.log(result);

    if (index == commands.length - 1) {
      console.log('\n---------------');
      customerService.getAllCommand().execute(function(err, result) {
        console.log("End Result", result.value);
      });
    }
  });
});

module.exports = customerService;
<|endoftext|>


<commit_before>"use strict";

var Rule = require('./peasy').Rule;
var BusinessService = require('./peasy').BusinessService;
var Command = require('./peasy').Command;

// CREATE RULES

var AgeRule = Rule.extend({
  association: "age",
  params: ['birthdate'],
  onValidate: function(done) {
    if (new Date().getFullYear() - this.birthdate.getFullYear() < 50) {
      this.__invalidate("You are too young");
    }
    var time = Math.floor((Math.random() * 3000) + 1);
    setTimeout(() => done(this), time); // simulate latency
  }
});

var NameRule = Rule.extend({
  association: "name",
  params: ['name'],
  onValidate: function(done) {
    if (this.name === "Aaron") {
      this.__invalidate("Name cannot be Aaron");
    }
    var time = Math.floor((Math.random() * 3000) + 1);
    setTimeout(() => done(this), time); // simulate latency
  }
});

var FieldRequiredRule = Rule.extend({
  params: ['field', 'data'],
  onValidate: function(done) {
    if (!this.data[this.field]) {
      this.association = this.field;
      this.__invalidate(this.field + " is required");
    }
    var time = Math.floor((Math.random() * 3000) + 1);
    setTimeout(() => done(this), time); // simulate latency
  }
});

// CREATE SERVICE AND WIRE UP VALIDATION/BUSINESS LOGIC FOR INSERT

var PersonService = BusinessService.extend({
  functions: [{
    '__getRulesForInsert': getRulesForInsert
  }]
}).service;

function getRulesForInsert(person, context, done) {

  //done([
      //new AgeRule(person.age),
      //new NameRule(person.name),
      //new FieldRequiredRule("address", person)
  //]);

  done([new AgeRule(person.age)
              .ifValidThenExecute(() => console.log("Age succeeded"))
              .ifInvalidThenExecute(() => console.log("Age failed"))
              .ifValidThenValidate(new NameRule(person.name)
                                         .ifValidThenExecute(() => console.log("Name succeeeded"))
                                         .ifInvalidThenExecute(() => console.log("Name failed"))
                                         .ifValidThenValidate(new FieldRequiredRule("address", person)
                                                                    .ifValidThenExecute(() => console.log("Address succeeeded"))
                                                                    .ifInvalidThenExecute(() => console.log("Address failed"))
                                                              ))]);
}

// CREATE AN IN-MEMORY DATA PROXY (this could be duck typed angular resource, react store, etc.)

var PersonDataProxy = function() {
  this.data = [
    { id: 1, name: "James Hendrix" },
    { id: 2, name: "James Page" },
    { id: 3, name: "David Gilmour" },
  ];
}

PersonDataProxy.prototype = {
  constructor: PersonDataProxy,
  insert: function(data, done) {
    var nextId = this.data.length + 1;
    data.id = nextId;
    this.data.push(data);
    done(data);
  }
};

var proxy = new PersonDataProxy();
var service = new PersonService(proxy);

var commands = [
  service.insertCommand({name: "Aaron", age: new Date('2/3/1975')}),
  service.insertCommand({name: "Aarons", age: new Date('2/3/1975'), address: 'aa'}),
  service.insertCommand({name: "Aaron", age: new Date('2/3/1925'), address: 'aa'}),
  service.insertCommand({name: "Aarons", age: new Date('2/3/1925')}),
  service.insertCommand({name: "aAaron", age: new Date('2/3/1925'), address: 'aaa'})
];

commands.forEach(function(command, index) {
  command.execute((result) => {
    console.log('\n---------------');
    console.log(result);

    if (index == commands.length - 1) {
      console.log('\n---------------');
      console.log("End Result", proxy.data);
    }
  });
});

module.exports = service;
<commit_msg>add more comments<commit_after>"use strict";

var Rule = require('./peasy').Rule;
var BusinessService = require('./peasy').BusinessService;
var Command = require('./peasy').Command;

// CREATE RULES

var AgeRule = Rule.extend({
  association: "age",
  params: ['birthdate'],
  onValidate: function(done) {
    if (new Date().getFullYear() - this.birthdate.getFullYear() < 50) {
      this.__invalidate("You are too young");
    }
    var time = Math.floor((Math.random() * 3000) + 1);
    setTimeout(() => done(this), time); // simulate latency
  }
});

var NameRule = Rule.extend({
  association: "name",
  params: ['name'],
  onValidate: function(done) {
    if (this.name === "Aaron") {
      this.__invalidate("Name cannot be Aaron");
    }
    var time = Math.floor((Math.random() * 3000) + 1);
    setTimeout(() => done(this), time); // simulate latency
  }
});

var FieldRequiredRule = Rule.extend({
  params: ['field', 'data'],
  onValidate: function(done) {
    if (!this.data[this.field]) {
      this.association = this.field;
      this.__invalidate(this.field + " is required");
    }
    var time = Math.floor((Math.random() * 3000) + 1);
    setTimeout(() => done(this), time); // simulate latency
  }
});

// CREATE SERVICE AND WIRE UP VALIDATION/BUSINESS LOGIC FOR INSERT

var PersonService = BusinessService.extend({
  functions: [{
    '__getRulesForInsert': getRulesForInsert
  }]
}).service;

function getRulesForInsert(person, context, done) {

  //done([
      //new AgeRule(person.age),
      //new NameRule(person.name),
      //new FieldRequiredRule("address", person)
  //]);

  done([new AgeRule(person.age)
              .ifValidThenExecute(() => console.log("Age succeeded"))
              .ifInvalidThenExecute(() => console.log("Age failed"))
              .ifValidThenValidate(new NameRule(person.name)
                                         .ifValidThenExecute(() => console.log("Name succeeeded"))
                                         .ifInvalidThenExecute(() => console.log("Name failed"))
                                         .ifValidThenValidate(new FieldRequiredRule("address", person)
                                                                    .ifValidThenExecute(() => console.log("Address succeeeded"))
                                                                    .ifInvalidThenExecute(() => console.log("Address failed"))
                                                              ))]);
}

// CREATE AN IN-MEMORY DATA PROXY (this could be a duck typed angular resource, react store, etc.)

var PersonDataProxy = function() {
  this.data = [
    { id: 1, name: "James Hendrix" },
    { id: 2, name: "James Page" },
    { id: 3, name: "David Gilmour" },
  ];
}

PersonDataProxy.prototype = {
  constructor: PersonDataProxy,
  insert: function(data, done) {
    var nextId = this.data.length + 1;
    data.id = nextId;
    this.data.push(data);
    done(data);
  }
};

// CREATE INSTANCE OF A PERSON SERVICE AND REQUIRED DATA PROXY

var proxy = new PersonDataProxy();
var service = new PersonService(proxy);

var commands = [
  service.insertCommand({name: "Aaron", age: new Date('2/3/1975')}),
  service.insertCommand({name: "Aarons", age: new Date('2/3/1975'), address: 'aa'}),
  service.insertCommand({name: "Aaron", age: new Date('2/3/1925'), address: 'aa'}),
  service.insertCommand({name: "Aarons", age: new Date('2/3/1925')}),
  service.insertCommand({name: "aAaron", age: new Date('2/3/1925'), address: 'aaa'})
];

// LOOP THROUGH EACH COMMAND AND EXECUTE IT

commands.forEach(function(command, index) {
  command.execute((result) => {
    console.log('\n---------------');
    console.log(result);

    if (index == commands.length - 1) {
      console.log('\n---------------');
      console.log("End Result", proxy.data);
    }
  });
});

module.exports = service;
<|endoftext|>