<commit_before>// dependencies ----------------------------------------------------------------------

import React            from 'react';
import Reflux           from 'reflux';
import hello            from 'hellojs';
import async            from 'async';
import Actions          from './user.actions.js';
import config           from '../../../config';
import router           from '../utils/router-container';
import scitran          from '../utils/scitran';
import crn              from '../utils/crn';
import upload           from '../upload/upload.actions';
import dashboardActions from '../dashboard/datasets.actions';
import datasetActions   from '../dataset/dataset.actions';
import notifications    from '../notification/notification.actions';

hello.init({google: config.auth.google.clientID});

let UserStore = Reflux.createStore({

// store setup -----------------------------------------------------------------------

    listenables: Actions,

    init() {
        this.setInitialState();
    },

    getInitialState() {
        return this.data;
    },

// data ------------------------------------------------------------------------------

    data: {},

    update(data) {
        for (let prop in data) {this.data[prop] = data[prop];}
        this.trigger(this.data);
    },

    /**
     * Set Initial State
     *
     * Sets the state to the data object defined
     * inside the function. Also takes a diffs object
     * which will set the state to the initial state
     * with any differences passed.
     */
    setInitialState(diffs) {
        let data = {
            token: window.localStorage.hello ? JSON.parse(window.localStorage.hello).google.access_token : null,
            google: null,
            scitran: window.localStorage.scitranUser ? JSON.parse(window.localStorage.scitranUser) : null,
            loading: false,
            signinError: '',
            showUploadModal: false
        };
        for (let prop in diffs) {data[prop] = diffs[prop];}
        this.update(data);
    },

// Actions ---------------------------------------------------------------------------

    /**
     * Toggle Modal
     */
    toggleModal(name) {
        let updates = {};
        updates['show' + name + 'Modal'] = !this.data['show' + name + 'Modal'];
        this.update(updates);
    },

    /**
     * Initialize OAuth
     *
     * Initializes the OAuth libarary (hello.js) and checks
     * if a user is currently logged in.
     */
    initOAuth() {
        hello.init({google: config.auth.google.clientID}, {redirect_uri: '/'});
        this.checkUser();
    },

    /**
     * Check User
     *
     * Checks if the user has an active sessions and
     * if they do instatiates their session data.
     */
    checkUser() {
        var googleAuth = hello('google').getAuthResponse();
        var token = googleAuth && googleAuth.access_token ? googleAuth.access_token : null;

        if (token) {
            this.checkAuth((token) => {
                this.update({token: token});
                hello('google').api('/me').then((profile) => {
                    this.update({google: profile});
                    scitran.verifyUser((err, res) => {
                        window.localStorage.scitranUser = JSON.stringify(res.body);
                        this.update({scitran: res.body});
                    });
                }, () => {
                    this.setInitialState();
                });
            }, this.clearAuth);
        } else {
            this.setInitialState();
        }
    },

    /**
     * Signin
     *
     * Initiates the google OAuth2 sign in flow. Creates a new
     * user if the user doesn't already exist.
     */
    signIn(options) {
        let transition = options.hasOwnProperty('transition') ? options.transition : true;
        this.update({loading: true});
        hello('google').login({scope: 'email,openid'}, (res) => {
            if (res.error) {
                this.update({loading: false});
                return;
            }
            this.update({token: res.authResponse.access_token});
            hello(res.network).api('/me').then((profile) => {
                scitran.verifyUser((err, res) => {
                    if (res.status === 403) {
                        let user = {
                            _id: profile.email,
                            firstname: profile.first_name,
                            lastname: profile.last_name
                        };
                        crn.createUser(user, (err) => {
                            if (err) {
                                this.clearAuth();
                                let message = This user account has been blocked. If you believe this is by mistake please contact the site adminstrator.;
                                if (!transition) {
                                    notifications.createAlert({type: 'Error', message: message});
                                } else {
                                    this.update({
                                        loading: false,
                                        signinError: message
                                    });
                                }
                                return;
                            }
                            scitran.verifyUser((err, res) => {
                                this.handleSignIn(transition, res.body, profile);
                            });
                        });
                    } else if (res.status !== 200) {
                        this.clearAuth();
                        let message = 'We are currently experiencing issues. Please try again later.';
                        if (!transition) {
                            notifications.createAlert({type: 'Error', message: message});
                        } else {
                            this.update({
                                loading: false,
                                signinError: message
                            });
                        }
                    } else {
                        this.handleSignIn(transition, res.body, profile);
                    }
                });
            });
        }, () => {
            // signin failure
        });
    },

    /**
     * Handle Sign In
     *
     * Handles necessary action after a signin has been completed.
     */
    handleSignIn(transition, scitranUser, googleProfile) {
        window.localStorage.scitranUser = JSON.stringify(scitranUser);
        this.update({scitran: scitranUser, google: googleProfile, loading: false});
        if (transition) {
            router.transitionTo('dashboard');
        } else {
            datasetActions.reloadDataset();
            dashboardActions.getDatasets(true);
        }
    },

    /**
     * Sign Out
     *
     * Signs the user out by destroying the current
     * OAuth2 session.
     */
    signOut(uploadStatus) {
        let signout = true;
        if (uploadStatus === 'uploading') {
            signout = confirm('You are currently uploading files. Signing out of this site will cancel the upload process. Are you sure you want to sign out?');
        }
        if (signout) {
            hello('google').logout().then(() => {
                upload.setInitialState();
                this.clearAuth();
                router.transitionTo('signIn');
            }, () => {
                // signout failure
            });
        }
    },

    /**
     * Get Preferences
     *
     * Calls back with the current user's preferences.
     */
    getPreferences(callback) {
        callback(this.data.scitran.preferences);
    },

    /**
     * Update Preferences
     */
    updatePreferences(preferences, callback) {
        let scitranUser = this.data.scitran;
        scitranUser.preferences = scitranUser.preferences ? scitranUser.preferences : {};
        for (let key in preferences) {
            scitranUser.preferences[key] = preferences[key];
        }
        scitran.updateUser(this.data.scitran._id, {preferences: preferences}, (err, res) => {
            this.update({scitran: scitranUser});
            if (callback) {callback(err, res);}
        });
    },

// helper methods --------------------------------------------------------------------

    /**
     * Clear Authentication
     *
     * Clears all user related data from memory and
     * browser storage.
     */
    clearAuth() {
        delete window.localStorage.hello;
        delete window.localStorage.scitranUser;
        this.setInitialState({
            token: null,
            google: null,
            scitran: null
        });
    },

    /**
     * Has Token
     *
     * Returns a boolean representing whether or not
     * the current session has an access token present
     * regardless of whether or not is is expired/valid.
     */
    hasToken() {
        if (!window.localStorage.hello) {return false;}
        let credentials = JSON.parse(window.localStorage.hello);
        return credentials.hasOwnProperty('google') && credentials.google.hasOwnProperty('access_token') && credentials.google.access_token;
    },

    /**
     * Is Token Valid
     *
     * Returns a boolean representing whether or not the
     * current access token in valid.
     */
    isTokenValid() {
        var session = hello('google').getAuthResponse();
        var currentTime = (new Date()).getTime() / 1000;
        return session && session.access_token && session.expires > currentTime;
    },

// request queue ---------------------------------------------------------------------

    /**
     * Authentication Request Queuing
     *
     * Before any request we verify the status of the OAuth token.
     * To avoid multiple signin dialogues in the event the token
     * is expired all auth checking is queued to be performed
     * synchronously. The 'checkAuth' method is the primary method
     * to start the token check process.
     */
    queue: async.queue((authReq, callback) => {
        let currentAccount = window.localStorage.hasOwnProperty('scitranUser') ? JSON.parse(window.localStorage.scitranUser).email : '';
        hello('google').login({scope: 'email,openid', force: false, login_hint: currentAccount, display: 'none'}).then((res) => {
            authReq.successCallback(res.authResponse.access_token);
            callback();
        }, () => {
            authReq.errorCallback();
            callback();
        });
    }, 1),

    checkAuth(successCallback, errorCallback) {
        let authReq = {successCallback, errorCallback};
        this.queue.push(authReq);
    }

});

export default UserStore;
<commit_msg>Handled new error format for user creation with suppressed error status<commit_after>// dependencies ----------------------------------------------------------------------

import React            from 'react';
import Reflux           from 'reflux';
import hello            from 'hellojs';
import async            from 'async';
import Actions          from './user.actions.js';
import config           from '../../../config';
import router           from '../utils/router-container';
import scitran          from '../utils/scitran';
import crn              from '../utils/crn';
import upload           from '../upload/upload.actions';
import dashboardActions from '../dashboard/datasets.actions';
import datasetActions   from '../dataset/dataset.actions';
import notifications    from '../notification/notification.actions';

hello.init({google: config.auth.google.clientID});

