<commit_before>var browserify = require('browserify');
var shim = require('browserify-shim');
var gulp = require('gulp');
var concat = require('gulp-concat');
var derequire = require('gulp-derequire');
var mocha = require('gulp-mocha');
var rename = require('gulp-rename');
var source = require('vinyl-source-stream');
var streamify = require('gulp-streamify');
var typescript = require('gulp-tsc');
var uglify = require('gulp-uglify');

var tests = [
	{ name: 'NavigationRouting', from: './test/NavigationRoutingTest.ts', to: 'navigationRouting.test.js' },
	{ name: 'StateInfo', from: './test/StateInfoTest.ts', to: 'stateInfo.test.js' },
	{ name: 'Navigation', from: './test/NavigationTest.ts', to: 'navigation.test.js' },
	{ name: 'NavigationData', from: './test/NavigationDataTest.ts', to: 'navigationData.test.js' }
];
var plugins = [
	{ name: 'NavigationReact', from: './src/react/NavigationReact.ts', to: 'navigation.react.js' },
	{ name: 'NavigationKnockout', from: './src/knockout/NavigationKnockout.ts', to: 'navigation.knockout.js' },
	{ name: 'NavigationAngular', from: './src/angular/NavigationAngular.ts', to: 'navigation.angular.js' }
];
var testTasks = [];
function testTask(from, to) {
	return browserify(from)
		.plugin('tsify')
		.bundle()
		.pipe(source(to))
		.pipe(rename(to))
		.pipe(gulp.dest('./build'))
        .pipe(mocha());
}
for (var i = 0; i < tests.length; i++) {
	(function (test) {
		gulp.task('Test' + test.name, function () {
			return testTask(test.from, test.to)
		});
	})(tests[i]);
	testTasks.push('Test' + tests[i].name);
}
gulp.task('test', testTasks);

gulp.task('BuildNavigationRouting', function () {
	return buildTask('NavigationRouting', './src/routing/NavigationRouting.ts', 'navigation.routing.js')
		.pipe(rename('navigation.routing.min.js'))
		.pipe(streamify(uglify()))
		.pipe(gulp.dest('./build'));
});
gulp.task('BuildNavigation', function () {
	return buildTask('Navigation', './src/Navigation.ts', 'navigation.js');
});
var buildTasks = ['BuildNavigationRouting', 'BuildNavigation'];
function buildTask(name, from, to) {
	return browserify(from, { standalone: name })
		.plugin('tsify')
		.transform(shim)
		.bundle()
		.pipe(source(to))
		.pipe(rename(to))
		.pipe(derequire())
		.pipe(gulp.dest('./build'));
}
for (var i = 0; i < plugins.length; i++) {
	(function (plugin) {
		gulp.task('Build' + plugin.name, function () {
			return buildTask(plugin.name, plugin.from, plugin.to);
		});
	})(plugins[i]);
	buildTasks.push('Build' + plugins[i].name);
}
gulp.task('UnifyNavigation', ['BuildNavigationRouting', 'BuildNavigation'], function () {
	return gulp.src(['./build/navigation.routing.js', './build/navigation.js'])
		.pipe(concat('navigation.js'))
		.pipe(gulp.dest('./build'))
		.pipe(rename('navigation.min.js'))
		.pipe(streamify(uglify()))
		.pipe(gulp.dest('./build'));
});
buildTasks.push('UnifyNavigation');
for (var i = 0; i < plugins.length; i++) {
	(function (plugin) {
		gulp.task('Unify' + plugin.name, ['UnifyNavigation', 'Build' + plugin.name], function () {
			return gulp.src(['./build/navigation.js', './build/' + plugin.to])
				.pipe(concat(plugin.to))
				.pipe(gulp.dest('./build'))
				.pipe(rename(plugin.to.replace(/js$/, 'min.js')))
				.pipe(streamify(uglify()))
				.pipe(gulp.dest('./build'));
		});
	})(plugins[i]);
	buildTasks.push('Unify' + plugins[i].name);
}
gulp.task('build', buildTasks);

var ts = ['./src/Navigation.ts'];
for (var i = 0; i < plugins.length; i++) {
	ts.push(plugins[i].from);
}
gulp.task('package', function () {
	return gulp.src(ts)
		.pipe(typescript())
		.pipe(gulp.dest('./build/npm/lib'));
})
<commit_msg>Added task to copy npm specific files to build<commit_after>var browserify = require('browserify');
var shim = require('browserify-shim');
var gulp = require('gulp');
var concat = require('gulp-concat');
var derequire = require('gulp-derequire');
var mocha = require('gulp-mocha');
var rename = require('gulp-rename');
var source = require('vinyl-source-stream');
var streamify = require('gulp-streamify');
var typescript = require('gulp-tsc');
var uglify = require('gulp-uglify');

var tests = [
	{ name: 'NavigationRouting', from: './test/NavigationRoutingTest.ts', to: 'navigationRouting.test.js' },
	{ name: 'StateInfo', from: './test/StateInfoTest.ts', to: 'stateInfo.test.js' },
	{ name: 'Navigation', from: './test/NavigationTest.ts', to: 'navigation.test.js' },
	{ name: 'NavigationData', from: './test/NavigationDataTest.ts', to: 'navigationData.test.js' }
];
var plugins = [
	{ name: 'NavigationReact', from: './src/react/NavigationReact.ts', to: 'navigation.react.js' },
	{ name: 'NavigationKnockout', from: './src/knockout/NavigationKnockout.ts', to: 'navigation.knockout.js' },
	{ name: 'NavigationAngular', from: './src/angular/NavigationAngular.ts', to: 'navigation.angular.js' }
];
var testTasks = [];
function testTask(from, to) {
	return browserify(from)
		.plugin('tsify')
		.bundle()
		.pipe(source(to))
		.pipe(rename(to))
		.pipe(gulp.dest('./build'))
        .pipe(mocha());
}
for (var i = 0; i < tests.length; i++) {
	(function (test) {
		gulp.task('Test' + test.name, function () {
			return testTask(test.from, test.to)
		});
	})(tests[i]);
	testTasks.push('Test' + tests[i].name);
}
gulp.task('test', testTasks);

gulp.task('BuildNavigationRouting', function () {
	return buildTask('NavigationRouting', './src/routing/NavigationRouting.ts', 'navigation.routing.js')
		.pipe(rename('navigation.routing.min.js'))
		.pipe(streamify(uglify()))
		.pipe(gulp.dest('./build'));
});
gulp.task('BuildNavigation', function () {
	return buildTask('Navigation', './src/Navigation.ts', 'navigation.js');
});
var buildTasks = ['BuildNavigationRouting', 'BuildNavigation'];
function buildTask(name, from, to) {
	return browserify(from, { standalone: name })
		.plugin('tsify')
		.transform(shim)
		.bundle()
		.pipe(source(to))
		.pipe(rename(to))
		.pipe(derequire())
		.pipe(gulp.dest('./build'));
}
for (var i = 0; i < plugins.length; i++) {
	(function (plugin) {
		gulp.task('Build' + plugin.name, function () {
			return buildTask(plugin.name, plugin.from, plugin.to);
		});
	})(plugins[i]);
	buildTasks.push('Build' + plugins[i].name);
}
gulp.task('UnifyNavigation', ['BuildNavigationRouting', 'BuildNavigation'], function () {
	return gulp.src(['./build/navigation.routing.js', './build/navigation.js'])
		.pipe(concat('navigation.js'))
		.pipe(gulp.dest('./build'))
		.pipe(rename('navigation.min.js'))
		.pipe(streamify(uglify()))
		.pipe(gulp.dest('./build'));
});
buildTasks.push('UnifyNavigation');
for (var i = 0; i < plugins.length; i++) {
	(function (plugin) {
		gulp.task('Unify' + plugin.name, ['UnifyNavigation', 'Build' + plugin.name], function () {
			return gulp.src(['./build/navigation.js', './build/' + plugin.to])
				.pipe(concat(plugin.to))
				.pipe(gulp.dest('./build'))
				.pipe(rename(plugin.to.replace(/js$/, 'min.js')))
				.pipe(streamify(uglify()))
				.pipe(gulp.dest('./build'));
		});
	})(plugins[i]);
	buildTasks.push('Unify' + plugins[i].name);
}
gulp.task('build', buildTasks);

gulp.task('npm', function () {
	return gulp.src('./npm/*')
		.pipe(gulp.dest('./build/npm/'));
});
var ts = ['./src/Navigation.ts'];
for (var i = 0; i < plugins.length; i++) {
	ts.push(plugins[i].from);
}
gulp.task('package', ['npm'], function () {
	return gulp.src(ts)
		.pipe(typescript())
		.pipe(gulp.dest('./build/npm/lib'));
});
<|endoftext|>


<commit_before>// Plugin to jQuery
(function($) {
	/*
	// Create a universal animation function that optimizes for the browsers capabilities
	$.fn.optAnimate = function(props, speed, easing, callback) {
		// If modernizr reports that the browser supports CSS animations, and the animateWithCss function has correctly been loaded/defined
		if (Modernizr.cssanimations && typeof($.fn.animateWithCss) == 'function') {
			return $(this).animateWithCss(props, speed, easing, callback);
		}
		else {
			return $(this).animate(props, speed, easing, callback);
		}
	};
	*/

	// Get the device's OS and add it as a class to the HTML tag
	// To be used for OS-specific styling (trying to stay more true to the native styling)
	$.fn.deviceOS = function() {
		var deviceOS = '';

		// Get the data
		var devicePlatform = navigator.userAgent.match(/Android/i)
			|| navigator.userAgent.match(/iPod/i)
			|| navigator.userAgent.match(/iPad/i)
			|| navigator.userAgent.match(/iPhone/i)
			|| navigator.userAgent.match(/webOS/i)
			|| 'Other';

		if (devicePlatform == 'iPod' || devicePlatform == 'iPad' || devicePlatform == 'iPhone') {
			deviceOS = 'ios';
		}
		else if (devicePlatform == 'Android') {
			deviceOS = 'android';
		}
		else {
			deviceOS = devicePlatform.toLowerCase();
		}

		// Add the deviceOS as a CSS class to the HTML tag
		$('html').addClass(deviceOS);

		return deviceOS;
	};

})(jQuery);

// Bind events to be triggered BEFORE EVERY page creation
$(document).live('pagebeforecreate', function() {
	// Function to find all jQuery Mobile back buttons and add an attribute to it
	function modifyBackButtons() {
		// Back buttons jQuery object
		var $backBtns = $('a[data-rel=back]');

		// Add attribute
		$backBtns.attr('data-direction', 'reverse');
	}

	// Functions to run on page-load
	(function() {
		modifyBackButtons();
	})();
});

// Bind generic events to be triggered on EVERY page initialization
$(document).live('pageinit', function() {
	// Function to change the class of the HTML tag based on the orientation of the device
	function changeOrientationClass(orientation) {
		// Add the orientation as a CSS class to the HTML tag
		$('html').addClass(orientation);
	}

	// Functions to run on orientation change
	$(window).bind('orientationchange', function(event){
		changeOrientationClass(event.orientation);
	});

	// Function to find all jQuery Mobile back buttons and add an attribute to it
	function modifyBackButtons() {
		// Back buttons jQuery object
		var $backBtns = $('a[data-rel=back]');

		// Add HTML
		$backBtns.append('');
	}

	// Functions to run on page-load
	(function() {
		$(window).trigger('orientationchange');
		$().deviceOS();
		modifyBackButtons();
	})();
});

