<commit_before>/*
Copyright (C) 2016 andrea rota <a@xelera.eu>

This file is part of Pattrn - http://pattrn.co/.

Pattrn is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Pattrn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Pattrn.  If not, see <http://www.gnu.org/licenses/>.
*/

import d3 from 'd3';

import { is_defined } from '../utils/is_defined.js';

/**
 * Generate layer groups/layers menu for data layer panel from
 * layer group data
 * @x-technical-debt: document parameters/return
 */
export function generate_data_layer_menu(pattrn_layer_groups, pattrn_data_sets, variable_list) {
   pattrn_layer_groups.forEach((layer_group, group_index) => {
     let layer_group_root = d3
       .select('#myExploreTab .layer-groups-root')
       .append('div')
       .classed('layer-group-root', true);

     let layer_group_element_id = `layer-group-selector-${layer_group.id}`;

     let radio_el_attributes = {
       id: layer_group_element_id,
       type: 'radio',
       name: 'layer_groups',
       value: layer_group.id
     };

     if(group_index === 0) radio_el_attributes.checked = true;

     layer_group_root
       .append('input')
         .classed('layer-group', true)
         .attr(radio_el_attributes);

     layer_group_root
       .append('div')
       .classed('layer-group-container', true);

     layer_group_root
       .select('.layer-group-container')
       .append('label')
       .attr({
         for: layer_group_element_id
       })
       .text(() => {
         return layer_group.name;
       });

     layer_group_root = layer_group_root
       .select('.layer-group-container')
       .append('ul');

     layer_group.layers.forEach((layer_data, layer_index) => {
       let layer_menu_root = layer_group_root
         .append('li')
         .classed('layer-menu-root', true)
         .classed(`layer-root-${layer_data.id}`, true);

       layer_menu_root.append('span')
         .classed('layer-root', true)
         .style('color', (d, i) => {
           return is_defined(pattrn_data_sets[layer_data.id]) ? pattrn_data_sets[layer_data.id] : 'inherit';
         })
         .append('label')
         .text(layer_data.name)
         .append('input')
         .attr('type', 'checkbox')
         .attr('checked', 'true');

       layer_menu_root.append('ul');

       layer_data.non_empty_variables.forEach((variable_group, variable_group_index) => {
         let variable_group_menu_root = layer_menu_root
           .append('li')
           .append('ul')
           .selectAll('li')
           .data(variable_group.names);

         variable_group_menu_root
           .enter()
           .append('li')
           .append('a')
           .attr('role', 'menuitem')
           .attr('data-toggle', 'tab')
           .attr('href', (d, i) => {
             return `#lg${group_index}_ly${layer_index}_vg${variable_group_index}_var${i}`;
           })
           .text((d, i) => {
             /**
              * if variable is defined in metadata file, return its name
              * otherwise return the variable id (column name)
              * Variables should always be defined in metadata, but whilst
              * transitioning from legacy event count charts to the Pattrn v2
              * layer/layer group structure, the variable used for event counts
              * (eventID, added at runtime) is used without it having to be
              * defined in the metadata file. This should be the only edge case,
              * and such it should be properly refactored to a non-edge setup
              * as part of technical debt noted elsewhere.
              */
             let variable = variable_list.find(variable => variable.id === d)

             return is_defined(variable) ? variable.name : d;
           });
       });

     });
   });
}
<commit_msg>fix extra nesting<commit_after>/*
Copyright (C) 2016 andrea rota <a@xelera.eu>

This file is part of Pattrn - http://pattrn.co/.

Pattrn is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Pattrn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Pattrn.  If not, see <http://www.gnu.org/licenses/>.
*/

import d3 from 'd3';

import { is_defined } from '../utils/is_defined.js';

/**
 * Generate layer groups/layers menu for data layer panel from
 * layer group data
 * @x-technical-debt: document parameters/return
 */
export function generate_data_layer_menu(pattrn_layer_groups, pattrn_data_sets, variable_list) {
   pattrn_layer_groups.forEach((layer_group, group_index) => {
     let layer_group_root = d3
       .select('#myExploreTab .layer-groups-root')
       .append('div')
       .classed('layer-group-root', true);

     let layer_group_element_id = `layer-group-selector-${layer_group.id}`;

     let radio_el_attributes = {
       id: layer_group_element_id,
       type: 'radio',
       name: 'layer_groups',
       value: layer_group.id
     };

     if(group_index === 0) radio_el_attributes.checked = true;

     layer_group_root
       .append('input')
         .classed('layer-group', true)
         .attr(radio_el_attributes);

     layer_group_root
       .append('div')
       .classed('layer-group-container', true);

     layer_group_root
       .select('.layer-group-container')
       .append('label')
       .attr({
         for: layer_group_element_id
       })
       .text(() => {
         return layer_group.name;
       });

     layer_group_root = layer_group_root
       .select('.layer-group-container')
       .append('ul');

     layer_group.layers.forEach((layer_data, layer_index) => {
       let layer_menu_root = layer_group_root
         .append('li')
         .classed('layer-menu-root', true)
         .classed(`layer-root-${layer_data.id}`, true);

       layer_menu_root.append('span')
         .classed('layer-root', true)
         .style('color', (d, i) => {
           return is_defined(pattrn_data_sets[layer_data.id]) ? pattrn_data_sets[layer_data.id] : 'inherit';
         })
         .append('label')
         .text(layer_data.name)
         .append('input')
         .attr('type', 'checkbox')
         .attr('checked', 'true');

       layer_menu_root.append('ul');

       layer_data.non_empty_variables.forEach((variable_group, variable_group_index) => {
         let variable_group_menu_root = layer_menu_root
           .select('ul')
           .selectAll('li')
           .data(variable_group.names);

         variable_group_menu_root
           .enter()
           .append('li')
           .append('a')
           .attr('role', 'menuitem')
           .attr('data-toggle', 'tab')
           .attr('href', (d, i) => {
             return `#lg${group_index}_ly${layer_index}_vg${variable_group_index}_var${i}`;
           })
           .text((d, i) => {
             /**
              * if variable is defined in metadata file, return its name
              * otherwise return the variable id (column name)
              * Variables should always be defined in metadata, but whilst
              * transitioning from legacy event count charts to the Pattrn v2
              * layer/layer group structure, the variable used for event counts
              * (eventID, added at runtime) is used without it having to be
              * defined in the metadata file. This should be the only edge case,
              * and such it should be properly refactored to a non-edge setup
              * as part of technical debt noted elsewhere.
              */
             let variable = variable_list.find(variable => variable.id === d)

             return is_defined(variable) ? variable.name : d;
           });
       });

     });
   });
}
<|endoftext|>


<commit_before>/*======================================================
************   Pull To Refresh   ************
======================================================*/
app.initPullToRefresh = function () {
    var isTouched, isMoved, touchesStart = {}, isScrolling, touchesDiff, touchStartTime, container, refresh = false, useTranslate = false, startTranslate = 0;
    function handleTouchStart(e) {
        if (isTouched) return;
        isMoved = false;
        isTouched = true;
        isScrolling = undefined;
        touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
        touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
        touchStartTime = (new Date()).getTime();
    }

    function handleTouchMove(e) {
        if (!isTouched) return;
        var pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
        var pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
        if (typeof isScrolling === 'undefined') {
            isScrolling = !!(isScrolling || Math.abs(pageY - touchesStart.y) > Math.abs(pageX - touchesStart.x));
        }
        if (!isScrolling) {
            isTouched = false;
            return;
        }
        if (!isMoved) {
            /*jshint validthis:true */
            container = $(this);
            container.removeClass('transitioning');
            startTranslate = container.hasClass('refreshing') ? 44 : 0;
            if (container[0].scrollHeight === container[0].offsetHeight || app.device.os !== 'ios') {
                useTranslate = true;
            }
            else {
                useTranslate = false;
            }
        }
        isMoved = true;
        touchesDiff = pageY - touchesStart.y;
        if (touchesDiff > 0 && container[0].scrollTop <= 0 || container[0].scrollTop < 0) {
            if (useTranslate) {
                e.preventDefault();
                container.transform('translate3d(0,' + (Math.pow(touchesDiff, 0.85) + startTranslate) + 'px,0)');
            }
            if ((useTranslate && Math.pow(touchesDiff, 0.85) > 44) || (!useTranslate && touchesDiff >= 88)) {
                refresh = true;
                container.addClass('pull-up');
            }
            else {
                refresh = false;
                container.removeClass('pull-up');
            }
        }
        else {
            container.removeClass('pull-up');
            refresh = false;
            return;
        }
    }
    function handleTouchEnd(e) {
        if (!isTouched || !isMoved) {
            isTouched = false;
            isMoved = false;
            return;
        }
        container.addClass('transitioning');
        container.transform('');
        if (refresh) {
            container.addClass('refreshing');
            container.trigger('refresh', {
                done: function () {
                    app.pullToRefreshDone(container);
                }
            });
        }
        isTouched = false;
        isMoved = false;
    }
    $(document).on(app.touchEvents.start, '.pull-to-refresh-content', handleTouchStart);
    $(document).on(app.touchEvents.move, '.pull-to-refresh-content', handleTouchMove);
    $(document).on(app.touchEvents.end, '.pull-to-refresh-content', handleTouchEnd);
};