let UserStore = Reflux.createStore({

// store setup -----------------------------------------------------------------------

    listenables: Actions,

    init() {
        this.setInitialState();
    },

    getInitialState() {
        return this.data;
    },

// data ------------------------------------------------------------------------------

    data: {},

    update(data) {
        for (let prop in data) {this.data[prop] = data[prop];}
        this.trigger(this.data);
    },

    /**
     * Set Initial State
     *
     * Sets the state to the data object defined
     * inside the function. Also takes a diffs object
     * which will set the state to the initial state
     * with any differences passed.
     */
    setInitialState(diffs) {
        let data = {
            token: window.localStorage.hello ? JSON.parse(window.localStorage.hello).google.access_token : null,
            google: null,
            scitran: window.localStorage.scitranUser ? JSON.parse(window.localStorage.scitranUser) : null,
            loading: false,
            signinError: '',
            showUploadModal: false
        };
        for (let prop in diffs) {data[prop] = diffs[prop];}
        this.update(data);
    },

// Actions ---------------------------------------------------------------------------

    /**
     * Toggle Modal
     */
    toggleModal(name) {
        let updates = {};
        updates['show' + name + 'Modal'] = !this.data['show' + name + 'Modal'];
        this.update(updates);
    },

    /**
     * Initialize OAuth
     *
     * Initializes the OAuth libarary (hello.js) and checks
     * if a user is currently logged in.
     */
    initOAuth() {
        hello.init({google: config.auth.google.clientID}, {redirect_uri: '/'});
        this.checkUser();
    },

    /**
     * Check User
     *
     * Checks if the user has an active sessions and
     * if they do instatiates their session data.
     */
    checkUser() {
        var googleAuth = hello('google').getAuthResponse();
        var token = googleAuth && googleAuth.access_token ? googleAuth.access_token : null;

        if (token) {
            this.checkAuth((token) => {
                this.update({token: token});
                hello('google').api('/me').then((profile) => {
                    this.update({google: profile});
                    scitran.verifyUser((err, res) => {
                        window.localStorage.scitranUser = JSON.stringify(res.body);
                        this.update({scitran: res.body});
                    });
                }, () => {
                    this.setInitialState();
                });
            }, this.clearAuth);
        } else {
            this.setInitialState();
        }
    },

    /**
     * Signin
     *
     * Initiates the google OAuth2 sign in flow. Creates a new
     * user if the user doesn't already exist.
     */
    signIn(options) {
        let transition = options.hasOwnProperty('transition') ? options.transition : true;
        this.update({loading: true});
        hello('google').login({scope: 'email,openid'}, (res) => {
            if (res.error) {
                this.update({loading: false});
                return;
            }
            this.update({token: res.authResponse.access_token});
            hello(res.network).api('/me').then((profile) => {
                scitran.verifyUser((err, res) => {
                    if (res.status === 403) {
                        let user = {
                            _id: profile.email,
                            firstname: profile.first_name,
                            lastname: profile.last_name
                        };
                        crn.createUser(user, (err, res) => {
                            if (res.body.status === 403) {
                                this.clearAuth();
                                let message = This user account has been blocked. If you believe this is by mistake please contact the site adminstrator.;
                                if (!transition) {
                                    notifications.createAlert({type: 'Error', message: message});
                                } else {
                                    this.update({
                                        loading: false,
                                        signinError: message
                                    });
                                }
                                return;
                            }
                            scitran.verifyUser((err, res) => {
                                this.handleSignIn(transition, res.body, profile);
                            });
                        });
                    } else if (res.status !== 200) {
                        this.clearAuth();
                        let message = 'We are currently experiencing issues. Please try again later.';
                        if (!transition) {
                            notifications.createAlert({type: 'Error', message: message});
                        } else {
                            this.update({
                                loading: false,
                                signinError: message
                            });
                        }
                    } else {
                        this.handleSignIn(transition, res.body, profile);
                    }
                });
            });
        }, () => {
            // signin failure
        });
    },

    /**
     * Handle Sign In
     *
     * Handles necessary action after a signin has been completed.
     */
    handleSignIn(transition, scitranUser, googleProfile) {
        window.localStorage.scitranUser = JSON.stringify(scitranUser);
        this.update({scitran: scitranUser, google: googleProfile, loading: false});
        if (transition) {
            router.transitionTo('dashboard');
        } else {
            datasetActions.reloadDataset();
            dashboardActions.getDatasets(true);
        }
    },

    /**
     * Sign Out
     *
     * Signs the user out by destroying the current
     * OAuth2 session.
     */
    signOut(uploadStatus) {
        let signout = true;
        if (uploadStatus === 'uploading') {
            signout = confirm('You are currently uploading files. Signing out of this site will cancel the upload process. Are you sure you want to sign out?');
        }
        if (signout) {
            hello('google').logout().then(() => {
                upload.setInitialState();
                this.clearAuth();
                router.transitionTo('signIn');
            }, () => {
                // signout failure
            });
        }
    },

    /**
     * Get Preferences
     *
     * Calls back with the current user's preferences.
     */
    getPreferences(callback) {
        callback(this.data.scitran.preferences);
    },

    /**
     * Update Preferences
     */
    updatePreferences(preferences, callback) {
        let scitranUser = this.data.scitran;
        scitranUser.preferences = scitranUser.preferences ? scitranUser.preferences : {};
        for (let key in preferences) {
            scitranUser.preferences[key] = preferences[key];
        }
        scitran.updateUser(this.data.scitran._id, {preferences: preferences}, (err, res) => {
            this.update({scitran: scitranUser});
            if (callback) {callback(err, res);}
        });
    },

// helper methods --------------------------------------------------------------------

    /**
     * Clear Authentication
     *
     * Clears all user related data from memory and
     * browser storage.
     */
    clearAuth() {
        delete window.localStorage.hello;
        delete window.localStorage.scitranUser;
        this.setInitialState({
            token: null,
            google: null,
            scitran: null
        });
    },

    /**
     * Has Token
     *
     * Returns a boolean representing whether or not
     * the current session has an access token present
     * regardless of whether or not is is expired/valid.
     */
    hasToken() {
        if (!window.localStorage.hello) {return false;}
        let credentials = JSON.parse(window.localStorage.hello);
        return credentials.hasOwnProperty('google') && credentials.google.hasOwnProperty('access_token') && credentials.google.access_token;
    },

    /**
     * Is Token Valid
     *
     * Returns a boolean representing whether or not the
     * current access token in valid.
     */
    isTokenValid() {
        var session = hello('google').getAuthResponse();
        var currentTime = (new Date()).getTime() / 1000;
        return session && session.access_token && session.expires > currentTime;
    },

// request queue ---------------------------------------------------------------------

    /**
     * Authentication Request Queuing
     *
     * Before any request we verify the status of the OAuth token.
     * To avoid multiple signin dialogues in the event the token
     * is expired all auth checking is queued to be performed
     * synchronously. The 'checkAuth' method is the primary method
     * to start the token check process.
     */
    queue: async.queue((authReq, callback) => {
        let currentAccount = window.localStorage.hasOwnProperty('scitranUser') ? JSON.parse(window.localStorage.scitranUser).email : '';
        hello('google').login({scope: 'email,openid', force: false, login_hint: currentAccount, display: 'none'}).then((res) => {
            authReq.successCallback(res.authResponse.access_token);
            callback();
        }, () => {
            authReq.errorCallback();
            callback();
        });
    }, 1),

    checkAuth(successCallback, errorCallback) {
        let authReq = {successCallback, errorCallback};
        this.queue.push(authReq);
    }

});

export default UserStore;
<|endoftext|>


<commit_before>import React, { Component } from 'react'
// components
import { Card, CardContent, CardHeader, Divider, Grid, withStyles } from '@material-ui/core'

import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import Typography from '@material-ui/core/Typography';
import Select from 'react-select';
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';
import AccountCircleIcon from '@material-ui/icons/AccountCircle';
import BusinessIcon from '@material-ui/icons/Business';

import EnhancedTable from './EnhancedTable';

import { emphasize } from '@material-ui/core/styles/colorManipulator';

// icons
import SearchIcon from '@material-ui/icons/Search';

const styles = theme => ({
  button: {
    margin: theme.spacing.unit,
  },
  leftIcon: {
    marginRight: theme.spacing.unit,
  },
  rightIcon: {
    marginLeft: theme.spacing.unit,
  },
  iconSmall: {
    fontSize: 20,
  },
  card: {
    margin: '30px'
  },
  root: {
    flexGrow: 1,
    height: 250,
  },
});

const options = [
  { label: 'Afghanistan' },
  { label: 'Aland Islands' },
  { label: 'Albania' },
  { label: 'Algeria' },
  { label: 'American Samoa' },
  { label: 'Andorra' },
  { label: 'Angola' },
  { label: 'Anguilla' },
  { label: 'Antarctica' },
  { label: 'Antigua and Barbuda' },
  { label: 'Argentina' },
  { label: 'Armenia' },
  { label: 'Aruba' },
  { label: 'Australia' },
  { label: 'Austria' },
  { label: 'Azerbaijan' },
  { label: 'Bahamas' },
  { label: 'Bahrain' },
  { label: 'Bangladesh' },
  { label: 'Barbados' },
  { label: 'Belarus' },
  { label: 'Belgium' },
  { label: 'Belize' },
  { label: 'Benin' },
  { label: 'Bermuda' },
  { label: 'Bhutan' },
  { label: 'Bolivia, Plurinational State of' },
  { label: 'Bonaire, Sint Eustatius and Saba' },
  { label: 'Bosnia and Herzegovina' },
  { label: 'Botswana' },
  { label: 'Bouvet Island' },
  { label: 'Brazil' },
  { label: 'British Indian Ocean Territory' },
  { label: 'Brunei Darussalam' },
].map(option => ({
  value: option.label,
  label: option.label,
}));

function TabContainer(props) {
  return (
    <Typography component="div" style={{ padding: 8 * 3 }}>
      {props.children}
    </Typography>
  );
}

class Search extends Component {
  constructor(props) {
    super(props);
  }

  state = {
    value: 0,
  };

  handleMenuChange = (event, value) => {
    this.setState({ value });
  };

  handleChange = name => value => {
    this.setState({
      [name]: value,
    });
  };

  handleTabChange = (event, value) => {
    this.setState({ value });
  };

  render () {

    const { value, toggle } = this.state;
    const { classes } = this.props;

    return <Card className={classes.card}>
        <CardHeader
            subheader='Find People or Busineses to Pay, Review & Earn Chlu'
        />
        <Tabs
          value={this.state.value}
          onChange={this.handleTabChange}
          fullWidth
          indicatorColor="secondary"
          textColor="secondary"
          centered
        >
          <Tab icon={<AccountCircleIcon />} label="People" />
          <Tab icon={<BusinessIcon />} label="Businesses" />
        </Tabs>

        <Divider/>
        <CardContent>

        {value === 0 && <TabContainer>
            <Grid container justify="space-evenly" alignItems="flex-end" spacing={16}>
              <Grid item xs={12} sm={12} md={2}>
                <Select
                  classes={classes}
                  options={options}
                  placeholder="Location"
                />
              </Grid>
              <Grid item xs={12} sm={12} md={3}>
                <TextField
                  id="search"
                  label="Name"
                  type="search"
                  fullWidth
                />
              </Grid>
              <Grid item xs={12} sm={12} md={2}>
                <Button variant="contained" color="secondary" className={classes.button}>
                  Search <SearchIcon className={classes.rightIcon} />
                </Button>
              </Grid>
            </Grid>
          </TabContainer>}
        {value === 1 && <TabContainer>
            <Grid container justify="space-evenly" alignItems="flex-end" spacing={16}>
              <Grid item xs={12} sm={12} md={2}>
                <Select
                  classes={classes}
                  options={options}
                  placeholder="Business Type"
                />
              </Grid>
              <Grid item xs={12} sm={12} md={2}>
                <Select
                  classes={classes}
                  options={options}
                  placeholder="Location"
                />
              </Grid>
              <Grid item xs={12} sm={12} md={3}>
                <TextField
                  id="search"
                  label="Name"
                  type="search"
                  fullWidth
                />
              </Grid>
              <Grid item xs={12} sm={12} md={2}>
                <Button variant="contained" color="secondary" className={classes.button}>
                  Search <SearchIcon className={classes.rightIcon} />
                </Button>
              </Grid>
            </Grid>
          </TabContainer>}

        <Divider/>
          <EnhancedTable/>
        </CardContent>
      </Card>
  }
}

