<commit_before>import { Component, PropTypes } from "react";
import { connect } from "react-apollo";
import gql from "graphql-tag";

import Authorized from "../../../blocks/authorzied";
import { header as headerActions } from "../../../store";

import Layout from "./Layout";
import Details from "./Details";

const mapQueriesToProps = () => ({
  filter: {
    query: gql`
      query GetFilterContent {
        family: currentFamily {
          person { photo, nickName, firstName, lastName, id: entityId }
        }
      }
    `,
  },
  data: {
    // XXX remove cache: false when heighliner caching is tested
    query: gql`
      query GetTransactions($limit: Int, $skip: Int, $people: [Int], $start: String, $end: String) {
        transactions(
          limit: $limit,
          skip: $skip,
          people: $people,
          start: $start,
          end: $end,
          cache: false
        ) {
          id
          date
          status
          summary
          person { firstName, lastName, photo }
          details {
            id
            amount
            account { id, name }
          }
        }
      }
    `,
    variables: { limit: 20, skip: 0, people: [], start: "", end: "" },
    forceFetch: true,
  },
});
@connect({ mapQueriesToProps })
class Template extends Component {

  static propTypes = {
    data: PropTypes.shape({
      loading: PropTypes.bool,
      transactions: PropTypes.array,
      refetch: PropTypes.func,
    }),
    filter: PropTypes.shape({
      family: PropTypes.array,
    }),
    dispatch: PropTypes.func,
  }

  state = {
    offset: 0,
    shouldUpdate: true,
    done: false,
    loaded: true,
    start: "",
    end: "",
    people: [],
    transactions: [], // XXX remove after refetchMore has landed in apollo-client
  }

  componentWillMount() {
    // coming back to this page with data in the store
    if (!this.props.data.loading && this.props.data.transactions) {
      this.setState({ transactions: this.props.data.transactions });
    }
  }

  componentDidMount() {
    if (process.env.NATIVE) {
      const item = { title: "Giving History" };
      this.props.dispatch(headerActions.set(item));
    }
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.data.loading && !nextProps.data.loading && !this.state.transactions.length) {
      this.setState({ transactions: nextProps.data.transactions });
    }
  }

  paginate = () => {
    this.props.data.refetch({
      limit: 20,
      skip: this.state.offset + 20,
      people: this.state.people,
      start: this.state.start,
      end: this.state.end,
    })
      .then(({ data }) => {
        const { transactions } = data;
        let done = false;
        if (transactions.length < 20) done = true;
        this.setState({
          transactions: this.state.transactions.concat(transactions),
          offset: this.state.offset + 20,
          done,
        });
      });
  }

  changeFamily = (people) => {
    this.setState({ loaded: false });
    this.props.data.refetch({
      start: this.state.start,
      end: this.state.end,
      limit: 20,
      skip: 0,
      people,
    })
      .then((response) => {
        if (!response || !response.data) return;
        const { transactions } = response.data;
        this.setState({
          offset: 0,
          done: transactions.length < 20,
          loaded: true,
          transactions,
          people,
        });
      });
  }

  changeDates = (start, end) => {
    this.setState({ loaded: false });
    this.props.data.refetch({
      people: this.state.people,
      limit: 20,
      skip: 0,
      start,
      end,
    })
      .then((response) => {
        if (!response || !response.data) return;
        const { transactions } = response.data;
        this.setState({
          offset: 0,
          done: transactions.length < 20,
          loaded: true,
          transactions,
          start,
          end,
        });
      });
  }

  render() {
    return (
      <Layout
        paginate={this.paginate}
        state={this.state}
        transactions={this.state.transactions}
        family={this.props.filter.family || []}
        alive
        ready={!this.props.data.loading}
        reloading={!this.state.loaded}
        done={this.state.done}
        changeFamily={this.changeFamily}
        changeDates={this.changeDates}
      />
    );
  }
}

const Routes = [
  {
    path: "history",
    component: Authorized,
    indexRoute: { component: Template },
    childRoutes: [
      {
        path: ":id",
        component: Details,
      },
    ],
  },
];

export default {
  Template,
  Routes,
};
<commit_msg>refactored give history<commit_after>import { Component, PropTypes } from "react";
import { graphql } from "react-apollo";
import { connect } from "react-redux";
import gql from "graphql-tag";

import Authorized from "../../../blocks/authorzied";
import { header as headerActions } from "../../../store";

import Layout from "./Layout";
import Details from "./Details";

const FILTER_QUERY = gql`
  query GetFilterContent {
    family: currentFamily {
      person { photo, nickName, firstName, lastName, id: entityId }
    }
  }
`;
const withFilter = graphql(FILTER_QUERY, { name: "filter" });

const TRANSACTIONS_QUERY = gql`
  query GetTransactions($limit: Int, $skip: Int, $people: [Int], $start: String, $end: String) {
    transactions(
      limit: $limit,
      skip: $skip,
      people: $people,
      start: $start,
      end: $end,
      cache: false
    ) {
      id
      date
      status
      summary
      person { firstName, lastName, photo }
      details {
        id
        amount
        account { id, name }
      }
    }
  }
`;
const withTransactions = graphql(TRANSACTIONS_QUERY, {
  options: ownProps => ({
    variables: { limit: 20, skip: 0, people: [], start: "", end: "" },
    forceFetch: true,
  }),
});

@withFilter
@connect()
@withTransactions
class Template extends Component {

  static propTypes = {
    data: PropTypes.shape({
      loading: PropTypes.bool,
      transactions: PropTypes.array,
      refetch: PropTypes.func,
    }),
    filter: PropTypes.shape({
      family: PropTypes.array,
    }),
    dispatch: PropTypes.func,
  }

  state = {
    offset: 0,
    shouldUpdate: true,
    done: false,
    loaded: true,
    start: "",
    end: "",
    people: [],
    transactions: [], // XXX remove after refetchMore has landed in apollo-client
  }

  componentWillMount() {
    // coming back to this page with data in the store
    if (!this.props.data.loading && this.props.data.transactions) {
      this.setState({ transactions: this.props.data.transactions });
    }
  }

  componentDidMount() {
    if (process.env.NATIVE) {
      const item = { title: "Giving History" };
      this.props.dispatch(headerActions.set(item));
    }
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.data.loading && !nextProps.data.loading && !this.state.transactions.length) {
      this.setState({ transactions: nextProps.data.transactions });
    }
  }

  paginate = () => {
    this.props.data.refetch({
      limit: 20,
      skip: this.state.offset + 20,
      people: this.state.people,
      start: this.state.start,
      end: this.state.end,
    })
      .then(({ data }) => {
        const { transactions } = data;
        let done = false;
        if (transactions.length < 20) done = true;
        this.setState({
          transactions: this.state.transactions.concat(transactions),
          offset: this.state.offset + 20,
          done,
        });
      });
  }

  changeFamily = (people) => {
    this.setState({ loaded: false });
    this.props.data.refetch({
      start: this.state.start,
      end: this.state.end,
      limit: 20,
      skip: 0,
      people,
    })
      .then((response) => {
        if (!response || !response.data) return;
        const { transactions } = response.data;
        this.setState({
          offset: 0,
          done: transactions.length < 20,
          loaded: true,
          transactions,
          people,
        });
      });
  }

  changeDates = (start, end) => {
    this.setState({ loaded: false });
    this.props.data.refetch({
      people: this.state.people,
      limit: 20,
      skip: 0,
      start,
      end,
    })
      .then((response) => {
        if (!response || !response.data) return;
        const { transactions } = response.data;
        this.setState({
          offset: 0,
          done: transactions.length < 20,
          loaded: true,
          transactions,
          start,
          end,
        });
      });
  }

  render() {
    return (
      <Layout
        paginate={this.paginate}
        state={this.state}
        transactions={this.state.transactions}
        family={this.props.filter.family || []}
        alive
        ready={!this.props.data.loading}
        reloading={!this.state.loaded}
        done={this.state.done}
        changeFamily={this.changeFamily}
        changeDates={this.changeDates}
      />
    );
  }
}

const Routes = [
  {
    path: "history",
    component: Authorized,
    indexRoute: { component: Template },
    childRoutes: [
      {
        path: ":id",
        component: Details,
      },
    ],
  },
];

export default {
  Template,
  Routes,
};
<|endoftext|>


<commit_before>import DS from 'ember-data';
import Ember from 'ember';

export default DS.RESTSerializer.extend({
  /**
   * This doesn't need to return anything... It is meant to mutate the data param
   * @param hash An empty object
   * @param type
   * @param record
   * @param options
   */
  serializeIntoHash: function (hash, type, record, options) {
    var serialized = this.serialize(record, options);
    console.log('serializing into hash...', hash, type, record, options, serialized);

    Ember.merge(hash, serialized);
  },

  extract: function (store, type, payload, id, requestType) {
    var newPayload = {};
    // DEPRECATED: typekey
    newPayload[type.typeKey] = payload;

    return this._super(store, type, newPayload, id, requestType);
  }

});
<commit_msg>just some changes to comments<commit_after>import DS from 'ember-data';
import Ember from 'ember';

export default DS.RESTSerializer.extend({
  /**
   * This doesn't need to return anything... It is meant to mutate the data param
   * This is a really weird way of doing things ember... What were you thinking?
   * @param hash An empty object
   * @param type
   * @param record
   * @param options
   */
  serializeIntoHash: function (hash, type, record, options) {
    var serialized = this.serialize(record, options);
    Ember.merge(hash, serialized);
  },

  extract: function (store, type, payload, id, requestType) {
    var newPayload = {};
    // I got a warning saying that typeKey was deprecated, but I don't see it anymore
    newPayload[type.typeKey] = payload;
    return this._super(store, type, newPayload, id, requestType);
  }

});
<|endoftext|>


<commit_before>var config = {
  baseUrl: 'http://localhost:3000', specs: ['test/*.js'],

  jasmineNodeOpts: {
    defaultTimeoutInterval: 720000
  }
};

if (process.env.TRAVIS) {
  config.sauceUser = process.env.SAUCE_USERNAME;
  config.sauceKey = process.env.SAUCE_ACCESS_KEY;
  config.multiCapabilities = [{
    'name': 'pageobject chrome latest',
    'browserName': 'chrome',
    'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,
    'build': process.env.TRAVIS_BUILD_NUMBER,
    'version': 'latest',
    // 'shardTestFiles': true,
    // 'maxInstances:': 2
  },
    {
      'name': 'pageobject firefox 47',
      'browserName': 'firefox',
      'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,
      'build': process.env.TRAVIS_BUILD_NUMBER,
      'version': '47',
      // 'shardTestFiles': true,
      // 'maxInstances': 2
    },{
      'name': 'pageobject internet explorer',
      'browserName': 'internet explorer',
      'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,
      'build': process.env.TRAVIS_BUILD_NUMBER,
      // 'shardTestFiles': true,
      // 'maxInstances': 2
    },
    {
      'name': 'pageobject safari',
      'browserName': 'safari',
      'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,
      'build': process.env.TRAVIS_BUILD_NUMBER,
      // 'shardTestFiles': true,
      // 'maxInstances': 2
    }];
}