app.pullToRefreshDone = function (container) {
    container = $(container);
    if (container.length === 0) container = $('.pull-to-refresh-content.refreshing');
    container.removeClass('refreshing').addClass('transitioning');
    container.transitionEnd(function () {
        container.removeClass('transitioning pull-up');
    });
};
<commit_msg>Change pullToRefresh logic to usual events<commit_after>/*======================================================
************   Pull To Refresh   ************
======================================================*/
app.initPullToRefresh = function (pageContainer) {
    var eventsTarget = $(pageContainer);
    if (!eventsTarget.hasClass('pull-to-refresh-content')) {
        eventsTarget = eventsTarget.find('.pull-to-refresh-content');
    }
    if (eventsTarget.length === 0) return;

    var isTouched, isMoved, touchesStart = {}, isScrolling, touchesDiff, touchStartTime, container, refresh = false, useTranslate = false, startTranslate = 0;
    function handleTouchStart(e) {
        if (isTouched) return;
        isMoved = false;
        isTouched = true;
        isScrolling = undefined;
        touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
        touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
        touchStartTime = (new Date()).getTime();
    }

    function handleTouchMove(e) {
        if (!isTouched) return;
        var pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
        var pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
        if (typeof isScrolling === 'undefined') {
            isScrolling = !!(isScrolling || Math.abs(pageY - touchesStart.y) > Math.abs(pageX - touchesStart.x));
        }
        if (!isScrolling) {
            isTouched = false;
            return;
        }
        if (!isMoved) {
            /*jshint validthis:true */
            container = $(this);
            container.removeClass('transitioning');
            startTranslate = container.hasClass('refreshing') ? 44 : 0;
            if (container[0].scrollHeight === container[0].offsetHeight || app.device.os !== 'ios') {
                useTranslate = true;
            }
            else {
                useTranslate = false;
            }
        }
        isMoved = true;
        touchesDiff = pageY - touchesStart.y;
        if (touchesDiff > 0 && container[0].scrollTop <= 0 || container[0].scrollTop < 0) {
            if (useTranslate) {
                e.preventDefault();
                container.transform('translate3d(0,' + (Math.pow(touchesDiff, 0.85) + startTranslate) + 'px,0)');
            }
            if ((useTranslate && Math.pow(touchesDiff, 0.85) > 44) || (!useTranslate && touchesDiff >= 88)) {
                refresh = true;
                container.addClass('pull-up');
            }
            else {
                refresh = false;
                container.removeClass('pull-up');
            }
        }
        else {
            container.removeClass('pull-up');
            refresh = false;
            return;
        }
    }
    function handleTouchEnd(e) {
        if (!isTouched || !isMoved) {
            isTouched = false;
            isMoved = false;
            return;
        }
        container.addClass('transitioning');
        container.transform('');
        if (refresh) {
            container.addClass('refreshing');
            container.trigger('refresh', {
                done: function () {
                    app.pullToRefreshDone(container);
                }
            });
        }
        isTouched = false;
        isMoved = false;
    }

    // Attach Events
    eventsTarget.on(app.touchEvents.start, handleTouchStart);
    eventsTarget.on(app.touchEvents.move, handleTouchMove);
    eventsTarget.on(app.touchEvents.end, handleTouchEnd);

    // Detach Events on page remove
    var page = eventsTarget.hasClass('page') ? eventsTarget : eventsTarget.parents('.page');
    if (page.length === 0) return;
    function detachEvents() {
        eventsTarget.off(app.touchEvents.start, handleTouchStart);
        eventsTarget.off(app.touchEvents.move, handleTouchMove);
        eventsTarget.off(app.touchEvents.end, handleTouchEnd);

        page.off('pageBeforeRemove', detachEvents);
    }
    page.on('pageBeforeRemove', detachEvents);

};

app.pullToRefreshDone = function (container) {
    container = $(container);
    if (container.length === 0) container = $('.pull-to-refresh-content.refreshing');
    container.removeClass('refreshing').addClass('transitioning');
    container.transitionEnd(function () {
        container.removeClass('transitioning pull-up');
    });
};
<|endoftext|>


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

import {
  modal,
  accounts as accountsActions,
  nav as navActions,
  give as giveActions,
} from "../../store";

import AccountType from "../../components/accountType";

import OnBoard from "../accounts";
import Give from "../give";
import ChangePayments from "../change-payments";

import {
  PrimaryButton,
  SecondaryButton,
  Guest as TertiaryButton,
} from "./Buttons";

const SAVED_ACCTS_QUERY = gql`
  query GetSavedPaymentAccounts {
    savedPayments(cache: false) {
      name, id: entityId, date,
      payment { accountNumber, paymentType }
    }
  }
`;

// XXX remove cache: false when heighliner caching is tested
const getSavedPaymentAccounts = graphql(SAVED_ACCTS_QUERY, {
  options: (ownProps) => ({
    variables: {
      // even though this is unused, we include it to trigger a recal when a person
      // logs in or logs out
      authorized: ownProps.authorized
    },
    forceFetch: true,
  })
});

/*

  The give now button is presented in the following order:

  1. Give with existing account if found
  2. Give now (if signed in)
  3. Give as guest (in small text) if not signed in

*/
const mapStateToProps = store => ({
  authorized: store.accounts.authorized,
  savedAccount: store.give.savedAccount,
});

@getSavedPaymentAccounts
export default class GiveNow extends Component {

  static propTypes = {
    authorized: PropTypes.bool,
    classes: PropTypes.array, // eslint-disable-line
    dataId: PropTypes.string,
    disabled: PropTypes.bool,
    disabledGuest: PropTypes.bool,
    dispatch: PropTypes.func,
    hideCard: PropTypes.bool,
    onClick: PropTypes.func,
    savedAccount: PropTypes.object, // eslint-disable-line
    savedPayments: PropTypes.object, // eslint-disable-line
    style: PropTypes.object, // eslint-disable-line
    text: PropTypes.string,
    theme: PropTypes.string,
    value: PropTypes.string,
  }

  state = {
    paymentDetails: false,
  }

  onClick = (e) => {
    let keepGoing = true;
    if (this.props.onClick) {
      keepGoing = this.props.onClick(e);
    }

    if (!keepGoing) {
      return;
    }

    this.props.dispatch(giveActions.setTransactionType("default"));

    if (this.props.savedPayments.savedPayments) {
      // const details = this.props.savedAccount[Object.keys(this.props.savedAccount)[0]]
      const details = this.getAccount();
      this.props.dispatch(giveActions.setAccount(details));
    }

    if (Meteor.userId() && !this.props.disabled) {
      this.props.dispatch(modal.render(Give));
    } else if (!Meteor.userId()) {
      this.props.dispatch(modal.render(OnBoard, {
        onSignin: this.getPaymentDetailsAfterLogin,
        onFinished: this.renderAfterLogin,
        coverHeader: true,
      }));

      this.props.dispatch(accountsActions.setAccount(true));
    }

    this.props.dispatch(navActions.setLevel("MODAL"));
  }

  getAccount = () => {
    const { savedAccount } = this.props;
    if (savedAccount && savedAccount.id) return savedAccount;

    if (!this.props.savedPayments) return {};

    const { savedPayments } = this.props.savedPayments;
    if (!savedPayments || !savedPayments.length) return {};

    return _.sortBy(savedPayments, "date")[savedPayments.length - 1];
  }

  buttonClasses = () => {
    let classes = ["btn"];

    if (this.props.savedPayments.savedPayments) {
      classes.push("has-card");
    }

    if (this.props.disabled && Meteor.userId()) {
      classes.push("btn--disabled");
    }

    if (this.props.classes) {
      classes = classes.concat(this.props.classes);
    }

    return classes.join(" ");
  }

  giveAsGuest = () => {
    if (this.props.disabled) return;

    this.props.dispatch(giveActions.setTransactionType("guest"));
    this.props.dispatch(modal.render(Give));
    // this.props.dispatch(navActions.setLevel("MODAL"))
  }

  register = () => {
    this.props.dispatch(accountsActions.setAccount(false));
    this.props.dispatch(modal.render(OnBoard, {
      onFinished: this.renderAfterLogin,
      coverHeader: true,
    }));
    // this.props.dispatch(navActions.setLevel("MODAL"))
  }

  changePayments = (e) => {
    e.preventDefault();

    this.props.dispatch(modal.render(ChangePayments, {
      // onFinished: () => {},
      savedAccounts: this.props.savedPayments.savedPayments,
      currentAccount: this.getAccount(),
    }));
  }

  buttonText = () => {
    let text = "Give Now";
    if (this.props.text) {
      text = this.props.text;
    }
    const { savedPayments } = this.props.savedPayments;
    if (savedPayments && savedPayments.length && !this.props.hideCard) {
      const details = this.getAccount();
      if (details && details.payment && details.payment.accountNumber) {
        let { accountNumber } = details.payment;
        accountNumber = accountNumber.slice(-4).trim();
        text = `Review Using ${accountNumber}`;
      }
    }

    if (!Meteor.userId()) text = "Sign In";

    return text;
  }

  icon = () => {
    if (this.props.savedPayments.savedPayments && !this.props.hideCard) {
      // const detail = this.props.savedAccount[Object.keys(this.props.savedAccount)[0]]
      const detail = this.getAccount();
      if (detail.payment && detail.payment.paymentType === "ACH") {
        return (
          <AccountType width="30px" height="21px" type="Bank" />
        );
      } else if (detail.payment && detail.payment.paymentType) {
        return (
          <AccountType width="30px" height="21px" type={detail.payment.paymentType} />
        );
      }
    }
    return null;
  }

  renderAfterLogin = () => {
    if (this.props.disabled) return this.props.dispatch(modal.hide());
    this.props.dispatch(modal.render(Give));
    return null;
  }

  render() {
    try {
      return (

          <PrimaryButton
            classes={this.props.theme || this.buttonClasses()}
            icon={this.icon()}
            text={this.buttonText()}
            onClick={this.onClick}
            value={this.props.value}
            style={this.props.style || {}}
            dataId={this.props.dataId}
          />
          {(() => {
            if (!this.props.authorized && !Meteor.userId()) {
              return (
                <SecondaryButton

                  onClick={this.register}
                />
              );
            }
            return null;
          })()}
          {(() => {
            if (!this.props.disabledGuest && !Meteor.userId()) {
              return (
                <TertiaryButton
                  disabled={this.props.disabled}
                  onClick={this.giveAsGuest}
                />
              );
            }
            return null;
          })()}

          {(() => {
            const { savedPayments } = this.props.savedPayments;
            if (savedPayments && savedPayments.length && !this.props.hideCard && Meteor.userId()) {
              return (
                <TertiaryButton
                  onClick={this.changePayments}
                  text={"Change payment account"}
                />
              );
            }
            return null;
          })()}

      );
    } catch (e) {
      return null;
    }
  }
}
<commit_msg>updated refactor<commit_after>import { Meteor } from "meteor/meteor";
import { Component, PropTypes } from "react";
import { graphql } from "react-apollo";
import { connect } from "react-redux";
import gql from "graphql-tag";