export default withStyles(styles)(Search);
<commit_msg>styling<commit_after>import React, { Component } from 'react'
// components
import { Card, CardContent, CardHeader, Divider, Grid, withStyles } from '@material-ui/core'

import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import Typography from '@material-ui/core/Typography';
import Select from 'react-select';
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';
import AccountCircleIcon from '@material-ui/icons/AccountCircle';
import BusinessIcon from '@material-ui/icons/Business';

import EnhancedTable from './EnhancedTable';

import { emphasize } from '@material-ui/core/styles/colorManipulator';

// icons
import SearchIcon from '@material-ui/icons/Search';

const styles = theme => ({
  button: {
    margin: theme.spacing.unit,
  },
  leftIcon: {
    marginRight: theme.spacing.unit,
  },
  rightIcon: {
    marginLeft: theme.spacing.unit,
  },
  iconSmall: {
    fontSize: 20,
  },
  card: {
    margin: '30px'
  },
  root: {
    flexGrow: 1,
    height: 250,
  },
});

const options = [
  { label: 'Afghanistan' },
  { label: 'Aland Islands' },
  { label: 'Albania' },
  { label: 'Algeria' },
  { label: 'American Samoa' },
  { label: 'Andorra' },
  { label: 'Angola' },
  { label: 'Anguilla' },
  { label: 'Antarctica' },
  { label: 'Antigua and Barbuda' },
  { label: 'Argentina' },
  { label: 'Armenia' },
  { label: 'Aruba' },
  { label: 'Australia' },
  { label: 'Austria' },
  { label: 'Azerbaijan' },
  { label: 'Bahamas' },
  { label: 'Bahrain' },
  { label: 'Bangladesh' },
  { label: 'Barbados' },
  { label: 'Belarus' },
  { label: 'Belgium' },
  { label: 'Belize' },
  { label: 'Benin' },
  { label: 'Bermuda' },
  { label: 'Bhutan' },
  { label: 'Bolivia, Plurinational State of' },
  { label: 'Bonaire, Sint Eustatius and Saba' },
  { label: 'Bosnia and Herzegovina' },
  { label: 'Botswana' },
  { label: 'Bouvet Island' },
  { label: 'Brazil' },
  { label: 'British Indian Ocean Territory' },
  { label: 'Brunei Darussalam' },
].map(option => ({
  value: option.label,
  label: option.label,
}));

function TabContainer(props) {
  return (
    <Typography component="div" style={{ padding: 8 * 3 }}>
      {props.children}
    </Typography>
  );
}

class Search extends Component {
  constructor(props) {
    super(props);
  }

  state = {
    value: 0,
  };

  handleMenuChange = (event, value) => {
    this.setState({ value });
  };

  handleChange = name => value => {
    this.setState({
      [name]: value,
    });
  };

  handleTabChange = (event, value) => {
    this.setState({ value });
  };

  render () {

    const { value, toggle } = this.state;
    const { classes } = this.props;

    return <Card className={classes.card}>
        <Divider/>
        <CardContent>

        {value === 0 && <TabContainer>
            <Grid container justify="space-evenly" alignItems="flex-end" spacing={16}>
              <Grid item xs={12} sm={12} md={12}>
                <Typography variant="headline" align="center">
                  Search for people to pay and review
                </Typography>
              </Grid>
              <Grid item xs={12} sm={12} md={2}>
                <Select
                  classes={classes}
                  options={options}
                  placeholder="Location"
                />
              </Grid>
              <Grid item xs={12} sm={12} md={3}>
                <TextField
                  id="search"
                  label="Name"
                  type="search"
                  fullWidth
                />
              </Grid>
              <Grid item xs={12} sm={12} md={2}>
                <Button variant="contained" color="secondary" className={classes.button}>
                  Search <SearchIcon className={classes.rightIcon} />
                </Button>
              </Grid>
            </Grid>
          </TabContainer>}
        {value === 1 && <TabContainer>
            <Grid container justify="space-evenly" alignItems="flex-end" spacing={16}>
              <Grid item xs={12} sm={12} md={12}>
                <Typography variant="headline" align="center">
                  Search for businesses to pay and review
                </Typography>
              </Grid>
              <Grid item xs={12} sm={12} md={2}>
                <Select
                  classes={classes}
                  options={options}
                  placeholder="Business Type"
                />
              </Grid>
              <Grid item xs={12} sm={12} md={2}>
                <Select
                  classes={classes}
                  options={options}
                  placeholder="Location"
                />
              </Grid>
              <Grid item xs={12} sm={12} md={3}>
                <TextField
                  id="search"
                  label="Name"
                  type="search"
                  fullWidth
                />
              </Grid>
              <Grid item xs={12} sm={12} md={2}>
                <Button variant="contained" color="secondary" className={classes.button}>
                  Search <SearchIcon className={classes.rightIcon} />
                </Button>
              </Grid>
            </Grid>
          </TabContainer>}

          <Tabs
            value={this.state.value}
            onChange={this.handleTabChange}
            fullWidth
            indicatorColor="secondary"
            textColor="secondary"
            centered
          >
            <Tab icon={<AccountCircleIcon />} label="People" />
            <Tab icon={<BusinessIcon />} label="Businesses" />
          </Tabs>

        <Divider/>
          <EnhancedTable/>
        </CardContent>
      </Card>
  }
}

export default withStyles(styles)(Search);
<|endoftext|>


<commit_before>import React, { Component } from "react";
import Perf from "react-addons-perf";
Perf.start();
window.Perf = Perf;

import Connection from "./Connection";

class App extends Component {
  render() {
    return (
      <Connection/>
    );
  }
}

export default App;
<commit_msg>Turns off perf. Oops.<commit_after>import React, { Component } from "react";
// import Perf from "react-addons-perf";
// Perf.start();
// window.Perf = Perf;

import Connection from "./Connection";

class App extends Component {
  render() {
    return (
      <Connection/>
    );
  }
}

export default App;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import './App.css';
import Landing from './components/Landing';
import Instruction from './components/Instruction';
import Question from './components/Question';
import Result from './components/Result';
import Data from './api/Data';

const imagePath = (name) => "./images/" + name;

class App extends Component {
  constructor(props) {
    super(props);

    var state = {
      // state machine
      landingPage: true,
      instructionPage: false,
      questionPage: false,
      resultPage: false,

      // default values
      questionId: 0,

      // below will be filled once we load the data
      data: '',
      numQuestions: '',
      answerStat: '',
    }

    var stored = localStorage.getItem('state');
    if (stored !== null) {
      state = JSON.parse(stored);
    }
    this.state = state;
  }

  getResult() {
    var arr = this.state.answerStat;
    var idx = arr.indexOf(Math.max(...arr));
    return this.state.data.answers[idx]
  }

  componentWillMount() {
    this.setState({
      data: Data,
      numQuestions: Data.questions.length,
      answerStat: Array.from({ length: Data.answers.length }, () => 0),
    });

    // Prefetch caching
    var image = new Image();
    for (let q of Data.questions) {
      image.url = q.image;
    }
  }

  userClickedAnswer(i) {
    // We accumulate the state and move forward
    var id = this.state.questionId;
    var stat = this.state.answerStat;
    if (id < (this.state.numQuestions - 1) && id >= 0) {
      // Only when the user clicks `like` (1), we add the score.
      if (i === 1) {
        var answer = this.state.data.questions[id].answer;
        stat[answer] += 1;
      }

      this.setState({
        questionId: id + 1,
        answerStat: stat,
      });
    } else {
      // Finished so show result page?
      console.log(this.state.answerStat);

      this.setState({
        questionPage: false,
        resultPage: true,
      });
    }

    console.log(JSON.stringify(this.state.answerStat));
  }

  showInstruction() {
    this.setState({
      landingPage: false,
      instructionPage: true,
    })
  }

  showQuestion() {
    this.setState({
      instructionPage: false,
      questionPage: true,
    })
  }

  renderLanding() {
    var question = this.state.data.questions[0];
    return (
      <Landing buttonClicked={this.showInstruction.bind(this)}
               background={imagePath(question.image)} />
    )
  }

  renderInstruction() {
    var question = this.state.data.questions[0];
    return (
      <Instruction clicked={this.showQuestion.bind(this)}
                   background={imagePath(question.image)} />
    )
  }

  renderResult() {
    localStorage.clear();
    return (
      <Result result={this.getResult()} />
    );
  }

  renderQuestion() {
    var index = this.state.questionId;
    var question = this.state.data.questions[index];
    return (
      <Question image={imagePath(question.image)}
                answered={this.userClickedAnswer.bind(this)}
                current={index}
                total={this.state.numQuestions}/>
    );
  }

  render() {
    var page = {};
    if (this.state.landingPage) {
      page = this.renderLanding();
    } else if (this.state.instructionPage) {
      localStorage.setItem('state', JSON.stringify(this.state));
      page = this.renderInstruction();
    } else if (this.state.questionPage) {
      localStorage.setItem('state', JSON.stringify(this.state));
      page = this.renderQuestion();
    } else if (this.state.resultPage) {
      page = this.renderResult();
    }

    return (

        {page}

    )
  }
}

export default App;
<commit_msg>fix: no need to prefetch<commit_after>import React, { Component } from 'react';
import './App.css';
import Landing from './components/Landing';
import Instruction from './components/Instruction';
import Question from './components/Question';
import Result from './components/Result';
import Data from './api/Data';

const imagePath = (name) => "./images/" + name;

class App extends Component {
  constructor(props) {
    super(props);

    var state = {
      // state machine
      landingPage: true,
      instructionPage: false,
      questionPage: false,
      resultPage: false,

      // default values
      questionId: 0,

      // below will be filled once we load the data
      data: '',
      numQuestions: '',
      answerStat: '',
    }

    var stored = localStorage.getItem('state');
    if (stored !== null) {
      state = JSON.parse(stored);
    }
    this.state = state;
  }