// Bind generic events to be triggered on the DASHBOARD page initialization
$('#page-dashboard').live('pageinit', function() {
	// Set variables for the dashboard
	var currentElemPerRow = '';

	// Detect and mark the "middle" elements of the dashboard
	function detectMiddleElements() {
		// Grab the width of the entire dashboard
		var dashWidth = parseInt($('nav#dashboard').width());

		// Grab the percentage width of the first element
		var elemWidth = parseInt($('nav#dashboard ul#dashboard-mapps li').width());

		// Find the number of elements per row
		var elemPerRow = Math.floor(dashWidth / elemWidth);

		// Remove the current element per row class, so there aren't more than one class
		$('nav#dashboard').removeClass(currentElemPerRow + '-per-row');

		// Set the number of elements per row as a css class on the dashboard tag
		$('nav#dashboard').addClass(elemPerRow + '-per-row');
		currentElemPerRow = elemPerRow;

		// Calculate the middle-th element
		var middleCount = Math.ceil(elemPerRow / 2);

		// Create the nth-child expression
		var everyNthChild = elemPerRow + String('n+') + middleCount;
		console.log(elemPerRow);
		console.log(middleCount);
		console.log(everyNthChild);
		console.log(elemPerRow + 'n+' + middleCount);

		// Finally, set every middle-th element to have a class
		$('nav#dashboard ul#dashboard-mapps li').removeClass('dash-middle-element');
		$('nav#dashboard ul#dashboard-mapps li:nth-child(' + everyNthChild +')').addClass('dash-middle-element');
	}

	// Detect device and meta info and display it on the page
	function deviceInfo() {
		// Get the data
		var devicePlatform = $().deviceOS();
		var displayDensity = window.devicePixelRatio;

		// Display it by adding it to the mobile-info span
		$('#mobile-info').append('
Device Platform: ' + devicePlatform + '
');
		$('#mobile-info').append('
Display Density: ' + displayDensity + '
');

	}

	// Make the info button footer clickable
	$('.info-button').click(function() {
		$('#hidden-info-div').animate({ height: 'toggle', leaveTransforms: true, useTranslate3d: true}, 800, 'easeOutExpo', function() {
			// Fix window height bugs by triggering an updatelayout and resize (repaint, please)
			$(window).trigger('resize');
			$(this).trigger('updatelayout');
		});
		$('footer').animate({ opacity: 'toggle'}, 1200, 'easeInExpo', function() {
			// Do something on callback
		});
	});

	// Functions to run on orientation change
	$(window).bind('orientationchange', function(event){
		detectMiddleElements();
	});

	// Functions to run on page-load
	(function() {
		detectMiddleElements();
		deviceInfo();
	})();
});

// Bind events to be triggered on the CAMPUS MAP page initialization
$('#page-campusmap').live('pageinit', function() {
	// Create a Google Map
	var startingCenterPoint = new google.maps.LatLng(43.758976, -71.688709);
	var zoomLevel = 15;
	var gmapObject = {'center': startingCenterPoint, 'zoom': zoomLevel};

	// Create the map
	$('div#campus-google-map').gmap( gmapObject );
});
// Bind events to be triggered on the CAMPUS MAP page showing
$('#page-campusmap').live("pageshow", function() {
	// Refresh/repaint
	$(window).trigger('resize');
	$(this).trigger('updatelayout');
	$('div#campus-google-map').gmap('refresh');
});
<commit_msg>Changed the generic document page initialization functions to be triggered on page creation instead. Created an event listener for when each m-app initializes and implemented a way for Android headers to be used as back buttons Also, added the browser/user agent string to the debug panel (for now)<commit_after>// Plugin to jQuery
(function($) {
	/*
	// Create a universal animation function that optimizes for the browsers capabilities
	$.fn.optAnimate = function(props, speed, easing, callback) {
		// If modernizr reports that the browser supports CSS animations, and the animateWithCss function has correctly been loaded/defined
		if (Modernizr.cssanimations && typeof($.fn.animateWithCss) == 'function') {
			return $(this).animateWithCss(props, speed, easing, callback);
		}
		else {
			return $(this).animate(props, speed, easing, callback);
		}
	};
	*/

	// Get the device's OS and add it as a class to the HTML tag
	// To be used for OS-specific styling (trying to stay more true to the native styling)
	$.fn.deviceOS = function() {
		var deviceOS = '';

		// Get the data
		var devicePlatform = navigator.userAgent.match(/Android/i)
			|| navigator.userAgent.match(/iPod/i)
			|| navigator.userAgent.match(/iPad/i)
			|| navigator.userAgent.match(/iPhone/i)
			|| navigator.userAgent.match(/webOS/i)
			|| 'Other';

		if (devicePlatform == 'iPod' || devicePlatform == 'iPad' || devicePlatform == 'iPhone') {
			deviceOS = 'ios';
		}
		else if (devicePlatform == 'Android') {
			deviceOS = 'android';
		}
		else {
			deviceOS = devicePlatform.toLowerCase();
		}

		// Add the deviceOS as a CSS class to the HTML tag
		$('html').addClass(deviceOS);

		return deviceOS;
	};

})(jQuery);

// Bind events to be triggered BEFORE EVERY page creation
$(document).live('pagebeforecreate', function() {
	// Function to find all jQuery Mobile back buttons and add an attribute to it
	function modifyBackButtons() {
		// Back buttons jQuery object
		var $backBtns = $('a[data-rel=back]');

		// Add attribute
		$backBtns.attr('data-direction', 'reverse');
	}

	// Functions to run on page-load
	(function() {
		modifyBackButtons();
	})();
});

// Bind generic events to be triggered on EVERY page initialization
$(document).live('pagecreate', function() {
	// Function to change the class of the HTML tag based on the orientation of the device
	function changeOrientationClass(orientation) {
		// Add the orientation as a CSS class to the HTML tag
		$('html').addClass(orientation);
	}

	// Functions to run on orientation change
	$(window).bind('orientationchange', function(event){
		changeOrientationClass(event.orientation);
	});

	// Function to find all jQuery Mobile back buttons and add an attribute to it
	function modifyBackButtons() {
		// Back buttons jQuery object
		var $backBtns = $('a[data-rel=back]');

		// Add HTML
		$backBtns.append('');
	}

	// Functions to run on page-load
	(function() {
		$(window).trigger('orientationchange');
		$().deviceOS();
		modifyBackButtons();
	})();
});

// Bind generic events to be triggered on EVERY m-app initialization
$('.m-app').live('pageinit', function() {
	// Function to add both an html element and a click listener to all android headers
	function convertAndroidHeaders() {
		// Header jQuery object
		var $header = $("html.android h1#header-logo");

		// Grab the url of the hard-coded back button
		var backUrl = $('a[data-rel=back]').attr('href');

		// Add a class and an html span element
		$header.addClass('back-button');
		$header.prepend('');

		// Make the header clickable
		$header.click(function() {
			// Use jQuery Mobile's page change function to animate with transitions and load with Ajax
			$.mobile.changePage(backUrl, {reverse: true});
		});
	}

	// Functions to run on page-load
	(function() {
		convertAndroidHeaders();
	})();
});

// Bind generic events to be triggered on the DASHBOARD page initialization
$('#page-dashboard').live('pageinit', function() {
	// Set variables for the dashboard
	var currentElemPerRow = '';

	// Detect and mark the "middle" elements of the dashboard
	function detectMiddleElements() {
		// Grab the width of the entire dashboard
		var dashWidth = parseInt($('nav#dashboard').width());

		// Grab the percentage width of the first element
		var elemWidth = parseInt($('nav#dashboard ul#dashboard-mapps li').width());

		// Find the number of elements per row
		var elemPerRow = Math.floor(dashWidth / elemWidth);

		// Remove the current element per row class, so there aren't more than one class
		$('nav#dashboard').removeClass(currentElemPerRow + '-per-row');

		// Set the number of elements per row as a css class on the dashboard tag
		$('nav#dashboard').addClass(elemPerRow + '-per-row');
		currentElemPerRow = elemPerRow;

		// Calculate the middle-th element
		var middleCount = Math.ceil(elemPerRow / 2);

		// Create the nth-child expression
		var everyNthChild = elemPerRow + String('n+') + middleCount;
		console.log(elemPerRow);
		console.log(middleCount);
		console.log(everyNthChild);
		console.log(elemPerRow + 'n+' + middleCount);

		// Finally, set every middle-th element to have a class
		$('nav#dashboard ul#dashboard-mapps li').removeClass('dash-middle-element');
		$('nav#dashboard ul#dashboard-mapps li:nth-child(' + everyNthChild +')').addClass('dash-middle-element');
	}

	// Detect device and meta info and display it on the page
	function deviceInfo() {
		// Get the data
		var devicePlatform = $().deviceOS();
		var displayDensity = window.devicePixelRatio;

		// Display it by adding it to the mobile-info span
		$('#mobile-info').append('
Device Platform: ' + devicePlatform + '
');
		$('#mobile-info').append('
Display Density: ' + displayDensity + '
');
		$('#mobile-info').append('
User Agent: ' + navigator.userAgent + '
');

	}

	// Make the info button footer clickable
	$('.info-button').click(function() {
		$('#hidden-info-div').animate({ height: 'toggle', leaveTransforms: true, useTranslate3d: true}, 800, 'easeOutExpo', function() {
			// Fix window height bugs by triggering an updatelayout and resize (repaint, please)
			$(window).trigger('resize');
			$(this).trigger('updatelayout');
		});
		$('footer').animate({ opacity: 'toggle'}, 1200, 'easeInExpo', function() {
			// Do something on callback
		});
	});

	// Functions to run on orientation change
	$(window).bind('orientationchange', function(event){
		detectMiddleElements();
	});

	// Functions to run on page-load
	(function() {
		detectMiddleElements();
		deviceInfo();
	})();
});

// Bind events to be triggered on the CAMPUS MAP page initialization
$('#page-campusmap').live('pageinit', function() {
	// Create a Google Map
	var startingCenterPoint = new google.maps.LatLng(43.758976, -71.688709);
	var zoomLevel = 15;
	var gmapObject = {'center': startingCenterPoint, 'zoom': zoomLevel};

	// Create the map
	$('div#campus-google-map').gmap( gmapObject );
});
// Bind events to be triggered on the CAMPUS MAP page showing
$('#page-campusmap').live("pageshow", function() {
	// Refresh/repaint
	$(window).trigger('resize');
	$(this).trigger('updatelayout');
	$('div#campus-google-map').gmap('refresh');
});
<|endoftext|>


<commit_before>'use strict';

var React = require('react-native');
var {
  Image,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
  Component
} = React;

var Icon = require('FontAwesome'),
    getImage = require('./helpers/getImage'),
    screen = require('Dimensions').get('window'),
    ParallaxView = require('react-native-parallax-view'),
    Modal = require('react-native-modal');

var Player = React.createClass({
  getInitialState: function() {
    return {
      isModalOpen: false
    }
  },

  openModal: function() {
    this.setState({
      isModalOpen: true
    });
  },

  closeModal: function() {
    this.setState({
      isModalOpen: false
    });
  },

  render: function() {
    return (
      <ParallaxView
      backgroundSource={getImage.authorAvatar(this.props.player)}
      blur={'dark'}
      windowHeight={160}
      header={(
        <TouchableOpacity onPress={this.openModal}>
          <View style={styles.headerContent}>
            <View style={styles.innerHeaderContent}>
              <Image source={getImage.authorAvatar(this.props.player)}
              style={styles.playerAvatar} />
              <Text style={styles.playerUsername}>{this.props.player.username}</Text>
              <Text style={styles.playerName}>{this.props.player.name}</Text>
              <View style={styles.playerDetailsRow}>
                <View style={styles.playerCounter}>
                  <Text style={styles.playerCounterText}>Followers</Text>
                  <Text style={styles.playerCounterValue}> {this.props.player.followers_count} </Text>
                </View>
                <View style={styles.playerCounter}>
                  <Text style={styles.playerCounterText}>Shots</Text>
                  <Text style={styles.playerCounterValue}> {this.props.player.shots_count} </Text>
                </View>
                <View style={styles.playerCounter}>
                  <Text style={styles.playerCounterText}>Likes</Text>
                  <Text style={styles.playerCounterValue}> {this.props.player.likes_count} </Text>
                </View>
                <View style={styles.playerCounter}>
                  <Text style={styles.playerCounterText}>Comments</Text>
                  <Text style={styles.playerCounterValue}> {this.props.player.comments_count} </Text>
                </View>
              </View>
            </View>
          </View>
        </TouchableOpacity>
      )}
      >
        <View style={styles.playerContent}>
          <Text>Add more details about {this.props.player.name}</Text>
        </View>

        <Modal isVisible={this.state.isModalOpen}
               onClose={this.closeModal}
               backdropType="blur"
               backdropBlur="dark"
               forceToFront={true}
               customShowHandler={this._showModalTransition}
               customHideHandler={this._hideModalTransition}
               onPressBackdrop={this.closeModal}>
          <Image source={getImage.authorAvatar(this.props.player)}
                 style={styles.playerImageModal}
                 resizeMode="contain"/>
        </Modal>
      </ParallaxView>
    );
  },
  _showModalTransition: function(transition) {
    transition('opacity', {
      duration: 200,
      begin: 0,
      end: 1
    });
    transition('height', {
      duration: 200,
      begin: - screen.height * 2,
      end: screen.height
    });
  },

  _hideModalTransition: function(transition) {
    transition('height', {
      duration: 200,
      begin: screen.height,
      end: screen.height * 2,
      reset: true
    });
    transition('opacity', {
      duration: 200,
      begin: 1,
      end: 0
    });
  },
});
var styles = StyleSheet.create({
  headerContent: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'transparent',
  },
  innerHeaderContent: {
    // Remove NavigatorHeight
    marginTop: -64,
    alignItems: 'center'
  },
  playerInfo: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'white',
    flexDirection: 'row'
  },
  playerUsername: {
    color: '#fff',
    fontWeight: '300'
  },
  playerName: {
    fontSize: 14,
    color: '#fff',
    fontWeight: '900',
    lineHeight: 18
  },
  //Player details list
  playerDetailsRow: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    flexDirection: 'row',
    width: screen.width / 2,
    marginTop: 20
  },
  playerCounter: {
    flex: 1,
    alignItems: 'center'
  },
  playerCounterText: {
    color: '#fff',
    fontSize: 10,
    justifyContent: 'space-between'
  },
  playerCounterValue: {
    color: '#fff',
    fontWeight: '900'
  },
  playerAvatar: {
    width: 80,
    height: 80,
    borderRadius: 40,
    borderWidth: 2,
    borderColor: '#fff',
    marginBottom: 10
  },
  //Modal
  playerImageModal: {
    height: screen.height / 3
  },
  //playerContent
  playerContent: {
    padding: 20
  }
});

module.exports = Player;
<commit_msg>Add player shots in player view #2<commit_after>"use strict";

var React = require("react-native");
var {
  Image,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
  Component,
  ActivityIndicatorIOS,
  ListView
} = React;

var Icon = require("FontAwesome"),
    getImage = require("./helpers/getImage"),
    HTML = require("react-native-htmlview"),
    screen = require("Dimensions").get("window"),
    ParallaxView = require("react-native-parallax-view"),
    Modal = require("react-native-modal");

var api = require("./helpers/api");

var Loading = require("./Loading");
var ShotCell = require("./ShotCell");
var ShotDetails = require("./ShotDetails");

var Player = React.createClass({

  getInitialState: function() {
    return {
      isModalOpen: false,
      isLoading: true,
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      })
    };
  },

  componentWillMount: function() {
    api.getResources(this.props.player.shots_url).then((responseData) => {
      this.setState({
        dataSource: this.state.dataSource.cloneWithRows(responseData),
        isLoading: false
      });
    }).done();
  },

  openModal: function() {
    this.setState({
      isModalOpen: true
    });
  },

  closeModal: function() {
    this.setState({
      isModalOpen: false
    });
  },

  render: function() {
    return (
      <ParallaxView
      backgroundSource={getImage.authorAvatar(this.props.player)}
      blur={"dark"}
      windowHeight={160}
      header={(
        <TouchableOpacity onPress={this.openModal}>
          <View style={styles.headerContent}>
            <View style={styles.innerHeaderContent}>
              <Image source={getImage.authorAvatar(this.props.player)}
              style={styles.playerAvatar} />
              <Text style={styles.playerUsername}>{this.props.player.username}</Text>
              <Text style={styles.playerName}>{this.props.player.name}</Text>
              <View style={styles.playerDetailsRow}>
                <View style={styles.playerCounter}>
                  <Icon name="users" size={18} color="#fff"/>
                  <Text style={styles.playerCounterValue}> {this.props.player.followers_count} </Text>
                </View>
                <View style={styles.playerCounter}>
                  <Icon name="camera-retro" size={18} color="#fff"/>
                  <Text style={styles.playerCounterValue}> {this.props.player.shots_count} </Text>
                </View>
                <View style={styles.playerCounter}>
                  <Icon name="heart-o" size={18} color="#fff"/>
                  <Text style={styles.playerCounterValue}> {this.props.player.likes_count} </Text>
                </View>
              </View>
            </View>
          </View>
        </TouchableOpacity>
      )}
      >
      <View style={styles.shotList}>
        {this.state.dataSource.length !== 0 ? this.renderShots() : <Loading />}
      </View>

        <Modal isVisible={this.state.isModalOpen}
               onClose={this.closeModal}
               backdropType="blur"
               backdropBlur="dark"
               forceToFront={true}
               customShowHandler={this._showModalTransition}
               customHideHandler={this._hideModalTransition}
               onPressBackdrop={this.closeModal}>
          <Image source={getImage.authorAvatar(this.props.player)}
                 style={styles.playerImageModal}
                 resizeMode="contain"/>
        </Modal>
      </ParallaxView>
    );
  },

  _showModalTransition: function(transition) {
    transition("opacity", {
      duration: 200,
      begin: 0,
      end: 1
    });
    transition("height", {
      duration: 200,
      begin: - screen.height * 2,
      end: screen.height
    });
  },

  _hideModalTransition: function(transition) {
    transition("height", {
      duration: 200,
      begin: screen.height,
      end: screen.height * 2,
      reset: true
    });
    transition("opacity", {
      duration: 200,
      begin: 1,
      end: 0
    });
  },

  renderShots: function() {
    return <ListView
      ref="listview"
      dataSource={this.state.dataSource}
      renderRow={this.renderRow}
      contentContainerStyle={styles.listStyle}
      horizontal={true}
    />;
  },

  renderRow: function(shot)  {
    return (
      <ShotCell
        onSelect={() => this.selectShot(shot)}
        shot={shot}
      />
    );
  },

  selectShot: function(shot: Object) {
    this.props.navigator.push({
      component: ShotDetails,
      passProps: {shot},
      title: shot.title
    });
  },
});