import {
  modal,
  accounts as accountsActions,
  nav as navActions,
  give as giveActions,
} from "../../store";

import AccountType from "../../components/accountType";

import OnBoard from "../accounts";
import Give from "../give";
import ChangePayments from "../change-payments";

import {
  PrimaryButton,
  SecondaryButton,
  Guest as TertiaryButton,
} from "./Buttons";

const SAVED_ACCTS_QUERY = gql`
  query GetSavedPaymentAccounts {
    savedPayments(cache: false) {
      name, id: entityId, date,
      payment { accountNumber, paymentType }
    }
  }
`;

// XXX remove cache: false when heighliner caching is tested
const withSavedPayments = graphql(SAVED_ACCTS_QUERY, {
  options: ownProps => ({
    name: "savedPayments",
    variables: {
      // even though this is unused, we include it to trigger a recal when a person
      // logs in or logs out
      authorized: ownProps.authorized,
    },
    forceFetch: true,
  }),
});

/*

  The give now button is presented in the following order:

  1. Give with existing account if found
  2. Give now (if signed in)
  3. Give as guest (in small text) if not signed in

*/
const mapStateToProps = store => ({
  authorized: store.accounts.authorized,
  savedAccount: store.give.savedAccount,
});

@connect({ mapStateToProps })
@withSavedPayments
export default class GiveNow extends Component {

  static propTypes = {
    authorized: PropTypes.bool,
    classes: PropTypes.array, // eslint-disable-line
    dataId: PropTypes.string,
    disabled: PropTypes.bool,
    disabledGuest: PropTypes.bool,
    dispatch: PropTypes.func,
    hideCard: PropTypes.bool,
    onClick: PropTypes.func,
    savedAccount: PropTypes.object, // eslint-disable-line
    savedPayments: PropTypes.object, // eslint-disable-line
    style: PropTypes.object, // eslint-disable-line
    text: PropTypes.string,
    theme: PropTypes.string,
    value: PropTypes.string,
  }

  state = {
    paymentDetails: false,
  }

  onClick = (e) => {
    let keepGoing = true;
    if (this.props.onClick) {
      keepGoing = this.props.onClick(e);
    }

    if (!keepGoing) {
      return;
    }

    this.props.dispatch(giveActions.setTransactionType("default"));

    if (this.props.savedPayments.savedPayments) {
      // const details = this.props.savedAccount[Object.keys(this.props.savedAccount)[0]]
      const details = this.getAccount();
      this.props.dispatch(giveActions.setAccount(details));
    }

    if (Meteor.userId() && !this.props.disabled) {
      this.props.dispatch(modal.render(Give));
    } else if (!Meteor.userId()) {
      this.props.dispatch(modal.render(OnBoard, {
        onSignin: this.getPaymentDetailsAfterLogin,
        onFinished: this.renderAfterLogin,
        coverHeader: true,
      }));

      this.props.dispatch(accountsActions.setAccount(true));
    }

    this.props.dispatch(navActions.setLevel("MODAL"));
  }

  getAccount = () => {
    const { savedAccount } = this.props;
    if (savedAccount && savedAccount.id) return savedAccount;

    if (!this.props.savedPayments) return {};

    const { savedPayments } = this.props.savedPayments;
    if (!savedPayments || !savedPayments.length) return {};

    return _.sortBy(savedPayments, "date")[savedPayments.length - 1];
  }

  buttonClasses = () => {
    let classes = ["btn"];

    if (this.props.savedPayments.savedPayments) {
      classes.push("has-card");
    }

    if (this.props.disabled && Meteor.userId()) {
      classes.push("btn--disabled");
    }

    if (this.props.classes) {
      classes = classes.concat(this.props.classes);
    }

    return classes.join(" ");
  }

  giveAsGuest = () => {
    if (this.props.disabled) return;

    this.props.dispatch(giveActions.setTransactionType("guest"));
    this.props.dispatch(modal.render(Give));
    // this.props.dispatch(navActions.setLevel("MODAL"))
  }

  register = () => {
    this.props.dispatch(accountsActions.setAccount(false));
    this.props.dispatch(modal.render(OnBoard, {
      onFinished: this.renderAfterLogin,
      coverHeader: true,
    }));
    // this.props.dispatch(navActions.setLevel("MODAL"))
  }

  changePayments = (e) => {
    e.preventDefault();

    this.props.dispatch(modal.render(ChangePayments, {
      // onFinished: () => {},
      savedAccounts: this.props.savedPayments.savedPayments,
      currentAccount: this.getAccount(),
    }));
  }

  buttonText = () => {
    let text = "Give Now";
    if (this.props.text) {
      text = this.props.text;
    }
    const { savedPayments } = this.props.savedPayments;
    if (savedPayments && savedPayments.length && !this.props.hideCard) {
      const details = this.getAccount();
      if (details && details.payment && details.payment.accountNumber) {
        let { accountNumber } = details.payment;
        accountNumber = accountNumber.slice(-4).trim();
        text = `Review Using ${accountNumber}`;
      }
    }

    if (!Meteor.userId()) text = "Sign In";

    return text;
  }

  icon = () => {
    if (this.props.savedPayments.savedPayments && !this.props.hideCard) {
      // const detail = this.props.savedAccount[Object.keys(this.props.savedAccount)[0]]
      const detail = this.getAccount();
      if (detail.payment && detail.payment.paymentType === "ACH") {
        return (
          <AccountType width="30px" height="21px" type="Bank" />
        );
      } else if (detail.payment && detail.payment.paymentType) {
        return (
          <AccountType width="30px" height="21px" type={detail.payment.paymentType} />
        );
      }
    }
    return null;
  }

  renderAfterLogin = () => {
    if (this.props.disabled) return this.props.dispatch(modal.hide());
    this.props.dispatch(modal.render(Give));
    return null;
  }

  render() {
    try {
      return (

          <PrimaryButton
            classes={this.props.theme || this.buttonClasses()}
            icon={this.icon()}
            text={this.buttonText()}
            onClick={this.onClick}
            value={this.props.value}
            style={this.props.style || {}}
            dataId={this.props.dataId}
          />
          {(() => {
            if (!this.props.authorized && !Meteor.userId()) {
              return (
                <SecondaryButton

                  onClick={this.register}
                />
              );
            }
            return null;
          })()}
          {(() => {
            if (!this.props.disabledGuest && !Meteor.userId()) {
              return (
                <TertiaryButton
                  disabled={this.props.disabled}
                  onClick={this.giveAsGuest}
                />
              );
            }
            return null;
          })()}

          {(() => {
            const { savedPayments } = this.props.savedPayments;
            if (savedPayments && savedPayments.length && !this.props.hideCard && Meteor.userId()) {
              return (
                <TertiaryButton
                  onClick={this.changePayments}
                  text={"Change payment account"}
                />
              );
            }
            return null;
          })()}

      );
    } catch (e) {
      return null;
    }
  }
}
<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import React, { Component } from 'react';
import classnames from 'classnames';

import { MDCSlider } from '@material/slider/dist/mdc.slider';

const DISCRETE = 'mdc-slider--discrete';
const SHOW_MARKERS = 'mdc-slider--display-markers';

export default class Slider extends Component {
  static propTypes = {
    className: PropTypes.string,
    value: PropTypes.number.isRequired,
    min: PropTypes.number,
    max: PropTypes.number,
    step: PropTypes.number,
    // Per MDC documentation providing step doesn't imply discrete, so an explicit property
    discrete: PropTypes.bool,
    showMarkers: PropTypes.bool,
    onInput: PropTypes.func,
    onChange: PropTypes.func,
  };

  componentDidMount() {
    this.slider = new MDCSlider(this.node);
    this.setup(this.props);

    this.slider.listen('MDCSlider:change', () => this.handleMDCSliderChange());
    this.slider.listen('MDCSlider:input', () => this.handleMDCSliderInput());
  }

  componentWillReceiveProps(newProps) {
    this.setup(newProps);
  }

  componentWillUnmount() {
    this.slider.unlisten('MDCSlider:change', () => this.handleMDCSliderChange());
    this.slider.unlisten('MDCSlider:input', () => this.handleMDCSliderInput());
    this.slider.destroy();
  }

  setup(props) {
    this.slider.disabled = props.disabled;
    if (props.min) {
      this.slider.min = props.min;
    }
    if (props.max) {
      this.slider.max = props.max;
    }
    if (props.step) {
      this.slider.step = props.step;
    }
    this.slider.value = props.value;
  }

  handleMDCSliderInput() {
    if (this.props.onInput) {
      this.props.onInput(this.slider.value);
    }
  }

  handleMDCSliderChange() {
    if (this.props.onChange) {
      this.props.onChange(this.slider.value);
    }
  }

  render() {
    const { className, value, min, max, step, discrete, showMarkers = false,
            ...otherProps } = this.props;

    return (

 { this.node = node; }}
        className={classnames('mdc-slider', {
          [SHOW_MARKERS]: showMarkers,
          [DISCRETE]: discrete,
        }, className)}
        {...otherProps}
      >

          { discrete && showMarkers &&

          }

          { discrete &&

          }
          <svg className="mdc-slider__thumb" width="21" height="21">
            <circle cx="10.5" cy="10.5" r="7.875" />
          </svg>

    );
  }
}
<commit_msg>style(Slider): fix lint errors<commit_after>import PropTypes from 'prop-types';
import React, { Component } from 'react';
import classnames from 'classnames';

import { MDCSlider } from '@material/slider/dist/mdc.slider';

const DISCRETE = 'mdc-slider--discrete';
const SHOW_MARKERS = 'mdc-slider--display-markers';

export default class Slider extends Component {
  static propTypes = {
    className: PropTypes.string,
    value: PropTypes.number.isRequired,
    min: PropTypes.number,
    max: PropTypes.number,
    step: PropTypes.number,
    // Per MDC documentation providing step doesn't imply discrete, so an explicit property
    discrete: PropTypes.bool,
    showMarkers: PropTypes.bool,
    onInput: PropTypes.func,
    onChange: PropTypes.func,
  };