  getResult() {
    var arr = this.state.answerStat;
    var idx = arr.indexOf(Math.max(...arr));
    return this.state.data.answers[idx]
  }

  componentWillMount() {
    this.setState({
      data: Data,
      numQuestions: Data.questions.length,
      answerStat: Array.from({ length: Data.answers.length }, () => 0),
    });
  }

  userClickedAnswer(i) {
    // We accumulate the state and move forward
    var id = this.state.questionId;
    var stat = this.state.answerStat;
    if (id < (this.state.numQuestions - 1) && id >= 0) {
      // Only when the user clicks `like` (1), we add the score.
      if (i === 1) {
        var answer = this.state.data.questions[id].answer;
        stat[answer] += 1;
      }

      this.setState({
        questionId: id + 1,
        answerStat: stat,
      });
    } else {
      // Finished so show result page?
      console.log(this.state.answerStat);

      this.setState({
        questionPage: false,
        resultPage: true,
      });
    }

    console.log(JSON.stringify(this.state.answerStat));
  }

  showInstruction() {
    this.setState({
      landingPage: false,
      instructionPage: true,
    })
  }

  showQuestion() {
    this.setState({
      instructionPage: false,
      questionPage: true,
    })
  }

  renderLanding() {
    var question = this.state.data.questions[0];
    return (
      <Landing buttonClicked={this.showInstruction.bind(this)}
               background={imagePath(question.image)} />
    )
  }

  renderInstruction() {
    var question = this.state.data.questions[0];
    return (
      <Instruction clicked={this.showQuestion.bind(this)}
                   background={imagePath(question.image)} />
    )
  }

  renderResult() {
    localStorage.clear();
    return (
      <Result result={this.getResult()} />
    );
  }

  renderQuestion() {
    var index = this.state.questionId;
    var question = this.state.data.questions[index];
    return (
      <Question image={imagePath(question.image)}
                answered={this.userClickedAnswer.bind(this)}
                current={index}
                total={this.state.numQuestions}/>
    );
  }

  render() {
    var page = {};
    if (this.state.landingPage) {
      page = this.renderLanding();
    } else if (this.state.instructionPage) {
      localStorage.setItem('state', JSON.stringify(this.state));
      page = this.renderInstruction();
    } else if (this.state.questionPage) {
      localStorage.setItem('state', JSON.stringify(this.state));
      page = this.renderQuestion();
    } else if (this.state.resultPage) {
      page = this.renderResult();
    }

    return (

        {page}

    )
  }
}

export default App;
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import { connect } from 'react-redux';
import {Sparklines} from 'react-sparkline';
import {SparklinesLine} from 'react-sparkline';
class WeatherList extends Component{
  renderWeather(cityData){
    const temps = cityData.list.map(weather => weather.main.temp);
    return(

        {cityData.city.name}

          <Sparklines height={120} width={180} data={temps}>
            <SparklinesLine color="red" />
          </Sparklines>

    );

  }
  render(){
      return(

            City
            Tempertaure
            Pressure
            Humidity

          {this.props.weather.map(this.renderWeather)}

      )
  }
}
function mapStateToProps({weather}){
  return( {weather}); // {weather} === {weather: weather} === {state = state.weather}
}
export default connect(mapStateToProps)(WeatherList);
<commit_msg>graphs fully running '<commit_after>import React, {Component} from 'react';
import { connect } from 'react-redux';
import {Sparklines} from 'react-sparklines';
import {SparklinesLine} from 'react-sparklines';
class WeatherList extends Component{
  renderWeather(cityData){
    const temps = cityData.list.map(weather => weather.main.temp);
    return(

        {cityData.city.name}

          <Sparklines height={120} width={180} data={temps}>
            <SparklinesLine color="red" />
          </Sparklines>

    );

  }
  render(){
      return(

            City
            Tempertaure
            Pressure
            Humidity

          {this.props.weather.map(this.renderWeather)}

      )
  }
}
function mapStateToProps({weather}){
  return( {weather}); // {weather} === {weather: weather} === {state = state.weather}
}
export default connect(mapStateToProps)(WeatherList);
<|endoftext|>


<commit_before>define([
    'app',
    'esri/symbols/SimpleFillSymbol',
    'esri/symbols/SimpleLineSymbol',
    'esri/renderers/ClassBreaksRenderer',
    'dojo/_base/Color'
], function(app, SimpleFillSymbol, SimpleLineSymbol, ClassBreaksRenderer, Color) {

    // define our map controller and register it with our app
    app.controller('MapCtrl', function($scope, $element, $attrs, $http, $filter) {

        angular.extend($scope, {
            statePrices: {},
            layer: null,
            map: null,
            loading: 'loading',
            load: function(evt) {
                var lyr = evt.layer;
                if (lyr) {
                    $scope.layer = lyr;
                    $scope.map = lyr._map;
                    lyr.fields.push({
                        name: 'GAS_DISPLAY',
                        type: 'esriFieldTypeSingle'
                    });
                    lyr.setDrawMode(false);
                    var unlisten = $scope.$on('layer.update-end', function(evt) {
                        unlisten();
                        $http.jsonp('http://apify.heroku.com/api/gasprices.json?callback=JSON_CALLBACK').
                        success(function(data) {
                            if (typeof(data) == 'string') {
                                data = JSON.parse(data);
                            }
                            $scope.loading = '';
                            $scope.drawFeatureLayer(data);
                        }).
                        error($scope.pricesError);
                    });
                }
            },

            drawFeatureLayer: function(data) {
                var lyr = $scope.layer;
                var range = parsePrices(data);
                var breaks = calcBreaks(range[0], range[1], 4);
                breaks.push(range[1].toFixed(2));
                var breakRenderer = createRenderer(breaks);
                lyr.setRenderer(breakRenderer);
                lyr.setDrawMode(true);
                lyr.redraw();
            },

            pricesError: function(e) {
                console.log('error getting gas price data: ', e);
            },

            mouseover: function(evt) {
                var price = evt.graphic && evt.graphic.attributes.GAS_DISPLAY;
                if (price) {
                    $scope.selectedPrice = evt.graphic.attributes.STATE_NAME + ' : ' + $filter('currency')(price);
                }
            },

            mouseout: function(evt) {
                $scope.selectedPrice = evt.graphic && '';
            }
        });

        function parsePrices(gasData) {
            var gmax = -Infinity,
                gmin = Infinity,
                layer = $scope.layer;
            angular.forEach(gasData, function(g) {
                if (["State","Alaska","Hawaii"].indexOf(g.state)<0) {
                    var price = parseFloat(g.regular.replace("$", "")).toFixed(2);
                    $scope.statePrices[g.state] = price;
                    if (price < gmin) {
                        gmin = price;
                    }
                    if (price > gmax) {
                        gmax = price;
                    }
                }
            });
            angular.forEach(layer.graphics, function(fg) {
                fg.attributes.GAS_DISPLAY = $scope.statePrices[fg.attributes.STATE_NAME];
            });
            return [gmin, gmax];
        }

        function createRenderer(breaks){
            var Sfs = SimpleFillSymbol;
            var outline = new SimpleLineSymbol("solid", new Color("#444"), 1);
            var br = new ClassBreaksRenderer(null, 'GAS_DISPLAY');
            br.setMaxInclusive(true);
            br.addBreak(breaks[0], breaks[1], new Sfs("solid", outline, new Color([255, 255, 178, 0.75])));
            br.addBreak(breaks[1], breaks[2], new Sfs("solid", outline, new Color([254, 204, 92, 0.75])));
            br.addBreak(breaks[2], breaks[3], new Sfs("solid", outline, new Color([253, 141, 60, 0.75])));
            br.addBreak(breaks[3], breaks[4], new Sfs("solid", outline, new Color([227, 26, 28, 0.75])));
            return br;
        }

        function calcBreaks(min, max, numberOfClasses) {
            var range = (max - min) / numberOfClasses;
            var breakValues = [];
            for ( var i = 0; i < numberOfClasses; i++ ) {
              breakValues[i] = (min + ( range * i )).toFixed(2);
            }
            return breakValues;
          }
    });
});<commit_msg>make sure we have numbers not strings<commit_after>define([
    'app',
    'esri/symbols/SimpleFillSymbol',
    'esri/symbols/SimpleLineSymbol',
    'esri/renderers/ClassBreaksRenderer',
    'dojo/_base/Color'
], function(app, SimpleFillSymbol, SimpleLineSymbol, ClassBreaksRenderer, Color) {

    // define our map controller and register it with our app
    app.controller('MapCtrl', function($scope, $element, $attrs, $http, $filter) {

        angular.extend($scope, {
            statePrices: {},
            layer: null,
            map: null,
            loading: 'loading',
            load: function(evt) {
                var lyr = evt.layer;
                if (lyr) {
                    $scope.layer = lyr;
                    $scope.map = lyr._map;
                    lyr.fields.push({
                        name: 'GAS_DISPLAY',
                        type: 'esriFieldTypeSingle'
                    });
                    lyr.setDrawMode(false);
                    var unlisten = $scope.$on('layer.update-end', function(evt) {
                        unlisten();
                        $http.jsonp('http://apify.heroku.com/api/gasprices.json?callback=JSON_CALLBACK').
                        success(function(data) {
                            if (typeof(data) == 'string') {
                                data = JSON.parse(data);
                            }
                            $scope.loading = '';
                            $scope.drawFeatureLayer(data);
                        }).
                        error($scope.pricesError);
                    });
                }
            },

            drawFeatureLayer: function(data) {
                var lyr = $scope.layer;
                var range = parsePrices(data);
                var breaks = calcBreaks(range[0], range[1], 4);
                breaks.push(range[1].toFixed(2));
                var breakRenderer = createRenderer(breaks);
                lyr.setRenderer(breakRenderer);
                lyr.setDrawMode(true);
                lyr.redraw();
            },

            pricesError: function(e) {
                console.log('error getting gas price data: ', e);
            },

            mouseover: function(evt) {
                var price = evt.graphic && evt.graphic.attributes.GAS_DISPLAY;
                if (price) {
                    $scope.selectedPrice = evt.graphic.attributes.STATE_NAME + ' : ' + $filter('currency')(price);
                }
            },

            mouseout: function(evt) {
                $scope.selectedPrice = evt.graphic && '';
            }
        });

        function parsePrices(gasData) {
            var gmax = -Infinity,
                gmin = Infinity,
                layer = $scope.layer;
            angular.forEach(gasData, function(g) {
                if (["State","Alaska","Hawaii"].indexOf(g.state)<0) {
                    var price = +parseFloat(g.regular.replace("$", "")).toFixed(2);
                    $scope.statePrices[g.state] = price;
                    if (price && price < gmin) {
                        gmin = price;
                    }
                    if (price > gmax) {
                        gmax = price;
                    }
                }
            });
            angular.forEach(layer.graphics, function(fg) {
                fg.attributes.GAS_DISPLAY = $scope.statePrices[fg.attributes.STATE_NAME];
            });
            return [gmin, gmax];
        }

        function createRenderer(breaks){
            var Sfs = SimpleFillSymbol;
            var outline = new SimpleLineSymbol("solid", new Color("#444"), 1);
            var br = new ClassBreaksRenderer(null, 'GAS_DISPLAY');
            br.setMaxInclusive(true);
            br.addBreak(breaks[0], breaks[1], new Sfs("solid", outline, new Color([255, 255, 178, 0.75])));
            br.addBreak(breaks[1], breaks[2], new Sfs("solid", outline, new Color([254, 204, 92, 0.75])));
            br.addBreak(breaks[2], breaks[3], new Sfs("solid", outline, new Color([253, 141, 60, 0.75])));
            br.addBreak(breaks[3], breaks[4], new Sfs("solid", outline, new Color([227, 26, 28, 0.75])));
            return br;
        }

        function calcBreaks(min, max, numberOfClasses) {
            var range = (max - min) / numberOfClasses;
            var breakValues = [];
            for ( var i = 0; i < numberOfClasses; i++ ) {
              breakValues[i] = (min + ( range * i )).toFixed(2);
            }
            return breakValues;
          }
    });
});<|endoftext|>