var styles = StyleSheet.create({
  listStyle: {
    flex: 1,
    backgroundColor: "red"
  },
  listView: {
    flex: 1,
    backgroundColor: "coral"
  },
  spinner: {
    width: 50,
  },
  headerContent: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
    backgroundColor: "transparent",
  },
  innerHeaderContent: {
    // Remove NavigatorHeight
    marginTop: -64,
    alignItems: "center"
  },
  playerInfo: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
    backgroundColor: "white",
    flexDirection: "row"
  },
  playerUsername: {
    color: "#fff",
    fontWeight: "300"
  },
  playerName: {
    fontSize: 14,
    color: "#fff",
    fontWeight: "900",
    lineHeight: 18
  },
  //Player details list
  playerDetailsRow: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
    flexDirection: "row",
    width: screen.width / 2,
    marginTop: 20
  },
  playerCounter: {
    flex: 1,
    alignItems: "center"
  },
  playerCounterValue: {
    color: "#fff",
    fontWeight: "900",
    fontSize: 14,
    marginTop: 5,
  },
  playerAvatar: {
    width: 80,
    height: 80,
    borderRadius: 40,
    borderWidth: 2,
    borderColor: "#fff",
    marginBottom: 10
  },
  //Modal
  playerImageModal: {
    height: screen.height / 3
  },
  //playerContent
  playerContent: {
    padding: 20
  }
});

module.exports = Player;
<|endoftext|>


<commit_before>/**
 * Created by tushar.mathur on 25/01/16.
 */

'use strict'

const bufferSave = require('./bufferSave')
const metaSave = require('./metaSave')
const metaLoad = require('./metaLoad')
const contentLoad = require('./contentLoad')
const metaUpdate = require('./metaUpdate')
const create = require('reactive-storage').create
const Immutable = require('immutable')

module.exports = (ob, fd) => {
  const offsets = create(Immutable.List([]))
  const loadedMETA = metaLoad(fd)
    .tap(x => offsets.set(i => i.merge(x.offsets)))
  const loadedContent = contentLoad(ob, loadedMETA)
  const savedContent = bufferSave(ob, fd, loadedContent)
    .tap(x => offsets.set(i => i.set(x.index, x.offset)))
  const currentMETA = metaUpdate(loadedMETA, savedContent, offsets.getStream())
  return metaSave(ob, fd, currentMETA)
}
<commit_msg>chore(downloadMTD): update reactive-storage usage for getting stream<commit_after>/**
 * Created by tushar.mathur on 25/01/16.
 */

'use strict'

const bufferSave = require('./bufferSave')
const metaSave = require('./metaSave')
const metaLoad = require('./metaLoad')
const contentLoad = require('./contentLoad')
const metaUpdate = require('./metaUpdate')
const create = require('reactive-storage').create
const Immutable = require('immutable')