exports.config = config;<commit_msg>Re-added Saucelabs config<commit_after>var config = {
  baseUrl: 'http://localhost:3000', specs: ['test/*.js'],

  jasmineNodeOpts: {
    defaultTimeoutInterval: 720000
  }
};

if (process.env.TRAVIS) {
  config.sauceUser = process.env.SAUCE_USERNAME;
  config.sauceKey = process.env.SAUCE_ACCESS_KEY;
  config.multiCapabilities = [{
    'name': 'pageobject chrome latest',
    'browserName': 'chrome',
    'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,
    'build': process.env.TRAVIS_BUILD_NUMBER,
    'version': 'latest',
    'shardTestFiles': true,
    'maxInstances:': 2
  },
    {
      'name': 'pageobject firefox 47',
      'browserName': 'firefox',
      'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,
      'build': process.env.TRAVIS_BUILD_NUMBER,
      'version': '47',
      'shardTestFiles': true,
      'maxInstances': 2
    },{
      'name': 'pageobject internet explorer',
      'browserName': 'internet explorer',
      'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,
      'build': process.env.TRAVIS_BUILD_NUMBER,
      'shardTestFiles': true,
      'maxInstances': 2
    },
    {
      'name': 'pageobject safari',
      'browserName': 'safari',
      'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,
      'build': process.env.TRAVIS_BUILD_NUMBER,
      'shardTestFiles': true,
      'maxInstances': 2
    }];
}

exports.config = config;<|endoftext|>


<commit_before>// Subscriptions
People = new Mongo.Collection('people');
Meteor.subscribe('people');

Template.who.helpers({
    headline: "Who We Are",
    content: "
WCASA is a membership agency comprised of organizations and
individuals working to end sexual violence in Wisconsin.
WCASA is made up of it's staff, board, volunteers and
 51 sexual assault service provider agencies.
",
    items: [{
        class: 'left',
        tabs: [{
            title: 'About WCASA',
            icon: '',
            id: 'about',
            template : 'about'
        },{
            title: 'WCASA Philosophies',
            icon: '',
            id: 'philosophies',
            template : 'philosophies'
        },{
            title: 'WCASA Staff',
            icon: '',
            id: 'staff',
            template: 'staff'
        },{
            title: 'Board of Directors',
            icon: '',
            id: 'board',
            template: 'board'
        }]
    }]
});
Template.personStaff.helpers({
    avatar: function () {
        return Site.findOne({}, { avatar: 1 });
    }
});
Template.personBoard.helpers({
    avatar: function () {
        return Site.findOne({}, { avatar: 1 });
    }
});

Template.staff.helpers({
    board: function () {
        return People.find({ boardMember: true }, { sort: { title: -1, name: 1 }});
    }
});

Template.board.helpers({
    staff: function () {
        return People.find({ boardMember: false }, { sort: { name: 1 }});
    }
});

<commit_msg>Corrected broken reference to staff/board in who.js<commit_after>// Subscriptions
People = new Mongo.Collection('people');
Meteor.subscribe('people');

Template.who.helpers({
    headline: "Who We Are",
    content: "
WCASA is a membership agency comprised of organizations and
individuals working to end sexual violence in Wisconsin.
WCASA is made up of it's staff, board, volunteers and
 51 sexual assault service provider agencies.
",
    items: [{
        class: 'left',
        tabs: [{
            title: 'About WCASA',
            icon: '',
            id: 'about',
            template : 'about'
        },{
            title: 'WCASA Philosophies',
            icon: '',
            id: 'philosophies',
            template : 'philosophies'
        },{
            title: 'WCASA Staff',
            icon: '',
            id: 'staff',
            template: 'staff'
        },{
            title: 'Board of Directors',
            icon: '',
            id: 'board',
            template: 'board'
        }]
    }]
});

Template.personStaff.helpers({
    avatar: function () {
        return Site.findOne({}, { avatar: 1 });
    }
});
Template.personBoard.helpers({
    avatar: function () {
        return Site.findOne({}, { avatar: 1 });
    }
});

Template.board.helpers({
    board: function () {
        return People.find({ boardMember: true }, { sort: { title: -1, name: 1 }});
    }
});

Template.staff.helpers({
    staff: function () {
        return People.find({ boardMember: false }, { sort: { name: 1 }});
    }
});

<|endoftext|>


<commit_before>/**
 * Cross-Origin Resource Sharing (CORS) Settings
 * (sails.config.cors)
 *
 * CORS is like a more modern version of JSONP-- it allows your server/API
 * to successfully respond to requests from client-side JavaScript code
 * running on some other domain (e.g. google.com)
 * Unlike JSONP, it works with POST, PUT, and DELETE requests
 *
 * For more information on CORS, check out:
 * http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
 *
 * Note that any of these settings (besides 'allRoutes') can be changed on a per-route basis
 * by adding a "cors" object to the route configuration:
 *
 * '/get foo': {
 *   controller: 'foo',
 *   action: 'bar',
 *   cors: {
 *     origin: 'http://foobar.com,https://owlhoot.com'
 *   }
 *  }
 *
 *  For more information on this configuration file, see:
 *  http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.cors.html
 *
 */

module.exports.cors = {

    /***************************************************************************
    *                                                                          *
    * Allow CORS on all routes by default? If not, you must enable CORS on a   *
    * per-route basis by either adding a "cors" configuration object to the    *
    * route config, or setting "cors:true" in the route config to use the      *
    * default settings below.                                                  *
    *                                                                          *
    ***************************************************************************/

    allRoutes: true,

    /***************************************************************************
    *                                                                          *
    * Which domains which are allowed CORS access? This can be a               *
    * comma-delimited list of hosts (beginning with http:// or https://) or    *
    * "*" to allow all domains CORS access.                                    *
    *                                                                          *
    ***************************************************************************/

    origin: 'http://localhost:8080,https://flux.uttnetgroup.net,https://bar.utt.fr',

    /***************************************************************************
    *                                                                          *
    * Allow cookies to be shared for CORS requests?                            *
    *                                                                          *
    ***************************************************************************/

    // credentials: true,

    /***************************************************************************
    *                                                                          *
    * Which methods should be allowed for CORS requests? This is only used in  *
    * response to preflight requests (see article linked above for more info)  *
    *                                                                          *
    ***************************************************************************/

    // methods: 'GET, POST, PUT, DELETE, OPTIONS, HEAD',

    /***************************************************************************
    *                                                                          *
    * Which headers should be allowed for CORS requests? This is only used in  *
    * response to preflight requests.                                          *
    *                                                                          *
    ***************************************************************************/

    headers: 'Authorization,content-type'

};
<commit_msg>Update CORS allowed origin<commit_after>/**
 * Cross-Origin Resource Sharing (CORS) Settings
 * (sails.config.cors)
 *
 * CORS is like a more modern version of JSONP-- it allows your server/API
 * to successfully respond to requests from client-side JavaScript code
 * running on some other domain (e.g. google.com)
 * Unlike JSONP, it works with POST, PUT, and DELETE requests
 *
 * For more information on CORS, check out:
 * http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
 *
 * Note that any of these settings (besides 'allRoutes') can be changed on a per-route basis
 * by adding a "cors" object to the route configuration:
 *
 * '/get foo': {
 *   controller: 'foo',
 *   action: 'bar',
 *   cors: {
 *     origin: 'http://foobar.com,https://owlhoot.com'
 *   }
 *  }
 *
 *  For more information on this configuration file, see:
 *  http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.cors.html
 *
 */

module.exports.cors = {

    /***************************************************************************
    *                                                                          *
    * Allow CORS on all routes by default? If not, you must enable CORS on a   *
    * per-route basis by either adding a "cors" configuration object to the    *
    * route config, or setting "cors:true" in the route config to use the      *
    * default settings below.                                                  *
    *                                                                          *
    ***************************************************************************/

    allRoutes: true,

    /***************************************************************************
    *                                                                          *
    * Which domains which are allowed CORS access? This can be a               *
    * comma-delimited list of hosts (beginning with http:// or https://) or    *
    * "*" to allow all domains CORS access.                                    *
    *                                                                          *
    ***************************************************************************/

    origin: 'http://localhost:8080,https://flux.uttnetgroup.fr,https://flux-dev.uttnetgroup.fr,https://bar.utt.fr',

    /***************************************************************************
    *                                                                          *
    * Allow cookies to be shared for CORS requests?                            *
    *                                                                          *
    ***************************************************************************/

    // credentials: true,

    /***************************************************************************
    *                                                                          *
    * Which methods should be allowed for CORS requests? This is only used in  *
    * response to preflight requests (see article linked above for more info)  *
    *                                                                          *
    ***************************************************************************/

    // methods: 'GET, POST, PUT, DELETE, OPTIONS, HEAD',

    /***************************************************************************
    *                                                                          *
    * Which headers should be allowed for CORS requests? This is only used in  *
    * response to preflight requests.                                          *
    *                                                                          *
    ***************************************************************************/

    headers: 'Authorization,content-type'

};
<|endoftext|>


<commit_before>describe('Inverted Index Tests', function() {
  var invertedIndex = new Index();
  var sourceFile = './books.json';

  beforeEach(function(done) {
    invertedIndex.createIndex('', function() {
      done();
    });
  });

  describe('Read book data', function() {
    it('asserts that json file is not empty', function() {
      expect(invertedIndex.content).not.toEqual([]);
    });
  });

});
<commit_msg>write populate index test suite<commit_after>describe('Inverted Index Tests', function() {
  var invertedIndex = new Index();
  var sourceFile = './books.json';

  beforeEach(function(done) {
    invertedIndex.createIndex('', function() {
      done();
    });
  });

  describe('Read book data', function() {
    it('asserts that json file is not empty', function() {
      expect(invertedIndex.content).not.toEqual([]);
    });
  });

  describe('Populate index', function() {
    it('verifies that the index is created once the JSON file has been read', function() {
      expect(invertedIndex.readIndex).toBeDefined();
      expect(invertedIndex.readIndex.length).not.toBe(null);
    });
  });
  it('index maps the string keys to the correct objects in the JSON array', function() {
    expect(invertedIndex.index.alice).toEqual([1, 0, 0]);
    expect(invertedIndex.index.ring).toEqual([0, 0, 1]);
  });

});
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Link } from 'react-router';
import DocumentTitle from 'react-document-title';

import * as ConferenceActions from '../../actions/ConferenceActions';
import * as UserActions from '../../actions/UserActions';
import assignToEmpty from '../../utils/assign';