<commit_before>import "aframe";
import "aframe-animation-component";
import "aframe-particle-system-component";
import "aframe-teleport-controls";
import "aframe-environment-component";
import "aframe-physics-system";
import "aframe-extras";
import "aframe-event-set-component";
import "super-hands";
import { Entity, Scene } from "aframe-react";
import React from "react";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { color: "red" };
  }

  changeColor() {
    const colors = ["red", "orange", "yellow", "green", "blue"];
    this.setState({
      color: colors[Math.floor(Math.random() * colors.length)]
    });
  }

  render() {
    return (
      <Scene>
        <Entity environment="ground: canyon; groundYScale: 10; groundTexture: squares; dressing: mushrooms; dressingScale: 10; dressingAmount: 20" />
        {/* <a-box
          id="floorgeometry"
          static-body
          width="100"
          height="0.001"
          depth="100"
          visible="false"
        /> */}
        <a-entity
          static-body
          id="floorgeometry"
          position="0 0.15 0"
          // geometry="primitive: plane; width: 100; height: 100"
          // rotation="-90 0 0"
          geometry="primitive: box; width: 100; height: 0.001; depth: 100"
          visible="false"
        />
        <a-assets>
          {/* <img
            id="groundTexture"
            src="https://cdn.aframe.io/a-painter/images/floor.jpg"
            alt=""
          /> */}
          {/* <img
            id="skyTexture"
            src="https://cdn.aframe.io/a-painter/images/sky.jpg"
          /> */}

          <a-mixin
            id="cube"
            geometry="primitive: box; width: 0.33; height: 0.33; depth: 0.33"
            hoverable
            grabbable
            drag-droppable
            dynamic-body
          />
          <a-mixin
            id="cube-hovered"
            material="opacity: 0.7; transparent: true"
          />
          <a-mixin id="cube-dragover" material="wireframe: true;" />
        </a-assets>
        {/* <Entity obj-model="obj: #dyno-obj; mtl: #dyno-mtl" position="2 2 2" /> */}

        {/* <Entity
          primitive="a-plane"
          src="#groundTexture"
          rotation="-90 0 0"
          height="100"
          width="100"
        /> */}
        {/* <Entity primitive="a-light" type="ambient" color="#445451" /> */}
        {/* <Entity
          primitive="a-light"
          type="point"
          intensity="2"
          position="2 4 4"
        /> */}
        {/* <Entity
          primitive="a-sky"
          height="2048"
          radius="30"
          src="#skyTexture"
          theta-length="90"
          width="2048"
        /> */}
        {/* <Entity particle-system={{ preset: "snow", particleCount: 2000 }} /> */}
        {/* <Entity
          text={{ value: "Salut Michael!", align: "center" }}
          position={{ x: 0, y: 2, z: -1 }}
        /> */}

        <Entity
          dynamic-body
          hoverable
          grabbable
          drag-droppable
          geometry={{ primitive: "box" }}
          material={{ color: this.state.color, opacity: 0.6 }}
          position={{ x: 2, y: 1, z: -3 }}
          class="cube"
        />

        <Entity
          id="box"
          hoverable
          grabbable
          drag-droppable
          dynamic-body
          geometry={{ primitive: "box" }}
          material={{ color: this.state.color, opacity: 0.6 }}
          // animation__rotate={{
          //   property: "rotation",
          //   dur: 2000,
          //   loop: true,
          //   to: "360 360 360"
          // }}
          // animation__scale={{
          //   property: "scale",
          //   dir: "alternate",
          //   dur: 100,
          //   loop: true,
          //   to: "1.1 1.1 1.1"
          // }}
          position={{ x: 0, y: 1, z: -3 }}
          events={{ click: this.changeColor.bind(this) }}
          class="cube"
        >
          <Entity
            // animation__scale={{
            //   property: "scale",
            //   dir: "alternate",
            //   dur: 100,
            //   loop: true,
            //   to: "2 2 2"
            // }}
            geometry={{ primitive: "box", depth: 0.2, height: 0.2, width: 0.2 }}
            material={{ color: "#24CAFF" }}
          />
        </Entity>

        <a-entity
          class="cube"
          mixin="cube"
          position="0 0.265 -1"
          material="color: red"
        />
        <a-entity
          class="cube"
          mixin="cube"
          position="0 0.265 -0.5"
          material="color: red"
        />
        <a-entity
          class="cube"
          mixin="cube"
          position="-1 0.265 -1"
          material="color: blue"
        />
        <a-entity
          class="cube"
          mixin="cube"
          position="-1 0.265 -0.5"
          material="color: blue"
        />
        <a-entity
          class="cube"
          mixin="cube"
          position="1 0.265 -1"
          material="color: green"
        />
        <a-entity
          class="cube"
          mixin="cube"
          position="1 0.265 -0.5"
          material="color: green"
        />

        {/* <Entity primitive="a-camera">
          <Entity
            primitive="a-cursor"
            animation__click={{
              property: "scale",
              startEvents: "click",
              from: "0.1 0.1 0.1",
              to: "1 1 1",
              dur: 150
            }}
          />
        </Entity> */}

        <a-entity id="cameraRig">
          {/* <a-camera universal-controls="movementControls: gamepad" /> */}
          <a-camera />
          {/* <a-entity camera look-controls /> */}
          <a-entity
            class="right-controller"
            // teleport-controls="cameraRig: #cameraRig; button: trigger; collisionEntities: [class='cube'], #floorgeometry"
            teleport-controls="cameraRig: #cameraRig; button: trigger; maxLength: 200; type: line; collisionEntities: .environmentGround, .environmentDressing, .cube"
            // teleport-controls="cameraRig: #cameraRig; button: trigger; maxLength: 20; type: line; collisionEntities: .environmentGround, .environmentDressing, .cube"
            // teleport-controls="cameraRig: #cameraRig; button: trigger; maxLength: 20; type: line; collisionEntities: #floorgeometry"
            // teleport-controls="cameraRig: #cameraRig; button: trigger; maxLength: 20; type: line; collisionEntities: .environmentGround, .cube"
            // teleport-controls="cameraRig: #cameraRig; button: trigger; maxLength: 20; type: line; collisionEntities: .environmentGround, .cube, #floorgeometry"
            // teleport-controls="cameraRig: #cameraRig; button: trigger; maxLength: 20; type: line; collisionEntities: [class='cube'], [class='environmentGround']"
            // gearvr-controls
            laser-controls
            raycaster="objects: .cube"
            // line="color: red; opacity: 0.75"
            super-hands
          />
        </a-entity>
      </Scene>
    );
  }
}
export default App;
<commit_msg>keep the static-body floor at 1mm, not 15cm, remove some commented code<commit_after>import "aframe";
import "aframe-animation-component";
import "aframe-particle-system-component";
import "aframe-teleport-controls";
import "aframe-environment-component";
import "aframe-physics-system";
import "aframe-extras";
import "aframe-event-set-component";
import "super-hands";
import { Entity, Scene } from "aframe-react";
import React from "react";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { color: "red" };
  }

  changeColor() {
    const colors = ["red", "orange", "yellow", "green", "blue"];
    this.setState({
      color: colors[Math.floor(Math.random() * colors.length)]
    });
  }

  render() {
    return (
      <Scene>
        <Entity environment="ground: canyon; groundYScale: 10; groundTexture: squares; dressing: mushrooms; dressingScale: 10; dressingAmount: 20" />
        <a-box
          id="floorgeometry"
          static-body
          width="100"
          height="0.001"
          depth="100"
          visible="false"
        />
        <a-assets>
          {/* <img
            id="groundTexture"
            src="https://cdn.aframe.io/a-painter/images/floor.jpg"
            alt=""
          /> */}
          {/* <img
            id="skyTexture"
            src="https://cdn.aframe.io/a-painter/images/sky.jpg"
          /> */}

          <a-mixin
            id="cube"
            geometry="primitive: box; width: 0.33; height: 0.33; depth: 0.33"
            hoverable
            grabbable
            drag-droppable
            dynamic-body
          />
          <a-mixin
            id="cube-hovered"
            material="opacity: 0.7; transparent: true"
          />
          <a-mixin id="cube-dragover" material="wireframe: true;" />
        </a-assets>

        {/* <Entity
          primitive="a-plane"
          src="#groundTexture"
          rotation="-90 0 0"
          height="100"
          width="100"
        /> */}
        {/* <Entity primitive="a-light" type="ambient" color="#445451" /> */}
        {/* <Entity
          primitive="a-light"
          type="point"
          intensity="2"
          position="2 4 4"
        /> */}
        {/* <Entity
          primitive="a-sky"
          height="2048"
          radius="30"
          src="#skyTexture"
          theta-length="90"
          width="2048"
        /> */}
        {/* <Entity particle-system={{ preset: "snow", particleCount: 2000 }} /> */}
        {/* <Entity
          text={{ value: "Salut Michael!", align: "center" }}
          position={{ x: 0, y: 2, z: -1 }}
        /> */}

        <Entity
          dynamic-body
          hoverable
          grabbable
          drag-droppable
          geometry={{ primitive: "box" }}
          material={{ color: this.state.color, opacity: 0.6 }}
          position={{ x: 2, y: 1, z: -3 }}
          class="cube"
        />

        <Entity
          id="box"
          hoverable
          grabbable
          drag-droppable
          dynamic-body
          geometry={{ primitive: "box" }}
          material={{ color: this.state.color, opacity: 0.6 }}
          // animation__rotate={{
          //   property: "rotation",
          //   dur: 2000,
          //   loop: true,
          //   to: "360 360 360"
          // }}
          // animation__scale={{
          //   property: "scale",
          //   dir: "alternate",
          //   dur: 100,
          //   loop: true,
          //   to: "1.1 1.1 1.1"
          // }}
          position={{ x: 0, y: 1, z: -3 }}
          events={{ click: this.changeColor.bind(this) }}
          class="cube"
        >
          <Entity
            // animation__scale={{
            //   property: "scale",
            //   dir: "alternate",
            //   dur: 100,
            //   loop: true,
            //   to: "2 2 2"
            // }}
            geometry={{ primitive: "box", depth: 0.2, height: 0.2, width: 0.2 }}
            material={{ color: "#24CAFF" }}
          />
        </Entity>

        <a-entity
          class="cube"
          mixin="cube"
          position="0 0.265 -1"
          material="color: red"
        />
        <a-entity
          class="cube"
          mixin="cube"
          position="0 0.265 -0.5"
          material="color: red"
        />
        <a-entity
          class="cube"
          mixin="cube"
          position="-1 0.265 -1"
          material="color: blue"
        />
        <a-entity
          class="cube"
          mixin="cube"
          position="-1 0.265 -0.5"
          material="color: blue"
        />
        <a-entity
          class="cube"
          mixin="cube"
          position="1 0.265 -1"
          material="color: green"
        />
        <a-entity
          class="cube"
          mixin="cube"
          position="1 0.265 -0.5"
          material="color: green"
        />

        {/* <Entity primitive="a-camera">
          <Entity
            primitive="a-cursor"
            animation__click={{
              property: "scale",
              startEvents: "click",
              from: "0.1 0.1 0.1",
              to: "1 1 1",
              dur: 150
            }}
          />
        </Entity> */}

        <a-entity id="cameraRig">
          {/* <a-camera universal-controls="movementControls: gamepad" /> */}
          <a-camera />
          {/* <a-entity camera look-controls /> */}
          <a-entity
            class="right-controller"
            teleport-controls="cameraRig: #cameraRig; button: trigger; maxLength: 200; type: line; collisionEntities: .environmentGround, .environmentDressing, .cube"
            // gearvr-controls
            laser-controls
            raycaster="objects: .cube"
            // line="color: red; opacity: 0.75"
            super-hands
          />
        </a-entity>
      </Scene>
    );
  }
}
export default App;
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import ProfileUploadField from './ProfileUploadField';
import AddonScreenshot from '../../../res/gecko-profiler-screenshot-2016-12-06.png';