module.exports = (ob, fd) => {
  const offsets = create(Immutable.List([]))
  const loadedMETA = metaLoad(fd)
    .tap(x => offsets.set(i => i.merge(x.offsets)))
  const loadedContent = contentLoad(ob, loadedMETA)
  const savedContent = bufferSave(ob, fd, loadedContent)
    .tap(x => offsets.set(i => i.set(x.index, x.offset)))
  const currentMETA = metaUpdate(loadedMETA, savedContent, offsets.stream)
  return metaSave(ob, fd, currentMETA)
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2016 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import React from 'react'
import PropTypes from 'prop-types'
import _ from 'underscore'
import I18n from 'i18n!grading_periods'
import SearchHelpers from '../shared/helpers/searchHelpers'

  let SearchGradingPeriodsField = React.createClass({
    propTypes: {
      changeSearchText: PropTypes.func.isRequired
    },

    onChange(event) {
      let trimmedText = event.target.value.trim();
      this.search(trimmedText);
    },

    search: _.debounce(function(trimmedText) {
      this.props.changeSearchText(trimmedText);
    }, 200),

    render() {
      return (

          <input type="text"
                 ref="input"
                 className="ic-Input"
                 placeholder={I18n.t("Search grading periods...")}
                 onChange={this.onChange}/>

      );
    }
  });

export default SearchGradingPeriodsField
<commit_msg>get SearchGradingPeriods to work w/ react 16<commit_after>/*
 * Copyright (C) 2016 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import React from 'react'
import PropTypes from 'prop-types'
import _ from 'underscore'
import I18n from 'i18n!grading_periods'

export default class SearchGradingPeriodsField extends React.Component {
  static propTypes = {
    changeSearchText: PropTypes.func.isRequired
  }

  onChange = event => {
    const trimmedText = event.target.value.trim()
    this.search(trimmedText)
  }

  search = _.debounce(function(trimmedText) {
    this.props.changeSearchText(trimmedText)
  }, 200)

  render() {
    return (

        <input
          type="text"
          ref="input"
          className="ic-Input"
          placeholder={I18n.t('Search grading periods...')}
          onChange={this.onChange}
        />

    )
  }
}
<|endoftext|>


<commit_before>'use strict';

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

function irand(){
  return Math.floor(Math.random()*10);
}

var input = [
  'get view.things',
  'get view',
  'get view.page',
  '(post|get) :page.view',
  'get page',
  'get',
  'get /:page/view',
  'get /',
  'get /:page',
  'get /:page/:view'
].sort(function(){
  return irand()*Math.pow(-1, irand());
});

console.log(input);
console.log(' ---- ');

function pp(obj, sep){
  if(!obj){ return '[nope]'; }
  return JSON.stringify(obj, null, sep || ' ');
}

input.forEach(app.set.bind(app));
Object.keys(app.store.children).forEach(function(path){
  var node = this[path];
  console.log('stem', node);
  console.log('regex', node.regex);
  console.log('parent', pp(node.parent));
  console.log('children', pp(node.children));
  console.log(' ---- ');
}, app.store.children);

app.set('get', function getHandle(){});

app.set({name: 'test'});

app.set('get /:page/:view', {
  children: ['one']
});

console.log(app.get('get /user/profile'));
console.log(app.get('get'));

console.log(app);
<commit_msg>readme examples<commit_after>'use strict';

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

var input = [
  {
    path: 'get /user/:page(\\d+)', opt: {
      parent: 'get /user',
      handle: function getUserPage(){}
    },
  },
  {
    path: 'get /user', opt: {
      picture: function getPicture(){},
      render: function markup(){}
    }
  }
].map(function(input){
  app.set(input.path, input.opt);
  return input;
});

console.log(input);
console.log(' ---- ');

console.log(app.get('get /user/10'));
<|endoftext|>


<commit_before>"use babel";
// @flow

import * as React from "react";
import path from "path";
import styled from "styled-components";
import ansiToHtml from "ansi-to-html";
import type { MoleculeDiagnostic } from "../Types/types";
import type { Range } from "../../LanguageServerProtocolFeature/Types/standard";

const getSeverityColor = (severity: number) => {
  switch (severity) {
    case 1:
      return "red";
    case 2:
      return "yellow";
    case 3:
      return "blue";
    case 5:
      return "green";
    default:
      return "blue";
  }
};

const getSeverityClasses = (severity: any): string => {
  switch (severity) {
    case 3:
      return "diagnostic-color-info-text icon icon-info";
    case 2:
      return "diagnostic-color-warning-text icon icon-alert";
    case 1:
      return "diagnostic-color-error-text icon icon-issue-opened";
    case 5:
      return "diagnostic-color-success-text icon icon-check";
    default:
      return "";
  }
};

const Box = styled.div`
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  border-bottom: 1px black solid;
  border-radius: 3px;
  padding: 4px;
`;

const Header = styled.div`
  margin: 0px 4px 4px 4px;
`;

const Content = styled.div`
  display: flex;
  list-style: none;
`;

const Severity = styled.div`
  background-color: ${props => getSeverityColor(props.severity)};
  border-radius: 10px;
  width: 2px;
  margin: 2px 12px 2px 12px;
`;

const Message = styled.div`
  margin-left: 4px;
`;

const Path = styled.span`
  display: inline;
  cursor: pointer;
  &:hover {
    text-decoration: underline;
  }
`;

const RangeIndicator = styled.span`
  display: inline;
`;

const SeverityIcon = styled.span`
  height: 16px;
  width: 16px;
`;

export default class DiagnosticDetails extends React.Component<Props, State> {
  state: State;
  props: Props;
  static defaultProps: DefaultProps;
  convert: any;
  defaultRange: any;

  constructor(props: Props) {
    super(props);
    this.convert = new ansiToHtml();
    this.defaultRange = {
      start: { line: 0, character: 0 },
      end: { line: 0, character: 0 },
    };
  }

  convertMessageToHtml(message: string) {
    return this.convert.toHtml(
      message
        .replace(/(?:\r\n|\r|\n)/g, "
")
        .replace(/\t/g, "    ")
        .replace(/ /g, " "),
    );
  }

  render() {
    const Comp = this.props.view;
    return (
      <Box>
        {Comp ? (
          <Comp {...this.props.diagnostic} jumpToFile={this.props.jumpTo} />
        ) : (

              <SeverityIcon
                className={getSeverityClasses(this.props.diagnostic.severity)}
              />
              <Path
                className="text-highlight"
                onClick={e =>
                  this.props.jumpTo(
                    this.props.diagnostic.path || "",
                    this.props.diagnostic.range || this.defaultRange,
                    e.detail === 1,
                  )
                }
              >
                {path.basename(this.props.diagnostic.path || "")}
              </Path>
              {this.props.diagnostic.range &&
              this.props.diagnostic.range.start.line != -1 ? (
                <RangeIndicator className="text-subtle">
                  {`${this.props.diagnostic.range.start.line}:${
                    this.props.diagnostic.range.start.character
                  }`}
                </RangeIndicator>
              ) : (
                false
              )}

            <Content>
              <Severity severity={this.props.diagnostic.severity} />
              <Message
                dangerouslySetInnerHTML={{
                  __html: this.convertMessageToHtml(
                    this.props.diagnostic.message,
                  ),
                }}
              />
            </Content>

        )}
      </Box>
    );
  }
}

DiagnosticDetails.defaultProps = {};

type DefaultProps = {};

type Props = {
  view?: React.ComponentType<any>,
  diagnostic: MoleculeDiagnostic,
  jumpTo: (path: string, range: Range, pending: boolean) => void,
};

type State = {};
<commit_msg>Fixes diagnostics design (#385)<commit_after>"use babel";
// @flow

import * as React from "react";
import path from "path";
import styled from "styled-components";
import ansiToHtml from "ansi-to-html";
import type { MoleculeDiagnostic } from "../Types/types";
import type { Range } from "../../LanguageServerProtocolFeature/Types/standard";

const getSeverityColor = (severity: number) => {
  switch (severity) {
    case 1:
      return "red";
    case 2:
      return "yellow";
    case 3:
      return "blue";
    case 5:
      return "green";
    default:
      return "blue";
  }
};

const getSeverityClasses = (severity: any): string => {
  switch (severity) {
    case 3:
      return "diagnostic-color-info-text icon icon-info";
    case 2:
      return "diagnostic-color-warning-text icon icon-alert";
    case 1:
      return "diagnostic-color-error-text icon icon-issue-opened";
    case 5:
      return "diagnostic-color-success-text icon icon-check";
    default:
      return "";
  }
};

const Box = styled.div`
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  border-bottom: 1px black solid;
  border-radius: 3px;
  padding: 4px;
  align-items: stretch;
`;

const Header = styled.div`
  margin: 0px 4px 4px 4px;
  display: flex;
  flex: 0 0 auto;
`;

const Content = styled.div`
  display: flex;
  list-style: none;
  flex: 0 0 auto;
  align-items: stretch;
  flex-direction: row;
`;

const Severity = styled.div`
  background-color: ${props => getSeverityColor(props.severity)};
  border-radius: 10px;
  width: 2px;
  margin: 2px 12px 2px 12px;
`;

const Message = styled.div`
  margin-left: 4px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  flex: 0 0 auto;
`;

const Path = styled.span`
  display: inline;
  cursor: pointer;
  margin: 0px 8px;
  &:hover {
    text-decoration: underline;
  }
`;

const RangeIndicator = styled.span`
  display: inline;
`;

const SeverityIcon = styled.span`
  height: 16px;
  width: 16px;
`;

const HeaderAndContentBox = styled.div`
  display: flex;
  flex-direction: column;
  flex: 0 0 auto;
  align-items: stretch;
`;

const MessageBox = styled.div`
  display: flex;
  flex-direction: column;
  flex: 1 0 0;
  align-items: stretch;
`;

export default class DiagnosticDetails extends React.Component<Props, State> {
  state: State;
  props: Props;
  static defaultProps: DefaultProps;
  convert: any;
  defaultRange: any;

  constructor(props: Props) {
    super(props);
    this.convert = new ansiToHtml();
    this.defaultRange = {
      start: { line: 0, character: 0 },
      end: { line: 0, character: 0 },
    };
  }

  convertMessageToHtml(message: string) {
    return this.convert.toHtml(message.replace(/(?:\r\n|\r|\n)/g, "
"));
  }

  render() {
    const Comp = this.props.view;
    return (
      <Box>
        {Comp ? (
          <Comp {...this.props.diagnostic} jumpToFile={this.props.jumpTo} />
        ) : (
          <HeaderAndContentBox>

              <SeverityIcon
                className={getSeverityClasses(this.props.diagnostic.severity)}
              />
              <Path
                className="text-highlight"
                onClick={e =>
                  this.props.jumpTo(
                    this.props.diagnostic.path || "",
                    this.props.diagnostic.range || this.defaultRange,
                    e.detail === 1,
                  )
                }
              >
                {path.basename(this.props.diagnostic.path || "")}
              </Path>
              {this.props.diagnostic.range &&
              this.props.diagnostic.range.start.line != -1 ? (
                <RangeIndicator className="text-subtle">
                  {`${this.props.diagnostic.range.start.line}:${
                    this.props.diagnostic.range.start.character
                  }`}
                </RangeIndicator>
              ) : (
                false
              )}

            <Content>
              <Severity severity={this.props.diagnostic.severity} />
              <MessageBox>
                <Message
                  dangerouslySetInnerHTML={{
                    __html: this.convertMessageToHtml(
                      this.props.diagnostic.message,
                    ),
                  }}
                />
              </MessageBox>
            </Content>
          </HeaderAndContentBox>
        )}
      </Box>
    );
  }
}

DiagnosticDetails.defaultProps = {};

type DefaultProps = {};

type Props = {
  view?: React.ComponentType<any>,
  diagnostic: MoleculeDiagnostic,
  jumpTo: (path: string, range: Range, pending: boolean) => void,
};

type State = {};
<|endoftext|>


<commit_before>var commonTools = require('../base/commonTools');
module.exports = {
    'leaflet_05_findPathService': function (browser) {
        var type = 'leaflet';
        var exampleName = '05_findPathService';
        commonTools.openExampleAndLoadMap(browser, type, exampleName);
        /*check elements exist*/
        browser.waitForElementPresent('.leaflet-pane.leaflet-marker-pane', 10000);
        browser.waitForElementPresent('.leaflet-pane.leaflet-marker-pane img', 10000);
        browser.waitForElementPresent('.leaflet-pane.leaflet-overlay-pane', 10000);
        browser.waitForElementPresent('.leaflet-pane.leaflet-overlay-pane svg', 10000);
        browser.waitForElementPresent('.leaflet-pane.leaflet-overlay-pane svg g', 10000);
        browser.waitForElementPresent('.leaflet-pane.leaflet-overlay-pane svg g path', 10000);
        browser.pause(2000);
        browser.elements('class name', 'leaflet-marker-icon', function (result) {
            this.assert.equal(result.value.length, 34, "expect Number of marker to be 34, actual is " + result.value.length);
        });
        browser.elements('tag name', 'path', function (result) {
            this.assert.equal(result.value.length, 31, "expect Number of findPathService path to be 31, actual is " + result.value.length);
        });
        //测试版权点击的正确性
        //commonTools.verifyCopyrightOfLeaflet(browser);
        browser.pause(1000);
        browser.end();
    }
};<commit_msg>fix vt<commit_after>var commonTools = require('../base/commonTools');
module.exports = {
    'leaflet_05_findPathService': function (browser) {
        var type = 'leaflet';
        var exampleName = '05_findPathService';
        commonTools.openExampleAndLoadMap(browser, type, exampleName);
        /*check elements exist*/
        browser.waitForElementPresent('.leaflet-pane.leaflet-marker-pane', 10000);
        browser.waitForElementPresent('.leaflet-pane.leaflet-marker-pane img', 10000);
        browser.waitForElementPresent('.leaflet-pane.leaflet-overlay-pane', 10000);
        browser.waitForElementPresent('.leaflet-pane.leaflet-overlay-pane svg', 10000);
        browser.waitForElementPresent('.leaflet-pane.leaflet-overlay-pane svg g', 10000);
        browser.waitForElementPresent('.leaflet-pane.leaflet-overlay-pane svg g path', 10000);
        browser.pause(2000);
        browser.elements('class name', 'leaflet-marker-icon', function (result) {
            this.assert.equal(result.value.length, 34, "expect Number of marker to be 34, actual is " + result.value.length);
        });
        browser.elements('tag name', 'path', function (result) {
            this.assert.equal(result.value.length, 1, "expect Number of findPathService path to be 31, actual is " + result.value.length);
        });
        //测试版权点击的正确性
        //commonTools.verifyCopyrightOfLeaflet(browser);
        browser.pause(1000);
        browser.end();
    }
};<|endoftext|>