/* Components */
import Conference from '../fragments/Conference';

export class ConferencePage extends Component {
  componentDidMount() {
    this.validateProps();
    const { actions, params, conferences } = this.props;
    actions.userActiveChanged(conferences[params.id].users.map(user => user.id));
  }

  componentWillUpdate(props) {
    const { actions, params, conferences } = props;
    actions.userActiveChanged(conferences[params.id].users.map(user => user.id));
  }

  componentDidUpdate() {
    this.validateProps();
  }

  componentWillUnmount() {
    this.props.actions.userActiveChanged([]);
  }

  deleteConference(id) {
    if (confirm(`Are you sure you want to permanently delete this conference?`)) {
      this.props.actions.conferenceDelete(id, this.redirectToConferencesPage.bind(this));
    }
  }

  redirectToConferencesPage() {
    this.props.history.pushState(null, '/conferences');
  }

  validateProps() {
    const { conferences, params, history } = this.props;
    if (!conferences[params.id]) {
      history.pushState(null, '/404');
      return ;
    }
  }

  render() {
    const { conferences, params, isAdmin, actions, users } = this.props;
    const conference = conferences[params.id];

    let editLink;
    let deleteButton;
    if (isAdmin) {
      editLink = (
        <Link className="btn btn-secondary btn-sm" to={`/conference/${conference.id}/edit`}>Edit conference</Link>
      );

      deleteButton = (
        <button className="btn btn-danger btn-sm" type="button"
          onClick={this.deleteConference.bind(this, conference.id)}>Delete</button>
      );
    }

    const canLink = isAdmin;
    const canUnlink = canLink;
    const onLink = actions.conferenceLinkUser;
    const onUnlink = actions.conferenceUnlinkUser;

    return (
      <DocumentTitle title={`Conference: ${conference.name} | X-Map`}>

          <Link to="/" className="close btn btn-sm btn-secondary" title="close page">×</Link>

{conference.name}

              {editLink}{deleteButton}

          <Conference conference={conference} canLink={canLink} canUnlink={canUnlink} onLink={onLink} onUnlink={onUnlink} users={users}/>

      </DocumentTitle>
    );
  }
}

ConferencePage.propTypes = {
  actions: PropTypes.object,
  conferences: PropTypes.object.isRequired,
  history: PropTypes.object.isRequired,
  isAdmin: PropTypes.bool,
  params: PropTypes.shape({
    id: PropTypes.string.isRequired
  }).isRequired,
  users: PropTypes.object.isRequired
};

function mapStateToProps(state) {
  return {
    conferences: state.conferences,
    users: state.users,
    isAdmin: state.session.isAdmin
  };
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(assignToEmpty(ConferenceActions, UserActions), dispatch)
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(ConferencePage);
<commit_msg>Render, pan and zoom to a conference marker.<commit_after>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Link } from 'react-router';
import DocumentTitle from 'react-document-title';
import { getConferenceMarker } from '../../utils/markers';

import * as ConferenceActions from '../../actions/ConferenceActions';
import * as UserActions from '../../actions/UserActions';

/* Assets */
import confDefaultMarker from '../../../img/xteam_marker.png';

/* Components */
import Conference from '../fragments/Conference';

export class ConferencePage extends Component {
  constructor(props) {
    super(props);
    this.marker = null;
  }

  componentWillMount() {
    const { conferences, params } = this.props;
    const conference = conferences[params.id];
    this.renderConferenceMarker(conference);
    this.panToConferenceMarker(conference);
  }

  componentDidMount() {
    this.validateProps();
    const { actions, params, conferences } = this.props;
    actions.userActiveChanged(conferences[params.id].users.map(user => user.id));
  }

  componentWillUpdate(props) {
    const { actions, params, conferences } = props;
    actions.userActiveChanged(conferences[params.id].users.map(user => user.id));
  }

  componentDidUpdate() {
    this.validateProps();
  }

  componentWillUnmount() {
    this.props.actions.userActiveChanged([]);
    this.marker.setVisible(false);
  }

  setZoom(zoom) {
    window.map.setZoom(zoom);
  }

  panToConferenceMarker(conference) {
    const { lat, lng } = conference;
    if (lat && lng) {
      window.map.panTo({ lat, lng });
      this.setZoom(6);
    }
  }

  deleteConference(id) {
    if (confirm(`Are you sure you want to permanently delete this conference?`)) {
      this.props.actions.conferenceDelete(id, this.redirectToConferencesPage.bind(this));
    }
  }

  redirectToConferencesPage() {
    this.props.history.pushState(null, '/conferences');
  }

  validateProps() {
    const { conferences, params, history } = this.props;
    if (!conferences[params.id]) {
      history.pushState(null, '/404');
      return ;
    }
  }

  renderConferenceMarker(conference) {
    this.marker = getConferenceMarker(conference, confDefaultMarker);
  }

  render() {
    const { conferences, params, isAdmin, actions, users } = this.props;
    const conference = conferences[params.id];

    let editLink;
    let deleteButton;
    if (isAdmin) {
      editLink = (
        <Link className="btn btn-secondary btn-sm" to={`/conference/${conference.id}/edit`}>Edit conference</Link>
      );

      deleteButton = (
        <button className="btn btn-danger btn-sm" type="button"
          onClick={this.deleteConference.bind(this, conference.id)}>Delete</button>
      );
    }

    const canLink = isAdmin;
    const canUnlink = canLink;
    const onLink = actions.conferenceLinkUser;
    const onUnlink = actions.conferenceUnlinkUser;

    return (
      <DocumentTitle title={`Conference: ${conference.name} | X-Map`}>

          <Link to="/" className="close btn btn-sm btn-secondary" title="close page">×</Link>

{conference.name}

              {editLink}{deleteButton}

          <Conference conference={conference} canLink={canLink} canUnlink={canUnlink} onLink={onLink} onUnlink={onUnlink} users={users}/>

      </DocumentTitle>
    );
  }
}

ConferencePage.propTypes = {
  actions: PropTypes.object,
  conferences: PropTypes.object.isRequired,
  history: PropTypes.object.isRequired,
  isAdmin: PropTypes.bool,
  params: PropTypes.shape({
    id: PropTypes.string.isRequired
  }).isRequired,
  users: PropTypes.object.isRequired,
  usersVisible: PropTypes.bool
};