require('./Home.css');

const InstallButton = ({ name, xpiURL, children }) => {
  return  {
    if (window.InstallTrigger) {
      window.InstallTrigger.install({ [name]: xpiURL });
    }
    e.preventDefault();
  }}>{children};
};

InstallButton.propTypes = {
  name: PropTypes.string.isRequired,
  xpiURL: PropTypes.string.isRequired,
  children: PropTypes.node,
};

const Home = ({ className, profilerURL }) => {
  return (

      <section className={`${className}-text`}>

perf.html - UI for the Gecko Profiler

Welcome to perf.html. You can look at profiles here.

          Capture profiles using
          the <InstallButton name='Gecko Profiler' xpiURL={profilerURL}>new
          version of the gecko profiler addon</InstallButton>.
          You can control the profiler with the following two
          shortcuts:

Ctrl+Shift+1: Stop / Restart profiling

Ctrl+Shift+2: Capture the profile and open up this interface.

          You can also open a profile that you've saved to a file:

          <ProfileUploadField />

  );
};

Home.propTypes = {
  className: PropTypes.string.isRequired,
  profilerURL: PropTypes.string.isRequired,
};

export default connect(() => ({
  className: 'home',
  profilerURL: 'https://raw.githubusercontent.com/mstange/Gecko-Profiler-Addon/master/gecko_profiler.xpi',
}))(Home);
<commit_msg>Make the addon installation link point to the devtools-html/Gecko-Profiler-Addon repo.<commit_after>import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import ProfileUploadField from './ProfileUploadField';
import AddonScreenshot from '../../../res/gecko-profiler-screenshot-2016-12-06.png';

require('./Home.css');

const InstallButton = ({ name, xpiURL, children }) => {
  return  {
    if (window.InstallTrigger) {
      window.InstallTrigger.install({ [name]: xpiURL });
    }
    e.preventDefault();
  }}>{children};
};

InstallButton.propTypes = {
  name: PropTypes.string.isRequired,
  xpiURL: PropTypes.string.isRequired,
  children: PropTypes.node,
};

const Home = ({ className, profilerURL }) => {
  return (

      <section className={`${className}-text`}>

perf.html - UI for the Gecko Profiler

Welcome to perf.html. You can look at profiles here.

          Capture profiles using
          the <InstallButton name='Gecko Profiler' xpiURL={profilerURL}>new
          version of the gecko profiler addon</InstallButton>.
          You can control the profiler with the following two
          shortcuts:

Ctrl+Shift+1: Stop / Restart profiling

Ctrl+Shift+2: Capture the profile and open up this interface.

          You can also open a profile that you've saved to a file:

          <ProfileUploadField />

  );
};

Home.propTypes = {
  className: PropTypes.string.isRequired,
  profilerURL: PropTypes.string.isRequired,
};

export default connect(() => ({
  className: 'home',
  profilerURL: 'https://raw.githubusercontent.com/devtools-html/Gecko-Profiler-Addon/master/gecko_profiler.xpi',
}))(Home);
<|endoftext|>


<commit_before>var async = require('async'),
	request = require('request'),
	assembleGadget = require('./factory').assembleGadget,
	error = require('../lib/error');

module.exports = assembleGadget({
	name: 'Gcal',
	account: 'Google',
	uri: 'https://www.google.com/calendar/',
	update: function(app, callback) {
		var account = this.user.accounts.google,
			that = this;

		var tasks = [ ];

		//Request new access token after expiry
		if (account.expires <= new Date) {
			tasks.push(function(callback) {
				var google = require('../accounts/google');

				google.refresh(app, account.refresh_token, function(err, result) {
					if (error(err, callback)) return;

					//Store new token; it will later be saved together with all other user data
					for (var key in result) {
						that.user.accounts.google[key] = result[key];
					}

					account = that.user.accounts.google;

					callback();
				});
			});
		}

		//Update calendar list every 24h
		if (!this.data.calendars ||
			+new Date - this.data.lastCalendarUpdate >= 24 * 60 * 60 * 1000)
		{
			tasks.push(updateCalendars);
		}

		//Check each calendar for events
		tasks.push(checkForEvents);

		async.waterfall(tasks, callback);

		function updateCalendars(callback) {
			request({
				url: 'https://www.googleapis.com/calendar/v3/users/me/calendarList',
				qs: {
					minAccessRole: 'reader',
					access_token: account.token
				},
				strictSSL: true
			}, function(err, res, body) {
				if (error(err, res, callback)) return;

				try {
					//Parse calendar list
					var doc = JSON.parse(body);
					that.data.calendars = [ ];

					for (var i = 0; i < doc.items.length; i++) {
						//Exclude Google holiday calendars
						if (!/#holiday@group\.v\.calendar\.google\.com/.test(doc.items[i].id)) {
							that.data.calendars.push(doc.items[i].id);
						}
					}

					that.data.lastCalendarUpdate = new Date;

					callback();
				} catch (err) {
					error(err, res, callback);
				}
			});
		}

		function isToday(dateString) {
			//Extract timezone from ISO 8601 date string
			var timezone = /(([+-])(\d\d):(\d\d)|Z)$/.exec(dateString),
				offset = 0;

			//If not UTC, compute offset in minutes
			if (timezone[0] !== 'Z') {
				offset = parseInt(timezone[3]) * 60 + parseInt(timezone[4]);

				if (timezone[2] === '-') {
					offset = -offset;
				}
			}

			//Add local timezone offset
			offset += new Date().getTimezoneOffset();

			var serverNow = new Date;

			//Determine local time
			localNow = new Date(+serverNow + offset * 60 * 1000);

			//Determine local day start in server time
			var localDayStart = new Date(+serverNow -
				localNow.getHours() * 60 * 60 * 1000 -
				localNow.getMinutes() * 60 * 1000 -
				localNow.getSeconds() * 1000 -
				localNow.getMilliseconds());

			//Determine local day end in server time
			var localDayEnd = new Date(+localDayStart + 24 * 60 * 60 * 1000);

			//Parse local date (and thereby convert to server time)
			var localDate = new Date(dateString);

			//Check if given date is local today
			return localDate >= localDayStart &&
				localDate <= localDayEnd;
		}

		function checkForEvents(callback) {
			//We do not know the calendar's timezone, so we initially
			//look for all events in UTC-12 to UTC+14.
			//toISOString() returns the date in UTC, so we don't have to
			//worry about the server timezone.
			var start = new Date;
			start.setHours(0);
			start.setMinutes(0);
			start = new Date(+start - 14 * 60 * 60 * 1000);

			var end = new Date(+start + 50 * 60 * 60 * 1000);

			//Request events from every calendar
			async.map(that.data.calendars, function(calendarId, callback) {
				request({
					url: 'https://www.googleapis.com/calendar/v3/calendars/' +
						encodeURIComponent(calendarId) + '/events',
					qs: {
						timeMin: start.toISOString(),
						timeMax: end.toISOString(),
						access_token: account.token
					},
					strictSSL: true
				}, function(err, res, body) {
					if (error(err, res, callback)) return;

					try {
						//Parse response
						var doc = JSON.parse(body),
							events = 0;

						//Count today's events
						for (var i = 0; i < doc.items.length; i++) {
							//Events spanning multiple days only have
							//start.date and end.date set
							if (doc.items[i].start &&
								doc.items[i].end &&
								doc.items[i].start.dateTime &&
								doc.items[i].start.dateTime &&
								(isToday(doc.items[i].start.dateTime) ||
								isToday(doc.items[i].end.dateTime)))
							{
								events++;
							}
						}

						callback(null, events);
					} catch (err) {
						error(err, res, callback, true);
					}
				});
			}, function(err, results) {
				if (error(err, callback)) return;

				//Sum up today's events from all calendars
				var totalEvents = 0;

				for (var i = 0; i < results.length; i++) {
					totalEvents += results[i];
				}

				callback(null, { value: totalEvents });
			});
		}
	},
	checkAvailability: function(app, callback) {
		var token = this.user.accounts.google.token;

		request({
			url: 'https://www.googleapis.com/calendar/v3/users/me/calendarList',
			qs: {
				minAccessRole: 'reader',
				access_token: token
			},
			strictSSL: true
		}, function(err, res, body) {
			if (err) return callback(false);

			if (res.statusCode !== 200) {
				return callback(false);
			}

			try {
				//Parse calendar list
				var doc = JSON.parse(body);
				callback(doc.items.length > 0);
			} catch (err) {
				callback(false);
			}
		});
	},
	intervals: [
		          5 * 60,            30, //5m after login, update every 30s
		     3 * 60 * 60,       10 * 60, //3h after login, update every 10m
		    24 * 60 * 60,       30 * 60, //1d after login, update every 30m
		7 * 24 * 60 * 60,   5 * 60 * 60 // 1w after login, update every 5h
	]
});<commit_msg>Only fetching necessary fields from Gcal<commit_after>var async = require('async'),
	request = require('request'),
	assembleGadget = require('./factory').assembleGadget,
	error = require('../lib/error');