<commit_before>import $ from 'jquery'

import request from 'superagent'

import {
  AUTH_LOGOUT_REQUEST, AUTH_LOGOUT_SUCCESS, AUTH_LOGOUT_FAILURE
} from '../constants/ActionTypes'

export const AUTH_LOGIN_SUCCESS = 'AUTH_LOGIN_SUCCESS'

const loginSuccess = (user, credentials) => ({ type: AUTH_LOGIN_SUCCESS, user, credentials })

export const login = (values, dispatch) => {
  /*
   * this action apply behavior of redux-form 5.3.1 to asyncronos validation
   * http://redux-form.com/5.3.1/#/examples/submit-validation?_k=kld09s
   */
  return new Promise((resolve, reject) => {
    request
      .post(`${process.env.API_URL}/auth/sign_in`)
      .send({...values})
      .end((err, res) => {
        if (err && err.status === 401) {
          reject({ _error: res.body.errors.join('') })
        } else if (err) {
          reject({ _error: `Response Error: ${err.status}` })
        } else {
          const credentials = {
            "Access-Token": res.header['access-token'],
            "Expiry": res.header['expiry'],
            "Token-Type": res.header['token-type'],
            "Uid": res.header['uid'],
            "Client": res.header['client']
          }
          const user = res.body.data

          // Create a session into the server-side rendering server
          request.post(`/api/login`).send({ credentials, user })

          dispatch(loginSuccess(user, credentials))
          resolve()
        }
      })
  })
}

export function logout() {
  return function (dispatch) {
    dispatch(logoutRequest())

    return Auth.signOut().then(
      user => dispatch(logoutSuccess()),
      error => dispatch(logoutFailure(error.data.errors[0]))
    )
  }
}

export function logoutRequest() {
  return {
    type: AUTH_LOGOUT_REQUEST
  }
}

export function logoutSuccess() {
  return {
    type: AUTH_LOGOUT_SUCCESS
  }
}

export function logoutFailure(error) {
  return {
    type: AUTH_LOGOUT_FAILURE,
    error
  }
}
<commit_msg>Refactoring AuthActions to new async request stack. #154<commit_after>import axios from 'axios'

import {
  AUTH_LOGOUT_REQUEST,
  AUTH_LOGOUT_SUCCESS,
  AUTH_LOGOUT_FAILURE
} from '../constants/ActionTypes'

export const AUTH_LOGIN_SUCCESS = 'AUTH_LOGIN_SUCCESS'

const loginSuccess = (user, credentials) => ({ type: AUTH_LOGIN_SUCCESS, user, credentials })
const loginRequest = values => axios.post(`${process.env.API_URL}/auth/sign_in`, values)
export const login = values => dispatch => loginRequest(values)
  .then(response => {
    const { headers, data: { data: user } } = response
    const credentials = {
      'Access-Token': headers['access-token'],
      'Token-Type': headers['token-type'],
      Expiry: headers['expiry'],
      Uid: headers['uid'],
      Client: headers['client']
    }

    // Create a session into the server-side rendering server
    axios.post(`/api/login`, { credentials, user })

    dispatch(loginSuccess(user, credentials))
  })
  .catch(error => {
    if (error.response) {
      const { response: { data: { errors }, status, headers } } = error
      if (status === 401) return Promise.reject({ _error: errors.join('') })
    }
    return Promise.reject({ _error: `Response ${error}` })
  })

export const logoutRequest = () => ({ type: AUTH_LOGOUT_REQUEST })
export const logoutSuccess = () => ({ type: AUTH_LOGOUT_SUCCESS })
export const logoutFailure = error => ({ type: AUTH_LOGOUT_FAILURE, error })
export const logout = () => dispatch => {
  dispatch(logoutRequest())
  return Auth.signOut().then(
    user => dispatch(logoutSuccess()),
    error => dispatch(logoutFailure(error.data.errors[0]))
  )
}
<|endoftext|>


<commit_before>// Require
var url, http, request;
url = require('url');
http = require('http');
request = require('request');

// Don't crash when an error occurs, instead log it
process.on('uncaughtException', function(err){
	console.log(err);
});

// Create our server
var server;
server = http.createServer(function(req,res){
	// Set caching
	res.setHeader('Access-Control-Max-Age', 5*60*1000);  // 5 minutes

	// Set CORS headers
	res.setHeader('Access-Control-Allow-Origin', '*');
	res.setHeader('Access-Control-Request-Method', '*');
	res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
	res.setHeader('Access-Control-Allow-Headers', '*');
	if ( req.method === 'OPTIONS' ) {
		res.writeHead(200);
		res.end();
		return;
	}

	// Get the params
	var query = url.parse(req.url,true).query;
	var imageUrl = query.url || null;
	var callback = query.callback || null;
	// check for param existance, error if not
	if ( !imageUrl || !callback ) {
		console.log('Missing arguments');
		res.writeHead(400); // 400 = Bad Request
		res.end();
		return;
	}

	// request the image url
	request({
		url: imageUrl,
		method: 'GET',
		encoding: 'base64',
		timeout: 30*1000
	},function(err,imageRes,imageData){
		if ( !err && imageRes && imageRes.statusCode === 200 ) {
			res.setHeader('Content-Type', 'application/javascript');
			var imageContentType = imageRes.headers['content-type'];
			var responseData = 'data:'+imageContentType+';base64,'+imageData;
			res.write(callback+'('+JSON.stringify(responseData)+')');
			res.end();
			console.log('Sent image:', imageUrl);
			return;
		}
		else {
			console.log('Failed image:', imageUrl);
			res.writeHead(imageRes && imageRes.statusCode || 400); // bad request
			res.end();
			return;
		}
	});
});

// Start our server
server.listen(process.env.WEBSITEPORT || process.env.PORT || 8000, function() {
	var address = server.address();
	console.log("opened server on %j", address);
});

// Export
module.exports = server;<commit_msg>better error handling<commit_after>// Require
var url, http, request;
url = require('url');
http = require('http');
request = require('request');

// Don't crash when an error occurs, instead log it
process.on('uncaughtException', function(err){
	console.log(err);
});

// Create our server
var server;
server = http.createServer(function(req,res){
	// Set caching
	res.setHeader('Access-Control-Max-Age', 5*60*1000);  // 5 minutes

	// Set CORS headers
	res.setHeader('Access-Control-Allow-Origin', '*');
	res.setHeader('Access-Control-Request-Method', '*');
	res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
	res.setHeader('Access-Control-Allow-Headers', '*');
	if ( req.method === 'OPTIONS' ) {
		res.writeHead(200);
		res.end();
		return;
	}

	// Get the params
	var query = url.parse(req.url,true).query;
	var imageUrl = query.url || null;
	var callback = query.callback || null;
	// check for param existance, error if not
	if ( !imageUrl || !callback ) {
		console.log('Missing arguments');
		res.writeHead(400); // 400 = Bad Request
		res.end();
		return;
	}

	// request the image url
	request({
		url: imageUrl,
		method: 'GET',
		encoding: 'base64',
		timeout: 60*1000
	},function(err,imageRes,imageData){
		var responseData, imageContentType;
		if ( !err && imageRes && imageRes.statusCode === 200 ) {
			res.setHeader('Content-Type', 'application/javascript');
			imageContentType = imageRes.headers['content-type'];
			responseData = 'data:'+imageContentType+';base64,'+imageData;
			res.write(callback+'('+JSON.stringify(responseData)+')');
			res.end();
			console.log('Sent image:', imageUrl);
			return;
		}
		else {
			console.log('Failed image:', imageUrl);
			res.writeHead(imageRes && imageRes.statusCode || 400); // bad request
			responseData = JSON.stringify('error:Application error');
			res.write(callback+'('+responseData+')');
			res.end();
			return;
		}
	});
});