function mapStateToProps(state) {
  return {
    conferences: state.conferences,
    users: state.users,
    usersVisible: state.users.visible,
    isAdmin: state.session.isAdmin
  };
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators({
      ...ConferenceActions,
      ...UserActions
    }, dispatch)
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(ConferencePage);
<|endoftext|>


<commit_before>/******************\
|    Tim the MIT   |
|      Beaver      |
| @author Anthony  |
| @version 0.1     |
| @date 2014/12/26 |
| @edit 2014/12/27 |
\******************/

var Beaver = (function() {
    /**********
     * config */
    var sqSize = 250;
    var moveIncr = 150;
    var moveAmt = 0.3*moveIncr/Math.max(
        window.innerWidth, window.innerHeight
    );

    /*************
     * constants */
    var NONE = 0;
    var LEFT = 1;
    var RIGHT = 2;
    var DOWN = 4;
    var DOWNL = DOWN+LEFT;
    var DOWNR = DOWN+RIGHT;
    var UP = 8;
    var UPL = UP+LEFT;
    var UPR = UP+RIGHT;
    var IMG_LOCS = [];
    var IMG_PREF = 'http://turbomaze.github.io/movable-tim-beaver/';
    IMG_LOCS[NONE] = IMG_PREF+'images/s.png';
    IMG_LOCS[LEFT] = IMG_PREF+'images/l.png';
    IMG_LOCS[RIGHT] = IMG_PREF+'images/r.png';
    IMG_LOCS[DOWN] = IMG_PREF+'images/d.png';
    IMG_LOCS[DOWNL] = IMG_PREF+'images/dl.png';
    IMG_LOCS[DOWNR] = IMG_PREF+'images/dr.png';
    IMG_LOCS[UP] = IMG_PREF+'images/u.png';
    IMG_LOCS[UPL] = IMG_PREF+'images/ul.png';
    IMG_LOCS[UPR] = IMG_PREF+'images/ur.png';
    var nodeMapping = [];
    nodeMapping[NONE] = 4;
    nodeMapping[LEFT] = 3;
    nodeMapping[RIGHT] = 5;
    nodeMapping[DOWN] = 7;
    nodeMapping[DOWNL] = 6;
    nodeMapping[DOWNR] = 8;
    nodeMapping[UP] = 1;
    nodeMapping[UPL] = 0;
    nodeMapping[UPR] = 2;

    /*********************
     * working variables */
    var pos;
    var keys;
    var tim, timInstr;
    var vel;
    var timer;
    var keyDownFun, keyUpFun;

    /******************
     * work functions */
    function initTimBeaver() {
        function beginUserControl() {
            //add the footer with instructions (and a cancel button)
            timInstr = document.createElement('div');
            timInstr.style.position = 'absolute';
            timInstr.style.left = '1em';
            timInstr.style.bottom = '1em';
            timInstr.style.fontFamily = 'Monospace';
            timInstr.style.fontSize = '1.5em';
            timInstr.style.backgroundColor = 'rgba(95, 140, 31, 0.3)';
            timInstr.style.padding = '0.5em';
            timInstr.style.borderBottomLeftRadius = '0.5em';
            timInstr.style.borderBottomRightRadius = '0.5em';
            timInstr.style.borderTop = '0.5em solid rgba(95, 140, 31, 1)';
            timInstr.id = 'tim-instr';
            timInstr.innerHTML = 'w or ↑ - up
'+
                'a or ← - left
'+
                's or ↓ - down
'+
                'd or → - right
'+
                '
'+
                '<input type="button" value="Get outa my face, Tim!"'+
                'id="tim-off-btn">';
            document.getElementsByTagName('body')[0].appendChild(
                timInstr
            );

            document.getElementById('tim-off-btn').addEventListener(
                'click',
                function() {
                    document.removeEventListener('keydown', keyDownFun);
                    document.removeEventListener('keyup', keyUpFun);
                    document.getElementsByTagName('body')[0].removeChild(
                        tim
                    );
                    document.getElementsByTagName('body')[0].removeChild(
                        timInstr
                    );
                }
            );

            keyDownFun = function(e) {
                if (!keys[e.keyCode]) { //isn't already pressed
                    keys[e.keyCode] = true; //recognize the press
                    clearInterval(timer); //get rid of the old timer

                    var moveCmd = getMoveCmd();
                    updateVel(moveCmd);
                    obeyCommand(moveCmd); //since it's a keydown event
                    if (moveCmd === NONE) return; //no point repeating

                    //continue to move
                    timer = setInterval(function() {
                        obeyCommand(moveCmd);
                    }, moveIncr);
                }
            };
            document.addEventListener('keydown', keyDownFun);
            keyUpFun = function(e) {
                keys[e.keyCode] = false;
                clearInterval(timer); //get rid of the old timer

                var moveCmd = getMoveCmd();
                updateVel(moveCmd);
                if (moveCmd === NONE) return;

                //move according to the new direction
                timer = setInterval(function() {
                    obeyCommand(moveCmd);
                }, moveIncr);
            };
            document.addEventListener('keyup', keyUpFun);
        } //enables the user to control tim

        //init misc working vars
        pos = [0, 0];
        keys = [];
                 /* 9 8 10 */
        vel = 0; /* 1 0  2 */
                 /* 3 4  6 */

        //init tim
        tim = document.createElement('img');
        tim.width = sqSize;
        tim.height = sqSize;
        tim.style.position = 'absolute';
        tim.src = IMG_LOCS[vel];
        moveTim(pos);
        document.getElementsByTagName('body')[0].appendChild(tim);

        //deal with window resizing
        window.addEventListener('resize', function() {
            moveTim(pos);
            moveAmt = 0.3*moveIncr/Math.max(
                window.innerWidth, window.innerHeight
            );
        });

        //move according to a plan, giving the user control when finished
        var moves = [
            2,2,2,2,2,2,2,2,2,2,2,6,4,4,4,1,1,1,1,1,1,1,
            1,1,5,4,4,6,2,2,2,2,2,2,2,2,6,4,4,5,1,1,1,1,
            1,1,1,9,8,8,8,10,10,2,2,2,2,6,4,4,5,1,1
        ];
        for (var ai = 0; ai < moves.length; ai++) {
            setTimeout((function(moveCmd, lastOne) {
                return function() {
                    updateVel(moveCmd);
                    obeyCommand(moveCmd);

                    if (lastOne) beginUserControl();
                };
            })(moves[ai], ai === moves.length-1), moveIncr*ai);
        }
    }

    function getMoveCmd() {
        var moveCmd = 0;
        if (keys[87] || keys[38]) moveCmd += UP;
        if (keys[65] || keys[37]) moveCmd += LEFT;
        if (keys[83] || keys[40]) moveCmd += DOWN;
        if (keys[68] || keys[39]) moveCmd += RIGHT;

        if ((keys[65] || keys[37]) && (keys[68] || keys[39])) {
            moveCmd -= LEFT+RIGHT; //they cancel each other out
        }
        if ((keys[87] || keys[38]) && (keys[83] || keys[40])) {
            moveCmd -= UP+DOWN; //they cancel each other out
        }

        return moveCmd;
    }

    function updateVel(cmd) {
        //given a start velocity and end velocity, this function returns
        //a list of intermediary velocities to smoothly transition the images
        function getPlan(start, end) {
            /* Nodes and edges where nodes are velocity directions
             * 0 -- 1 -- 2
             * |         |
             * 3    4    5
             * |    |    |
             * 6 -- 7 -- 8
             */
            var graph = [
        /* 0 */ [1, 3],
        /* 1 */ [0, 2],
        /* 2 */ [1, 5],
        /* 3 */ [0, 6],
        /* 4 */ [7],
        /* 5 */ [2, 8],
        /* 6 */ [3, 7],
        /* 7 */ [4, 6, 8],
        /* 8 */ [5, 7]
            ]; //edges for each node
            var visited = []; //nodes you've already seen
            var paths = [[start]]; //plausible paths
            var solution = [];
            //iterate potential paths; guaranteed to terminate
            while (paths.length >= 1) {
                var path = paths.shift(); //take the current path
                var idx = path[path.length-1]; //look at its most recent node
                //look at the most recent node's connections
                var conns = graph[idx];
                for (var ni = 0; ni < conns.length; ni++) {
                    //if you've found the goal node
                    if (conns[ni] === end) {
                        //then you're done!!!
                        solution = path.concat(conns[ni]);
                        paths = [];
                        break;
                    } else if (visited.indexOf(conns[ni]) === -1) {
                        //add all nodes you haven't seen before to the stack
                        paths.push(path.concat(conns[ni]));
                        visited.push(conns[ni]);
                    }
                }
            }

            var transitions = [
                [ -1, UP,  -1, LEFT,   -1,    -1,    -1,   -1,    -1],
                [UPL, -1, UPR,   -1,   -1,    -1,    -1,   -1,    -1],
                [ -1, UP,  -1,   -1,   -1, RIGHT,    -1,   -1,    -1],
                [UPL, -1,  -1,   -1, NONE,    -1, DOWNL,   -1,    -1],
                [ -1, -1,  -1, LEFT,   -1, RIGHT,    -1, DOWN,    -1],
                [ -1, -1, UPR,   -1, NONE,    -1,    -1,   -1, DOWNR],
                [ -1, -1,  -1, LEFT,   -1,    -1,    -1, DOWN,    -1],
                [ -1, -1,  -1,   -1, NONE,    -1, DOWNL,   -1, DOWNR],
                [ -1, -1,  -1,   -1,   -1, RIGHT,    -1, DOWN,    -1]
            ]; //what velocities get you from idx1 to idx2?

            //come up with a plan based on the path
            var plan = [];
            for (var si = 0; si < solution.length-1; si++) {
                plan.push(transitions[solution[si]][solution[si+1]]);
            }
            return plan;
        }

        //update the velocity
        var oldVel = vel;
        vel = cmd;

        //update the picture if the velocity changed
        if (oldVel !== vel) {
            var mapping = [];
            var plan = getPlan(
                nodeMapping[oldVel], nodeMapping[vel]
            ); //how will you transition smoothly?
            updateImgSeq(plan, 1.5*moveIncr/plan.length);
        }
    }

    function updateImgSeq(seq, incr, origLength) {
        for (var ai = 0; ai < seq.length; ai++) {
            setTimeout((function(imgLoc) {
                return function() {
                    tim.src = imgLoc;
                };
            })(IMG_LOCS[seq[ai]]), incr*ai);
        }
    }

    function obeyCommand(cmd) {
        if (cmd >= 8) {
            pos[1] -= moveAmt; //up
            cmd -= 8;
        }
        if (cmd >= 4) {
            pos[1] += moveAmt; //down
            cmd -= 4;
        }
        if (cmd >= 2) {
            pos[0] += moveAmt; //right
            cmd -= 2;
        }
        if (cmd >= 1) {
            pos[0] -= moveAmt; //left
            cmd -= 1;
        }
        pos[0] = Math.max(0, Math.min(1, pos[0])); //keep it between 0 and 1
        pos[1] = Math.max(0, Math.min(1, pos[1]));

        moveTim(pos);
    }

    function moveTim(loc) {
        pos = [loc[0], loc[1]];
        tim.style.left = (window.innerWidth-sqSize)*pos[0]+'px';
        tim.style.top = (window.innerHeight-sqSize)*pos[1]+'px';
    }

    return {
        init: initTimBeaver
    };
})();

window.addEventListener('load', Beaver.init);<commit_msg>Changes the look of the exit button.<commit_after>/******************\
|    Tim the MIT   |
|      Beaver      |
| @author Anthony  |
| @version 0.1     |
| @date 2014/12/26 |
| @edit 2014/12/27 |
\******************/

var Beaver = (function() {
    /**********
     * config */
    var sqSize = 250;
    var moveIncr = 150;
    var moveAmt = 0.3*moveIncr/Math.max(
        window.innerWidth, window.innerHeight
    );

    /*************
     * constants */
    var NONE = 0;
    var LEFT = 1;
    var RIGHT = 2;
    var DOWN = 4;
    var DOWNL = DOWN+LEFT;
    var DOWNR = DOWN+RIGHT;
    var UP = 8;
    var UPL = UP+LEFT;
    var UPR = UP+RIGHT;
    var IMG_LOCS = [];
    var IMG_PREF = 'http://turbomaze.github.io/movable-tim-beaver/';
    IMG_LOCS[NONE] = IMG_PREF+'images/s.png';
    IMG_LOCS[LEFT] = IMG_PREF+'images/l.png';
    IMG_LOCS[RIGHT] = IMG_PREF+'images/r.png';
    IMG_LOCS[DOWN] = IMG_PREF+'images/d.png';
    IMG_LOCS[DOWNL] = IMG_PREF+'images/dl.png';
    IMG_LOCS[DOWNR] = IMG_PREF+'images/dr.png';
    IMG_LOCS[UP] = IMG_PREF+'images/u.png';
    IMG_LOCS[UPL] = IMG_PREF+'images/ul.png';
    IMG_LOCS[UPR] = IMG_PREF+'images/ur.png';
    var nodeMapping = [];
    nodeMapping[NONE] = 4;
    nodeMapping[LEFT] = 3;
    nodeMapping[RIGHT] = 5;
    nodeMapping[DOWN] = 7;
    nodeMapping[DOWNL] = 6;
    nodeMapping[DOWNR] = 8;
    nodeMapping[UP] = 1;
    nodeMapping[UPL] = 0;
    nodeMapping[UPR] = 2;

    /*********************
     * working variables */
    var pos;
    var keys;
    var tim, timInstr;
    var vel;
    var timer;
    var keyDownFun, keyUpFun;

    /******************
     * work functions */
    function initTimBeaver() {
        function beginUserControl() {
            //add the footer with instructions (and a cancel button)
            timInstr = document.createElement('div');
            timInstr.style.position = 'absolute';
            timInstr.style.left = '1em';
            timInstr.style.bottom = '1em';
            timInstr.style.fontFamily = 'Monospace';
            timInstr.style.fontSize = '1.5em';
            timInstr.style.backgroundColor = 'rgba(95, 140, 31, 0.3)';
            timInstr.style.padding = '0.5em';
            timInstr.style.borderBottomLeftRadius = '0.5em';
            timInstr.style.borderBottomRightRadius = '0.5em';
            timInstr.style.borderTop = '0.5em solid rgba(95, 140, 31, 1)';
            timInstr.id = 'tim-instr';
            timInstr.innerHTML = 'w or ↑ - up
'+
                'a or ← - left
'+
                's or ↓ - down
'+
                'd or → - right
'+
                '
'+
                ''+
                'Get outa my face, Tim!';
            document.getElementsByTagName('body')[0].appendChild(
                timInstr
            );

            document.getElementById('tim-off-btn').addEventListener(
                'click',
                function() {
                    document.removeEventListener('keydown', keyDownFun);
                    document.removeEventListener('keyup', keyUpFun);
                    document.getElementsByTagName('body')[0].removeChild(
                        tim
                    );
                    document.getElementsByTagName('body')[0].removeChild(
                        timInstr
                    );
                }
            );

            keyDownFun = function(e) {
                if (!keys[e.keyCode]) { //isn't already pressed
                    keys[e.keyCode] = true; //recognize the press
                    clearInterval(timer); //get rid of the old timer

                    var moveCmd = getMoveCmd();
                    updateVel(moveCmd);
                    obeyCommand(moveCmd); //since it's a keydown event
                    if (moveCmd === NONE) return; //no point repeating

                    //continue to move
                    timer = setInterval(function() {
                        obeyCommand(moveCmd);
                    }, moveIncr);
                }
            };
            document.addEventListener('keydown', keyDownFun);
            keyUpFun = function(e) {
                keys[e.keyCode] = false;
                clearInterval(timer); //get rid of the old timer

                var moveCmd = getMoveCmd();
                updateVel(moveCmd);
                if (moveCmd === NONE) return;

                //move according to the new direction
                timer = setInterval(function() {
                    obeyCommand(moveCmd);
                }, moveIncr);
            };
            document.addEventListener('keyup', keyUpFun);
        } //enables the user to control tim

        //init misc working vars
        pos = [0, 0];
        keys = [];
                 /* 9 8 10 */
        vel = 0; /* 1 0  2 */
                 /* 3 4  6 */

        //init tim
        tim = document.createElement('img');
        tim.width = sqSize;
        tim.height = sqSize;
        tim.style.position = 'absolute';
        tim.src = IMG_LOCS[vel];
        moveTim(pos);
        document.getElementsByTagName('body')[0].appendChild(tim);

        //deal with window resizing
        window.addEventListener('resize', function() {
            moveTim(pos);
            moveAmt = 0.3*moveIncr/Math.max(
                window.innerWidth, window.innerHeight
            );
        });

        //move according to a plan, giving the user control when finished
        var moves = [
            2/*,2,2,2,2,2,2,2,2,2,2,6,4,4,4,1,1,1,1,1,1,1,
            1,1,5,4,4,6,2,2,2,2,2,2,2,2,6,4,4,5,1,1,1,1,
            1,1,1,9,8,8,8,10,10,2,2,2,2,6,4,4,5,1,1*/
        ];
        for (var ai = 0; ai < moves.length; ai++) {
            setTimeout((function(moveCmd, lastOne) {
                return function() {
                    updateVel(moveCmd);
                    obeyCommand(moveCmd);

                    if (lastOne) beginUserControl();
                };
            })(moves[ai], ai === moves.length-1), moveIncr*ai);
        }
    }

    function getMoveCmd() {
        var moveCmd = 0;
        if (keys[87] || keys[38]) moveCmd += UP;
        if (keys[65] || keys[37]) moveCmd += LEFT;
        if (keys[83] || keys[40]) moveCmd += DOWN;
        if (keys[68] || keys[39]) moveCmd += RIGHT;

        if ((keys[65] || keys[37]) && (keys[68] || keys[39])) {
            moveCmd -= LEFT+RIGHT; //they cancel each other out
        }
        if ((keys[87] || keys[38]) && (keys[83] || keys[40])) {
            moveCmd -= UP+DOWN; //they cancel each other out
        }

        return moveCmd;
    }

    function updateVel(cmd) {
        //given a start velocity and end velocity, this function returns
        //a list of intermediary velocities to smoothly transition the images
        function getPlan(start, end) {
            /* Nodes and edges where nodes are velocity directions
             * 0 -- 1 -- 2
             * |         |
             * 3    4    5
             * |    |    |
             * 6 -- 7 -- 8
             */
            var graph = [
        /* 0 */ [1, 3],
        /* 1 */ [0, 2],
        /* 2 */ [1, 5],
        /* 3 */ [0, 6],
        /* 4 */ [7],
        /* 5 */ [2, 8],
        /* 6 */ [3, 7],
        /* 7 */ [4, 6, 8],
        /* 8 */ [5, 7]
            ]; //edges for each node
            var visited = []; //nodes you've already seen
            var paths = [[start]]; //plausible paths
            var solution = [];
            //iterate potential paths; guaranteed to terminate
            while (paths.length >= 1) {
                var path = paths.shift(); //take the current path
                var idx = path[path.length-1]; //look at its most recent node
                //look at the most recent node's connections
                var conns = graph[idx];
                for (var ni = 0; ni < conns.length; ni++) {
                    //if you've found the goal node
                    if (conns[ni] === end) {
                        //then you're done!!!
                        solution = path.concat(conns[ni]);
                        paths = [];
                        break;
                    } else if (visited.indexOf(conns[ni]) === -1) {
                        //add all nodes you haven't seen before to the stack
                        paths.push(path.concat(conns[ni]));
                        visited.push(conns[ni]);
                    }
                }
            }

            var transitions = [
                [ -1, UP,  -1, LEFT,   -1,    -1,    -1,   -1,    -1],
                [UPL, -1, UPR,   -1,   -1,    -1,    -1,   -1,    -1],
                [ -1, UP,  -1,   -1,   -1, RIGHT,    -1,   -1,    -1],
                [UPL, -1,  -1,   -1, NONE,    -1, DOWNL,   -1,    -1],
                [ -1, -1,  -1, LEFT,   -1, RIGHT,    -1, DOWN,    -1],
                [ -1, -1, UPR,   -1, NONE,    -1,    -1,   -1, DOWNR],
                [ -1, -1,  -1, LEFT,   -1,    -1,    -1, DOWN,    -1],
                [ -1, -1,  -1,   -1, NONE,    -1, DOWNL,   -1, DOWNR],
                [ -1, -1,  -1,   -1,   -1, RIGHT,    -1, DOWN,    -1]
            ]; //what velocities get you from idx1 to idx2?

            //come up with a plan based on the path
            var plan = [];
            for (var si = 0; si < solution.length-1; si++) {
                plan.push(transitions[solution[si]][solution[si+1]]);
            }
            return plan;
        }

        //update the velocity
        var oldVel = vel;
        vel = cmd;

        //update the picture if the velocity changed
        if (oldVel !== vel) {
            var mapping = [];
            var plan = getPlan(
                nodeMapping[oldVel], nodeMapping[vel]
            ); //how will you transition smoothly?
            updateImgSeq(plan, 1.5*moveIncr/plan.length);
        }
    }

    function updateImgSeq(seq, incr, origLength) {
        for (var ai = 0; ai < seq.length; ai++) {
            setTimeout((function(imgLoc) {
                return function() {
                    tim.src = imgLoc;
                };
            })(IMG_LOCS[seq[ai]]), incr*ai);
        }
    }

    function obeyCommand(cmd) {
        if (cmd >= 8) {
            pos[1] -= moveAmt; //up
            cmd -= 8;
        }
        if (cmd >= 4) {
            pos[1] += moveAmt; //down
            cmd -= 4;
        }
        if (cmd >= 2) {
            pos[0] += moveAmt; //right
            cmd -= 2;
        }
        if (cmd >= 1) {
            pos[0] -= moveAmt; //left
            cmd -= 1;
        }
        pos[0] = Math.max(0, Math.min(1, pos[0])); //keep it between 0 and 1
        pos[1] = Math.max(0, Math.min(1, pos[1]));

        moveTim(pos);
    }

    function moveTim(loc) {
        pos = [loc[0], loc[1]];
        tim.style.left = (window.innerWidth-sqSize)*pos[0]+'px';
        tim.style.top = (window.innerHeight-sqSize)*pos[1]+'px';
    }

    return {
        init: initTimBeaver
    };
})();

window.addEventListener('load', Beaver.init);<|endoftext|>


<commit_before>function AeonTheme(jsonPath, onComplete, global) {
    GOWN.Theme.call(this, onComplete, global);
    if (jsonPath) {
        this.loadImage(jsonPath);
    }
}

AeonTheme.prototype = Object.create( GOWN.Theme.prototype );
AeonTheme.prototype.constructor = AeonTheme;

AeonTheme.prototype.themeApplyTheme = GOWN.Theme.prototype.applyTheme;
AeonTheme.prototype.applyTheme = function() {
    var b = GOWN.Button;
    var bg = AeonTheme.BUTTON_SCALE_9_GRID;

    this.setSkin(b.SKIN_NAME, b.UP,
        this.getScaleContainer("button-up-skin0000", bg));
    this.setSkin(b.SKIN_NAME, b.DOWN,
        this.getScaleContainer("button-down-skin0000", bg));
    this.setSkin(b.SKIN_NAME, b.HOVER,
        this.getScaleContainer("button-hover-skin0000", bg));

    var tb = GOWN.ToggleButton;
    if (tb) {
        var sbg = AeonTheme.SELECTED_BUTTON_SCALE_9_GRID;

        this.setSkin(tb.SKIN_NAME, b.UP,
            this.getScaleContainer("button-up-skin0000", bg));
        this.setSkin(tb.SKIN_NAME, b.DOWN,
            this.getScaleContainer("button-down-skin0000", bg));
        this.setSkin(tb.SKIN_NAME, b.HOVER,
            this.getScaleContainer("button-hover-skin0000", bg));

        this.setSkin(tb.SKIN_NAME, tb.SELECTED_UP,
            this.getScaleContainer("toggle-button-selected-up-skin0000", sbg));
        this.setSkin(tb.SKIN_NAME, tb.SELECTED_DOWN,
            this.getScaleContainer("toggle-button-selected-down-skin0000", sbg));
        this.setSkin(tb.SKIN_NAME, tb.SELECTED_HOVER,
            this.getScaleContainer("toggle-button-selected-hover-skin0000", sbg));
    }

    if (GOWN.ScrollBar) {
        var sb = GOWN.ScrollBar;

        this.setSkin(sb.SKIN_NAME, "horizontal_track",
            this.getScaleContainer("horizontal-scroll-bar-track-skin0000",
                AeonTheme.HORIZONTAL_SCROLL_BAR_TRACK_SCALE_9_GRID));
        this.setSkin(sb.SKIN_NAME, "vertical_track",
            this.getScaleContainer("vertical-scroll-bar-track-skin0000",
                AeonTheme.VERTICAL_SCROLL_BAR_TRACK_SCALE_9_GRID));
    }
    if (GOWN.ScrollThumb) {
        var st = GOWN.ScrollThumb;
        this.setSkin(st.SKIN_NAME, "horizontal_" + b.UP,
            this.getScaleContainer("horizontal-scroll-bar-thumb-up-skin0000",
                AeonTheme.HORIZONTAL_SCROLL_BAR_THUMB_SCALE_9_GRID));
        this.setSkin(st.SKIN_NAME, "horizontal_" + b.DOWN,
            this.getScaleContainer("horizontal-scroll-bar-thumb-down-skin0000",
                AeonTheme.HORIZONTAL_SCROLL_BAR_THUMB_SCALE_9_GRID));
        this.setSkin(st.SKIN_NAME, "horizontal_" + b.HOVER,
            this.getScaleContainer("horizontal-scroll-bar-thumb-hover-skin0000",
                AeonTheme.HORIZONTAL_SCROLL_BAR_THUMB_SCALE_9_GRID));
        this.setSkin(st.SKIN_NAME, "horizontal_thumb",
            this.getImage("horizontal-scroll-bar-thumb-icon0000"));

        this.setSkin(st.SKIN_NAME, "vertical_" + b.UP,
            this.getScaleContainer("vertical-scroll-bar-thumb-up-skin0000",
                AeonTheme.VERTICAL_SCROLL_BAR_THUMB_SCALE_9_GRID));
        this.setSkin(st.SKIN_NAME, "vertical_" + b.DOWN,
            this.getScaleContainer("vertical-scroll-bar-thumb-down-skin0000",
                AeonTheme.VERTICAL_SCROLL_BAR_THUMB_SCALE_9_GRID));
        this.setSkin(st.SKIN_NAME, "vertical_" + b.HOVER,
            this.getScaleContainer("vertical-scroll-bar-thumb-hover-skin0000",
                AeonTheme.VERTICAL_SCROLL_BAR_THUMB_SCALE_9_GRID));
        this.setSkin(st.SKIN_NAME, "vertical_thumb",
            this.getImage("vertical-scroll-bar-thumb-icon0000"));
    }

    if (GOWN.PickerList) {
        var pl = GOWN.PickerList;
        tb = GOWN.ToggleButton;
        sbg = AeonTheme.SELECTED_BUTTON_SCALE_9_GRID;

        this.setSkin(pl.SKIN_NAME, b.UP,
            this.getScaleContainer("button-up-skin0000", bg));
        this.setSkin(pl.SKIN_NAME, b.DOWN,
            this.getScaleContainer("button-down-skin0000", bg));
        this.setSkin(pl.SKIN_NAME, b.HOVER,
            this.getScaleContainer("button-hover-skin0000", bg));

        this.setSkin(pl.SKIN_NAME, tb.SELECTED_UP,
            this.getScaleContainer("button-down-skin0000", sbg));
        this.setSkin(pl.SKIN_NAME, tb.SELECTED_DOWN,
            this.getScaleContainer("button-down-skin0000", sbg));
        this.setSkin(pl.SKIN_NAME, tb.SELECTED_HOVER,
            this.getScaleContainer("button-down-skin0000", sbg));

        this.setSkin(pl.SKIN_NAME, "picker_list_" + b.UP,
            this.getImage("picker-list-up-icon0000"));
        this.setSkin(pl.SKIN_NAME, "picker_list_" + b.DOWN,
            this.getImage("picker-list-down-icon0000"));
        this.setSkin(pl.SKIN_NAME, "picker_list_" + b.HOVER,
            this.getImage("picker-list-hover-icon0000"));
    }

    if (GOWN.TextInput) {
        var ti = GOWN.TextInput;
        this.setSkin(ti.SKIN_NAME, "background",
            this.getScaleContainer("text-input-background-enabled-skin0000",
                AeonTheme.TEXT_INPUT_SCALE_9_GRID));
    }

    if (GOWN.Check) {
        var chk = GOWN.Check;

        this.setSkin(chk.SKIN_NAME, b.UP,
            this.getImage("check-up-icon0000"));
        this.setSkin(chk.SKIN_NAME, b.DOWN,
            this.getImage("check-down-icon0000"));
        this.setSkin(chk.SKIN_NAME, b.HOVER,
            this.getImage("check-hover-icon0000"));

        this.setSkin(chk.SKIN_NAME, tb.SELECTED_UP,
            this.getImage("check-selected-up-icon0000"));
        this.setSkin(chk.SKIN_NAME, tb.SELECTED_DOWN,
            this.getImage("check-selected-down-icon0000"));
        this.setSkin(chk.SKIN_NAME, tb.SELECTED_HOVER,
            this.getImage("check-selected-hover-icon0000"));
    }
    this.themeApplyTheme();
};

AeonTheme.BUTTON_SCALE_9_GRID = new PIXI.Rectangle(7, 7, 8, 31);
AeonTheme.SELECTED_BUTTON_SCALE_9_GRID = new PIXI.Rectangle(7, 7, 8, 31);
AeonTheme.HORIZONTAL_SCROLL_BAR_THUMB_SCALE_9_GRID = new PIXI.Rectangle(5, 2, 93, 18);
AeonTheme.HORIZONTAL_SCROLL_BAR_TRACK_SCALE_9_GRID = new PIXI.Rectangle(1, 2, 6, 26);
AeonTheme.HORIZONTAL_SCROLL_BAR_STEP_BUTTON_SCALE_9_GRID = new PIXI.Rectangle(2, 2, 10, 11);
AeonTheme.TEXT_INPUT_SCALE_9_GRID = new PIXI.Rectangle(2, 2, 6, 6);
AeonTheme.VERTICAL_SCROLL_BAR_THUMB_SCALE_9_GRID = new PIXI.Rectangle(2, 5, 18, 93);
AeonTheme.VERTICAL_SCROLL_BAR_TRACK_SCALE_9_GRID = new PIXI.Rectangle(2, 1, 26, 6);
AeonTheme.VERTICAL_SCROLL_BAR_STEP_BUTTON_SCALE_9_GRID = new PIXI.Rectangle(2, 2, 11, 10);

GOWN.AeonTheme = AeonTheme;
<commit_msg>fix Scale9 values<commit_after>function AeonTheme(jsonPath, onComplete, global) {
    GOWN.Theme.call(this, onComplete, global);
    if (jsonPath) {
        this.loadImage(jsonPath);
    }
}

AeonTheme.prototype = Object.create( GOWN.Theme.prototype );
AeonTheme.prototype.constructor = AeonTheme;

AeonTheme.prototype.themeApplyTheme = GOWN.Theme.prototype.applyTheme;
AeonTheme.prototype.applyTheme = function() {
    var b = GOWN.Button;
    var bg = AeonTheme.BUTTON_SCALE_9_GRID;

    this.setSkin(b.SKIN_NAME, b.UP,
        this.getScaleContainer("button-up-skin0000", bg));
    this.setSkin(b.SKIN_NAME, b.DOWN,
        this.getScaleContainer("button-down-skin0000", bg));
    this.setSkin(b.SKIN_NAME, b.HOVER,
        this.getScaleContainer("button-hover-skin0000", bg));

    var tb = GOWN.ToggleButton;
    if (tb) {
        var sbg = AeonTheme.SELECTED_BUTTON_SCALE_9_GRID;

        this.setSkin(tb.SKIN_NAME, b.UP,
            this.getScaleContainer("button-up-skin0000", bg));
        this.setSkin(tb.SKIN_NAME, b.DOWN,
            this.getScaleContainer("button-down-skin0000", bg));
        this.setSkin(tb.SKIN_NAME, b.HOVER,
            this.getScaleContainer("button-hover-skin0000", bg));

        this.setSkin(tb.SKIN_NAME, tb.SELECTED_UP,
            this.getScaleContainer("toggle-button-selected-up-skin0000", sbg));
        this.setSkin(tb.SKIN_NAME, tb.SELECTED_DOWN,
            this.getScaleContainer("toggle-button-selected-down-skin0000", sbg));
        this.setSkin(tb.SKIN_NAME, tb.SELECTED_HOVER,
            this.getScaleContainer("toggle-button-selected-hover-skin0000", sbg));
    }

    if (GOWN.ScrollBar) {
        var sb = GOWN.ScrollBar;

        this.setSkin(sb.SKIN_NAME, "horizontal_track",
            this.getScaleContainer("horizontal-scroll-bar-track-skin0000",
                AeonTheme.HORIZONTAL_SCROLL_BAR_TRACK_SCALE_9_GRID));
        this.setSkin(sb.SKIN_NAME, "vertical_track",
            this.getScaleContainer("vertical-scroll-bar-track-skin0000",
                AeonTheme.VERTICAL_SCROLL_BAR_TRACK_SCALE_9_GRID));
    }
    if (GOWN.ScrollThumb) {
        var st = GOWN.ScrollThumb;
        this.setSkin(st.SKIN_NAME, "horizontal_" + b.UP,
            this.getScaleContainer("horizontal-scroll-bar-thumb-up-skin0000",
                AeonTheme.HORIZONTAL_SCROLL_BAR_THUMB_SCALE_9_GRID));
        this.setSkin(st.SKIN_NAME, "horizontal_" + b.DOWN,
            this.getScaleContainer("horizontal-scroll-bar-thumb-down-skin0000",
                AeonTheme.HORIZONTAL_SCROLL_BAR_THUMB_SCALE_9_GRID));
        this.setSkin(st.SKIN_NAME, "horizontal_" + b.HOVER,
            this.getScaleContainer("horizontal-scroll-bar-thumb-hover-skin0000",
                AeonTheme.HORIZONTAL_SCROLL_BAR_THUMB_SCALE_9_GRID));
        this.setSkin(st.SKIN_NAME, "horizontal_thumb",
            this.getImage("horizontal-scroll-bar-thumb-icon0000"));

        this.setSkin(st.SKIN_NAME, "vertical_" + b.UP,
            this.getScaleContainer("vertical-scroll-bar-thumb-up-skin0000",
                AeonTheme.VERTICAL_SCROLL_BAR_THUMB_SCALE_9_GRID));
        this.setSkin(st.SKIN_NAME, "vertical_" + b.DOWN,
            this.getScaleContainer("vertical-scroll-bar-thumb-down-skin0000",
                AeonTheme.VERTICAL_SCROLL_BAR_THUMB_SCALE_9_GRID));
        this.setSkin(st.SKIN_NAME, "vertical_" + b.HOVER,
            this.getScaleContainer("vertical-scroll-bar-thumb-hover-skin0000",
                AeonTheme.VERTICAL_SCROLL_BAR_THUMB_SCALE_9_GRID));
        this.setSkin(st.SKIN_NAME, "vertical_thumb",
            this.getImage("vertical-scroll-bar-thumb-icon0000"));
    }

    if (GOWN.PickerList) {
        var pl = GOWN.PickerList;
        tb = GOWN.ToggleButton;
        sbg = AeonTheme.SELECTED_BUTTON_SCALE_9_GRID;

        this.setSkin(pl.SKIN_NAME, b.UP,
            this.getScaleContainer("button-up-skin0000", bg));
        this.setSkin(pl.SKIN_NAME, b.DOWN,
            this.getScaleContainer("button-down-skin0000", bg));
        this.setSkin(pl.SKIN_NAME, b.HOVER,
            this.getScaleContainer("button-hover-skin0000", bg));

        this.setSkin(pl.SKIN_NAME, tb.SELECTED_UP,
            this.getScaleContainer("button-down-skin0000", sbg));
        this.setSkin(pl.SKIN_NAME, tb.SELECTED_DOWN,
            this.getScaleContainer("button-down-skin0000", sbg));
        this.setSkin(pl.SKIN_NAME, tb.SELECTED_HOVER,
            this.getScaleContainer("button-down-skin0000", sbg));

        this.setSkin(pl.SKIN_NAME, "picker_list_" + b.UP,
            this.getImage("picker-list-up-icon0000"));
        this.setSkin(pl.SKIN_NAME, "picker_list_" + b.DOWN,
            this.getImage("picker-list-down-icon0000"));
        this.setSkin(pl.SKIN_NAME, "picker_list_" + b.HOVER,
            this.getImage("picker-list-hover-icon0000"));
    }

    if (GOWN.TextInput) {
        var ti = GOWN.TextInput;
        this.setSkin(ti.SKIN_NAME, "background",
            this.getScaleContainer("text-input-background-enabled-skin0000",
                AeonTheme.TEXT_INPUT_SCALE_9_GRID));
    }

    if (GOWN.Check) {
        var chk = GOWN.Check;

        this.setSkin(chk.SKIN_NAME, b.UP,
            this.getImage("check-up-icon0000"));
        this.setSkin(chk.SKIN_NAME, b.DOWN,
            this.getImage("check-down-icon0000"));
        this.setSkin(chk.SKIN_NAME, b.HOVER,
            this.getImage("check-hover-icon0000"));

        this.setSkin(chk.SKIN_NAME, tb.SELECTED_UP,
            this.getImage("check-selected-up-icon0000"));
        this.setSkin(chk.SKIN_NAME, tb.SELECTED_DOWN,
            this.getImage("check-selected-down-icon0000"));
        this.setSkin(chk.SKIN_NAME, tb.SELECTED_HOVER,
            this.getImage("check-selected-hover-icon0000"));
    }
    this.themeApplyTheme();
};

AeonTheme.BUTTON_SCALE_9_GRID = new PIXI.Rectangle(8, 8, 6, 29);
AeonTheme.SELECTED_BUTTON_SCALE_9_GRID = new PIXI.Rectangle(8, 8, 6, 29);
AeonTheme.HORIZONTAL_SCROLL_BAR_THUMB_SCALE_9_GRID = new PIXI.Rectangle(5, 2, 93, 18);
AeonTheme.HORIZONTAL_SCROLL_BAR_TRACK_SCALE_9_GRID = new PIXI.Rectangle(1, 2, 6, 26);
AeonTheme.HORIZONTAL_SCROLL_BAR_STEP_BUTTON_SCALE_9_GRID = new PIXI.Rectangle(2, 2, 10, 11);
AeonTheme.TEXT_INPUT_SCALE_9_GRID = new PIXI.Rectangle(2, 2, 6, 6);
AeonTheme.VERTICAL_SCROLL_BAR_THUMB_SCALE_9_GRID = new PIXI.Rectangle(2, 5, 18, 93);
AeonTheme.VERTICAL_SCROLL_BAR_TRACK_SCALE_9_GRID = new PIXI.Rectangle(2, 1, 26, 6);
AeonTheme.VERTICAL_SCROLL_BAR_STEP_BUTTON_SCALE_9_GRID = new PIXI.Rectangle(2, 2, 11, 10);

GOWN.AeonTheme = AeonTheme;
<|endoftext|>


<commit_before>"use strict";
/*
    This module work on Node.js
 */
const path = require("path");
const fs = require("fs");
const yaml = require("js-yaml");
const moment = require("moment");
const slugg = require("slugg");
const mkdirp = require('mkdirp');
import storage from "../../node/storage/accounts";
import {exec} from "child_process"
/**
 * Return index.json path which find from `Date` object
 * @param {Date} date
 * @returns {string}
 */
function getPostFileDir(date) {
    var fileDirPath = "posts/" + date.getFullYear();
    return path.join(storage.get("ecmascript-daily-dir"), fileDirPath);
}
export function savePost(serializedObject, callback) {
    if (!serializedObject) {
        throw new Error("no data for saving");
    }
    var item = JSON.parse(serializedObject);
    createPostFrom(item, callback);
}

function pickFromMatter(item) {
    var object = {
        layout: "news",
        // site title
        title: item.title,
        // site url
        "item-url": item.url,
        date: moment.utc(item.date).format()
    };
    if (item.tags && item.tags.length > 0) {
        object.tags = item.tags;
    }

    if (item.relatedLinks && item.relatedLinks.length > 0) {
        object.related = item.relatedLinks.map(link => {
            return {
                title: link.title,
                url: link.URL
            };
        });
    }
    return object;
}
function createPost(item) {
    var frontMatter = pickFromMatter(item);
    return ("---\n" +
    yaml.safeDump(frontMatter) +
    "---\n" +
    String(item.content) + "\n").replace(/[\n\r]/g, '\n');
}
function creteSafeSlug(item) {
    var slugForItem = slugg(item.title);
    if (slugForItem.length <= 1) {
        slugForItem = slugg(item.url);
    }
    // avoid ENAMETOOLONG
    if (slugForItem.length > 200) {
        return slugForItem.slice(0, 200);
    }
    return slugForItem;
}
function createPostFrom(item, callback) {
    const date = moment.utc(item.date);
    const repositoryDirectory = storage.get("ecmascript-daily-dir");
    const postDir = path.join(repositoryDirectory, "_posts", date.format("YYYY"));
    // if no dir, create dir
    mkdirp.sync(postDir);
    const fileName = date.format("YYYY-MM-DD") + "-" + creteSafeSlug(item) + ".md";
    const filePath = path.join(postDir, fileName);
    fs.writeFileSync(filePath, createPost(item), "utf8");
    // sync
    const title = item.title;
    var syncScript = path.join(__dirname, "git-sync.sh");
    exec(`bash ${syncScript} "${title}"`, {
        cwd: repositoryDirectory
    }, callback);
}<commit_msg>fix ecmascript dialy<commit_after>"use strict";
/*
    This module work on Node.js
 */
const path = require("path");
const fs = require("fs");
const yaml = require("js-yaml");
const moment = require("moment");
const slugg = require("slugg");
const mkdirp = require('mkdirp');
import storage from "../../node/storage/accounts";
import {exec} from "child_process"
/**
 * Return index.json path which find from `Date` object
 * @param {Date} date
 * @returns {string}
 */
function getPostFileDir(date) {
    var fileDirPath = "posts/" + date.getFullYear();
    return path.join(storage.get("ecmascript-daily-dir"), fileDirPath);
}
export function savePost(serializedObject, callback) {
    if (!serializedObject) {
        throw new Error("no data for saving");
    }
    var item = JSON.parse(serializedObject);
    createPostFrom(item, callback);
}

function pickFromMatter(item) {
    var object = {
        layout: "news",
        // site title
        title: item.title,
        // site url
        "item-url": item.url,
        date: moment.utc(item.date).format()
    };
    if (item.tags && item.tags.length > 0) {
        object.tags = item.tags;
    }

    if (item.relatedLinks && item.relatedLinks.length > 0) {
        object.related = item.relatedLinks.map(link => {
            return {
                title: link.title,
                url: link.URL
            };
        });
    }
    return object;
}
function createPost(item) {
    var frontMatter = pickFromMatter(item);
    return ("---\n" +
    yaml.safeDump(frontMatter) +
    "---\n" +
    String(item.content) + "\n").replace(/[\n\r]/g, '\n');
}
function creteSafeSlug(item) {
    var slugForItem = slugg(item.title);
    if (slugForItem.length <= 1) {
        slugForItem = slugg(item.url);
    }
    // avoid ENAMETOOLONG
    if (slugForItem.length > 200) {
        return slugForItem.slice(0, 200);
    }
    return slugForItem;
}
function createPostFrom(item, callback) {
    const date = moment.utc(item.date);
    const repositoryDirectory = storage.get("ecmascript-daily-dir");
    const postDir = path.join(repositoryDirectory, "_posts", date.format("YYYY"));
    // if no dir, create dir
    mkdirp.sync(postDir);
    const fileName = date.format("YYYY-MM-DD") + "-" + creteSafeSlug(item) + ".md";
    const filePath = path.join(postDir, fileName);
    fs.writeFileSync(filePath, createPost(item), "utf8");
    // sync
    const title = item.title;
    var syncScript = path.join(repositoryDirectory, "./tools/git-sync.sh");
    exec(`bash ${syncScript} "${title}"`, {
        cwd: repositoryDirectory
    }, callback);
}
<|endoftext|>


<commit_before>import React from 'react';
import { Link } from 'react-router';
import { Grid, Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';

import { handleLogin, handleFacebookLogin, handleGoogleLogin, handleIVLELogin } from '../../../modules/login';

import * as IconsHelper from '../../../util/icons';

export default class Login extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      errors: {},
    };
  }

  handleSubmit(event) {
    event.preventDefault();
  }

  componentDidUpdate(prevProps, prevState) {
    const self = this;

    // Necessary because the real DOM hasn't been updated at this point, only the virtual DOM. lol....
    if (prevProps.open != this.props.open)
      setTimeout(() => {
        self.setState({ errors: {} });

        handleLogin({
          component: self,
          clearErrors() {
            self.setState({ errors: {} });
          },
          setError(er, text) {
            let errorsObject = {};
            errorsObject[er] = text;
            errorsObject = $.extend({}, self.state.errors, errorsObject);
            self.setState({ errors: errorsObject });
          },
          afterLogin() {
            self.props.closeLogin();
          },
        });
      });
  }

  socialLoginHandler(handler) {
    const self = this;

    return (event) => handler({
        afterLogin() {
          self.props.closeLogin();
        }
      });
  }

  render() {
    return (
      <Dialog
        open={ this.props.open }
        onRequestClose={ this.props.closeLogin }
        contentStyle={{ maxWidth: 550 }}
        autoScrollBodyContent={true}>
        <form ref="login" className="login" onSubmit={ this.handleSubmit }>
          <Grid fluid={true}>
            <Row>
              <Col>

Login to Free4All

              </Col>
            </Row>
            <Row className="openid" style={{ marginBottom: 10 }}>
              <Col xs={12} sm={4} smOffset={0}>
                <FlatButton
                  style={{ width: "100%", backgroundColor: "#ff8c00", marginBottom: 10 }}
                  labelColor="#ffffff"
                  label="NUS OpenID"
                  onTouchTap={ this.socialLoginHandler(handleIVLELogin) } />
              </Col>
              <Col xs={12} sm={4} smOffset={0}>
                <FlatButton
                  style={{ width: "100%", backgroundColor: "#395697", marginBottom: 10 }}
                  labelColor="#ffffff"
                  label="Facebook"
                  icon={ IconsHelper.icon("fa fa-facebook-f") }
                  onTouchTap={ this.socialLoginHandler(handleFacebookLogin) } />
              </Col>
              <Col xs={12} sm={4} smOffset={0}>
                <FlatButton
                  style={{ width: "100%", backgroundColor: "#e0492f", marginBottom: 10 }}
                  labelColor="#ffffff"
                  label="Google"
                  icon={ IconsHelper.icon("fa fa-google") }
                  onTouchTap={ this.socialLoginHandler(handleGoogleLogin) } />
              </Col>
            </Row>
            <Row>
              <Col xs={12}>

                  OR

              </Col>
            </Row>
            <Row>
              <Col xs={12} sm={6}>
                <TextField
                  type="email"
                  ref="emailAddress"
                  name="emailAddress"
                  hintText="Email Address"
                  errorText={ this.state.errors.emailAddress }
                  fullWidth={true}
                />
                <TextField
                  type="password"
                  ref="password"
                  name="password"
                  hintText="Password"
                  errorText={ this.state.errors.password }
                  fullWidth={true}
                />
              </Col>
              <Col xs={12} sm={6}>

Not yet a member? <Link to="/signup">Sign up</Link>

<Link to="/recover-password">Forgot Password?</Link>

              </Col>
            </Row>
            <Row style={{ marginTop: 20 }}>
              <Col xs={6} xsOffset={3} sm={3} smOffset={9}>
                <RaisedButton type="submit" style={{ width: "100%" }} primary={true} label="Login" />
              </Col>
            </Row>
          </Grid>
        </form>
      </Dialog>
    );
  }
}
<commit_msg>Close dialog for link clicks<commit_after>import React from 'react';
import { Link } from 'react-router';
import { Grid, Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';

import { handleLogin, handleFacebookLogin, handleGoogleLogin, handleIVLELogin } from '../../../modules/login';

import * as IconsHelper from '../../../util/icons';

export default class Login extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      errors: {},
    };
  }

  handleSubmit(event) {
    event.preventDefault();
  }

  componentDidUpdate(prevProps, prevState) {
    const self = this;

    // Necessary because the real DOM hasn't been updated at this point, only the virtual DOM. lol....
    if (prevProps.open != this.props.open)
      setTimeout(() => {
        self.setState({ errors: {} });

        handleLogin({
          component: self,
          clearErrors() {
            self.setState({ errors: {} });
          },
          setError(er, text) {
            let errorsObject = {};
            errorsObject[er] = text;
            errorsObject = $.extend({}, self.state.errors, errorsObject);
            self.setState({ errors: errorsObject });
          },
          afterLogin() {
            self.props.closeLogin();
          },
        });
      });
  }

  socialLoginHandler(handler) {
    const self = this;

    return (event) => handler({
        afterLogin() {
          self.props.closeLogin();
        }
      });
  }

  render() {
    return (
      <Dialog
        open={ this.props.open }
        onRequestClose={ this.props.closeLogin }
        contentStyle={{ maxWidth: 550 }}
        autoScrollBodyContent={true}>
        <form ref="login" className="login" onSubmit={ this.handleSubmit }>
          <Grid fluid={true}>
            <Row>
              <Col>

Login to Free4All

              </Col>
            </Row>
            <Row className="openid" style={{ marginBottom: 10 }}>
              <Col xs={12} sm={4} smOffset={0}>
                <FlatButton
                  style={{ width: "100%", backgroundColor: "#ff8c00", marginBottom: 10 }}
                  labelColor="#ffffff"
                  label="NUS OpenID"
                  onTouchTap={ this.socialLoginHandler(handleIVLELogin) } />
              </Col>
              <Col xs={12} sm={4} smOffset={0}>
                <FlatButton
                  style={{ width: "100%", backgroundColor: "#395697", marginBottom: 10 }}
                  labelColor="#ffffff"
                  label="Facebook"
                  icon={ IconsHelper.icon("fa fa-facebook-f") }
                  onTouchTap={ this.socialLoginHandler(handleFacebookLogin) } />
              </Col>
              <Col xs={12} sm={4} smOffset={0}>
                <FlatButton
                  style={{ width: "100%", backgroundColor: "#e0492f", marginBottom: 10 }}
                  labelColor="#ffffff"
                  label="Google"
                  icon={ IconsHelper.icon("fa fa-google") }
                  onTouchTap={ this.socialLoginHandler(handleGoogleLogin) } />
              </Col>
            </Row>
            <Row>
              <Col xs={12}>

                  OR

              </Col>
            </Row>
            <Row>
              <Col xs={12} sm={6}>
                <TextField
                  type="email"
                  ref="emailAddress"
                  name="emailAddress"
                  hintText="Email Address"
                  errorText={ this.state.errors.emailAddress }
                  fullWidth={true}
                />
                <TextField
                  type="password"
                  ref="password"
                  name="password"
                  hintText="Password"
                  errorText={ this.state.errors.password }
                  fullWidth={true}
                />
              </Col>
              <Col xs={12} sm={6}>

                  Not yet a member? <Link to="/signup" onTouchTap={ this.props.closeLogin }>Sign up</Link>

                  <Link to="/recover-password" onTouchTap={ this.props.closeLogin }>Forgot Password?</Link>

              </Col>
            </Row>
            <Row style={{ marginTop: 20 }}>
              <Col xs={6} xsOffset={3} sm={3} smOffset={9}>
                <RaisedButton type="submit" style={{ width: "100%" }} primary={true} label="Login" />
              </Col>
            </Row>
          </Grid>
        </form>
      </Dialog>
    );
  }
}
<|endoftext|>