module.exports = assembleGadget({
	name: 'Gcal',
	account: 'Google',
	uri: 'https://www.google.com/calendar/',
	update: function(app, callback) {
		var account = this.user.accounts.google,
			that = this;

		var tasks = [ ];

		//Request new access token after expiry
		if (account.expires <= new Date) {
			tasks.push(function(callback) {
				var google = require('../accounts/google');

				google.refresh(app, account.refresh_token, function(err, result) {
					if (error(err, callback)) return;

					//Store new token; it will later be saved together with all other user data
					for (var key in result) {
						that.user.accounts.google[key] = result[key];
					}

					account = that.user.accounts.google;

					callback();
				});
			});
		}

		//Update calendar list every 24h
		if (!this.data.calendars ||
			+new Date - this.data.lastCalendarUpdate >= 24 * 60 * 60 * 1000)
		{
			tasks.push(updateCalendars);
		}

		//Check each calendar for events
		tasks.push(checkForEvents);

		async.waterfall(tasks, callback);

		function updateCalendars(callback) {
			request({
				url: 'https://www.googleapis.com/calendar/v3/users/me/calendarList',
				qs: {
					minAccessRole: 'reader',
					fields: 'items/id',
					access_token: account.token
				},
				strictSSL: true
			}, function(err, res, body) {
				if (error(err, res, callback)) return;

				try {
					//Parse calendar list
					var doc = JSON.parse(body);
					that.data.calendars = [ ];

					for (var i = 0; i < doc.items.length; i++) {
						//Exclude Google holiday calendars
						if (!/#holiday@group\.v\.calendar\.google\.com/.test(doc.items[i].id)) {
							that.data.calendars.push(doc.items[i].id);
						}
					}

					that.data.lastCalendarUpdate = new Date;

					callback();
				} catch (err) {
					error(err, res, callback);
				}
			});
		}

		function isToday(dateString) {
			//Extract timezone from ISO 8601 date string
			var timezone = /(([+-])(\d\d):(\d\d)|Z)$/.exec(dateString),
				offset = 0;

			//If not UTC, compute offset in minutes
			if (timezone[0] !== 'Z') {
				offset = parseInt(timezone[3]) * 60 + parseInt(timezone[4]);

				if (timezone[2] === '-') {
					offset = -offset;
				}
			}

			//Add local timezone offset
			offset += new Date().getTimezoneOffset();

			var serverNow = new Date;

			//Determine local time
			localNow = new Date(+serverNow + offset * 60 * 1000);

			//Determine local day start in server time
			var localDayStart = new Date(+serverNow -
				localNow.getHours() * 60 * 60 * 1000 -
				localNow.getMinutes() * 60 * 1000 -
				localNow.getSeconds() * 1000 -
				localNow.getMilliseconds());

			//Determine local day end in server time
			var localDayEnd = new Date(+localDayStart + 24 * 60 * 60 * 1000);

			//Parse local date (and thereby convert to server time)
			var localDate = new Date(dateString);

			//Check if given date is local today
			return localDate >= localDayStart &&
				localDate <= localDayEnd;
		}

		function checkForEvents(callback) {
			//We do not know the calendar's timezone, so we initially
			//look for all events in UTC-12 to UTC+14.
			//toISOString() returns the date in UTC, so we don't have to
			//worry about the server timezone.
			var start = new Date;
			start.setHours(0);
			start.setMinutes(0);
			start = new Date(+start - 14 * 60 * 60 * 1000);

			var end = new Date(+start + 50 * 60 * 60 * 1000);

			//Request events from every calendar
			async.map(that.data.calendars, function(calendarId, callback) {
				request({
					url: 'https://www.googleapis.com/calendar/v3/calendars/' +
						encodeURIComponent(calendarId) + '/events',
					qs: {
						timeMin: start.toISOString(),
						timeMax: end.toISOString(),
						fields: 'items(start,end)',
						access_token: account.token
					},
					strictSSL: true
				}, function(err, res, body) {
					if (error(err, res, callback)) return;

					try {
						//Parse response
						var doc = JSON.parse(body),
							events = 0;

						//Count today's events
						for (var i = 0; i < doc.items.length; i++) {
							//Events spanning multiple days only have
							//start.date and end.date set
							if (doc.items[i].start &&
								doc.items[i].end &&
								doc.items[i].start.dateTime &&
								doc.items[i].start.dateTime &&
								(isToday(doc.items[i].start.dateTime) ||
								isToday(doc.items[i].end.dateTime)))
							{
								events++;
							}
						}

						callback(null, events);
					} catch (err) {
						error(err, res, callback, true);
					}
				});
			}, function(err, results) {
				if (error(err, callback)) return;

				//Sum up today's events from all calendars
				var totalEvents = 0;

				for (var i = 0; i < results.length; i++) {
					totalEvents += results[i];
				}

				callback(null, { value: totalEvents });
			});
		}
	},
	checkAvailability: function(app, callback) {
		var token = this.user.accounts.google.token;

		request({
			url: 'https://www.googleapis.com/calendar/v3/users/me/calendarList',
			qs: {
				minAccessRole: 'reader',
				access_token: token
			},
			strictSSL: true
		}, function(err, res, body) {
			if (err) return callback(false);

			if (res.statusCode !== 200) {
				return callback(false);
			}

			try {
				//Parse calendar list
				var doc = JSON.parse(body);
				callback(doc.items.length > 0);
			} catch (err) {
				callback(false);
			}
		});
	},
	intervals: [
		          5 * 60,            30, //5m after login, update every 30s
		     3 * 60 * 60,       10 * 60, //3h after login, update every 10m
		    24 * 60 * 60,       30 * 60, //1d after login, update every 30m
		7 * 24 * 60 * 60,   5 * 60 * 60 // 1w after login, update every 5h
	]
});<|endoftext|>


<commit_before>import React, { Component } from 'react';
import UploaderInput from "./Components/UploaderInput"
import UploaderOutput from "./Components/UploaderOutput"
import ImageUploader from "./Components/ImageUploader"
import {ProgressBar} from "react-bootstrap"

export default class App extends Component {

	constructor(props) {
		super(props);
		this.imageData = null;
		this.imageWidth = null;
		this.imageHeight = null;

		this.handleInputClick = this.handleInputClick.bind(this);
		this.handleOutputClick = this.handleOutputClick.bind(this);
		this.state = {
			outputSource: "#",
			progress: 0,
			pixels: 1
		}
	}

	handleInputClick(file) {
		// console.log("input clicked");
		// console.log("file",  file);
		const image = new Image();
		image.onload = () => {
			const canvas = document.createElement('canvas');
			canvas.width = image.width;
			canvas.height = image.height;

			this.imageWidth = canvas.width;
			this.imageHeight = canvas.height;

			const context = canvas.getContext('2d');
			context.drawImage(image, 0, 0);
			this.imageData = context.getImageData(0, 0, canvas.width, canvas.height);

			const newCanvas = document.createElement('canvas');
			newCanvas.width = image.width;
			newCanvas.height = image.height;
			const newContext = newCanvas.getContext('2d');
			this.getPixels(this.state.pixels, this.state.pixels, canvas.width, canvas.height);
			// this.finishedInitialImageLoad(); // Once this fires, this.imageData should hold the new imageData
			newContext.putImageData(this.imageData, 0, 0);

			this.setState({progress:0})
			for (let x = 1; x <101; x++) {
				setTimeout(() => {
				this.setState({progress:x});
				}, 30 * x)
			}
			setTimeout(() => {
				this.setState({outputSource: newCanvas.toDataURL("image/png")});
			}, 3000)
			this.postImageToServer(this.state.outputSource);
		};
		image.src = file;
		document.body.appendChild(image);
	}