  componentDidMount() {
    this.slider = new MDCSlider(this.node);
    this.setup(this.props);

    this.slider.listen('MDCSlider:change', () => this.handleMDCSliderChange());
    this.slider.listen('MDCSlider:input', () => this.handleMDCSliderInput());
  }

  componentWillReceiveProps(newProps) {
    this.setup(newProps);
  }

  componentWillUnmount() {
    this.slider.unlisten('MDCSlider:change', () => this.handleMDCSliderChange());
    this.slider.unlisten('MDCSlider:input', () => this.handleMDCSliderInput());
    this.slider.destroy();
  }

  setup(props) {
    this.slider.disabled = props.disabled;
    if (props.min) {
      this.slider.min = props.min;
    }
    if (props.max) {
      this.slider.max = props.max;
    }
    if (props.step) {
      this.slider.step = props.step;
    }
    this.slider.value = props.value;
  }

  handleMDCSliderInput() {
    if (this.props.onInput) {
      this.props.onInput(this.slider.value);
    }
  }

  handleMDCSliderChange() {
    if (this.props.onChange) {
      this.props.onChange(this.slider.value);
    }
  }

  render() {
    const {
      className,
      value, // eslint-disable-line no-unused-vars
      min, // eslint-disable-line no-unused-vars
      max, // eslint-disable-line no-unused-vars
      step, // eslint-disable-line no-unused-vars
      discrete,
      showMarkers = false,
      ...otherProps
    } = this.props;

    return (

 { this.node = node; }}
        className={classnames('mdc-slider', {
          [SHOW_MARKERS]: showMarkers,
          [DISCRETE]: discrete,
        }, className)}
        {...otherProps}
      >

          { discrete && showMarkers &&

          }

          { discrete &&

          }
          <svg className="mdc-slider__thumb" width="21" height="21">
            <circle cx="10.5" cy="10.5" r="7.875" />
          </svg>

    );
  }
}
<|endoftext|>


<commit_before>import { find, pathEq, sortBy } from "ramda"

export default class Lobby {
  constructor(Game) {
    this.Game = Game
    this.players = []
  }

  async push(player) {
    if (find(pathEq(["client", "uuid"], player.client.uuid), this.players)) {
      return
    }

    if (this.players.length === 0) {
      this.players.push(player)
      return
    }

    const opponent = this.players.pop()

    const [whitePlayer, blackPlayer] = sortBy(
      () => { return Math.random() },
      [player, opponent]
    )

    const game = await this.Game.create(
      whitePlayer.client.user,
      blackPlayer.client.user
    )

    const gameData = await game.serialize()

    whitePlayer.startGame(gameData)
    blackPlayer.startGame(gameData)
  }
}
<commit_msg>fix lobby<commit_after>import { find, pathEq, sortBy } from "ramda"

export default class Lobby {
  constructor(Game) {
    this.Game = Game
    this.players = []
  }

  async push(player) {
    if (find(pathEq(["socket", "uuid"], player.socket.uuid), this.players)) {
      return
    }

    if (this.players.length === 0) {
      this.players.push(player)
      return
    }

    const opponent = this.players.pop()

    const [whitePlayer, blackPlayer] = sortBy(
      () => { return Math.random() },
      [player, opponent]
    )

    const game = await this.Game.create(
      whitePlayer.socket.user,
      blackPlayer.socket.user
    )

    const gameData = await game.serialize()

    whitePlayer.startGame(gameData)
    blackPlayer.startGame(gameData)
  }
}
<|endoftext|>


<commit_before>// Namespace
var mejs = mejs || {};

// version number
mejs.version = '2.6.3';

// player number (for missing, same id attr)
mejs.meIndex = 0;

// media types accepted by plugins
mejs.plugins = {
	silverlight: [
		{version: [3,0], types: ['video/mp4','video/m4v','video/mov','video/wmv','audio/wma','audio/m4a','audio/mp3','audio/wav','audio/mpeg']}
	],
	flash: [
		{version: [9,0,124], types: ['video/mp4','video/m4v','video/mov','video/flv','video/x-flv','audio/flv','audio/x-flv','audio/mp3','audio/m4a','audio/mpeg']}
		//,{version: [12,0], types: ['video/webm']} // for future reference (hopefully!)
	],
	youtube: [
		{version: null, types: ['video/youtube']}
	],
	vimeo: [
		{version: null, types: ['video/vimeo']}
	]
};<commit_msg>2.6.4<commit_after>// Namespace
var mejs = mejs || {};

// version number
mejs.version = '2.6.4';

// player number (for missing, same id attr)
mejs.meIndex = 0;

// media types accepted by plugins
mejs.plugins = {
	silverlight: [
		{version: [3,0], types: ['video/mp4','video/m4v','video/mov','video/wmv','audio/wma','audio/m4a','audio/mp3','audio/wav','audio/mpeg']}
	],
	flash: [
		{version: [9,0,124], types: ['video/mp4','video/m4v','video/mov','video/flv','video/x-flv','audio/flv','audio/x-flv','audio/mp3','audio/m4a','audio/mpeg']}
		//,{version: [12,0], types: ['video/webm']} // for future reference (hopefully!)
	],
	youtube: [
		{version: null, types: ['video/youtube']}
	],
	vimeo: [
		{version: null, types: ['video/vimeo']}
	]
};<|endoftext|>


<commit_before>var chessground = require('chessground');
var clock = require('../clock');
var renderPromotion = require('../promotion').view;
var utils = require('../../utils');

function oppositeColor(c) {
  return c === 'white' ? 'black' : 'white';
}

function renderPlayer(ctrl){
  var clockRunningColor = ctrl.isClockRunning() ? ctrl.data.game.player : null;
  var children = [
    m('div.infos')
  ];
  if (ctrl.clock)
    children.push(clock.view(ctrl.clock, ctrl.data.player.color, clockRunningColor));
  return m('section.player', children);
}

function renderOpponent(ctrl){
  function renderOpponentInfo(ctrl) {
    var opp = ctrl.data.opponent;
    if (opp.ai) return [ m('h2', 'Stockfish level ' + opp.ai) ];
    else if (opp.user) return [ m('h2', opp.user.id), m('h3', opp.rating) ];
    else return [ m('h2', 'Anonymous') ];
  }

  var clockRunningColor = ctrl.isClockRunning() ? ctrl.data.game.player : null;
  var children = [
    m('div.infos', renderOpponentInfo(ctrl))
  ];
  if (ctrl.clock)
    children.push(clock.view(ctrl.clock, oppositeColor(ctrl.data.player.color), clockRunningColor));

  return m('section.opponent', children);
}

function renderBoard(ctrl){
  var vw = utils.getViewportDims().vw;
  return m('section#board.grey.merida', { style: { height: vw + 'px' }}, [
    chessground.view(ctrl.chessground), renderPromotion(ctrl)
  ]);
}

module.exports = {
  renderBoard: renderBoard,
  renderPlayer: renderPlayer,
  renderOpponent: renderOpponent
};
<commit_msg>Display player name during game<commit_after>var chessground = require('chessground');
var clock = require('../clock');
var renderPromotion = require('../promotion').view;
var utils = require('../../utils');

function oppositeColor(c) {
  return c === 'white' ? 'black' : 'white';
}

function renderPlayer(ctrl){
  var clockRunningColor = ctrl.isClockRunning() ? ctrl.data.game.player : null;
  var player = ctrl.data.player;
  var playerInfos = player.user ? [ m('h2', player.user.username),
    m('h3', player.rating) ] : null;
  var children = [
    m('div.infos', playerInfos)
  ];
  if (ctrl.clock)
    children.push(clock.view(ctrl.clock, ctrl.data.player.color, clockRunningColor));
  return m('section.player', children);
}

function renderOpponent(ctrl){
  function renderOpponentInfo(ctrl) {
    var opp = ctrl.data.opponent;
    if (opp.ai) return [ m('h2', 'Stockfish level ' + opp.ai) ];
    else if (opp.user) return [ m('h2', opp.user.id), m('h3', opp.rating) ];
    else return [ m('h2', 'Anonymous') ];
  }

  var clockRunningColor = ctrl.isClockRunning() ? ctrl.data.game.player : null;
  var children = [
    m('div.infos', renderOpponentInfo(ctrl))
  ];
  if (ctrl.clock)
    children.push(clock.view(ctrl.clock, oppositeColor(ctrl.data.player.color), clockRunningColor));

  return m('section.opponent', children);
}

function renderBoard(ctrl){
  var vw = utils.getViewportDims().vw;
  return m('section#board.grey.merida', { style: { height: vw + 'px' }}, [
    chessground.view(ctrl.chessground), renderPromotion(ctrl)
  ]);
}

module.exports = {
  renderBoard: renderBoard,
  renderPlayer: renderPlayer,
  renderOpponent: renderOpponent
};
<|endoftext|>


<commit_before>import React from 'react';
import { Link } from 'react-router-dom';
import { Grid, Row, Col } from 'react-bootstrap';

import './Footer.scss';

const copyrightYear = () => {
  const currentYear = 2019;
  return currentYear;
};

const Footer = () => (

    <Grid>

        © {copyrightYear()} Suvai Organics
         | Healthy, Tasty and Organic

          <Link to="pages/terms">
            Terms
             of Service
          </Link>

          <Link to="/pages/privacy">
            Privacy
             Policy
          </Link>

    </Grid>

);

Footer.propTypes = {};

export default Footer;
<commit_msg>Miscellaneous updates<commit_after>import React from 'react';
import { Link } from 'react-router-dom';
import { Grid, Row, Col } from 'react-bootstrap';

import './Footer.scss';

const copyrightYear = () => {
  const currentYear = 2019;
  return currentYear;
};

const Footer = () => (

    <Grid>

        © {copyrightYear()} Suvai Organics
         | Foods that love you back

          <Link to="pages/terms">
            Terms
             of Service
          </Link>

          <Link to="/pages/privacy">
            Privacy
             Policy
          </Link>

    </Grid>

);

Footer.propTypes = {};

export default Footer;
<|endoftext|>


<commit_before>'use strict';

import Action from '../actions/Action';
import ActionDispatcher from '../actions/ActionDispatcher';