<commit_before>import {createAction} from 'redux-actions'

export const GROUP_DIALOG_OPEN = 'GROUP_DIALOG_OPEN'

export const groupDialogOpen = createAction(GROUP_DIALOG_OPEN)
<commit_msg>Add the GROUP_DIALOG_REJECT action<commit_after>import {createAction} from 'redux-actions'

export const GROUP_DIALOG_OPEN = 'GROUP_DIALOG_OPEN'
export const GROUP_DIALOG_REJECT = 'GROUP_DIALOG_REJECT'

export const groupDialogOpen = createAction(GROUP_DIALOG_OPEN)
export const groupDialogReject = createAction(GROUP_DIALOG_REJECT)
<|endoftext|>


<commit_before>/**
 * HTTP Server Settings
 * (sails.config.http)
 *
 * Configuration for the underlying HTTP server in Sails.
 * Only applies to HTTP requests (not WebSockets)
 *
 * For more information on configuration, check out:
 * http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.http.html
 */

module.exports.http = {

  /****************************************************************************
  *                                                                           *
  * Express middleware to use for every Sails request. To add custom          *
  * middleware to the mix, add a function to the middleware config object and *
  * add its key to the "order" array. The $custom key is reserved for         *
  * backwards-compatibility with Sails v0.9.x apps that use the               *
  * `customMiddleware` config option.                                         *
  *                                                                           *
  ****************************************************************************/

  middleware: {
    xframe: (req, res, next) => {
      res.header('X-FRAME-OPTIONS', 'SAMEORIGIN');
      next();
    },

  /***************************************************************************
  *                                                                          *
  * The order in which middleware should be run for HTTP request. (the Sails *
  * router is invoked by the "router" middleware below.)                     *
  *                                                                          *
  ***************************************************************************/

    order: [
      'xframe',
      'startRequestTimer',
      'cookieParser',
      'session',
      'myRequestLogger',
      'bodyParser',
      'handleBodyParserError',
      'compress',
      'methodOverride',
      'poweredBy',
      '$custom',
      'router',
      'www',
      'favicon',
      '404',
      '500'
    ]

  /****************************************************************************
  *                                                                           *
  * Example custom middleware; logs each request to the console.              *
  *                                                                           *
  ****************************************************************************/

    // myRequestLogger: function (req, res, next) {
    //     console.log("Requested :: ", req.method, req.url);
    //     return next();
    // }

  /***************************************************************************
  *                                                                          *
  * The body parser that will handle incoming multipart HTTP requests. By    *
  * default as of v0.10, Sails uses                                          *
  * [skipper](http://github.com/balderdashy/skipper). See                    *
  * http://www.senchalabs.org/connect/multipart.html for other options.      *
  *                                                                          *
  ***************************************************************************/

    // bodyParser: require('skipper')

  }

  /***************************************************************************
  *                                                                          *
  * The number of seconds to cache flat files on disk being served by        *
  * Express static middleware (by default, these files are in `.tmp/public`) *
  *                                                                          *
  * The HTTP static cache is only active in a 'production' environment,      *
  * since that's the only time Express will cache flat-files.                *
  *                                                                          *
  ***************************************************************************/

  // cache: 31557600000
};
<commit_msg>Get rid of the x-powered-by header<commit_after>/**
 * HTTP Server Settings
 * (sails.config.http)
 *
 * Configuration for the underlying HTTP server in Sails.
 * Only applies to HTTP requests (not WebSockets)
 *
 * For more information on configuration, check out:
 * http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.http.html
 */