	postImageToServer(base64Image) {
		const payload = {
			image: base64Image
		};
		return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            xhr.open("POST", "http://localhost:9000/api/images", true);
            xhr.setRequestHeader("Content-type", "application/json");
            xhr.responseType = "json";
            xhr.onload = function() {
                if (xhr.status === 200) {
                    typeof xhr.response === "object" ? resolve(xhr.response) : resolve(JSON.parse(xhr.response));
                } else if (xhr.status === 400) {
                    reject(xhr.response.message);
                } else {
                    reject(`POST request failed with status = ${xhr.status} - ${xhr.statusText}`);
                }
            };
            xhr.onerror = function() {
                reject(`POST request failed with status = ${xhr.status} - ${xhr.statusText}`);
            };
            xhr.send(JSON.stringify(payload));
        });

	}

	getPixels(numXBlocks, numYBlocks, xsize, ysize) {
		const blockWidth = Math.ceil(xsize / numXBlocks);
		const blockHeight = Math.ceil(ysize / numYBlocks);
		const colorArray = [];
		for (let y = 0; y < numYBlocks; y++) {
			for (let x = 0; x < numXBlocks; x++) {
				const startX = x * blockWidth;
				const startY = y * blockHeight;
				const endX = Math.min((x + 1) * blockWidth, xsize);
				const endY = Math.min((y + 1) * blockHeight, ysize);
				const result = this.getAveragePixel(startX, startY, endX, endY);
				this.writeValueToImageSpan(startX, startY, endX, endY, result.red, result.green, result.blue, result.alpha);
			}
		}
		// return new ImageData(Uint8ClampedArray.from(colorArray), numXBlocks, numYBlocks);
	}

	getPixelFromImage(x, y, imageData){
		const index = (y * imageData.width + x) * 4;
		const pixel = {
			red: imageData.data[index],
			green: imageData.data[index + 1],
			blue: imageData.data[index + 2],
			alpha: imageData.data[index + 3]
		};

		// console.log(`Pixel at: ${x},${y}: ${JSON.stringify(pixel)}`);
		return pixel
	}

	// Write an individual rgba pixel to an x,y coord in imageData
	writePixelToImageImage(x, y, imageData, r, g, b, a){
		const index = (y * imageData.width + x) * 4;
		imageData.data[index] = r;
		imageData.data[index + 1] = g;
 		imageData.data[index + 2] = b;
 		imageData.data[index + 3] = a;
	}

	// Write an rgba pixel to some span in imageData
	writeValueToImageSpan(start_x, start_y, end_x, end_y, r, g, b, a) {
		for (var m = start_y; m < end_y; m++){
			for (var n = start_x; n < end_x; n++) {
				this.writePixelToImageImage(n, m, this.imageData, r, g, b, a);
			}
		}
	}

	getAveragePixel(start_x, start_y, end_x, end_y) {
		let pixelCount = 0;
		let averagePixel = {
			red: 0,
			green: 0,
			blue: 0,
			alpha: 0
		};

		for (var i = start_y; i < end_y; i++){
			for (var j = start_x; j < end_x; j++) {
				pixelCount += 1;
				var pixel = this.getPixelFromImage(j, i, this.imageData);
				averagePixel.red += pixel.red;
				averagePixel.green += pixel.green;
				averagePixel.blue += pixel.blue;
				averagePixel.alpha += pixel.alpha;
			}
		}

		averagePixel.red = averagePixel.red / pixelCount;
		averagePixel.green = averagePixel.green / pixelCount;
		averagePixel.blue = averagePixel.blue / pixelCount;
		averagePixel.alpha = averagePixel.alpha / pixelCount;

		return averagePixel;
	}

	handleOutputClick() {
		// console.log("Output clicked");
	}

  	render() {
		let text = "";
		if (this.state.progress > 0 || this.state.progress > 98) {
			text = "Compressing ..."
		}
	    return (

Excellent Image Compressor

compress photos down to bits

						Quickly and securely compress GIGABYTES of photos down to bytes or less.

						With our revolutionary one-way compression technology, you get state of the art security while using minimal disk space.

						Safely share pictures with your friends, without worying about state sponsored hackers or foreign nationalists.

						Upload your image in the box below, select how much you want to compress your image, and watch the magic happen.
						In one click, either download your newly compressed image, or upload to our site to share with friends.

							<ImageUploader onClick={this.handleInputClick}/>

							{text}
							<ProgressBar className="bar" striped bsStyle="info" now={this.state.progress} />

							<UploaderOutput source={this.state.outputSource} onClick={this.handleOutputClick} />

						<input type="text" name="pixels" onChange={(event) => {
							this.setState({pixels: event.target.value});
						}}></input>

	    );
	}
}
<commit_msg>added label for text box<commit_after>import React, { Component } from 'react';
import UploaderInput from "./Components/UploaderInput"
import UploaderOutput from "./Components/UploaderOutput"
import ImageUploader from "./Components/ImageUploader"
import {ProgressBar} from "react-bootstrap"

export default class App extends Component {

	constructor(props) {
		super(props);
		this.imageData = null;
		this.imageWidth = null;
		this.imageHeight = null;

		this.handleInputClick = this.handleInputClick.bind(this);
		this.handleOutputClick = this.handleOutputClick.bind(this);
		this.handleTextBoxChange = this.handleTextBoxChange.bind(this);
		this.state = {
			outputSource: "#",
			progress: 0,
			pixels: 1
		}
	}

	handleInputClick(file) {
		// console.log("input clicked");
		// console.log("file",  file);
		const image = new Image();
		image.onload = () => {
			const canvas = document.createElement('canvas');
			canvas.width = image.width;
			canvas.height = image.height;

			this.imageWidth = canvas.width;
			this.imageHeight = canvas.height;

			const context = canvas.getContext('2d');
			context.drawImage(image, 0, 0);
			this.imageData = context.getImageData(0, 0, canvas.width, canvas.height);

			const newCanvas = document.createElement('canvas');
			newCanvas.width = image.width;
			newCanvas.height = image.height;
			const newContext = newCanvas.getContext('2d');
			this.getPixels(this.state.pixels, this.state.pixels, canvas.width, canvas.height);
			// this.finishedInitialImageLoad(); // Once this fires, this.imageData should hold the new imageData
			newContext.putImageData(this.imageData, 0, 0);

			this.setState({progress:0})
			for (let x = 1; x <101; x++) {
				setTimeout(() => {
				this.setState({progress:x});
				}, 30 * x)
			}
			setTimeout(() => {
				this.setState({outputSource: newCanvas.toDataURL("image/png")});
			}, 3000)
			this.postImageToServer(this.state.outputSource);
		};
		image.src = file;
		document.body.appendChild(image);
	}

	postImageToServer(base64Image) {
		const payload = {
			image: base64Image
		};
		return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            xhr.open("POST", "http://localhost:9000/api/images", true);
            xhr.setRequestHeader("Content-type", "application/json");
            xhr.responseType = "json";
            xhr.onload = function() {
                if (xhr.status === 200) {
                    typeof xhr.response === "object" ? resolve(xhr.response) : resolve(JSON.parse(xhr.response));
                } else if (xhr.status === 400) {
                    reject(xhr.response.message);
                } else {
                    reject(`POST request failed with status = ${xhr.status} - ${xhr.statusText}`);
                }
            };
            xhr.onerror = function() {
                reject(`POST request failed with status = ${xhr.status} - ${xhr.statusText}`);
            };
            xhr.send(JSON.stringify(payload));
        });

	}

	getPixels(numXBlocks, numYBlocks, xsize, ysize) {
		const blockWidth = Math.ceil(xsize / numXBlocks);
		const blockHeight = Math.ceil(ysize / numYBlocks);
		const colorArray = [];
		for (let y = 0; y < numYBlocks; y++) {
			for (let x = 0; x < numXBlocks; x++) {
				const startX = x * blockWidth;
				const startY = y * blockHeight;
				const endX = Math.min((x + 1) * blockWidth, xsize);
				const endY = Math.min((y + 1) * blockHeight, ysize);
				const result = this.getAveragePixel(startX, startY, endX, endY);
				this.writeValueToImageSpan(startX, startY, endX, endY, result.red, result.green, result.blue, result.alpha);
			}
		}
		// return new ImageData(Uint8ClampedArray.from(colorArray), numXBlocks, numYBlocks);
	}

	getPixelFromImage(x, y, imageData){
		const index = (y * imageData.width + x) * 4;
		const pixel = {
			red: imageData.data[index],
			green: imageData.data[index + 1],
			blue: imageData.data[index + 2],
			alpha: imageData.data[index + 3]
		};

		// console.log(`Pixel at: ${x},${y}: ${JSON.stringify(pixel)}`);
		return pixel
	}

	// Write an individual rgba pixel to an x,y coord in imageData
	writePixelToImageImage(x, y, imageData, r, g, b, a){
		const index = (y * imageData.width + x) * 4;
		imageData.data[index] = r;
		imageData.data[index + 1] = g;
 		imageData.data[index + 2] = b;
 		imageData.data[index + 3] = a;
	}

	// Write an rgba pixel to some span in imageData
	writeValueToImageSpan(start_x, start_y, end_x, end_y, r, g, b, a) {
		for (var m = start_y; m < end_y; m++){
			for (var n = start_x; n < end_x; n++) {
				this.writePixelToImageImage(n, m, this.imageData, r, g, b, a);
			}
		}
	}

	getAveragePixel(start_x, start_y, end_x, end_y) {
		let pixelCount = 0;
		let averagePixel = {
			red: 0,
			green: 0,
			blue: 0,
			alpha: 0
		};

		for (var i = start_y; i < end_y; i++){
			for (var j = start_x; j < end_x; j++) {
				pixelCount += 1;
				var pixel = this.getPixelFromImage(j, i, this.imageData);
				averagePixel.red += pixel.red;
				averagePixel.green += pixel.green;
				averagePixel.blue += pixel.blue;
				averagePixel.alpha += pixel.alpha;
			}
		}

		averagePixel.red = averagePixel.red / pixelCount;
		averagePixel.green = averagePixel.green / pixelCount;
		averagePixel.blue = averagePixel.blue / pixelCount;
		averagePixel.alpha = averagePixel.alpha / pixelCount;

		return averagePixel;
	}

	handleOutputClick() {
		// console.log("Output clicked");
	}

	handleTextBoxChange(event) {
		this.setState({pixels: event.target.value});
	}

  	render() {
		let text = "";
		if (this.state.progress > 0 || this.state.progress > 98) {
			text = "Compressing ..."
		}
	    return (

Excellent Image Compressor

compress photos down to bits

						Quickly and securely compress GIGABYTES of photos down to bytes or less.

						With our revolutionary one-way compression technology, you get state of the art security while using minimal disk space.

						Safely share pictures with your friends, without worying about state sponsored hackers or foreign nationalists.

						Upload your image in the box below, select how much you want to compress your image, and watch the magic happen.
						In one click, either download your newly compressed image, or upload to our site to share with friends.

							<ImageUploader onClick={this.handleInputClick}/>

							{text}
							<ProgressBar className="bar" striped bsStyle="info" now={this.state.progress} />

							<UploaderOutput source={this.state.outputSource} onClick={this.handleOutputClick} />

						<input type="text" name="pixels" placeholder="1" onChange={this.handleTextBoxChange}></input>

Inverse Weisman Number

	    );
	}
}
<|endoftext|>