// Start our server
server.listen(process.env.WEBSITEPORT || process.env.PORT || 8000, function() {
	var address = server.address();
	console.log("opened server on %j", address);
});

// Export
module.exports = server;<|endoftext|>


<commit_before>import { createSelector } from 'reselect';

/**
 * Direct selector to the compteUtilisateur state domain
 */
const selectCompteUtilisateurDomain = () => (state) => state.compteUtilisateur;
/**
 * Other specific selectors
 */
export const selectUserId = () => (state, props) => props.params.userId;

/**
 * Default selector used by CompteUtilisateur
 */

export const selectCompteUtilisateur = () => createSelector(
  [selectCompteUtilisateurDomain()],
  (substate) => substate.auth
);

export const selectPayments = () => createSelector(
  selectCompteUtilisateurDomain(),
  (substate) => substate.payments.datas
);

export const selectPaymentsPagingToken = () => createSelector(
  selectCompteUtilisateurDomain(),
  (substate) => substate.payments.pagingToken
);

export const selectAuthUtilisateurId = () => createSelector(
  [selectCompteUtilisateur()],
  (auth) => (auth ? auth.id : undefined)
);

export const selectRoles = () => createSelector(
  [selectCompteUtilisateur()],
  (auth) => (auth ? auth.roles : undefined)
);

export const selectRelaiId = () => createSelector(
  [selectCompteUtilisateur()],
  (auth) => (auth ? auth.relaiId : undefined)
);

export const selectAuthApiKey = () => createSelector(
  [selectCompteUtilisateur()],
  (auth) => (auth ? auth.apiKey : undefined)
);

export const selectBalance = () => createSelector(
  selectCompteUtilisateurDomain(),
  (substate) => substate.balances.find((bal) => bal.asset_code === 'PROXI'),
);

export const selectMontantBalance = () => createSelector(
  selectBalance(),
  (balance) => parseFloat(balance.balance),
);

export const selectMaxBalance = () => createSelector(
  selectBalance(),
  (balance) => parseFloat(balance.limit),
);

export const selectLoading = () => createSelector(
  [selectCompteUtilisateurDomain()],
  (substate) => substate.loading
);

export const selectVirements = () => createSelector(
  selectCompteUtilisateurDomain(),
  (substate) => (
      substate.virements ?
        substate.virements.filter((dep) => dep.type === 'virement' && !dep.transfertEffectue) :
        null
    ),
);
<commit_msg>correction bug quand balance === null<commit_after>import { createSelector } from 'reselect';

/**
 * Direct selector to the compteUtilisateur state domain
 */
const selectCompteUtilisateurDomain = () => (state) => state.compteUtilisateur;
/**
 * Other specific selectors
 */
export const selectUserId = () => (state, props) => props.params.userId;

/**
 * Default selector used by CompteUtilisateur
 */

export const selectCompteUtilisateur = () => createSelector(
  [selectCompteUtilisateurDomain()],
  (substate) => substate.auth
);

export const selectPayments = () => createSelector(
  selectCompteUtilisateurDomain(),
  (substate) => substate.payments.datas
);

export const selectPaymentsPagingToken = () => createSelector(
  selectCompteUtilisateurDomain(),
  (substate) => substate.payments.pagingToken
);

export const selectAuthUtilisateurId = () => createSelector(
  [selectCompteUtilisateur()],
  (auth) => (auth ? auth.id : undefined)
);

export const selectRoles = () => createSelector(
  [selectCompteUtilisateur()],
  (auth) => (auth ? auth.roles : undefined)
);

export const selectRelaiId = () => createSelector(
  [selectCompteUtilisateur()],
  (auth) => (auth ? auth.relaiId : undefined)
);

export const selectAuthApiKey = () => createSelector(
  [selectCompteUtilisateur()],
  (auth) => (auth ? auth.apiKey : undefined)
);

export const selectBalance = () => createSelector(
  selectCompteUtilisateurDomain(),
  (substate) => substate.balances.find((bal) => bal.asset_code === 'PROXI'),
);

export const selectMontantBalance = () => createSelector(
  selectBalance(),
  (balance) => (balance ? parseFloat(balance.balance) : null),
);

export const selectMaxBalance = () => createSelector(
  selectBalance(),
  (balance) => parseFloat(balance.limit),
);

export const selectLoading = () => createSelector(
  [selectCompteUtilisateurDomain()],
  (substate) => substate.loading
);

export const selectVirements = () => createSelector(
  selectCompteUtilisateurDomain(),
  (substate) => (
      substate.virements ?
        substate.virements.filter((dep) => dep.type === 'virement' && !dep.transfertEffectue) :
        null
    ),
);
<|endoftext|>


<commit_before>import React from "react";
import "../../assets/stylesheets/application.css";
import { Link } from "react-router-dom";
import { setExistingContractParams, getNetworkVersion, getNetWorkNameById } from "../../utils/blockchainHelpers";
import { defaultCompanyStartDate } from "./utils";
import { defaultCompanyEndDate, gweiToWei, weiToGwei } from "../../utils/utils";
import { StepNavigation } from "../Common/StepNavigation";
import { InputField } from "../Common/InputField";
import { RadioInputField } from "../Common/RadioInputField";
import { CrowdsaleBlock } from "./CrowdsaleBlock";
import { WhitelistInputBlock } from "../Common/WhitelistInputBlock";
import {
  NAVIGATION_STEPS,
  VALIDATION_MESSAGES,
  VALIDATION_TYPES,
  TEXT_FIELDS,
  CONTRACT_TYPES,
  CHAINS
} from "../../utils/constants";
import { inject, observer } from "mobx-react";
import { Loader } from '../Common/Loader'
import { noGasPriceAvailable, warningOnMainnetAlert, mainnetIsOnMaintenance } from '../../utils/alerts'

const { CROWDSALE_SETUP } = NAVIGATION_STEPS;
const { EMPTY, VALID } = VALIDATION_TYPES;
const {
  START_TIME,
  END_TIME,
  MINCAP,
  RATE,
  SUPPLY,
  WALLET_ADDRESS,
  CROWDSALE_SETUP_NAME,
  ALLOWMODIFYING,
  ENABLE_WHITELISTING
} = TEXT_FIELDS;

@inject("contractStore", "crowdsaleBlockListStore", "pricingStrategyStore", "web3Store", "tierStore", "generalStore", "gasPriceStore", "reservedTokenStore")
@observer
export class stepThree extends React.Component {
  constructor(props) {
    super(props);
    const { contractStore, crowdsaleBlockListStore, tierStore, gasPriceStore } = props;
    window.scrollTo(0, 0);
    if (contractStore.crowdsale.addr.length > 0) {
      contractStore.setContractProperty("pricingStrategy", "addr", []);
      setExistingContractParams(contractStore.abi, contractStore.addr[0], contractStore.setContractProperty);
    }
    crowdsaleBlockListStore.emptyList();
    tierStore.setTierProperty("Tier 1", "tier", 0);
    tierStore.setTierProperty("off", "updatable", 0);
    tierStore.setTierProperty("no", "whitelistEnabled", 0);

    this.state = {
      loading: true,
      gasPriceSelected: gasPriceStore.slow.id
    }
  }

  showErrorMessages = parent => {
    this.props.tierStore.invalidateToken();
  };

  changeState = (event, parent, key, property) => {
    if (property.indexOf("whitelist_") === 0) {
      const { tierStore } = this.props;
      const whitelistInputProps = { ...tierStore.tiers[key].whitelistInput };
      const prop = property.split("_")[1];

      whitelistInputProps[prop] = event.target.value;
      tierStore.setTierProperty(whitelistInputProps, "whitelistInput", key);
    }
  };

  addCrowdsale() {
    const { crowdsaleBlockListStore, tierStore } = this.props;
    let num = crowdsaleBlockListStore.blockList.length + 1;
    const newTier = {
      tier: "Tier " + (num + 1),
      supply: 0,
      rate: 0,
      updatable: "off",
      whitelist: [],
      whitelistElements: [],
      whitelistInput: {}
    };

    const newTierValidations = {
      tier: VALID,
      startTime: VALID,
      endTime: VALID,
      supply: EMPTY,
      rate: EMPTY
    };

    tierStore.addTier(newTier);
    tierStore.addTierValidations(newTierValidations);
    this.addCrowdsaleBlock(num);
  }

  updateCrowdsaleBlockListStore = (event, property, index) => {
    const { crowdsaleBlockListStore } = this.props;
    const value = event.target.value;
    crowdsaleBlockListStore.setCrowdsaleBlockProperty(value, property, index);
    crowdsaleBlockListStore.validateCrowdsaleListBlockProperty(property, index);
  };

  updateTierStore = (event, property, index) => {
    const { tierStore } = this.props;
    const value = event.target.value;
    tierStore.setTierProperty(value, property, index);
    tierStore.validateTiers(property, index);
  };

  updatePricingStrategyStore = (event, index, property) => {
    const { pricingStrategyStore } = this.props;
    const value = event.target.value;
    pricingStrategyStore.setStrategyProperty(value, property, index);
  };

  goToDeploymentStage = () => {
    this.props.history.push('/4')
  }

  addCrowdsaleBlock(num) {
    this.props.crowdsaleBlockListStore.addCrowdsaleItem(<CrowdsaleBlock num={num} />);
  }