/**
 * The UIComponent class is the base class for all atomic view components,
 * atoms, molecules and organisms.
 *
 */

class UIComponent extends ActionDispatcher {
  constructor(name) {
    super();

    /**
     * Define read-only 'name' property
     *
     */

    Object.defineProperty(this, 'name', {
      value: name,
      writable: false
    });

    this.dispatchAction(Action.ADDED);
  }

  /**
   * Render
   *
   */
  render() {

  }
}

export default UIComponent;
<commit_msg>feat(UIComponent): type & cid definition<commit_after>'use strict';

import Action from '../actions/Action';
import ActionDispatcher from '../actions/ActionDispatcher';

/**
 * The UIComponent class is the base class for all atomic view components,
 * atoms, molecules and organisms.
 *
 * @param {cid} Component cid
 *
 */

class UIComponent extends ActionDispatcher {
  constructor(type, cid) {
    super();

    /**
     * Define read-only 'type' property
     *
     */

    Object.defineProperty(this, 'type', {
      value: type,
      writable: false
    });

    /**
     * Define read-only 'cid' property
     *
     */

    Object.defineProperty(this, 'cid', {
      value: cid,
      writable: false
    });

    this.dispatchAction(Action.ADDED);
  }

  /**
   * Render
   *
   */
  render() {

  }
}

export default UIComponent;
<|endoftext|>


<commit_before>function getPageKind() {
    var parentNodeTxt = $('#selectedMainNav').text();
    parentNodeTxt = parentNodeTxt.replace("/\n","");
    parentNodeTxt = parentNodeTxt.replace("","");
    parentNodeTxt = parentNodeTxt.trim();
    if (parentNodeTxt.length > 0 && parentNodeTxt.charAt(parentNodeTxt.length-1)=='s') {
            parentNodeTxt = parentNodeTxt.substring(0, parentNodeTxt.length-1);
    }
    return parentNodeTxt;
}

function getObjectQuery() {
    var selectedNodeTxt = $('#currentOriginalNode').text();
    selectedNodeTxt = selectedNodeTxt.trim();
    selectedNodeTxt = selectedNodeTxt.split(' ').join('');//selectedNodeTxt.replace(" ", "")
    parentNodeTxt = getPageKind();

    if (parentNodeTxt == "Slice") {
        return "&slice=" + selectedNodeTxt;
    } else if (parentNodeTxt == "Site") {
        return "&site=" + selectedNodeTxt;
    } else if (parentNodeTxt == "Node") {
        return "&node=" + selectedNodeTxt;
    } else {
        return "";
    }
}

function setPageStatInt(labelName, valueName, legend, units, value) {
    $(labelName).text(legend).show();
    $(valueName).text(Math.round(value)+units).show();
}

function setPageStatFloat(labelName, valueName, legend, units, value, dp) {
    $(labelName).text(legend).show();
    $(valueName).text(Number(value).toFixed(dp)+units).show();
}

// ----------------------------------------------------------------------------
// node count and average cpu utilization

function updatePageAnalyticsData(summaryData) {
    window.pageAnalyticsUrl = summaryData["dataSourceUrl"];
    lastRow = summaryData.rows.length-1;

    if (summaryData.msg) {
        $("#minidashStatus").text(summaryData.msg).show();
    } else {
        $("#minidashStatus").text("").hide();
    }

    if (summaryData.rows.length <= 0) {
        //console.log("no data received from page analytics ajax")
        return;
    }

    //Old minidashboard
    //setPageStatInt(".nodesLabel", ".nodesValue", "Node Count", "", summaryData.rows[lastRow]["count_hostname"]);
    //setPageStatInt(".cpuLabel", ".cpuValue", "Avg Load", "%", summaryData.rows[lastRow]["avg_cpu"]);

    //New miniDashboard
    setPageStatInt("#miniDashNodeCountLabel", "#miniDashNodeCount", "Node Count", "", summaryData.rows[lastRow]["count_hostname"]);
    setPageStatInt("#miniDashAvgLoadLabel", "#miniDashAvgLoad", "Avg Load", "%", summaryData.rows[lastRow]["avg_cpu"]);
}

function updatePageAnalytics() {
    var url= '/analytics/bigquery/?avg=%cpu&count=%hostname&cached=default' + getObjectQuery();
    $.ajax({
    url: url,
    dataType : 'json',
    type : 'GET',
    success: function(newData) {
        updatePageAnalyticsData(newData);
        setTimeout(updatePageAnalytics, 30000);
    },
    error: function() {
        console.log("error retrieving statistics; retry in 5 seconds");
        setTimeout(updatePageBandwidth, 5000);
    }
});
}

// ----------------------------------------------------------------------------
// bandwidth

function updatePageBandwidthData(summaryData) {
    window.pageBandwidthUrl = summaryData["dataSourceUrl"];
    lastRow = summaryData.rows.length-1;

    if (summaryData.rows.length <= 0) {
        //console.log("no data received from page bandwidth ajax")
        return;
    }

    //Old minidashboard
    //setPageStatFloat(".bandwidthLabel", ".bandwidthValue", "Bandwidth", " Gbps", summaryData.rows[lastRow]["sum_computed_bytes_sent_div_elapsed"]*8.0/1024/1024/1024,2);

    //New minidashboard
    setPageStatFloat("#miniDashBandwidthLabel", "#miniDashBandwidth", "Bandwidth", " Gbps", summaryData.rows[lastRow]["sum_computed_bytes_sent_div_elapsed"]*8.0/1024/1024/1024,2);
}

function updatePageBandwidth() {
    var url='/analytics/bigquery/?computed=%bytes_sent/%elapsed&cached=default' + getObjectQuery();

    if (getPageKind()!="Slice") {
        url = url + "&event=node_heartbeat";
    }

    $.ajax({
    url : url,
    dataType : 'json',
    type : 'GET',
    success: function(newData) {
        updatePageBandwidthData(newData);
        setTimeout(updatePageBandwidth, 30000);
    },
    error: function() {
        console.log("error retrieving statistics; retry in 5 seconds")
        setTimeout(updatePageBandwidth, 5000);
    }
});
}

$( document ).ready(function() {
    updatePageAnalytics();
    updatePageBandwidth();
});

<commit_msg>minidashboard, WIP<commit_after>// ----------------------------------------------------------------------------
// node count and average cpu utilization

function updatePageCPU() {
    var url="/stats/?model_name=" + admin_object_name + "&pk=" + admin_object_id + "&meter=cpu" + "&controller_name=" + admin_object_controller;
    console.log("fetching stats url " + url);
    $.ajax({
    url: url,
    dataType : 'json',
    type : 'GET',
    success: function(newData) {
        console.log(newData);
        setTimeout(updatePageAnalytics, 30000);
    },
    error: function() {
    }
});
}

$( document ).ready(function() {
    if (admin_object_name == "Sliver" && admin_object_id != undefined) {
        updatePageCPU();
    }
});

<|endoftext|>


<commit_before>var Utils     = require('./utils')
  , DataTypes = require('./data-types')