module.exports.http = {

  /****************************************************************************
  *                                                                           *
  * Express middleware to use for every Sails request. To add custom          *
  * middleware to the mix, add a function to the middleware config object and *
  * add its key to the "order" array. The $custom key is reserved for         *
  * backwards-compatibility with Sails v0.9.x apps that use the               *
  * `customMiddleware` config option.                                         *
  *                                                                           *
  ****************************************************************************/

  middleware: {
    xframe: (req, res, next) => {
      res.header('X-FRAME-OPTIONS', 'SAMEORIGIN');
      next();
    },

  /***************************************************************************
  *                                                                          *
  * The order in which middleware should be run for HTTP request. (the Sails *
  * router is invoked by the "router" middleware below.)                     *
  *                                                                          *
  ***************************************************************************/

    order: [
      'xframe',
      'startRequestTimer',
      'cookieParser',
      'session',
      'myRequestLogger',
      'bodyParser',
      'handleBodyParserError',
      'compress',
      'methodOverride',
      '$custom',
      'router',
      'www',
      'favicon',
      '404',
      '500'
    ]

  /****************************************************************************
  *                                                                           *
  * Example custom middleware; logs each request to the console.              *
  *                                                                           *
  ****************************************************************************/

    // myRequestLogger: function (req, res, next) {
    //     console.log("Requested :: ", req.method, req.url);
    //     return next();
    // }

  /***************************************************************************
  *                                                                          *
  * The body parser that will handle incoming multipart HTTP requests. By    *
  * default as of v0.10, Sails uses                                          *
  * [skipper](http://github.com/balderdashy/skipper). See                    *
  * http://www.senchalabs.org/connect/multipart.html for other options.      *
  *                                                                          *
  ***************************************************************************/

    // bodyParser: require('skipper')

  }

  /***************************************************************************
  *                                                                          *
  * The number of seconds to cache flat files on disk being served by        *
  * Express static middleware (by default, these files are in `.tmp/public`) *
  *                                                                          *
  * The HTTP static cache is only active in a 'production' environment,      *
  * since that's the only time Express will cache flat-files.                *
  *                                                                          *
  ***************************************************************************/

  // cache: 31557600000
};
<|endoftext|>