  renderLink() {
    return (

 this.addCrowdsale()} className="button button_fill_secondary">
          {" "}
          Add Tier

        <Link
          to={{ pathname: "/4", query: { state: this.state, changeState: this.changeState } }}
          onClick={e => this.beforeNavigate(e)}
          className="button button_fill"
        >
          Continue
        </Link>

    );
  }

  beforeNavigate = e => {
    e.preventDefault();
    e.stopPropagation();

    const { tierStore } = this.props;

    for (let index = 0; index < tierStore.tiers.length; index++) {
      tierStore.validateTiers("endTime", index);
      tierStore.validateTiers("startTime", index);
    }

    if (tierStore.areTiersValid) {
      getNetworkVersion()
        .then(networkID => {
          if (getNetWorkNameById(networkID) === CHAINS.MAINNET) {
            const { generalStore, reservedTokenStore } = this.props

            const tiersCount = tierStore.tiers.length
            const priceSelected = generalStore.gasPrice
            const reservedCount = reservedTokenStore.tokens.length
            let whitelistCount = 0

            if (tierStore.tiers[0].whitelistdisabled === 'no') {
              whitelistCount = tierStore.tiers.reduce((total, tier) => {
                total += tier.whitelist.filter(address => !address.deleted).length
                return total
              }, 0)
            }

            //return warningOnMainnetAlert(tiersCount, priceSelected, reservedCount, whitelistCount, this.goToDeploymentStage)
            return mainnetIsOnMaintenance()
          }
          this.goToDeploymentStage()
        })
        .catch(error => {
          console.error(error)
          this.showErrorMessages(e)
        })
    } else {
      this.showErrorMessages(e);
    }
  };

  componentDidMount() {
    const { tierStore, web3Store, gasPriceStore } = this.props;
    const { curAddress } = web3Store;
    tierStore.setTierProperty(curAddress, "walletAddress", 0);
    tierStore.setTierProperty(defaultCompanyStartDate(), "startTime", 0);
    tierStore.setTierProperty(defaultCompanyEndDate(tierStore.tiers[0].startTime), "endTime", 0);

    gasPriceStore.updateValues()
      .then(() => this.setGasPrice(gasPriceStore.slow))
      .catch(() => noGasPriceAvailable())
      .then(() => this.setState({ loading: false }))
  }

  setGasPrice({ id, price }) {
    this.setState({
      gasPriceSelected: id
    })

    // Don't modify the price when choosing custom
    if (id !== this.props.gasPriceStore.custom.id) {
      this.props.generalStore.setGasPrice(price)
    }
  }

  renderGasPriceInput() {
    const { generalStore, gasPriceStore } = this.props

    return (

        Gas Price

            <input
              type="radio"
              checked={this.state.gasPriceSelected === gasPriceStore.slow.id}
              name="gas-price-option-slow"
              onChange={() => this.setGasPrice(gasPriceStore.slow)}
              value="slow"
            />
            {gasPriceStore.slow.description()}

            <input
              type="radio"
              checked={this.state.gasPriceSelected === gasPriceStore.standard.id}
              name="gas-price-option-normal"
              onChange={() => this.setGasPrice(gasPriceStore.standard)}
              value="slow"
            />
            {gasPriceStore.standard.description()}

            <input
              type="radio"
              checked={this.state.gasPriceSelected === gasPriceStore.fast.id}
              name="gas-price-option-fast"
              onChange={() => this.setGasPrice(gasPriceStore.fast)}
              value="slow"
            />
            {gasPriceStore.fast.description()}

            <input
              type="radio"
              checked={this.state.gasPriceSelected === gasPriceStore.custom.id}
              name="gas-price-option-fast"
              onChange={() => this.setGasPrice(gasPriceStore.custom)}
              value="slow"
            />
            {gasPriceStore.custom.description()}

        {
          this.state.gasPriceSelected === gasPriceStore.custom.id ?
            <input
              className="input"
              style={{ display: 'inline-block' }}
              type="number"
              value={weiToGwei(generalStore.gasPrice)}
              onChange={(e) => generalStore.setGasPrice(gweiToWei(e.target.value))}
            /> :
            null
        }

Slow is cheap, fast is expensive

    );
  }

  updateWhitelistEnabled = (e) => {
    this.props.tierStore.setGlobalMinCap('')
    this.updateTierStore(e, "whitelistEnabled", 0)
  }

  render() {
    const { contractStore, crowdsaleBlockListStore, tierStore } = this.props;
    let globalSettingsBlock = (

Global settings

          <InputField
            side="left"
            type="text"
            title={WALLET_ADDRESS}
            value={tierStore.tiers[0].walletAddress}
            valid={tierStore.validTiers[0] && tierStore.validTiers[0].walletAddress}
            errorMessage={VALIDATION_MESSAGES.WALLET_ADDRESS}
            onChange={e => this.updateTierStore(e, "walletAddress", 0)}
            description={`Where the money goes after investors transactions. Immediately after each transaction. We recommend to setup a multisig wallet with hardware based signers.`}
          />
          {this.renderGasPriceInput()}

          <InputField
            side="left"
            type="number"
            disabled={tierStore.tiers[0].whitelistEnabled === "yes"}
            title={MINCAP}
            value={tierStore.globalMinCap}
            valid={VALID}
            errorMessage={VALIDATION_MESSAGES.MINCAP}
            onChange={e => tierStore.setGlobalMinCap(e.target.value)}
            description={`Minimum amount tokens to buy. Not a minimal size of a transaction. If minCap is 1 and user bought 1 token in a previous transaction and buying 0.1 token it will allow him to buy.`}
          />
          <RadioInputField
            extraClassName="right"
            title={ENABLE_WHITELISTING}
            items={[{ label: 'yes', value: 'yes' }, { label: 'no', value: 'no' }]}
            defaultValue={tierStore.tiers[0].whitelistEnabled}
            onChange={e => this.updateWhitelistEnabled(e)}
            description={`Enables whitelisting. If disabled, anyone can participate in the crowdsale.`}
          />

    );
    if (contractStore.contractType === CONTRACT_TYPES.whitelistwithcap) {
      let whitelistInputBlock = (

Whitelist

          <WhitelistInputBlock num={0} onChange={(e, cntrct, num, prop) => this.changeState(e, cntrct, 0, prop)} />

      );
      return (

          <StepNavigation activeStep={CROWDSALE_SETUP} />

Crowdsale setup

                The most important and exciting part of the crowdsale process. Here you can define parameters of your
                crowdsale campaign.

            {globalSettingsBlock}

          {/* First tier */}

                <InputField
                  extraClassName="left"
                  type="text"
                  title={CROWDSALE_SETUP_NAME}
                  value={tierStore.tiers[0].tier}
                  valid={tierStore.validTiers[0] && tierStore.validTiers[0].tier}
                  errorMessage={VALIDATION_MESSAGES.TIER}
                  onChange={e => this.updateTierStore(e, "tier", 0)}
                  description={`Name of a tier, e.g. PrePreIco, PreICO, ICO with bonus A, ICO with bonus B, etc. We simplified that and will increment a number after each tier.`}
                />
                <RadioInputField
                  extraClassName="right"
                  title={ALLOWMODIFYING}
                  items={[{ label: 'on', value: 'on' }, { label: 'off', value: 'off' }]}
                  onChange={e => this.updateTierStore(e, "updatable", 0)}
                  description={`Pandora box feature. If it's enabled, a creator of the crowdsale can modify Start time, End time, Rate, Limit after publishing.`}
                />

                <InputField
                  side="left"
                  type="datetime-local"
                  title={START_TIME}
                  value={tierStore.tiers[0].startTime}
                  valid={tierStore.validTiers[0] && tierStore.validTiers[0].startTime}
                  errorMessage={VALIDATION_MESSAGES.START_TIME}
                  onChange={e => this.updateTierStore(e, "startTime", 0)}
                  description={`Date and time when the tier starts. Can't be in the past from the current moment.`}
                />
                <InputField
                  side="right"
                  type="datetime-local"
                  title={END_TIME}
                  value={tierStore.tiers[0].endTime}
                  valid={tierStore.validTiers[0] && tierStore.validTiers[0].endTime}
                  errorMessage={VALIDATION_MESSAGES.END_TIME}
                  onChange={e => this.updateTierStore(e, "endTime", 0)}
                  description={`Date and time when the tier ends. Can be only in the future.`}
                />

                <InputField
                  side="left"
                  type="number"
                  title={RATE}
                  value={tierStore.tiers[0].rate}
                  valid={tierStore.validTiers[0] && tierStore.validTiers[0].rate}
                  errorMessage={VALIDATION_MESSAGES.RATE}
                  onChange={e => this.updateTierStore(e, "rate", 0)}
                  description={`Exchange rate Ethereum to Tokens. If it's 100, then for 1 Ether you can buy 100 tokens`}
                />
                <InputField
                  side="right"
                  type="number"
                  title={SUPPLY}
                  value={tierStore.tiers[0].supply}
                  valid={tierStore.validTiers[0] && tierStore.validTiers[0].supply}
                  errorMessage={VALIDATION_MESSAGES.SUPPLY}
                  onChange={e => this.updateTierStore(e, "supply", 0)}
                  description={`How many tokens will be sold on this tier. Cap of crowdsale equals to sum of supply of all tiers`}
                />

            {tierStore.tiers[0].whitelistEnabled === "yes" ? whitelistInputBlock : ""}

          {/* Other tiers */}

{crowdsaleBlockListStore.blockList}

{this.renderLink()}

          <Loader show={this.state.loading}/>

      );
    }
  }
}
<commit_msg>Make modifiable off by default<commit_after>import React from "react";
import "../../assets/stylesheets/application.css";
import { Link } from "react-router-dom";
import { setExistingContractParams, getNetworkVersion, getNetWorkNameById } from "../../utils/blockchainHelpers";
import { defaultCompanyStartDate } from "./utils";
import { defaultCompanyEndDate, gweiToWei, weiToGwei } from "../../utils/utils";
import { StepNavigation } from "../Common/StepNavigation";
import { InputField } from "../Common/InputField";
import { RadioInputField } from "../Common/RadioInputField";
import { CrowdsaleBlock } from "./CrowdsaleBlock";
import { WhitelistInputBlock } from "../Common/WhitelistInputBlock";
import {
  NAVIGATION_STEPS,
  VALIDATION_MESSAGES,
  VALIDATION_TYPES,
  TEXT_FIELDS,
  CONTRACT_TYPES,
  CHAINS
} from "../../utils/constants";
import { inject, observer } from "mobx-react";
import { Loader } from '../Common/Loader'
import { noGasPriceAvailable, warningOnMainnetAlert, mainnetIsOnMaintenance } from '../../utils/alerts'

const { CROWDSALE_SETUP } = NAVIGATION_STEPS;
const { EMPTY, VALID } = VALIDATION_TYPES;
const {
  START_TIME,
  END_TIME,
  MINCAP,
  RATE,
  SUPPLY,
  WALLET_ADDRESS,
  CROWDSALE_SETUP_NAME,
  ALLOWMODIFYING,
  ENABLE_WHITELISTING
} = TEXT_FIELDS;

@inject("contractStore", "crowdsaleBlockListStore", "pricingStrategyStore", "web3Store", "tierStore", "generalStore", "gasPriceStore", "reservedTokenStore")
@observer
export class stepThree extends React.Component {
  constructor(props) {
    super(props);
    const { contractStore, crowdsaleBlockListStore, tierStore, gasPriceStore } = props;
    window.scrollTo(0, 0);
    if (contractStore.crowdsale.addr.length > 0) {
      contractStore.setContractProperty("pricingStrategy", "addr", []);
      setExistingContractParams(contractStore.abi, contractStore.addr[0], contractStore.setContractProperty);
    }
    crowdsaleBlockListStore.emptyList();
    tierStore.setTierProperty("Tier 1", "tier", 0);
    tierStore.setTierProperty("off", "updatable", 0);
    tierStore.setTierProperty("no", "whitelistEnabled", 0);

    this.state = {
      loading: true,
      gasPriceSelected: gasPriceStore.slow.id
    }
  }

  showErrorMessages = parent => {
    this.props.tierStore.invalidateToken();
  };

  changeState = (event, parent, key, property) => {
    if (property.indexOf("whitelist_") === 0) {
      const { tierStore } = this.props;
      const whitelistInputProps = { ...tierStore.tiers[key].whitelistInput };
      const prop = property.split("_")[1];

      whitelistInputProps[prop] = event.target.value;
      tierStore.setTierProperty(whitelistInputProps, "whitelistInput", key);
    }
  };