module.exports = (function() {
  var QueryInterface = function(sequelize) {
    this.sequelize = sequelize
    this.QueryGenerator = require('./connectors/' + this.sequelize.options.connector + '/query-generator')
  }
  Utils.addEventEmitter(QueryInterface)

  QueryInterface.prototype.createTable = function(tableName, attributes, options) {
    var sql  = this.QueryGenerator.createTableQuery(tableName, attributes, options)
      , self = this

    return queryAndEmit.call(this, sql, 'createTable')
  }

  QueryInterface.prototype.dropTable = function(tableName) {
    var sql  = this.QueryGenerator.dropTableQuery(tableName)
      , self = this

    return queryAndEmit.call(this, sql, 'dropTable')
  }

  QueryInterface.prototype.dropAllTables = function() {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      var chainer = new Utils.QueryChainer()

      self.showAllTables().success(function(tableNames) {
        tableNames.forEach(function(tableName) {
          chainer.add(self.sequelize.getQueryInterface().dropTable(tableName))
        })
        chainer
          .run()
          .success(function() {
            self.emit('dropAllTables', null)
            emitter.emit('success', null)
          })
          .error(function(err) {
            self.emit('dropAllTables', err)
            emitter.emit('failure', err)
          })
      }).error(function(err) {
        self.emit('dropAllTables', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.renameTable = function(before, after) {
    var sql  = this.QueryGenerator.renameTableQuery(before, after)
      , self = this

    return queryAndEmit.call(this, sql, 'renameTable')
  }

  QueryInterface.prototype.showAllTables = function() {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      self.sequelize.query('SHOW TABLES;', null, { raw: true }).success(function(data) {
        var tableNames = Sequelize.Utils._.map(data, function(hash) {
          return Sequelize.Utils._.values(hash)
        })

        self.emit('showAllTables', null)
        emitter.emit('success', Sequelize.Utils._.flatten(tableNames))
      }).error(function(err) {
        self.emit('showAllTables', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.describeTable = function(tableName) {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      self.sequelize.query('DESCRIBE `' + tableName + '`;', null, { raw: true }).success(function(data) {
        emitter.emit('success', data)
      }).error(function(err) {
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.addColumn = function(tableName, attributeName, dataTypeOrOptions) {
    var attributes = {}

    if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
      attributes[attributeName] = { type: dataTypeOrOptions, allowNull: false }
    else
      attributes[attributeName] = dataTypeOrOptions

    var options = Utils.simplifyAttributes(attributes)
      , sql     = this.QueryGenerator.addColumnQuery(tableName, options)
      , self    = this

    return queryAndEmit.call(this, sql, 'addColumn')
  }

  QueryInterface.prototype.removeColumn = function(tableName, attributeName) {
    var sql  = this.QueryGenerator.removeColumnQuery(tableName, attributeName)
      , self = this

    return queryAndEmit.call(this, sql, 'removeColumn')
  }

  QueryInterface.prototype.changeColumn = function(tableName, attributeName, dataTypeOrOptions) {
    var attributes = {}

    if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
      attributes[attributeName] = { type: dataTypeOrOptions, allowNull: false }
    else
      attributes[attributeName] = dataTypeOrOptions

    var options = Utils.simplifyAttributes(attributes)
      , sql     = this.QueryGenerator.changeColumnQuery(tableName, options)
      , self    = this

    return queryAndEmit.call(this, sql, 'changeColumn')
  }

  QueryInterface.prototype.renameColumn = function(tableName, attrNameBefore, attrNameAfter) {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      self.describeTable(tableName).success(function(data) {
        data = data.filter(function(h) { return h.Field == attrNameBefore })[0]

        var options =  {}

        options[attrNameAfter] = {
          type: data.Type,
          allowNull: data.Null == 'YES',
          defaultValue: data.Default
        }

        var sql = self.QueryGenerator.renameColumnQuery(tableName,
          attrNameBefore,
          Utils.simplifyAttributes(options)
        )

        self.sequelize.query(sql).success(function() {
          self.emit('renameColumn', null)
          emitter.emit('success', null)
        }).error(function(err) {
          self.emit('renameColumn', err)
          emitter.emit('failure', err)
        })
      }).error(function(err) {
        self.emit('renameColumn', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.addIndex = function() {

  }

  QueryInterface.prototype.removeIndex = function() {

  }

  QueryInterface.prototype.insert = function(model, tableName, values) {
    var self = this
      , sql  = self.QueryGenerator.insertQuery(tableName, values)

    return queryAndEmit.call(this, [sql, model], 'insert', {
      success: function(obj) { obj.isNewRecord = false }
    })
  }

  QueryInterface.prototype.update = function(model, tableName, values, identifier) {
    var sql  = this.QueryGenerator.updateQuery(tableName, values, identifier)
      , self = this

    return queryAndEmit.call(this, [sql, model], 'update')
  }

  QueryInterface.prototype.delete = function(model, tableName, identifier) {
    var sql  = this.QueryGenerator.deleteQuery(tableName, identifier)
      , self = this

    return queryAndEmit.call(this, [sql, model], 'delete')
  }

  QueryInterface.prototype.select = function(factory, tableName, options, queryOptions) {
    var sql    = this.QueryGenerator.selectQuery(tableName, options)
      , _query = query.call(this, sql, factory, queryOptions)
      , self   = this

    _query
      .success(function(){ self.emit('select', null) })
      .error(function(err){ self.emit('select', err)})

    return _query
  }

  QueryInterface.prototype.rawSelect = function(tableName, options, attributeSelector) {
    var self = this

    if(attributeSelector == undefined)
      throw new Error('Please pass an attribute selector!')

    return new Utils.CustomEventEmitter(function(emitter) {
      var sql    = self.QueryGenerator.selectQuery(tableName, options)
        , _query = query.call(self, sql, null, { plain: true, raw: true })

      _query.success(function(data) {
        self.emit('rawSelect', null)
        emitter.emit('success', data[attributeSelector])
      }).error(function(err) {
        self.emit('rawSelect', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  // private

  var queryAndEmit = function(sqlOrQueryParams, methodName, options) {
    var self = this

    options = Utils._.extend({
      success: function(obj){},
      error: function(err){}
    }, options || {})

    return new Utils.CustomEventEmitter(function(emitter) {
      var query = null

      if(Array.isArray(sqlOrQueryParams))
        query = self.sequelize.query.apply(self.sequelize, sqlOrQueryParams)
      else
        query = self.sequelize.query(sqlOrQueryParams)

      // append the query for better testing
      emitter.query = query

      query.success(function(obj) {
        options.success && options.success(obj)
        self.emit(methodName, null)
        emitter.emit('success', obj)
      }).error(function(err) {
        options.error && options.error(err)
        self.emit(methodName, err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  var query = function() {
    var args = Utils._.map(arguments, function(arg, _) { return arg })

    // add this as callee via the second argument
    if(arguments.length == 1) args.push(this)

    return this.sequelize.query.apply(this.sequelize, args)
  }

  return QueryInterface
})()
<commit_msg>removed unused code<commit_after>var Utils     = require('./utils')
  , DataTypes = require('./data-types')

module.exports = (function() {
  var QueryInterface = function(sequelize) {
    this.sequelize = sequelize
    this.QueryGenerator = require('./connectors/' + this.sequelize.options.connector + '/query-generator')
  }
  Utils.addEventEmitter(QueryInterface)

  QueryInterface.prototype.createTable = function(tableName, attributes, options) {
    var sql = this.QueryGenerator.createTableQuery(tableName, attributes, options)
    return queryAndEmit.call(this, sql, 'createTable')
  }

  QueryInterface.prototype.dropTable = function(tableName) {
    var sql = this.QueryGenerator.dropTableQuery(tableName)
    return queryAndEmit.call(this, sql, 'dropTable')
  }

  QueryInterface.prototype.dropAllTables = function() {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      var chainer = new Utils.QueryChainer()

      self.showAllTables().success(function(tableNames) {
        tableNames.forEach(function(tableName) {
          chainer.add(self.sequelize.getQueryInterface().dropTable(tableName))
        })
        chainer
          .run()
          .success(function() {
            self.emit('dropAllTables', null)
            emitter.emit('success', null)
          })
          .error(function(err) {
            self.emit('dropAllTables', err)
            emitter.emit('failure', err)
          })
      }).error(function(err) {
        self.emit('dropAllTables', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.renameTable = function(before, after) {
    var sql = this.QueryGenerator.renameTableQuery(before, after)
    return queryAndEmit.call(this, sql, 'renameTable')
  }

  QueryInterface.prototype.showAllTables = function() {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      self.sequelize.query('SHOW TABLES;', null, { raw: true }).success(function(data) {
        var tableNames = Sequelize.Utils._.map(data, function(hash) {
          return Sequelize.Utils._.values(hash)
        })

        self.emit('showAllTables', null)
        emitter.emit('success', Sequelize.Utils._.flatten(tableNames))
      }).error(function(err) {
        self.emit('showAllTables', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.describeTable = function(tableName) {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      self.sequelize.query('DESCRIBE `' + tableName + '`;', null, { raw: true }).success(function(data) {
        emitter.emit('success', data)
      }).error(function(err) {
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.addColumn = function(tableName, attributeName, dataTypeOrOptions) {
    var attributes = {}

    if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
      attributes[attributeName] = { type: dataTypeOrOptions, allowNull: false }
    else
      attributes[attributeName] = dataTypeOrOptions

    var options = Utils.simplifyAttributes(attributes)
      , sql     = this.QueryGenerator.addColumnQuery(tableName, options)

    return queryAndEmit.call(this, sql, 'addColumn')
  }

  QueryInterface.prototype.removeColumn = function(tableName, attributeName) {
    var sql = this.QueryGenerator.removeColumnQuery(tableName, attributeName)
    return queryAndEmit.call(this, sql, 'removeColumn')
  }

  QueryInterface.prototype.changeColumn = function(tableName, attributeName, dataTypeOrOptions) {
    var attributes = {}

    if(Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1)
      attributes[attributeName] = { type: dataTypeOrOptions, allowNull: false }
    else
      attributes[attributeName] = dataTypeOrOptions

    var options = Utils.simplifyAttributes(attributes)
      , sql     = this.QueryGenerator.changeColumnQuery(tableName, options)

    return queryAndEmit.call(this, sql, 'changeColumn')
  }

  QueryInterface.prototype.renameColumn = function(tableName, attrNameBefore, attrNameAfter) {
    var self = this

    return new Utils.CustomEventEmitter(function(emitter) {
      self.describeTable(tableName).success(function(data) {
        data = data.filter(function(h) { return h.Field == attrNameBefore })[0]

        var options =  {}

        options[attrNameAfter] = {
          type: data.Type,
          allowNull: data.Null == 'YES',
          defaultValue: data.Default
        }

        var sql = self.QueryGenerator.renameColumnQuery(tableName,
          attrNameBefore,
          Utils.simplifyAttributes(options)
        )

        self.sequelize.query(sql).success(function() {
          self.emit('renameColumn', null)
          emitter.emit('success', null)
        }).error(function(err) {
          self.emit('renameColumn', err)
          emitter.emit('failure', err)
        })
      }).error(function(err) {
        self.emit('renameColumn', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  QueryInterface.prototype.addIndex = function(tableName, attributes, options) {
    var sql = this.QueryGenerator.addIndexQuery(tableName, attributes, options)
    return queryAndEmit.call(this, sql, 'addIndex')
  }

  QueryInterface.prototype.showIndexes = function() {

  }

  QueryInterface.prototype.removeIndex = function() {

  }

  QueryInterface.prototype.insert = function(model, tableName, values) {
    var sql = this.QueryGenerator.insertQuery(tableName, values)

    return queryAndEmit.call(this, [sql, model], 'insert', {
      success: function(obj) { obj.isNewRecord = false }
    })
  }

  QueryInterface.prototype.update = function(model, tableName, values, identifier) {
    var sql = this.QueryGenerator.updateQuery(tableName, values, identifier)
    return queryAndEmit.call(this, [sql, model], 'update')
  }

  QueryInterface.prototype.delete = function(model, tableName, identifier) {
    var sql = this.QueryGenerator.deleteQuery(tableName, identifier)
    return queryAndEmit.call(this, [sql, model], 'delete')
  }

  QueryInterface.prototype.select = function(factory, tableName, options, queryOptions) {
    var sql    = this.QueryGenerator.selectQuery(tableName, options)
      , _query = query.call(this, sql, factory, queryOptions)
      , self   = this

    _query
      .success(function(){ self.emit('select', null) })
      .error(function(err){ self.emit('select', err)})

    return _query
  }

  QueryInterface.prototype.rawSelect = function(tableName, options, attributeSelector) {
    var self = this

    if(attributeSelector == undefined)
      throw new Error('Please pass an attribute selector!')

    return new Utils.CustomEventEmitter(function(emitter) {
      var sql    = self.QueryGenerator.selectQuery(tableName, options)
        , _query = query.call(self, sql, null, { plain: true, raw: true })

      _query.success(function(data) {
        self.emit('rawSelect', null)
        emitter.emit('success', data[attributeSelector])
      }).error(function(err) {
        self.emit('rawSelect', err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  // private

  var queryAndEmit = function(sqlOrQueryParams, methodName, options) {
    var self = this

    options = Utils._.extend({
      success: function(obj){},
      error: function(err){}
    }, options || {})

    return new Utils.CustomEventEmitter(function(emitter) {
      var query = null

      if(Array.isArray(sqlOrQueryParams))
        query = self.sequelize.query.apply(self.sequelize, sqlOrQueryParams)
      else
        query = self.sequelize.query(sqlOrQueryParams)

      // append the query for better testing
      emitter.query = query

      query.success(function(obj) {
        options.success && options.success(obj)
        self.emit(methodName, null)
        emitter.emit('success', obj)
      }).error(function(err) {
        options.error && options.error(err)
        self.emit(methodName, err)
        emitter.emit('failure', err)
      })
    }).run()
  }

  var query = function() {
    var args = Utils._.map(arguments, function(arg, _) { return arg })

    // add this as callee via the second argument
    if(arguments.length == 1) args.push(this)

    return this.sequelize.query.apply(this.sequelize, args)
  }

  return QueryInterface
})()
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import warning from 'warning'
import PropTypes from 'prop-types'
import { discrete, linear } from './scales'
import Rail from '../Rail'
import Ticks from '../Ticks'
import Tracks from '../Tracks'
import Handles from '../Handles'
import { mode1, mode2 } from './modes'
import * as utils from './utils'

const prfx = 'react-compound-slider:'

const noop = () => {}

const areValuesEqual = (a, b) =>
  a === b ||
  (a.length === b.length &&
    a.reduce((res, val, idx) => res && b[idx] === val, true))

class Slider extends Component {
  constructor(props) {
    super(props)

    this.slider = null

    this.valueToPerc = linear()
    this.valueToStep = discrete()
    this.pixelToStep = discrete()

    this.onMouseMove = this.onMouseMove.bind(this)
    this.onTouchMove = this.onTouchMove.bind(this)
    this.onMove = this.onMove.bind(this)

    this.onMouseDown = this.onMouseDown.bind(this)
    this.onTouchStart = this.onTouchStart.bind(this)
    this.onStart = this.onStart.bind(this)

    this.onMouseUp = this.onMouseUp.bind(this)
    this.onTouchEnd = this.onTouchEnd.bind(this)
  }

  componentWillMount() {
    const { defaultValues, domain, step, reversed, values } = this.props

    warning(
      defaultValues === undefined,
      `${prfx} 'defaultValues' is being deprecated, use 'values' instead`,
    )

    this.updateRange(domain, step, reversed)
    this.updateValues(values || defaultValues, reversed)
  }

  componentWillReceiveProps(next) {
    const { domain, step, reversed, values } = next
    const { props } = this

    if (
      domain[0] !== props.domain[0] ||
      domain[1] !== props.domain[1] ||
      step !== props.step ||
      reversed !== props.reversed
    ) {
      this.updateRange(domain, step, reversed)

      if (values === props.values) {
        this.updateValues(this.latestValues, reversed)
        props.onUpdate(this.latestValues)
        props.onChange(this.latestValues)
      } else {
        this.updateValues(values, reversed)
      }
    } else if (
      values !== props.values &&
      !areValuesEqual(values, this.latestValues)
    ) {
      this.updateValues(values, reversed)
    }
  }

  updateValues(arr = [], reversed) {
    this.values = arr
      .map(x => {
        const val = this.valueToStep(x)
        warning(
          x === val,
          `${prfx} Invalid value encountered. Changing ${x} to ${val}.`,
        )
        return val
      })
      .map((val, i) => ({ key: `$$-${i}`, val }))
      .sort(utils.getSortByVal(reversed))

    this.latestValues = this.values.map(d => d.val)
  }

  updateRange([min, max], step, reversed) {
    const range = utils.getStepRange(min, max, step)

    this.valueToStep
      .range(range.slice())
      .domain([min - step / 2, max + step / 2])

    if (reversed === true) {
      this.valueToPerc.domain([min, max]).range([100, 0])
      range.reverse()
    } else {
      this.valueToPerc.domain([min, max]).range([0, 100])
    }

    this.pixelToStep.range(range)

    warning(
      max > min,
      `${prfx} Max must be greater than min (even if reversed). Max is ${max}. Min is ${min}.`,
    )

    warning(
      range.length <= 10001,
      `${prfx} Increase step value. Found ${range.length.toLocaleString()} values in range.`,
    )

    const last = range.length - 1

    warning(
      range[reversed ? last : 0] === min && range[reversed ? 0 : last] === max,
      `${prfx} The range is incorrectly calculated. Check domain (min, max) and step values.`,
    )
  }

  onMouseDown(e, key) {
    this.onStart(e, key, false)
  }

  onTouchStart(e, key) {
    if (utils.isNotValidTouch(e)) {
      return
    }
    this.onStart(e, key, true)
  }

  onStart(e, key, isTouch) {
    const { values } = this

    e.stopPropagation && e.stopPropagation()
    e.preventDefault && e.preventDefault()

    const active = values.find(value => {
      return value.key === key
    })

    if (active) {
      this.active = key
      isTouch ? this.addTouchEvents() : this.addMouseEvents()
    } else {
      this.active = null
      this.requestMove(e, isTouch)
    }
  }

  requestMove(e, isTouch) {
    const { values: prev, props: { vertical, reversed } } = this
    const { slider } = this

    this.pixelToStep.domain(utils.getSliderDomain(slider, vertical))

    let step

    if (isTouch) {
      step = this.pixelToStep(utils.getTouchPosition(vertical, e))
    } else {
      step = this.pixelToStep(vertical ? e.clientY : e.pageX)
    }

    let active = null
    let lowest = Infinity

    for (let i = 0; i < prev.length; i++) {
      const diff = Math.abs(this.valueToStep(prev[i].val) - step)

      if (diff < lowest) {
        active = prev[i].key
        lowest = diff
      }
    }

    if (active) {
      const next = utils.updateValues(prev, active, step, reversed)
      this.onMove(prev, next, true)
    }
  }

  addMouseEvents() {
    document.addEventListener('mousemove', this.onMouseMove)
    document.addEventListener('mouseup', this.onMouseUp)
  }

  addTouchEvents() {
    document.addEventListener('touchmove', this.onTouchMove)
    document.addEventListener('touchend', this.onTouchEnd)
  }

  onMouseMove(e) {
    const { values: prev, props: { vertical, reversed } } = this
    const { active, slider } = this

    this.pixelToStep.domain(utils.getSliderDomain(slider, vertical))

    const step = this.pixelToStep(vertical ? e.clientY : e.pageX)
    const next = utils.updateValues(prev, active, step, reversed)

    this.onMove(prev, next)
  }

  onTouchMove(e) {
    const { values: prev, props: { vertical, reversed } } = this
    const { active, slider } = this

    if (utils.isNotValidTouch(e)) {
      return
    }

    this.pixelToStep.domain(utils.getSliderDomain(slider, vertical))

    const step = this.pixelToStep(utils.getTouchPosition(vertical, e))
    const next = utils.updateValues(prev, active, step, reversed)

    this.onMove(prev, next)
  }

  onMove(prev, next, submit) {
    const { mode, onUpdate, onChange } = this.props

    if (next !== prev) {
      let values

      switch (mode) {
        case 1:
          values = mode1(prev, next)
          break
        case 2:
          values = mode2(prev, next)
          break
        default:
          values = next
          warning(false, `${prfx} Invalid mode value.`)
      }

      this.values = values
      this.latestValues = values.map(d => d.val)

      onUpdate(this.latestValues)

      if (submit) {
        onChange(this.latestValues)
      }
    }
  }

  onMouseUp() {
    const { values, props: { onChange } } = this
    onChange(values.map(d => d.val))

    document.removeEventListener('mousemove', this.onMouseMove)
    document.removeEventListener('mouseup', this.onMouseUp)
  }

  onTouchEnd() {
    const { values, props: { onChange } } = this
    onChange(values.map(d => d.val))

    document.removeEventListener('touchmove', this.onTouchMove)
    document.removeEventListener('touchend', this.onTouchEnd)
  }

  render() {
    const { values, props: { className, rootStyle } } = this

    const handles = values.map(({ key, val }) => {
      return { id: key, value: val, percent: this.valueToPerc(val) }
    })

    const children = React.Children.map(this.props.children, child => {
      if (
        child.type === Rail ||
        child.type === Ticks ||
        child.type === Tracks ||
        child.type === Handles
      ) {
        return React.cloneElement(child, {
          scale: this.valueToPerc,
          handles,
          emitMouse: this.onMouseDown,
          emitTouch: this.onTouchStart,
        })
      }

      return child
    })

    return (
      <div
        style={rootStyle || {}}
        className={className}
        ref={d => (this.slider = d)}
      >
        {children}
      </div>
    )
  }
}

Slider.propTypes = {
  /**
   * CSS class name applied to the root div of the slider.
   */
  className: PropTypes.string,
  /**
   * An object with any inline styles you want applied to the root div.
   */
  rootStyle: PropTypes.object,
  /**
   * Two element array of numbers providing the min and max values for the slider [min, max] e.g. [0, 100].
   * It does not matter if the slider is reversed on the screen, domain is always [min, max] with min < max.
   */
  domain: PropTypes.array,
  /**
   * An array of numbers. You can supply one for a value slider, two for a range slider or more to create n-handled sliders.
   * The values should correspond to valid step values in the domain.
   * The numbers will be forced into the domain if they are two small or large.
   */
  values: PropTypes.array,
  /**
   * [DEPRECATED]: use `values` instead.
   */
  defaultValues: PropTypes.array,
  /**
   * The step value for the slider.
   */
  step: PropTypes.number,
  /**
   * The interaction mode. Value of 1 will allow handles to cross.
   * Value of 2 will keep the sliders from crossing and separated by a step.
   */
  mode: PropTypes.oneOf([1, 2]),
  /**
   * Set to true if the slider is displayed vertically to tell the slider to use the height to calculate positions.
   */
  vertical: PropTypes.bool,
  /**
   * Reverse the display of slider values.
   */
  reversed: PropTypes.bool,
  /**
   * Function called with the values at each update (caution: high-volume updates when dragging).
   */
  onUpdate: PropTypes.func,
  /**
   * Function called with the values when interaction stops.
   */
  onChange: PropTypes.func,
  /**
   * Component children to render
   */
  children: PropTypes.any,
}

Slider.defaultProps = {
  mode: 1,
  step: 0.1,
  domain: [0, 100],
  vertical: false,
  reversed: false,
  onUpdate: noop,
  onChange: noop,
}

export default Slider
<commit_msg>compare function<commit_after>import React, { Component } from 'react'
import warning from 'warning'
import PropTypes from 'prop-types'
import { discrete, linear } from './scales'
import Rail from '../Rail'
import Ticks from '../Ticks'
import Tracks from '../Tracks'
import Handles from '../Handles'
import { mode1, mode2 } from './modes'
import * as utils from './utils'

const prfx = 'react-compound-slider:'

const noop = () => {}

const compare = b => (m, d, i) => m && b[i] === d

const areValuesEqual = (a, b) => {
  return a === b || (a.length === b.length && a.reduce(compare(b), true))
}

class Slider extends Component {
  constructor(props) {
    super(props)

    this.slider = null

    this.valueToPerc = linear()
    this.valueToStep = discrete()
    this.pixelToStep = discrete()

    this.onMouseMove = this.onMouseMove.bind(this)
    this.onTouchMove = this.onTouchMove.bind(this)
    this.onMove = this.onMove.bind(this)

    this.onMouseDown = this.onMouseDown.bind(this)
    this.onTouchStart = this.onTouchStart.bind(this)
    this.onStart = this.onStart.bind(this)

    this.onMouseUp = this.onMouseUp.bind(this)
    this.onTouchEnd = this.onTouchEnd.bind(this)
  }

  componentWillMount() {
    const { defaultValues, domain, step, reversed, values } = this.props

    warning(
      defaultValues === undefined,
      `${prfx} 'defaultValues' is being deprecated, use 'values' instead`,
    )

    this.updateRange(domain, step, reversed)
    this.updateValues(values || defaultValues, reversed)
  }

  componentWillReceiveProps(next) {
    const { domain, step, reversed, values } = next
    const { props } = this

    if (
      domain[0] !== props.domain[0] ||
      domain[1] !== props.domain[1] ||
      step !== props.step ||
      reversed !== props.reversed
    ) {
      this.updateRange(domain, step, reversed)

      if (values === props.values) {
        this.updateValues(this.latestValues, reversed)
        props.onUpdate(this.latestValues)
        props.onChange(this.latestValues)
      } else {
        this.updateValues(values, reversed)
      }
    } else if (
      values !== props.values &&
      !areValuesEqual(values, this.latestValues)
    ) {
      this.updateValues(values, reversed)
    }
  }

  updateValues(arr = [], reversed) {
    this.values = arr
      .map(x => {
        const val = this.valueToStep(x)
        warning(
          x === val,
          `${prfx} Invalid value encountered. Changing ${x} to ${val}.`,
        )
        return val
      })
      .map((val, i) => ({ key: `$$-${i}`, val }))
      .sort(utils.getSortByVal(reversed))

    this.latestValues = this.values.map(d => d.val)
  }

  updateRange([min, max], step, reversed) {
    const range = utils.getStepRange(min, max, step)

    this.valueToStep
      .range(range.slice())
      .domain([min - step / 2, max + step / 2])

    if (reversed === true) {
      this.valueToPerc.domain([min, max]).range([100, 0])
      range.reverse()
    } else {
      this.valueToPerc.domain([min, max]).range([0, 100])
    }

    this.pixelToStep.range(range)

    warning(
      max > min,
      `${prfx} Max must be greater than min (even if reversed). Max is ${max}. Min is ${min}.`,
    )

    warning(
      range.length <= 10001,
      `${prfx} Increase step value. Found ${range.length.toLocaleString()} values in range.`,
    )

    const last = range.length - 1

    warning(
      range[reversed ? last : 0] === min && range[reversed ? 0 : last] === max,
      `${prfx} The range is incorrectly calculated. Check domain (min, max) and step values.`,
    )
  }

  onMouseDown(e, key) {
    this.onStart(e, key, false)
  }

  onTouchStart(e, key) {
    if (utils.isNotValidTouch(e)) {
      return
    }
    this.onStart(e, key, true)
  }

  onStart(e, key, isTouch) {
    const { values } = this

    e.stopPropagation && e.stopPropagation()
    e.preventDefault && e.preventDefault()

    const active = values.find(value => {
      return value.key === key
    })

    if (active) {
      this.active = key
      isTouch ? this.addTouchEvents() : this.addMouseEvents()
    } else {
      this.active = null
      this.requestMove(e, isTouch)
    }
  }

  requestMove(e, isTouch) {
    const { values: prev, props: { vertical, reversed } } = this
    const { slider } = this

    this.pixelToStep.domain(utils.getSliderDomain(slider, vertical))

    let step

    if (isTouch) {
      step = this.pixelToStep(utils.getTouchPosition(vertical, e))
    } else {
      step = this.pixelToStep(vertical ? e.clientY : e.pageX)
    }

    let active = null
    let lowest = Infinity

    for (let i = 0; i < prev.length; i++) {
      const diff = Math.abs(this.valueToStep(prev[i].val) - step)

      if (diff < lowest) {
        active = prev[i].key
        lowest = diff
      }
    }

    if (active) {
      const next = utils.updateValues(prev, active, step, reversed)
      this.onMove(prev, next, true)
    }
  }

  addMouseEvents() {
    document.addEventListener('mousemove', this.onMouseMove)
    document.addEventListener('mouseup', this.onMouseUp)
  }

  addTouchEvents() {
    document.addEventListener('touchmove', this.onTouchMove)
    document.addEventListener('touchend', this.onTouchEnd)
  }

  onMouseMove(e) {
    const { values: prev, props: { vertical, reversed } } = this
    const { active, slider } = this

    this.pixelToStep.domain(utils.getSliderDomain(slider, vertical))

    const step = this.pixelToStep(vertical ? e.clientY : e.pageX)
    const next = utils.updateValues(prev, active, step, reversed)

    this.onMove(prev, next)
  }

  onTouchMove(e) {
    const { values: prev, props: { vertical, reversed } } = this
    const { active, slider } = this

    if (utils.isNotValidTouch(e)) {
      return
    }

    this.pixelToStep.domain(utils.getSliderDomain(slider, vertical))

    const step = this.pixelToStep(utils.getTouchPosition(vertical, e))
    const next = utils.updateValues(prev, active, step, reversed)

    this.onMove(prev, next)
  }

  onMove(prev, next, submit) {
    const { mode, onUpdate, onChange } = this.props

    if (next !== prev) {
      let values

      switch (mode) {
        case 1:
          values = mode1(prev, next)
          break
        case 2:
          values = mode2(prev, next)
          break
        default:
          values = next
          warning(false, `${prfx} Invalid mode value.`)
      }

      this.values = values
      this.latestValues = values.map(d => d.val)

      onUpdate(this.latestValues)

      if (submit) {
        onChange(this.latestValues)
      }
    }
  }

  onMouseUp() {
    const { values, props: { onChange } } = this
    onChange(values.map(d => d.val))

    document.removeEventListener('mousemove', this.onMouseMove)
    document.removeEventListener('mouseup', this.onMouseUp)
  }

  onTouchEnd() {
    const { values, props: { onChange } } = this
    onChange(values.map(d => d.val))

    document.removeEventListener('touchmove', this.onTouchMove)
    document.removeEventListener('touchend', this.onTouchEnd)
  }

  render() {
    const { values, props: { className, rootStyle } } = this

    const handles = values.map(({ key, val }) => {
      return { id: key, value: val, percent: this.valueToPerc(val) }
    })

    const children = React.Children.map(this.props.children, child => {
      if (
        child.type === Rail ||
        child.type === Ticks ||
        child.type === Tracks ||
        child.type === Handles
      ) {
        return React.cloneElement(child, {
          scale: this.valueToPerc,
          handles,
          emitMouse: this.onMouseDown,
          emitTouch: this.onTouchStart,
        })
      }

      return child
    })

    return (
      <div
        style={rootStyle || {}}
        className={className}
        ref={d => (this.slider = d)}
      >
        {children}
      </div>
    )
  }
}

Slider.propTypes = {
  /**
   * CSS class name applied to the root div of the slider.
   */
  className: PropTypes.string,
  /**
   * An object with any inline styles you want applied to the root div.
   */
  rootStyle: PropTypes.object,
  /**
   * Two element array of numbers providing the min and max values for the slider [min, max] e.g. [0, 100].
   * It does not matter if the slider is reversed on the screen, domain is always [min, max] with min < max.
   */
  domain: PropTypes.array,
  /**
   * An array of numbers. You can supply one for a value slider, two for a range slider or more to create n-handled sliders.
   * The values should correspond to valid step values in the domain.
   * The numbers will be forced into the domain if they are two small or large.
   */
  values: PropTypes.array,
  /**
   * [DEPRECATED]: use `values` instead.
   */
  defaultValues: PropTypes.array,
  /**
   * The step value for the slider.
   */
  step: PropTypes.number,
  /**
   * The interaction mode. Value of 1 will allow handles to cross.
   * Value of 2 will keep the sliders from crossing and separated by a step.
   */
  mode: PropTypes.oneOf([1, 2]),
  /**
   * Set to true if the slider is displayed vertically to tell the slider to use the height to calculate positions.
   */
  vertical: PropTypes.bool,
  /**
   * Reverse the display of slider values.
   */
  reversed: PropTypes.bool,
  /**
   * Function called with the values at each update (caution: high-volume updates when dragging).
   */
  onUpdate: PropTypes.func,
  /**
   * Function called with the values when interaction stops.
   */
  onChange: PropTypes.func,
  /**
   * Component children to render
   */
  children: PropTypes.any,
}

Slider.defaultProps = {
  mode: 1,
  step: 0.1,
  domain: [0, 100],
  vertical: false,
  reversed: false,
  onUpdate: noop,
  onChange: noop,
}

export default Slider
<|endoftext|>