  addCrowdsale() {
    const { crowdsaleBlockListStore, tierStore } = this.props;
    let num = crowdsaleBlockListStore.blockList.length + 1;
    const newTier = {
      tier: "Tier " + (num + 1),
      supply: 0,
      rate: 0,
      updatable: "off",
      whitelist: [],
      whitelistElements: [],
      whitelistInput: {}
    };

    const newTierValidations = {
      tier: VALID,
      startTime: VALID,
      endTime: VALID,
      supply: EMPTY,
      rate: EMPTY
    };

    tierStore.addTier(newTier);
    tierStore.addTierValidations(newTierValidations);
    this.addCrowdsaleBlock(num);
  }

  updateCrowdsaleBlockListStore = (event, property, index) => {
    const { crowdsaleBlockListStore } = this.props;
    const value = event.target.value;
    crowdsaleBlockListStore.setCrowdsaleBlockProperty(value, property, index);
    crowdsaleBlockListStore.validateCrowdsaleListBlockProperty(property, index);
  };

  updateTierStore = (event, property, index) => {
    const { tierStore } = this.props;
    const value = event.target.value;
    tierStore.setTierProperty(value, property, index);
    tierStore.validateTiers(property, index);
  };

  updatePricingStrategyStore = (event, index, property) => {
    const { pricingStrategyStore } = this.props;
    const value = event.target.value;
    pricingStrategyStore.setStrategyProperty(value, property, index);
  };

  goToDeploymentStage = () => {
    this.props.history.push('/4')
  }

  addCrowdsaleBlock(num) {
    this.props.crowdsaleBlockListStore.addCrowdsaleItem(<CrowdsaleBlock num={num} />);
  }

  renderLink() {
    return (

 this.addCrowdsale()} className="button button_fill_secondary">
          {" "}
          Add Tier

        <Link
          to={{ pathname: "/4", query: { state: this.state, changeState: this.changeState } }}
          onClick={e => this.beforeNavigate(e)}
          className="button button_fill"
        >
          Continue
        </Link>

    );
  }

  beforeNavigate = e => {
    e.preventDefault();
    e.stopPropagation();

    const { tierStore } = this.props;

    for (let index = 0; index < tierStore.tiers.length; index++) {
      tierStore.validateTiers("endTime", index);
      tierStore.validateTiers("startTime", index);
    }

    if (tierStore.areTiersValid) {
      getNetworkVersion()
        .then(networkID => {
          if (getNetWorkNameById(networkID) === CHAINS.MAINNET) {
            const { generalStore, reservedTokenStore } = this.props

            const tiersCount = tierStore.tiers.length
            const priceSelected = generalStore.gasPrice
            const reservedCount = reservedTokenStore.tokens.length
            let whitelistCount = 0

            if (tierStore.tiers[0].whitelistdisabled === 'no') {
              whitelistCount = tierStore.tiers.reduce((total, tier) => {
                total += tier.whitelist.filter(address => !address.deleted).length
                return total
              }, 0)
            }

            //return warningOnMainnetAlert(tiersCount, priceSelected, reservedCount, whitelistCount, this.goToDeploymentStage)
            return mainnetIsOnMaintenance()
          }
          this.goToDeploymentStage()
        })
        .catch(error => {
          console.error(error)
          this.showErrorMessages(e)
        })
    } else {
      this.showErrorMessages(e);
    }
  };

  componentDidMount() {
    const { tierStore, web3Store, gasPriceStore } = this.props;
    const { curAddress } = web3Store;
    tierStore.setTierProperty(curAddress, "walletAddress", 0);
    tierStore.setTierProperty(defaultCompanyStartDate(), "startTime", 0);
    tierStore.setTierProperty(defaultCompanyEndDate(tierStore.tiers[0].startTime), "endTime", 0);

    gasPriceStore.updateValues()
      .then(() => this.setGasPrice(gasPriceStore.slow))
      .catch(() => noGasPriceAvailable())
      .then(() => this.setState({ loading: false }))
  }

  setGasPrice({ id, price }) {
    this.setState({
      gasPriceSelected: id
    })

    // Don't modify the price when choosing custom
    if (id !== this.props.gasPriceStore.custom.id) {
      this.props.generalStore.setGasPrice(price)
    }
  }

  renderGasPriceInput() {
    const { generalStore, gasPriceStore } = this.props

    return (

        Gas Price

            <input
              type="radio"
              checked={this.state.gasPriceSelected === gasPriceStore.slow.id}
              name="gas-price-option-slow"
              onChange={() => this.setGasPrice(gasPriceStore.slow)}
              value="slow"
            />
            {gasPriceStore.slow.description()}

            <input
              type="radio"
              checked={this.state.gasPriceSelected === gasPriceStore.standard.id}
              name="gas-price-option-normal"
              onChange={() => this.setGasPrice(gasPriceStore.standard)}
              value="slow"
            />
            {gasPriceStore.standard.description()}

            <input
              type="radio"
              checked={this.state.gasPriceSelected === gasPriceStore.fast.id}
              name="gas-price-option-fast"
              onChange={() => this.setGasPrice(gasPriceStore.fast)}
              value="slow"
            />
            {gasPriceStore.fast.description()}

            <input
              type="radio"
              checked={this.state.gasPriceSelected === gasPriceStore.custom.id}
              name="gas-price-option-fast"
              onChange={() => this.setGasPrice(gasPriceStore.custom)}
              value="slow"
            />
            {gasPriceStore.custom.description()}

        {
          this.state.gasPriceSelected === gasPriceStore.custom.id ?
            <input
              className="input"
              style={{ display: 'inline-block' }}
              type="number"
              value={weiToGwei(generalStore.gasPrice)}
              onChange={(e) => generalStore.setGasPrice(gweiToWei(e.target.value))}
            /> :
            null
        }

Slow is cheap, fast is expensive

    );
  }

  updateWhitelistEnabled = (e) => {
    this.props.tierStore.setGlobalMinCap('')
    this.updateTierStore(e, "whitelistEnabled", 0)
  }

  render() {
    const { contractStore, crowdsaleBlockListStore, tierStore } = this.props;
    let globalSettingsBlock = (

Global settings

          <InputField
            side="left"
            type="text"
            title={WALLET_ADDRESS}
            value={tierStore.tiers[0].walletAddress}
            valid={tierStore.validTiers[0] && tierStore.validTiers[0].walletAddress}
            errorMessage={VALIDATION_MESSAGES.WALLET_ADDRESS}
            onChange={e => this.updateTierStore(e, "walletAddress", 0)}
            description={`Where the money goes after investors transactions. Immediately after each transaction. We recommend to setup a multisig wallet with hardware based signers.`}
          />
          {this.renderGasPriceInput()}

          <InputField
            side="left"
            type="number"
            disabled={tierStore.tiers[0].whitelistEnabled === "yes"}
            title={MINCAP}
            value={tierStore.globalMinCap}
            valid={VALID}
            errorMessage={VALIDATION_MESSAGES.MINCAP}
            onChange={e => tierStore.setGlobalMinCap(e.target.value)}
            description={`Minimum amount tokens to buy. Not a minimal size of a transaction. If minCap is 1 and user bought 1 token in a previous transaction and buying 0.1 token it will allow him to buy.`}
          />
          <RadioInputField
            extraClassName="right"
            title={ENABLE_WHITELISTING}
            items={[{ label: 'yes', value: 'yes' }, { label: 'no', value: 'no' }]}
            defaultValue={tierStore.tiers[0].whitelistEnabled}
            onChange={e => this.updateWhitelistEnabled(e)}
            description={`Enables whitelisting. If disabled, anyone can participate in the crowdsale.`}
          />

    );
    if (contractStore.contractType === CONTRACT_TYPES.whitelistwithcap) {
      let whitelistInputBlock = (

Whitelist

          <WhitelistInputBlock num={0} onChange={(e, cntrct, num, prop) => this.changeState(e, cntrct, 0, prop)} />

      );
      return (

          <StepNavigation activeStep={CROWDSALE_SETUP} />

Crowdsale setup

                The most important and exciting part of the crowdsale process. Here you can define parameters of your
                crowdsale campaign.

            {globalSettingsBlock}

          {/* First tier */}

                <InputField
                  extraClassName="left"
                  type="text"
                  title={CROWDSALE_SETUP_NAME}
                  value={tierStore.tiers[0].tier}
                  valid={tierStore.validTiers[0] && tierStore.validTiers[0].tier}
                  errorMessage={VALIDATION_MESSAGES.TIER}
                  onChange={e => this.updateTierStore(e, "tier", 0)}
                  description={`Name of a tier, e.g. PrePreIco, PreICO, ICO with bonus A, ICO with bonus B, etc. We simplified that and will increment a number after each tier.`}
                />
                <RadioInputField
                  extraClassName="right"
                  title={ALLOWMODIFYING}
                  items={[{ label: 'on', value: 'on' }, { label: 'off', value: 'off' }]}
                  defaultValue="off"
                  onChange={e => this.updateTierStore(e, "updatable", 0)}
                  description={`Pandora box feature. If it's enabled, a creator of the crowdsale can modify Start time, End time, Rate, Limit after publishing.`}
                />

                <InputField
                  side="left"
                  type="datetime-local"
                  title={START_TIME}
                  value={tierStore.tiers[0].startTime}
                  valid={tierStore.validTiers[0] && tierStore.validTiers[0].startTime}
                  errorMessage={VALIDATION_MESSAGES.START_TIME}
                  onChange={e => this.updateTierStore(e, "startTime", 0)}
                  description={`Date and time when the tier starts. Can't be in the past from the current moment.`}
                />
                <InputField
                  side="right"
                  type="datetime-local"
                  title={END_TIME}
                  value={tierStore.tiers[0].endTime}
                  valid={tierStore.validTiers[0] && tierStore.validTiers[0].endTime}
                  errorMessage={VALIDATION_MESSAGES.END_TIME}
                  onChange={e => this.updateTierStore(e, "endTime", 0)}
                  description={`Date and time when the tier ends. Can be only in the future.`}
                />

                <InputField
                  side="left"
                  type="number"
                  title={RATE}
                  value={tierStore.tiers[0].rate}
                  valid={tierStore.validTiers[0] && tierStore.validTiers[0].rate}
                  errorMessage={VALIDATION_MESSAGES.RATE}
                  onChange={e => this.updateTierStore(e, "rate", 0)}
                  description={`Exchange rate Ethereum to Tokens. If it's 100, then for 1 Ether you can buy 100 tokens`}
                />
                <InputField
                  side="right"
                  type="number"
                  title={SUPPLY}
                  value={tierStore.tiers[0].supply}
                  valid={tierStore.validTiers[0] && tierStore.validTiers[0].supply}
                  errorMessage={VALIDATION_MESSAGES.SUPPLY}
                  onChange={e => this.updateTierStore(e, "supply", 0)}
                  description={`How many tokens will be sold on this tier. Cap of crowdsale equals to sum of supply of all tiers`}
                />

            {tierStore.tiers[0].whitelistEnabled === "yes" ? whitelistInputBlock : ""}

          {/* Other tiers */}

{crowdsaleBlockListStore.blockList}

{this.renderLink()}

          <Loader show={this.state.loading}/>

      );
    }
  }
}
<|endoftext|>