<commit_before>/*jshint indent: 4, browser:true*/
/*global L*/
/*
 * L.TimeDimension: TimeDimension object manages the time component of a layer.
 * It can be shared among different layers and it can be added to a map, and become
 * the default timedimension component for any layer added to the map.
 */

L.TimeDimension = (L.Layer || L.Class).extend({

    includes: L.Mixin.Events,

    initialize: function (options) {
        L.setOptions(this, options);
        // _availableTimes is an array with all the available times in ms.
        this._availableTimes = this._generateAvailableTimes();
        this._currentTimeIndex = -1;
        this._loadingTimeIndex = -1;
        this._loadingTimeout = this.options.loadingTimeout || 3000;
        this._syncedLayers = [];
        if (this._availableTimes.length > 0) {
            this.setCurrentTime(this.options.currentTime || this._getDefaultCurrentTime());
        }
        if (this.options.lowerLimitTime) {
            this.setLowerLimit(this.options.lowerLimitTime);
        }
        if (this.options.upperLimitTime) {
            this.setUpperLimit(this.options.upperLimitTime);
        }
    },

    getAvailableTimes: function () {
        return this._availableTimes;
    },

    getCurrentTimeIndex: function () {
        if (this._currentTimeIndex === -1) {
            return this._availableTimes.length - 1;
        }
        return this._currentTimeIndex;
    },

    getCurrentTime: function () {
        var index = -1;
        if (this._loadingTimeIndex !== -1) {
            index = this._loadingTimeIndex;
        } else {
            index = this.getCurrentTimeIndex();
        }
        if (index >= 0) {
            return this._availableTimes[index];
        } else {
            return 0;
        }
    },

    isLoading: function () {
        return (this._loadingTimeIndex !== -1);
    },

    setCurrentTimeIndex: function (newIndex) {
        var upperLimit = this._upperLimit || this._availableTimes.length - 1;
        var lowerLimit = this._lowerLimit || 0;
        //clamp the value
        newIndex = Math.min(Math.max(lowerLimit, newIndex), upperLimit);
        if (newIndex < 0) {
            return;
        }
        this._loadingTimeIndex = newIndex;
        var newTime = this._availableTimes[newIndex];
        console.log('INIT -- Current time: ' + new Date(newTime).toISOString());
        if (this._checkSyncedLayersReady(this._availableTimes[this._loadingTimeIndex])) {
            this._newTimeIndexLoaded();
        } else {
            this.fire('timeloading', {
                time: newTime
            });
            // add timeout of 3 seconds if layers doesn't response
            setTimeout((function (index) {
                if (index == this._loadingTimeIndex) {
                    console.log('Change time for timeout');
                    this._newTimeIndexLoaded();
                }
            }).bind(this, newIndex), this._loadingTimeout);
        }

    },

    _newTimeIndexLoaded: function () {
        if (this._loadingTimeIndex === -1) {
            return;
        }
        var time = this._availableTimes[this._loadingTimeIndex];
        console.log('END -- Current time: ' + new Date(time).toISOString());
        this._currentTimeIndex = this._loadingTimeIndex;
        this.fire('timeload', {
            time: time
        });
        this._loadingTimeIndex = -1;
    },

    _checkSyncedLayersReady: function (time) {
        for (var i = 0, len = this._syncedLayers.length; i < len; i++) {
            if (this._syncedLayers[i].isReady) {
                if (!this._syncedLayers[i].isReady(time)) {
                    return false;
                }
            }
        }
        return true;
    },

    setCurrentTime: function (time) {
        var newIndex = this._seekNearestTimeIndex(time);
        this.setCurrentTimeIndex(newIndex);
    },

    seekNearestTime: function (time) {
        var index = this._seekNearestTimeIndex(time);
        return this._availableTimes[index];
    },

    nextTime: function (numSteps, loop) {
        if (!numSteps) {
            numSteps = 1;
        }
        var newIndex = this._currentTimeIndex;
        var upperLimit = this._upperLimit || this._availableTimes.length - 1;
        var lowerLimit = this._lowerLimit || 0;
        if (this._loadingTimeIndex > -1) {
            newIndex = this._loadingTimeIndex;
        }
        newIndex = newIndex + numSteps;
        if (newIndex > upperLimit) {
            if (!!loop) {
                newIndex = lowerLimit;
            } else {
                newIndex = upperLimit;
            }
        }
        // loop backwards
        if (newIndex < lowerLimit) {
            if (!!loop) {
                newIndex = upperLimit;
            } else {
                newIndex = lowerLimit;
            }
        }
        this.setCurrentTimeIndex(newIndex);
    },

    prepareNextTimes: function (numSteps, howmany, loop) {
        if (!numSteps) {
            numSteps = 1;
        }

        var newIndex = this._currentTimeIndex;
        var currentIndex = newIndex;
        if (this._loadingTimeIndex > -1) {
            newIndex = this._loadingTimeIndex;
        }
        // assure synced layers have a buffer/cache of at least howmany elements
        for (var i = 0, len = this._syncedLayers.length; i < len; i++) {
            if (this._syncedLayers[i].setMinimumForwardCache) {
                this._syncedLayers[i].setMinimumForwardCache(howmany);
            }
        }
        var count = howmany;
        var upperLimit = this._upperLimit || this._availableTimes.length - 1;
        var lowerLimit = this._lowerLimit || 0;
        while (count > 0) {
            newIndex = newIndex + numSteps;
            if (newIndex > upperLimit) {
                if (!!loop) {
                    newIndex = lowerLimit;
                } else {
                    break;
                }
            }
            if (newIndex < lowerLimit) {
                if (!!loop) {
                    newIndex = upperLimit;
                } else {
                    break;
                }
            }
            if (currentIndex === newIndex) {
                //we looped around the timeline
                //no need to load further, the next times are already loading
                break;
            }
            this.fire('timeloading', {
                time: this._availableTimes[newIndex]
            });
            count--;
        }
    },

    getNumberNextTimesReady: function (numSteps, howmany, loop) {
        if (!numSteps) {
            numSteps = 1;
        }

        var newIndex = this._currentTimeIndex;
        if (this._loadingTimeIndex > -1) {
            newIndex = this._loadingTimeIndex;
        }
        var count = howmany;
        var ready = 0;
        var upperLimit = this._upperLimit || this._availableTimes.length - 1;
        var lowerLimit = this._lowerLimit || 0;
        while (count > 0) {
            newIndex = newIndex + numSteps;
            if (newIndex > upperLimit) {
                if (!!loop) {
                    newIndex = lowerLimit;
                } else {
                    count = 0;
                    ready = howmany;
                    break;
                }
            }
            if (newIndex < lowerLimit) {
                if (!!loop) {
                    newIndex = upperLimit;
                } else {
                    count = 0;
                    ready = howmany;
                    break;
                }
            }
            var time = this._availableTimes[newIndex];
            if (this._checkSyncedLayersReady(time)) {
                ready++;
            }
            count--;
        }
        return ready;
    },

    previousTime: function (numSteps, loop) {
        this.nextTime(numSteps*(-1), loop);
    },

    registerSyncedLayer: function (layer) {
        this._syncedLayers.push(layer);
        layer.on('timeload', this._onSyncedLayerLoaded, this);
    },

    unregisterSyncedLayer: function (layer) {
        var index = this._syncedLayers.indexOf(layer);
        if (index != -1) {
            this._syncedLayers.splice(index, 1);
        }
        layer.off('timeload', this._onSyncedLayerLoaded, this);
    },

    _onSyncedLayerLoaded: function (e) {
        if (e.time == this._availableTimes[this._loadingTimeIndex] && this._checkSyncedLayersReady(e.time)) {
            this._newTimeIndexLoaded();
        }
    },

    _generateAvailableTimes: function () {
        if (this.options.times) {
            return L.TimeDimension.Util.parseTimesExpression(this.options.times);
        } else if (this.options.timeInterval) {
            var tiArray = L.TimeDimension.Util.parseTimeInterval(this.options.timeInterval);
            var period = this.options.period || 'P1D';
            var validTimeRange = this.options.validTimeRange || undefined;
            return L.TimeDimension.Util.explodeTimeRange(tiArray[0], tiArray[1], period, validTimeRange);
        } else {
            return [];
        }
    },

    _getDefaultCurrentTime: function () {
        var index = this._seekNearestTimeIndex(new Date().getTime());
        return this._availableTimes[index];
    },

    _seekNearestTimeIndex: function (time) {
        var newIndex = 0;
        var len = this._availableTimes.length;
        for (; newIndex < len; newIndex++) {
            if (time < this._availableTimes[newIndex]) {
                break;
            }
        }
        // We've found the first index greater than the time. Return the previous
        if (newIndex > 0) {
            newIndex--;
        }
        return newIndex;
    },

    setAvailableTimes: function (times, mode) {
        var currentTime = this.getCurrentTime(),
            lowerLimitTime = this.getLowerLimit(),
            upperLimitTime = this.getUpperLimit();

        if (mode == 'extremes') {
            var period = this.options.period || 'P1D';
            this._availableTimes = L.TimeDimension.Util.explodeTimeRange(new Date(times[0]), new Date(times[times.length - 1]), period);
        } else {
            var parsedTimes = L.TimeDimension.Util.parseTimesExpression(times);
            if (this._availableTimes.length === 0) {
                this._availableTimes = parsedTimes;
            } else if (mode == 'intersect') {
                this._availableTimes = L.TimeDimension.Util.intersect_arrays(parsedTimes, this._availableTimes);
            } else if (mode == 'union') {
                this._availableTimes = L.TimeDimension.Util.union_arrays(parsedTimes, this._availableTimes);
            } else if (mode == 'replace') {
                this._availableTimes = parsedTimes;
            } else {
                throw 'Merge available times mode not implemented: ' + mode;
            }
        }

        if (lowerLimitTime) {
            this.setLowerLimit(lowerLimitTime); //restore lower limit
        }
        if (upperLimitTime) {
            this.setUpperLimit(upperLimitTime); //restore upper limit
        }
        this.setCurrentTime(currentTime);
        this.fire('availabletimeschanged', {
            availableTimes: this._availableTimes,
            currentTime: currentTime
        });
        console.log('available times changed');
    },
    getLowerLimit: function () {
        return this._availableTimes[this.getLowerLimitIndex()];
    },
    getUpperLimit: function () {
        return this._availableTimes[this.getUpperLimitIndex()];
    },
    setLowerLimit: function (time) {
        var index = this._seekNearestTimeIndex(time);
        this.setLowerLimitIndex(index);
    },
    setUpperLimit: function (time) {
        var index = this._seekNearestTimeIndex(time);
        this.setUpperLimitIndex(index);
    },
    setLowerLimitIndex: function (index) {
        this._lowerLimit = Math.min(Math.max(index || 0, 0), this._upperLimit || this._availableTimes.length - 1);
        this.fire('limitschanged', {
            lowerLimit: this._lowerLimit,
            upperLimit: this._upperLimit
        });
    },
    setUpperLimitIndex: function (index) {
        this._upperLimit = Math.max(Math.min(index, this._availableTimes.length - 1), this._lowerLimit || 0);
        this.fire('limitschanged', {
            lowerLimit: this._lowerLimit,
            upperLimit: this._upperLimit
        });
    },
    getLowerLimitIndex: function () {
        return this._lowerLimit;
    },
    getUpperLimitIndex: function () {
        return this._upperLimit;
    }
});

L.Map.addInitHook(function () {
    if (this.options.timeDimension) {
        this.timeDimension = L.timeDimension(this.options.timeDimensionOptions || {});
    }
});

L.timeDimension = function (options) {
    return new L.TimeDimension(options);
};
<commit_msg>Update leaflet.timedimension.js<commit_after>/*jshint indent: 4, browser:true*/
/*global L*/
/*
 * L.TimeDimension: TimeDimension object manages the time component of a layer.
 * It can be shared among different layers and it can be added to a map, and become
 * the default timedimension component for any layer added to the map.
 */

L.TimeDimension = (L.Layer || L.Class).extend({

    includes: L.Mixin.Events,

    initialize: function (options) {
        L.setOptions(this, options);
        // _availableTimes is an array with all the available times in ms.
        this._availableTimes = this._generateAvailableTimes();
        this._currentTimeIndex = -1;
        this._loadingTimeIndex = -1;
        this._loadingTimeout = this.options.loadingTimeout || 3000;
        this._syncedLayers = [];
        if (this._availableTimes.length > 0) {
            this.setCurrentTime(this.options.currentTime || this._getDefaultCurrentTime());
        }
        if (this.options.lowerLimitTime) {
            this.setLowerLimit(this.options.lowerLimitTime);
        }
        if (this.options.upperLimitTime) {
            this.setUpperLimit(this.options.upperLimitTime);
        }
    },

    getAvailableTimes: function () {
        return this._availableTimes;
    },

    getCurrentTimeIndex: function () {
        if (this._currentTimeIndex === -1) {
            return this._availableTimes.length - 1;
        }
        return this._currentTimeIndex;
    },

    getCurrentTime: function () {
        var index = -1;
        if (this._loadingTimeIndex !== -1) {
            index = this._loadingTimeIndex;
        } else {
            index = this.getCurrentTimeIndex();
        }
        if (index >= 0) {
            return this._availableTimes[index];
        } else {
            return 0;
        }
    },

    isLoading: function () {
        return (this._loadingTimeIndex !== -1);
    },

    setCurrentTimeIndex: function (newIndex) {
        var upperLimit = this._upperLimit || this._availableTimes.length - 1;
        var lowerLimit = this._lowerLimit || 0;
        //clamp the value
        newIndex = Math.min(Math.max(lowerLimit, newIndex), upperLimit);
        if (newIndex < 0) {
            return;
        }
        this._loadingTimeIndex = newIndex;
        var newTime = this._availableTimes[newIndex];
        console.log('INIT -- Current time: ' + new Date(newTime).toISOString());
        if (this._checkSyncedLayersReady(this._availableTimes[this._loadingTimeIndex])) {
            this._newTimeIndexLoaded();
        } else {
            this.fire('timeloading', {
                time: newTime
            });
            // add timeout of 3 seconds if layers doesn't response
            setTimeout((function (index) {
                if (index == this._loadingTimeIndex) {
                    console.log('Change time for timeout');
                    this._newTimeIndexLoaded();
                }
            }).bind(this, newIndex), this._loadingTimeout);
        }

    },

    _newTimeIndexLoaded: function () {
        if (this._loadingTimeIndex === -1) {
            return;
        }
        var time = this._availableTimes[this._loadingTimeIndex];
        console.log('END -- Current time: ' + new Date(time).toISOString());
        this._currentTimeIndex = this._loadingTimeIndex;
        this.fire('timeload', {
            time: time
        });
        this._loadingTimeIndex = -1;
    },

    _checkSyncedLayersReady: function (time) {
        for (var i = 0, len = this._syncedLayers.length; i < len; i++) {
            if (this._syncedLayers[i].isReady) {
                if (!this._syncedLayers[i].isReady(time)) {
                    if (map.getBounds().contains(this._syncedLayers[i]._baseLayer.options.bounds))
                        return false;
                }
            }
        }
        return true;
    },

    setCurrentTime: function (time) {
        var newIndex = this._seekNearestTimeIndex(time);
        this.setCurrentTimeIndex(newIndex);
    },

    seekNearestTime: function (time) {
        var index = this._seekNearestTimeIndex(time);
        return this._availableTimes[index];
    },

    nextTime: function (numSteps, loop) {
        if (!numSteps) {
            numSteps = 1;
        }
        var newIndex = this._currentTimeIndex;
        var upperLimit = this._upperLimit || this._availableTimes.length - 1;
        var lowerLimit = this._lowerLimit || 0;
        if (this._loadingTimeIndex > -1) {
            newIndex = this._loadingTimeIndex;
        }
        newIndex = newIndex + numSteps;
        if (newIndex > upperLimit) {
            if (!!loop) {
                newIndex = lowerLimit;
            } else {
                newIndex = upperLimit;
            }
        }
        // loop backwards
        if (newIndex < lowerLimit) {
            if (!!loop) {
                newIndex = upperLimit;
            } else {
                newIndex = lowerLimit;
            }
        }
        this.setCurrentTimeIndex(newIndex);
    },

    prepareNextTimes: function (numSteps, howmany, loop) {
        if (!numSteps) {
            numSteps = 1;
        }

        var newIndex = this._currentTimeIndex;
        var currentIndex = newIndex;
        if (this._loadingTimeIndex > -1) {
            newIndex = this._loadingTimeIndex;
        }
        // assure synced layers have a buffer/cache of at least howmany elements
        for (var i = 0, len = this._syncedLayers.length; i < len; i++) {
            if (this._syncedLayers[i].setMinimumForwardCache) {
                this._syncedLayers[i].setMinimumForwardCache(howmany);
            }
        }
        var count = howmany;
        var upperLimit = this._upperLimit || this._availableTimes.length - 1;
        var lowerLimit = this._lowerLimit || 0;
        while (count > 0) {
            newIndex = newIndex + numSteps;
            if (newIndex > upperLimit) {
                if (!!loop) {
                    newIndex = lowerLimit;
                } else {
                    break;
                }
            }
            if (newIndex < lowerLimit) {
                if (!!loop) {
                    newIndex = upperLimit;
                } else {
                    break;
                }
            }
            if (currentIndex === newIndex) {
                //we looped around the timeline
                //no need to load further, the next times are already loading
                break;
            }
            this.fire('timeloading', {
                time: this._availableTimes[newIndex]
            });
            count--;
        }
    },

    getNumberNextTimesReady: function (numSteps, howmany, loop) {
        if (!numSteps) {
            numSteps = 1;
        }

        var newIndex = this._currentTimeIndex;
        if (this._loadingTimeIndex > -1) {
            newIndex = this._loadingTimeIndex;
        }
        var count = howmany;
        var ready = 0;
        var upperLimit = this._upperLimit || this._availableTimes.length - 1;
        var lowerLimit = this._lowerLimit || 0;
        while (count > 0) {
            newIndex = newIndex + numSteps;
            if (newIndex > upperLimit) {
                if (!!loop) {
                    newIndex = lowerLimit;
                } else {
                    count = 0;
                    ready = howmany;
                    break;
                }
            }
            if (newIndex < lowerLimit) {
                if (!!loop) {
                    newIndex = upperLimit;
                } else {
                    count = 0;
                    ready = howmany;
                    break;
                }
            }
            var time = this._availableTimes[newIndex];
            if (this._checkSyncedLayersReady(time)) {
                ready++;
            }
            count--;
        }
        return ready;
    },

    previousTime: function (numSteps, loop) {
        this.nextTime(numSteps*(-1), loop);
    },

    registerSyncedLayer: function (layer) {
        this._syncedLayers.push(layer);
        layer.on('timeload', this._onSyncedLayerLoaded, this);
    },

    unregisterSyncedLayer: function (layer) {
        var index = this._syncedLayers.indexOf(layer);
        if (index != -1) {
            this._syncedLayers.splice(index, 1);
        }
        layer.off('timeload', this._onSyncedLayerLoaded, this);
    },

    _onSyncedLayerLoaded: function (e) {
        if (e.time == this._availableTimes[this._loadingTimeIndex] && this._checkSyncedLayersReady(e.time)) {
            this._newTimeIndexLoaded();
        }
    },

    _generateAvailableTimes: function () {
        if (this.options.times) {
            return L.TimeDimension.Util.parseTimesExpression(this.options.times);
        } else if (this.options.timeInterval) {
            var tiArray = L.TimeDimension.Util.parseTimeInterval(this.options.timeInterval);
            var period = this.options.period || 'P1D';
            var validTimeRange = this.options.validTimeRange || undefined;
            return L.TimeDimension.Util.explodeTimeRange(tiArray[0], tiArray[1], period, validTimeRange);
        } else {
            return [];
        }
    },

    _getDefaultCurrentTime: function () {
        var index = this._seekNearestTimeIndex(new Date().getTime());
        return this._availableTimes[index];
    },

    _seekNearestTimeIndex: function (time) {
        var newIndex = 0;
        var len = this._availableTimes.length;
        for (; newIndex < len; newIndex++) {
            if (time < this._availableTimes[newIndex]) {
                break;
            }
        }
        // We've found the first index greater than the time. Return the previous
        if (newIndex > 0) {
            newIndex--;
        }
        return newIndex;
    },

    setAvailableTimes: function (times, mode) {
        var currentTime = this.getCurrentTime(),
            lowerLimitTime = this.getLowerLimit(),
            upperLimitTime = this.getUpperLimit();

        if (mode == 'extremes') {
            var period = this.options.period || 'P1D';
            this._availableTimes = L.TimeDimension.Util.explodeTimeRange(new Date(times[0]), new Date(times[times.length - 1]), period);
        } else {
            var parsedTimes = L.TimeDimension.Util.parseTimesExpression(times);
            if (this._availableTimes.length === 0) {
                this._availableTimes = parsedTimes;
            } else if (mode == 'intersect') {
                this._availableTimes = L.TimeDimension.Util.intersect_arrays(parsedTimes, this._availableTimes);
            } else if (mode == 'union') {
                this._availableTimes = L.TimeDimension.Util.union_arrays(parsedTimes, this._availableTimes);
            } else if (mode == 'replace') {
                this._availableTimes = parsedTimes;
            } else {
                throw 'Merge available times mode not implemented: ' + mode;
            }
        }

        if (lowerLimitTime) {
            this.setLowerLimit(lowerLimitTime); //restore lower limit
        }
        if (upperLimitTime) {
            this.setUpperLimit(upperLimitTime); //restore upper limit
        }
        this.setCurrentTime(currentTime);
        this.fire('availabletimeschanged', {
            availableTimes: this._availableTimes,
            currentTime: currentTime
        });
        console.log('available times changed');
    },
    getLowerLimit: function () {
        return this._availableTimes[this.getLowerLimitIndex()];
    },
    getUpperLimit: function () {
        return this._availableTimes[this.getUpperLimitIndex()];
    },
    setLowerLimit: function (time) {
        var index = this._seekNearestTimeIndex(time);
        this.setLowerLimitIndex(index);
    },
    setUpperLimit: function (time) {
        var index = this._seekNearestTimeIndex(time);
        this.setUpperLimitIndex(index);
    },
    setLowerLimitIndex: function (index) {
        this._lowerLimit = Math.min(Math.max(index || 0, 0), this._upperLimit || this._availableTimes.length - 1);
        this.fire('limitschanged', {
            lowerLimit: this._lowerLimit,
            upperLimit: this._upperLimit
        });
    },
    setUpperLimitIndex: function (index) {
        this._upperLimit = Math.max(Math.min(index, this._availableTimes.length - 1), this._lowerLimit || 0);
        this.fire('limitschanged', {
            lowerLimit: this._lowerLimit,
            upperLimit: this._upperLimit
        });
    },
    getLowerLimitIndex: function () {
        return this._lowerLimit;
    },
    getUpperLimitIndex: function () {
        return this._upperLimit;
    }
});

L.Map.addInitHook(function () {
    if (this.options.timeDimension) {
        this.timeDimension = L.timeDimension(this.options.timeDimensionOptions || {});
    }
});

L.timeDimension = function (options) {
    return new L.TimeDimension(options);
};
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import autobind from 'autobind-decorator'
import themed from 'react-themed'
import classnames from 'classnames'
import isEqual from 'lodash/isEqual'
import { Dropdown } from '../Dropdown'
import MenuWrapper from './MenuWrapper'

@themed(/^DropdownMenu/)

export default class DropdownMenu extends Component {
  static propTypes = {
    theme: PropTypes.object,
    options: PropTypes.array,
    onItemSelect: PropTypes.func,
    className: PropTypes.string,
    selectedIndex: PropTypes.number,
    selectedValue: PropTypes.node,
    createAnchorText: PropTypes.func,
  }

  static defaultProps = {
    theme: {},
    options: [],
    selectedIndex: 0,
    selectedValue: null,
    onItemSelect: () => {},
  }

  constructor(props) {
    super(props)
    const selectedIndex = this.selectedIndexFromValue() || this.props.selectedIndex || 0
    this.state = { selectedIndex }
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.selectedIndex !== nextProps.selectedIndex) {
      this.setState({ selectedIndex: nextProps.selectedIndex })
    } else if (this.props.selectedValue !== nextProps.selectedValue) {
      this.setState({ selectedIndex: this.selectedIndexFromValue(nextProps.selectedValue) })
    }
  }

  shouldComponentUpdate(nextProps) {
    const { options, selectedIndex, selectedValue } = this.props

    return !isEqual(options, nextProps.options)
      || selectedIndex !== nextProps.selectedIndex
      || selectedValue !== nextProps.selectedValue
  }

  get selectedItem() {
    return this.props.options[this.state.selectedIndex] || ''
  }

  get selectedItemLabel() {
    const item = this.selectedItem
    return typeof item === 'object' ? item.label : item
  }

  selectedIndexFromValue(selectedValue = this.props.selectedValue) {
    const index = this.props.options.findIndex(option => option.value === selectedValue)
    return index === -1 ? 0 : index
  }

  @autobind
  itemSelectionHandler(item, index) {
    const { onItemSelect } = this.props

    if (onItemSelect) onItemSelect(item, index)

    this.setState({ selectedIndex: index })
  }

  renderAnchorFieldText() {
    const { createAnchorText } = this.props

    if (createAnchorText) return createAnchorText(this.selectedItemLabel)
    return this.selectedItemLabel
  }

  render() {
    const {
      theme,
      className,
      options,
      selectedIndex,
      selectedValue,
      onItemSelect,
      createAnchorText,
      ...props
    } = this.props

    return (
      <Dropdown
        className={classnames(className, theme.DropdownMenu)}
        anchorField={{ children: this.renderAnchorFieldText() }}
        {...props}
      >
        <MenuWrapper
          options={options}
          onItemSelect={this.itemSelectionHandler}
        />
      </Dropdown>
    )
  }
}
<commit_msg>added a condition to shouldComponentUpdate for change of selectedIndex in state<commit_after>import React, { Component } from 'react'
import PropTypes from 'prop-types'
import autobind from 'autobind-decorator'
import themed from 'react-themed'
import classnames from 'classnames'
import isEqual from 'lodash/isEqual'
import { Dropdown } from '../Dropdown'
import MenuWrapper from './MenuWrapper'

@themed(/^DropdownMenu/)

export default class DropdownMenu extends Component {
  static propTypes = {
    theme: PropTypes.object,
    options: PropTypes.array,
    onItemSelect: PropTypes.func,
    className: PropTypes.string,
    selectedIndex: PropTypes.number,
    selectedValue: PropTypes.node,
    createAnchorText: PropTypes.func,
  }

  static defaultProps = {
    theme: {},
    options: [],
    selectedIndex: 0,
    selectedValue: null,
    onItemSelect: () => {},
  }

  constructor(props) {
    super(props)
    const selectedIndex = this.selectedIndexFromValue() || this.props.selectedIndex || 0
    this.state = { selectedIndex }
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.selectedIndex !== nextProps.selectedIndex) {
      this.setState({ selectedIndex: nextProps.selectedIndex })
    } else if (this.props.selectedValue !== nextProps.selectedValue) {
      this.setState({ selectedIndex: this.selectedIndexFromValue(nextProps.selectedValue) })
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    const { options, selectedIndex, selectedValue } = this.props

    return !isEqual(options, nextProps.options)
      || selectedIndex !== nextProps.selectedIndex
      || selectedValue !== nextProps.selectedValue
      || this.state.selectedIndex !== nextState.selectedIndex
  }

  get selectedItem() {
    return this.props.options[this.state.selectedIndex] || ''
  }

  get selectedItemLabel() {
    const item = this.selectedItem
    return typeof item === 'object' ? item.label : item
  }

  selectedIndexFromValue(selectedValue = this.props.selectedValue) {
    const index = this.props.options.findIndex(option => option.value === selectedValue)
    return index === -1 ? 0 : index
  }

  @autobind
  itemSelectionHandler(item, index) {
    const { onItemSelect } = this.props

    if (onItemSelect) onItemSelect(item, index)

    this.setState({ selectedIndex: index })
  }

  renderAnchorFieldText() {
    const { createAnchorText } = this.props

    if (createAnchorText) return createAnchorText(this.selectedItemLabel)
    return this.selectedItemLabel
  }

  render() {
    const {
      theme,
      className,
      options,
      selectedIndex,
      selectedValue,
      onItemSelect,
      createAnchorText,
      ...props
    } = this.props

    return (
      <Dropdown
        className={classnames(className, theme.DropdownMenu)}
        anchorField={{ children: this.renderAnchorFieldText() }}
        {...props}
      >
        <MenuWrapper
          options={options}
          onItemSelect={this.itemSelectionHandler}
        />
      </Dropdown>
    )
  }
}
<|endoftext|>


<commit_before>import EXIF from 'exif-js';

const MAX_IMAGE_PIXELS = 1638400; // 1280x1280px

const getImageUrl = inputFile => new Promise((resolve, reject) => {
  if (window.URL && URL.createObjectURL) {
    try {
      resolve(URL.createObjectURL(inputFile));
    } catch (error) {
      reject(error);
    }
    return;
  }

  const reader = new FileReader();
  reader.onerror = (...args) => reject(...args);
  reader.onload  = ({ target }) => resolve(target.result);

  reader.readAsDataURL(inputFile);
});

const loadImage = inputFile => new Promise((resolve, reject) => {
  getImageUrl(inputFile).then(url => {
    const img = new Image();

    img.onerror = (...args) => reject(...args);
    img.onload  = () => resolve(img);

    img.src = url;
  }).catch(reject);
});

const getOrientation = (img, type = 'image/png') => new Promise(resolve => {
  if (!['image/jpeg', 'image/webp'].includes(type)) {
    resolve(1);
    return;
  }

  EXIF.getData(img, () => {
    const orientation = EXIF.getTag(img, 'Orientation');
    resolve(orientation);
  });
});

const processImage = (img, { width, height, orientation, type = 'image/png' }) => new Promise(resolve => {
  const canvas  = document.createElement('canvas');

  if (4 < orientation && orientation < 9) {
    canvas.width  = height;
    canvas.height = width;
  } else {
    canvas.width  = width;
    canvas.height = height;
  }

  const context = canvas.getContext('2d');

  switch (orientation) {
  case 2: context.transform(-1, 0, 0, 1, width, 0); break;
  case 3: context.transform(-1, 0, 0, -1, width, height); break;
  case 4: context.transform(1, 0, 0, -1, 0, height); break;
  case 5: context.transform(0, 1, 1, 0, 0, 0); break;
  case 6: context.transform(0, 1, -1, 0, height, 0); break;
  case 7: context.transform(0, -1, -1, 0, height, width); break;
  case 8: context.transform(0, -1, 1, 0, 0, width); break;
  }

  context.drawImage(img, 0, 0, width, height);

  // The Tor Browser and maybe other browsers may prevent reading from canvas
  // and return an all-white image instead. Assume reading failed if the resized
  // image is perfectly white.
  const imageData = context.getImageData(0, 0, width, height);
  if (imageData.every(value => value === 255)) {
    throw 'Failed to read from canvas';
  }

  canvas.toBlob(resolve, type);
});

const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) => {
  const { width, height } = img;

  const newWidth  = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (width / height)));
  const newHeight = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (height / width)));

  getOrientation(img, type)
    .then(orientation => processImage(img, {
      width: newWidth,
      height: newHeight,
      orientation,
      type,
    }))
    .then(resolve)
    .catch(reject);
});

export default inputFile => new Promise((resolve, reject) => {
  if (!inputFile.type.match(/image.*/) || inputFile.type === 'image/gif') {
    resolve(inputFile);
    return;
  }

  loadImage(inputFile).then(img => {
    if (img.width * img.height < MAX_IMAGE_PIXELS) {
      resolve(inputFile);
      return;
    }

    resizeImage(img, inputFile.type)
      .then(resolve)
      .catch(() => resolve(inputFile));
  }).catch(reject);
});
<commit_msg>[Glitch] Fix client-side resizing of image uploads<commit_after>import EXIF from 'exif-js';

const MAX_IMAGE_PIXELS = 1638400; // 1280x1280px

const getImageUrl = inputFile => new Promise((resolve, reject) => {
  if (window.URL && URL.createObjectURL) {
    try {
      resolve(URL.createObjectURL(inputFile));
    } catch (error) {
      reject(error);
    }
    return;
  }

  const reader = new FileReader();
  reader.onerror = (...args) => reject(...args);
  reader.onload  = ({ target }) => resolve(target.result);

  reader.readAsDataURL(inputFile);
});

const loadImage = inputFile => new Promise((resolve, reject) => {
  getImageUrl(inputFile).then(url => {
    const img = new Image();

    img.onerror = (...args) => reject(...args);
    img.onload  = () => resolve(img);

    img.src = url;
  }).catch(reject);
});

const getOrientation = (img, type = 'image/png') => new Promise(resolve => {
  if (!['image/jpeg', 'image/webp'].includes(type)) {
    resolve(1);
    return;
  }

  EXIF.getData(img, () => {
    const orientation = EXIF.getTag(img, 'Orientation');
    resolve(orientation);
  });
});

const processImage = (img, { width, height, orientation, type = 'image/png' }) => new Promise(resolve => {
  const canvas  = document.createElement('canvas');

  if (4 < orientation && orientation < 9) {
    canvas.width  = height;
    canvas.height = width;
  } else {
    canvas.width  = width;
    canvas.height = height;
  }

  const context = canvas.getContext('2d');

  switch (orientation) {
  case 2: context.transform(-1, 0, 0, 1, width, 0); break;
  case 3: context.transform(-1, 0, 0, -1, width, height); break;
  case 4: context.transform(1, 0, 0, -1, 0, height); break;
  case 5: context.transform(0, 1, 1, 0, 0, 0); break;
  case 6: context.transform(0, 1, -1, 0, height, 0); break;
  case 7: context.transform(0, -1, -1, 0, height, width); break;
  case 8: context.transform(0, -1, 1, 0, 0, width); break;
  }

  context.drawImage(img, 0, 0, width, height);

  // The Tor Browser and maybe other browsers may prevent reading from canvas
  // and return an all-white image instead. Assume reading failed if the resized
  // image is perfectly white.
  const imageData = context.getImageData(0, 0, width, height);
  if (imageData.data.every(value => value === 255)) {
    throw 'Failed to read from canvas';
  }

  canvas.toBlob(resolve, type);
});

const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) => {
  const { width, height } = img;

  const newWidth  = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (width / height)));
  const newHeight = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (height / width)));

  getOrientation(img, type)
    .then(orientation => processImage(img, {
      width: newWidth,
      height: newHeight,
      orientation,
      type,
    }))
    .then(resolve)
    .catch(reject);
});

export default inputFile => new Promise((resolve, reject) => {
  if (!inputFile.type.match(/image.*/) || inputFile.type === 'image/gif') {
    resolve(inputFile);
    return;
  }

  loadImage(inputFile).then(img => {
    if (img.width * img.height < MAX_IMAGE_PIXELS) {
      resolve(inputFile);
      return;
    }

    resizeImage(img, inputFile.type)
      .then(resolve)
      .catch(() => resolve(inputFile));
  }).catch(reject);
});
<|endoftext|>


<commit_before>describe("IgnoreAdd", function () {
  beforeEach(function () {
    this.server = sinon.fakeServer.create();
  });

  afterEach(function () {
    this.puppet.unobserve();
    this.server.restore();
  });

  it('should not send add patch to an ignored property', function () {
    var patchSpy = spyOn(XMLHttpRequest.prototype, 'send').andCallThrough();
    var obj;
    this.puppet = new Puppet('/test', function (myObj) {
      obj = myObj;
    });
    this.puppet.ignoreAdd = /\/\$.+/;

    this.server.respond('{"hello": 0}');

    waits(0);

    runs(function () {
      obj.hello = 1;
      obj.publicProp = 1;
      obj.$privateProp = 1;
    });

    waits(0);

    runs(function () {
      expect(patchSpy.callCount).toBe(2);
      expect(patchSpy).toHaveBeenCalledWith('[{"op":"replace","path":"/hello","value":1},{"op":"add","path":"/publicProp","value":1}]');
    });
  });

  it('should not send replace patch to an ignored property', function () {
    var patchSpy = spyOn(XMLHttpRequest.prototype, 'send').andCallThrough();
    var obj;
    this.puppet = new Puppet('/test', function (myObj) {
      obj = myObj;
    });
    this.puppet.ignoreAdd = /\/\$.+/;

    this.server.respond('{"hello": 0}');

    waits(0);

    runs(function () {
      obj.publicProp = 1;
      obj.$privateProp = 1;
    });

    waits(0);

    runs(function () {
      expect(patchSpy.callCount).toBe(2);
      expect(patchSpy).toHaveBeenCalledWith('[{"op":"add","path":"/publicProp","value":1}]');
      obj.publicProp = 2;
      obj.$privateProp = 2;
    });

    waits(0);

    runs(function () {
      expect(patchSpy.callCount).toBe(3);
      expect(patchSpy).toHaveBeenCalledWith('[{"op":"replace","path":"/publicProp","value":2}]');
    });
  });

  it('should not send replace patch to an ignored deep object', function () {
    var patchSpy = spyOn(XMLHttpRequest.prototype, 'send').andCallThrough();
    var obj;
    this.puppet = new Puppet('/test', function (myObj) {
      obj = myObj;
    });
    this.puppet.ignoreAdd = /\/\$.+/;

    this.server.respond('{"hello": 0}');

    waits(0);

    runs(function () {
      obj.publicProp = ["a", "b", "c"];
      obj.$privateProp = ["a", "b", "c"];
    });

    waits(0);

    runs(function () {
      expect(patchSpy.callCount).toBe(2);
      expect(patchSpy).toHaveBeenCalledWith('[{"op":"add","path":"/publicProp","value":["a","b","c"]}]');
      obj.publicProp[2] = "cc";
      obj.$privateProp[2] = "cc";
    });

    waits(0);

    runs(function () {
      expect(patchSpy.callCount).toBe(3);
      expect(patchSpy).toHaveBeenCalledWith('[{"op":"replace","path":"/publicProp/2","value":"cc"}]');
    });
  });

  it('should not send any patch if all changes were ignored', function () {
    var patchSpy = spyOn(XMLHttpRequest.prototype, 'send').andCallThrough();
    var obj;
    this.puppet = new Puppet('/test', function (myObj) {
      obj = myObj;
    });
    this.puppet.ignoreAdd = /\/\$.+/;

    this.server.respond('{"hello": 0}');

    waits(0);

    runs(function () {
      expect(patchSpy.callCount).toBe(1);
      obj.$privateProp = 1;
    });

    waits(0);

    runs(function () {
      expect(patchSpy.callCount).toBe(1);
    });
  });
});<commit_msg>adjust check intervals because test did not pass in shimmed mode of json-patch-duplex.js<commit_after>describe("IgnoreAdd", function () {
  jsonpatch.intervals = [10];

  beforeEach(function () {
    this.server = sinon.fakeServer.create();
  });

  afterEach(function () {
    this.puppet.unobserve();
    this.server.restore();
  });

  it('should not send add patch to an ignored property', function () {
    var patchSpy = spyOn(XMLHttpRequest.prototype, 'send').andCallThrough();
    var obj;
    this.puppet = new Puppet('/test', function (myObj) {
      obj = myObj;
    });
    this.puppet.ignoreAdd = /\/\$.+/;

    this.server.respond('{"hello": 0}');

    waits(10);

    runs(function () {
      obj.hello = 1;
      obj.publicProp = 1;
      obj.$privateProp = 1;
    });

    waits(10);

    runs(function () {
      expect(patchSpy.callCount).toBe(2);
      expect(patchSpy).toHaveBeenCalledWith('[{"op":"replace","path":"/hello","value":1},{"op":"add","path":"/publicProp","value":1}]');
    });
  });

  it('should not send replace patch to an ignored property', function () {
    var patchSpy = spyOn(XMLHttpRequest.prototype, 'send').andCallThrough();
    var obj;
    this.puppet = new Puppet('/test', function (myObj) {
      obj = myObj;
    });
    this.puppet.ignoreAdd = /\/\$.+/;

    this.server.respond('{"hello": 0}');

    waits(10);

    runs(function () {
      obj.publicProp = 1;
      obj.$privateProp = 1;
    });

    waits(10);

    runs(function () {
      expect(patchSpy.callCount).toBe(2);
      expect(patchSpy).toHaveBeenCalledWith('[{"op":"add","path":"/publicProp","value":1}]');
      obj.publicProp = 2;
      obj.$privateProp = 2;
    });

    waits(10);

    runs(function () {
      expect(patchSpy.callCount).toBe(3);
      expect(patchSpy).toHaveBeenCalledWith('[{"op":"replace","path":"/publicProp","value":2}]');
    });
  });

  it('should not send replace patch to an ignored deep object', function () {
    var patchSpy = spyOn(XMLHttpRequest.prototype, 'send').andCallThrough();
    var obj;
    this.puppet = new Puppet('/test', function (myObj) {
      obj = myObj;
    });
    this.puppet.ignoreAdd = /\/\$.+/;

    this.server.respond('{"hello": 0}');

    waits(10);

    runs(function () {
      obj.publicProp = ["a", "b", "c"];
      obj.$privateProp = ["a", "b", "c"];
    });

    waits(10);

    runs(function () {
      expect(patchSpy.callCount).toBe(2);
      expect(patchSpy).toHaveBeenCalledWith('[{"op":"add","path":"/publicProp","value":["a","b","c"]}]');
      obj.publicProp[2] = "cc";
      obj.$privateProp[2] = "cc";
    });

    waits(10);

    runs(function () {
      expect(patchSpy.callCount).toBe(3);
      expect(patchSpy).toHaveBeenCalledWith('[{"op":"replace","path":"/publicProp/2","value":"cc"}]');
    });
  });

  it('should not send any patch if all changes were ignored', function () {
    var patchSpy = spyOn(XMLHttpRequest.prototype, 'send').andCallThrough();
    var obj;
    this.puppet = new Puppet('/test', function (myObj) {
      obj = myObj;
    });
    this.puppet.ignoreAdd = /\/\$.+/;

    this.server.respond('{"hello": 0}');

    waits(10);

    runs(function () {
      expect(patchSpy.callCount).toBe(1);
      obj.$privateProp = 1;
    });

    waits(10);

    runs(function () {
      expect(patchSpy.callCount).toBe(1);
    });
  });
});<|endoftext|>


<commit_before>/** ---IMPORTS  */

/** ---OUT --- */
var Arrow = module.exports = {}
Arrow.create = function(options){
	options = options || {}
	var context = {}
	var final = null
	var stack = []
	,	 api = {}

	api.customStack = setCustomStack
	api.finally = setFinalHandler
	api.context = setContext
	api.getStack = inspectStack
	api.flush = flushStack
	Object.freeze(api)

	stackManager.use = use
	stackManager.finally = setFinalHandler
	stackManager.context = setContext
	stackManager.api = api

	/* applying options */
	if ( options.customStack ) { setCustomStack(options.customStack) }
	if ( options.final ) { setFinalHandler(options.final) }
	if ( options.context && options.context === typeof 'object' ){
		context = options.context
	}

	return stackManager
	function stackManager(){
		var	layerIndex = 0
		,	handlerIndex = 0
		,	args = [].slice.call(arguments)
		,	messages = []
		// calback ( if specified)
		,	_final = final
		|| (
			('function' === typeof args[args.length -1])
			?args.pop()	// shortens arguments by 1
			: 	null
		)

		args.push(next)
		return next()
		function next( err, msg ){
			var layer = stack[layerIndex]
			/**
			* next() will llot for handler at handlerIndex
			* on the current layer which will be applied the arguments
			* and call next(err).
			* next() will then look for a handler at handlerIndex++
			* If next() does not find any defined handler
			* it will step over to the next layer
			* if there is no further layer next() is done
			* --------------------------------------------------------
			* If an error occurs next() tests if err is an object
			* which can (and will) be thrown
			* --------------------------------------------------------
			* If err is a string it's a warning
			* thus it will be passed to the warning collection
			* further the current layer will be aborded
			* and it will be stepped over to the next layer.
			*/
			if (!layer || ( err && err instanceof Error)){
				args.pop()
				if (msg) messages.push(msg)

				args.unshift(err, msg)

				// handles  callback before exiting
				if (_final){
					return _final.apply(context /*proto*/, args/*args*/)
				}
				return {err : err,
						msg : messages }
			}
			if (err && err === 'skip'){ /* error is message */
				if (msg) messages.push(msg)
				layerIndex++
				handlerIndex = 0

				return next()
			}
			if (msg) messages.push(msg)

			var handler = layer[handlerIndex]
			if (!handler){
				layerIndex++
				handlerIndex = 0		// prepare for next layer

				return next()
			}

			handlerIndex++
			return handler.apply(context, args)
		}
	}
	function use(check){
		if (!check)	return stackManager // no argument parsed

		var args = [].slice.call(arguments)
		,	arg = 0
		,	layer = []
		,	err = null

		// validates every parsed layer
		for ( ; arg < args.length ; arg++){

			if (Array.isArray( args[arg] )){
				//		--> current argument is a layer
				// 		v Is null if no error in current layer
				err = 	validateLayer( layer )
				|| 		validateLayer( args[arg] )

				// 		^ Is null if no error in nested layer

				if (err) break

				// adds current layer (if defined)
				if ( layer.length > 0) { stack.push(layer); layer = [] }
				if ( args[arg].length > 0) { stack.push(args[arg]) }
				// and nested layer to stack

			}else {
				layer.push(args[arg])
			}
		}

		err = (err)					// holds error if occured
		? err						//if no error yet, validate open layer
		: validateLayer(layer)		//if no error in open layer error is null

		if (err) throw new Error(err)
		if (layer.length > 0)  { stack.push(layer); layer = [] } // adds open layer to stack

		return stackManager
		function validateLayer(_layer_){
			var index = 0

			for ( ; index < _layer_.length ; index++ ){
				if( typeof _layer_[index] !== 'function' ){
					return ('Type of Argument ( '
							+ _layer_[index]
							+ ' ) is [ '
							+ (typeof _layer_[index])
							+ ' ] -- Must be [ function ]!')
				}
			}
			return null // if there is no error
		}
	}
	function setCustomStack(stack){
		return use.apply(stackManager, [].slice.call(arguments))
	}
	function setFinalHandler(fn){
		if ('function' === typeof fn) { final = fn }
		return stackManager
	}
	function setContext(ctx){
		if('object' === typeof ctx){ context = ctx }
		return stackManager
	}
	function flushStack(){
		stack = []
		console.warn('Stack wiped!!!')
		return stackManager
	}
	function inspectStack(){
		return stack
	}
}
<commit_msg>tweaks<commit_after>/** ---IMPORTS  */

/** ---OUT --- */
var Arrow = module.exports = {}
Arrow.create = function(options){
	options = options || {}
	var context = {}
	var final = null
	var stack = []
	,	 api = {}

	api.customStack = setCustomStack
	api.finally = setFinalHandler
	api.context = setContext
	api.getStack = inspectStack
	api.flush = flushStack
	Object.freeze(api)

	stackManager.use = use
	stackManager.finally = setFinalHandler
	stackManager.context = setContext
	stackManager.api = api

	/* applying options */
	if ( options.customStack ) { setCustomStack(options.customStack) }
	if ( options.final ) { setFinalHandler(options.final) }
	if ( options.context && options.context === typeof 'object' ){
		context = options.context
	}

	return stackManager
	function stackManager(){
		var	layerIndex = 0
		,	handlerIndex = 0
		,	args = [].slice.call(arguments)
		,	messages = []
		// calback ( if specified)
		,	_final = final
		|| (
			('function' === typeof args[args.length -1])
			?args.pop()	// shortens arguments by 1
			: 	null
		)

		args.push(next)
		return next()
		function next( err, msg ){
			var layer = stack[layerIndex]
			/**
			* next() will look for a handler at handlerIndex
			* on the current layer which will be applied the arguments
			* and call next(err).
			* next() will then look for a handler at handlerIndex++
			* If next() does not find any defined handler
			* it will step over to the next layer
			* if there is no further layer next() is done
			* --------------------------------------------------------
			* If an error occurs next() tests if err is an object
			* which can (and will) be thrown
			* --------------------------------------------------------
			* If a message is parsed it will be added to the messages collection
			* If err === 'skip' the current layer will be aborded
			* and it will be stepped over to the next layer.
			*/
			if (!layer || ( err && 'object' )){
				args.pop()
				if (msg) messages.push(msg)

				args.unshift(err, msg)

				// handles  callback before exiting
				if (_final){
					return _final.apply(context /*proto*/, args/*args*/)
				}
				return { err : err, msg : messages }
			}
			if (err && err === 'skip'){ /* error is a command */
				if (msg) messages.push( msg )
				layerIndex++
				handlerIndex = 0

				return next()
			}
			if (msg) messages.push( msg )

			var handler = layer[handlerIndex]
			if (!handler){
				layerIndex++
				handlerIndex = 0		// prepare for next layer

				return next()
			}

			handlerIndex++
			return handler.apply(context, args)
		}
	}
	function use(check){
		if (!check)	return stackManager // no argument parsed

		var args = [].slice.call(arguments)
		,	arg = 0
		,	layer = []
		,	err = null

		// validates every parsed layer
		for ( ; arg < args.length ; arg++){

			if (Array.isArray( args[arg] )){
				//		--> current argument is a layer
				// 		v Is null if no error in current layer
				err = 	validateLayer( layer )
				|| 		validateLayer( args[arg] )

				// 		^ Is null if no error in nested layer

				if (err) break

				// adds current layer (if defined)
				if ( layer.length > 0) { stack.push(layer); layer = [] }
				if ( args[arg].length > 0) { stack.push(args[arg]) }
				// and nested layer to stack

			}else {
				layer.push(args[arg])
			}
		}

		err = (err)					// holds error if occured
		? err						//if no error yet, validate open layer
		: validateLayer(layer)		//if no error in open layer error is null

		if (err) throw new Error(err)
		if (layer.length > 0)  { stack.push(layer); layer = [] } // adds open layer to stack

		return stackManager
		function validateLayer(_layer_){
			var index = 0

			for ( ; index < _layer_.length ; index++ ){
				if( typeof _layer_[index] !== 'function' ){
					return ('Type of Argument ( '
							+ _layer_[index]
							+ ' ) is [ '
							+ (typeof _layer_[index])
							+ ' ] -- Must be [ function ]!')
				}
			}
			return null // if there is no error
		}
	}
	function setCustomStack(stack){
		return use.apply(stackManager, [].slice.call(arguments))
	}
	function setFinalHandler(fn){
		if ('function' === typeof fn) { final = fn }
		return stackManager
	}
	function setContext(ctx){
		if('object' === typeof ctx){ context = ctx }
		return stackManager
	}
	function flushStack(){
		stack = []
		console.warn('Stack wiped!!!')
		return stackManager
	}
	function inspectStack(){
		return stack
	}
}<|endoftext|>


<commit_before>"user strict";

const state = {
  type: null,
  expression: null,
  timeFormat: null,
  messageFormat: null,
  rfc5424TimeFormat: null,
  withPriority: null,
};

const getters = {
  toParams: (state) => {
    return {
      expression: state.expression,
      time_format: state.timeFormat,
      message_format: state.messageFormat,
      rfc5424_time_format: state.rfc5424TimeFormat,
      with_priority: state.withPriority
    };
  },
  pluginName: (state) => {
    return state.type;
  }
};

const actions = {
  updateType({ commit, state }, event) {
    commit("setType", event.target.value);
    commit("clearParams");
  },
  updateExpression({ commit, state }, event) {
    commit("setExpression", event.target.value);
  },
  updateTimeFormat({ commit, state }, event) {
    commit("setTimeFormat", event.target.value);
  },
  updateMessageFormat({ commit, state }, event) {
    commit("setMessageFormat", event.target.value);
  },
  updateRfc5424TimeFormat({ commit, state }, event) {
    commit("setRfc5424TimeFormat", event.target.value);
  },
  updateWithPriority({ commit, state }, event) {
    commit("setWithPriority", event.target.value);
  }
};

const mutations = {
  setType(state, value) {
    state.type = value;
  },
  setExpression(state, value) {
    state.expression = value;
  },
  setTimeFormat(state, value) {
    state.timeFormat = value;
  },
  setMessageFormat(state, value) {
    state.messageFormat = value;
  },
  setRfc5424TimeFormat(state, value) {
    state.rfc5424TimeFormat = value;
  },
  setWithPriority(state, value) {
    state.withPriority = value;
  },
  clearParams(state) {
    state.expression = null;
    state.timeFormat = null;
    state.messageFormat = null;
    state.rfc5424TimeFormat = null;
    state.withPriority = null;
  }
};

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations
};
<commit_msg>Use true/false value for checkbox value<commit_after>"user strict";

const state = {
  type: null,
  expression: null,
  timeFormat: null,
  messageFormat: null,
  rfc5424TimeFormat: null,
  withPriority: null,
};

const getters = {
  toParams: (state) => {
    return {
      expression: state.expression,
      time_format: state.timeFormat,
      message_format: state.messageFormat,
      rfc5424_time_format: state.rfc5424TimeFormat,
      with_priority: state.withPriority
    };
  },
  pluginName: (state) => {
    return state.type;
  }
};

const actions = {
  updateType({ commit, state }, event) {
    commit("setType", event.target.value);
    commit("clearParams");
  },
  updateExpression({ commit, state }, event) {
    commit("setExpression", event.target.value);
  },
  updateTimeFormat({ commit, state }, event) {
    commit("setTimeFormat", event.target.value);
  },
  updateMessageFormat({ commit, state }, event) {
    commit("setMessageFormat", event.target.value);
  },
  updateRfc5424TimeFormat({ commit, state }, event) {
    commit("setRfc5424TimeFormat", event.target.value);
  },
  updateWithPriority({ commit, state }, event) {
    commit("setWithPriority", event.target.checked);
  }
};

const mutations = {
  setType(state, value) {
    state.type = value;
  },
  setExpression(state, value) {
    state.expression = value;
  },
  setTimeFormat(state, value) {
    state.timeFormat = value;
  },
  setMessageFormat(state, value) {
    state.messageFormat = value;
  },
  setRfc5424TimeFormat(state, value) {
    state.rfc5424TimeFormat = value;
  },
  setWithPriority(state, value) {
    state.withPriority = value;
  },
  clearParams(state) {
    state.expression = null;
    state.timeFormat = null;
    state.messageFormat = null;
    state.rfc5424TimeFormat = null;
    state.withPriority = null;
  }
};

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations
};
<|endoftext|>


<commit_before>goog.provide('ol.test.array');

describe('ol.array', function() {

  describe('binaryFindNearest', function() {
    it('returns expected value', function() {
      var arr = [1000, 500, 100];

      expect(ol.array.binaryFindNearest(arr, 10000)).to.eql(0);
      expect(ol.array.binaryFindNearest(arr, 1000)).to.eql(0);
      expect(ol.array.binaryFindNearest(arr, 900)).to.eql(0);

      expect(ol.array.binaryFindNearest(arr, 750)).to.eql(1);

      expect(ol.array.binaryFindNearest(arr, 550)).to.eql(1);
      expect(ol.array.binaryFindNearest(arr, 500)).to.eql(1);
      expect(ol.array.binaryFindNearest(arr, 450)).to.eql(1);

      expect(ol.array.binaryFindNearest(arr, 300)).to.eql(2);

      expect(ol.array.binaryFindNearest(arr, 200)).to.eql(2);
      expect(ol.array.binaryFindNearest(arr, 100)).to.eql(2);
      expect(ol.array.binaryFindNearest(arr, 50)).to.eql(2);
    });
  });

  describe('linearFindNearest', function() {
    it('returns expected value', function() {
      var arr = [1000, 500, 100];

      expect(ol.array.linearFindNearest(arr, 10000, 0)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 10000, 1)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 10000, -1)).to.eql(0);

      expect(ol.array.linearFindNearest(arr, 1000, 0)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 1000, 1)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 1000, -1)).to.eql(0);

      expect(ol.array.linearFindNearest(arr, 900, 0)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 900, 1)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 900, -1)).to.eql(1);

      expect(ol.array.linearFindNearest(arr, 750, 0)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 750, 1)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 750, -1)).to.eql(1);

      expect(ol.array.linearFindNearest(arr, 550, 0)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 550, 1)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 550, -1)).to.eql(1);

      expect(ol.array.linearFindNearest(arr, 500, 0)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 500, 1)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 500, -1)).to.eql(1);

      expect(ol.array.linearFindNearest(arr, 450, 0)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 450, 1)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 450, -1)).to.eql(2);

      expect(ol.array.linearFindNearest(arr, 300, 0)).to.eql(2);
      expect(ol.array.linearFindNearest(arr, 300, 1)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 300, -1)).to.eql(2);

      expect(ol.array.linearFindNearest(arr, 200, 0)).to.eql(2);
      expect(ol.array.linearFindNearest(arr, 200, 1)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 200, -1)).to.eql(2);

      expect(ol.array.linearFindNearest(arr, 100, 0)).to.eql(2);
      expect(ol.array.linearFindNearest(arr, 100, 1)).to.eql(2);
      expect(ol.array.linearFindNearest(arr, 100, -1)).to.eql(2);

      expect(ol.array.linearFindNearest(arr, 50, 0)).to.eql(2);
      expect(ol.array.linearFindNearest(arr, 50, 1)).to.eql(2);
      expect(ol.array.linearFindNearest(arr, 50, -1)).to.eql(2);
    });
  });

  describe.only('reverseSubArray', function() {
    it('returns expected value', function() {
      var arr;
      var expected = [1, 2, 3, 4, 5, 6];

      arr = [1, 5, 4, 3, 2, 6];
      ol.array.reverseSubArray(arr, 1, 4);
      expect(arr).to.eql(expected);

      arr = [3, 2, 1, 4, 5, 6];
      ol.array.reverseSubArray(arr, 0, 2);
      expect(arr).to.eql(expected);

      arr = [1, 2, 3, 6, 5, 4];
      ol.array.reverseSubArray(arr, 3, 5);
      expect(arr).to.eql(expected);

      arr = [6, 5, 4, 3, 2, 1];
      ol.array.reverseSubArray(arr, 0, 5);
      expect(arr).to.eql(expected);
    });
  });
});

goog.require('ol.array');
<commit_msg>Don't use describe.only in test<commit_after>goog.provide('ol.test.array');

describe('ol.array', function() {

  describe('binaryFindNearest', function() {
    it('returns expected value', function() {
      var arr = [1000, 500, 100];

      expect(ol.array.binaryFindNearest(arr, 10000)).to.eql(0);
      expect(ol.array.binaryFindNearest(arr, 1000)).to.eql(0);
      expect(ol.array.binaryFindNearest(arr, 900)).to.eql(0);

      expect(ol.array.binaryFindNearest(arr, 750)).to.eql(1);

      expect(ol.array.binaryFindNearest(arr, 550)).to.eql(1);
      expect(ol.array.binaryFindNearest(arr, 500)).to.eql(1);
      expect(ol.array.binaryFindNearest(arr, 450)).to.eql(1);

      expect(ol.array.binaryFindNearest(arr, 300)).to.eql(2);

      expect(ol.array.binaryFindNearest(arr, 200)).to.eql(2);
      expect(ol.array.binaryFindNearest(arr, 100)).to.eql(2);
      expect(ol.array.binaryFindNearest(arr, 50)).to.eql(2);
    });
  });

  describe('linearFindNearest', function() {
    it('returns expected value', function() {
      var arr = [1000, 500, 100];

      expect(ol.array.linearFindNearest(arr, 10000, 0)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 10000, 1)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 10000, -1)).to.eql(0);

      expect(ol.array.linearFindNearest(arr, 1000, 0)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 1000, 1)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 1000, -1)).to.eql(0);

      expect(ol.array.linearFindNearest(arr, 900, 0)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 900, 1)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 900, -1)).to.eql(1);

      expect(ol.array.linearFindNearest(arr, 750, 0)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 750, 1)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 750, -1)).to.eql(1);

      expect(ol.array.linearFindNearest(arr, 550, 0)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 550, 1)).to.eql(0);
      expect(ol.array.linearFindNearest(arr, 550, -1)).to.eql(1);

      expect(ol.array.linearFindNearest(arr, 500, 0)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 500, 1)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 500, -1)).to.eql(1);

      expect(ol.array.linearFindNearest(arr, 450, 0)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 450, 1)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 450, -1)).to.eql(2);

      expect(ol.array.linearFindNearest(arr, 300, 0)).to.eql(2);
      expect(ol.array.linearFindNearest(arr, 300, 1)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 300, -1)).to.eql(2);

      expect(ol.array.linearFindNearest(arr, 200, 0)).to.eql(2);
      expect(ol.array.linearFindNearest(arr, 200, 1)).to.eql(1);
      expect(ol.array.linearFindNearest(arr, 200, -1)).to.eql(2);

      expect(ol.array.linearFindNearest(arr, 100, 0)).to.eql(2);
      expect(ol.array.linearFindNearest(arr, 100, 1)).to.eql(2);
      expect(ol.array.linearFindNearest(arr, 100, -1)).to.eql(2);

      expect(ol.array.linearFindNearest(arr, 50, 0)).to.eql(2);
      expect(ol.array.linearFindNearest(arr, 50, 1)).to.eql(2);
      expect(ol.array.linearFindNearest(arr, 50, -1)).to.eql(2);
    });
  });

  describe('reverseSubArray', function() {
    it('returns expected value', function() {
      var arr;
      var expected = [1, 2, 3, 4, 5, 6];

      arr = [1, 5, 4, 3, 2, 6];
      ol.array.reverseSubArray(arr, 1, 4);
      expect(arr).to.eql(expected);

      arr = [3, 2, 1, 4, 5, 6];
      ol.array.reverseSubArray(arr, 0, 2);
      expect(arr).to.eql(expected);

      arr = [1, 2, 3, 6, 5, 4];
      ol.array.reverseSubArray(arr, 3, 5);
      expect(arr).to.eql(expected);

      arr = [6, 5, 4, 3, 2, 1];
      ol.array.reverseSubArray(arr, 0, 5);
      expect(arr).to.eql(expected);
    });
  });
});

goog.require('ol.array');
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';
import classnames from 'classnames';
import _ from 'lodash';
import StepContent from '../../components/Stepper/StepContent';
import StepWrapper from '../../components/Stepper/StepWrapper';
import AmountSelection from '../../components/AmountSelection/AmountSelection';
import MemberDetailsForm from '../../components/MemberDetailsForm/MemberDetailsForm';
import Payment from '../../components/Payment/Payment';
import OneClick from '../../components/OneClick/OneClick';
import Cookie from 'js-cookie';
import { localCurrencies } from './utils';
import unintendedDonationsExperiment from '../../experiments/unintended-donations';
import { setExperimentVariant } from '../../state/experiments';
import { resetMember } from '../../state/member/reducer';
import {
  changeAmount,
  changeCurrency,
  changeStep,
  setSubmitting,
  setSupportedLocalCurrency,
} from '../../state/fundraiser/actions';

export class FundraiserView extends Component {
  async componentDidMount() {
    if (window.dataLayer) {
      await window.dataLayer.push({
        event: unintendedDonationsExperiment.activationEvent,
      });
    }
    this.intervalId = setInterval(() => {
      if (window.google_optimize !== undefined) {
        const variant = window.google_optimize.get(
          unintendedDonationsExperiment.experimentId
        );
        console.log('variant', variant);
        if (variant) {
          this.props.setExperimentVariant({
            variant,
            experimentId: unintendedDonationsExperiment.experimentId,
          });
        }
        clearInterval(this.intervalId);
      }
    }, 500);

    const { donationAmount } = this.props.fundraiser;
    this.props.setSupportedLocalCurrency(this.supportedLocalCurrency());
    if (donationAmount && donationAmount > 0) {
      this.props.selectAmount(donationAmount);
      this.props.changeStep(1);
    }
  }

  componentDidUpdate(prevProps) {
    if (
      prevProps.experiments.length == 0 &&
      this.props.experiments.length > 0
    ) {
      const { variant } =
        this.props.experiments.find(
          e => (e.experimentId = unintendedDonationsExperiment.experimentId)
        ) || {};
      console.log(this.props);
      if (variant && variant === '1' && this.props.idMismatch) {
        this.props.resetMember();
        this.props.changeStep(0);
      }
    }
  }

  selectAmount(amount) {
    this.props.selectAmount(amount);
    const userId =
      window.champaign.personalization.member.id || Cookie.get('__bpmx');
    if (typeof window.fbq === 'function') {
      window.fbq('track', 'InitiateCheckout', {
        value: amount,
        currency: this.props.fundraiser.currency,
        content_name: this.props.page.title,
        content_ids: [this.props.page.id],
        content_type: 'product',
        user_id: userId,
        product_catalog_id: 445876772724152,
        page_id: this.props.page.id,
      });
    }
  }

  supportedLocalCurrency() {
    const country = window.champaign.personalization.member.country;
    // Member is in a country where we are not concerned of confusion in currencies when we display the currency sign
    // - this is currently any country outside of Lat Am
    if (!Object.keys(localCurrencies).includes(country)) return true;
    return localCurrencies[country] === this.props.fundraiser.currency;
  }

  proceed() {
    this.props.changeStep(this.props.fundraiser.currentStep + 1);
  }

  showStepTwo() {
    const { variant } =
      this.props.experiments.find(
        e => (e.experimentId = unintendedDonationsExperiment.experimentId)
      ) || {};

    if (variant && variant === '1' && this.props.idMismatch) {
      return true;
    }

    const { outstandingFields } = this.props.fundraiser;
    return !outstandingFields || outstandingFields.length !== 0;
  }

  render() {
    const {
      fundraiser: {
        formId,
        fields,
        formValues,
        donationBands,
        donationAmount,
        donationFeaturedAmount,
        currency,
        currentStep,
        outstandingFields,
        submitting,
        oneClickError,
        supportedLocalCurrency,
      },
    } = this.props;

    // todo move this into AmountSelection (connect it to store)
    const firstStepButtonTitle = _.isEmpty(formValues) ? (
      <FormattedMessage
        id="fundraiser.proceed_to_details"
        defaultMessage="Proceed to details (default)"
      />
    ) : (
      <FormattedMessage
        id="fundraiser.proceed_to_payment"
        defaultMessage="Proceed to payment (default)"
      />
    );

    const classNames = classnames({
      'FundraiserView-container': true,
      'form--big': true,
    });

    const oneClickErrorMessage = oneClickError ? (

        <FormattedMessage
          id="fundraiser.one_click_failed"
          defaultMessage="We're sorry but we could not process your donation. Please try again with a different card"
        />

    ) : null;

    const supportedCurrencyDisclaimer = !supportedLocalCurrency ? (

        <FormattedMessage
          id="fundraiser.currency_disclaimer"
          defaultMessage="Hello! We're working hard to soon be able to accept donations in your local currency. Meanwhile, we appreciate your patience — your donation will be processed in the foreign currency you select. Please note that your credit card might impose fees which SumOfUs has no control of. We truly appreciate your understanding."
        />

    ) : null;

    if (this.props.oneClickDonate) {
      return (

          <OneClick />

      );
    }

    return (

        <StepWrapper
          title={this.props.fundraiser.title}
          submitting={submitting}
          currentStep={currentStep}
          changeStep={this.props.changeStep}
        >
          <StepContent title={AmountSelection.title(donationAmount, currency)}>

              {oneClickErrorMessage}
              {supportedCurrencyDisclaimer}
              <AmountSelection
                donationAmount={donationAmount}
                currency={currency}
                donationBands={donationBands}
                donationFeaturedAmount={donationFeaturedAmount}
                nextStepTitle={firstStepButtonTitle}
                changeCurrency={this.props.selectCurrency.bind(this)}
                selectAmount={amount => this.selectAmount(amount)}
                proceed={this.proceed.bind(this)}
              />

          </StepContent>

          {this.showStepTwo() && (
            <StepContent title={<FormattedMessage id="fundraiser.details" />}>
              <MemberDetailsForm
                buttonText={
                  <FormattedMessage
                    id="fundraiser.proceed_to_payment"
                    defaultMessage="Proceed to payment"
                  />
                }
                fields={fields}
                outstandingFields={outstandingFields}
                formValues={formValues}
                formId={formId}
                pageId={this.props.page.id}
                proceed={this.proceed.bind(this)}
              />
            </StepContent>
          )}

          <StepContent title={<FormattedMessage id="fundraiser.payment" />}>
            <Payment
              page={this.props.page}
              disableFormReveal={this.showStepTwo()}
              setSubmitting={s => this.props.setSubmitting(s)}
            />
          </StepContent>
        </StepWrapper>

    );
  }
}

export const mapStateToProps = state => ({
  paymentMethods: state.paymentMethods,
  features: state.features,
  fundraiser: state.fundraiser,
  member: state.member,
  page: state.page,
  oneClickError: state.fundraiser.oneClickError,
  oneClickDonate:
    state.fundraiser.oneClick &&
    state.paymentMethods.length > 0 &&
    !state.fundraiser.disableSavedPayments,
  supportedLocalCurrency: state.fundraiser.supportedLocalCurrency,
  experiments: state.abTests.experiments,
  idMismatch: state.fundraiser.id_mismatch,
});

export const mapDispatchToProps = dispatch => ({
  resetMember: () => dispatch(resetMember()),
  changeStep: step => dispatch(changeStep(step)),
  selectAmount: amount => dispatch(changeAmount(amount)),
  selectCurrency: currency => dispatch(changeCurrency(currency)),
  setSubmitting: submitting => dispatch(setSubmitting(submitting)),
  setSupportedLocalCurrency: value =>
    dispatch(setSupportedLocalCurrency(value)),
  setExperimentVariant: value => dispatch(setExperimentVariant(value)),
});

export default connect(mapStateToProps, mapDispatchToProps)(FundraiserView);
<commit_msg>adding loading state<commit_after>import React, { Component, Fragment } from 'react';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';
import classnames from 'classnames';
import _ from 'lodash';
import StepContent from '../../components/Stepper/StepContent';
import StepWrapper from '../../components/Stepper/StepWrapper';
import AmountSelection from '../../components/AmountSelection/AmountSelection';
import MemberDetailsForm from '../../components/MemberDetailsForm/MemberDetailsForm';
import Payment from '../../components/Payment/Payment';
import OneClick from '../../components/OneClick/OneClick';
import Cookie from 'js-cookie';
import { localCurrencies } from './utils';
import unintendedDonationsExperiment from '../../experiments/unintended-donations';
import { setExperimentVariant } from '../../state/experiments';
import { resetMember } from '../../state/member/reducer';
import {
  changeAmount,
  changeCurrency,
  changeStep,
  setSubmitting,
  setSupportedLocalCurrency,
} from '../../state/fundraiser/actions';

export class FundraiserView extends Component {
  constructor(props) {
    super(props);

    this.state = {
      isLoaded: false,
    };
  }

  async componentDidMount() {
    if (window.dataLayer) {
      await window.dataLayer.push({
        event: unintendedDonationsExperiment.activationEvent,
      });
    }
    this.intervalId = setInterval(() => {
      if (window.google_optimize !== undefined) {
        const variant = window.google_optimize.get(
          unintendedDonationsExperiment.experimentId
        );
        console.log('variant', variant);
        if (variant) {
          this.props.setExperimentVariant({
            variant,
            experimentId: unintendedDonationsExperiment.experimentId,
          });
        }
        clearInterval(this.intervalId);
        this.setState({
          isLoaded: true,
        });
      }
    }, 500);

    const { donationAmount } = this.props.fundraiser;
    this.props.setSupportedLocalCurrency(this.supportedLocalCurrency());
    if (donationAmount && donationAmount > 0) {
      this.props.selectAmount(donationAmount);
      this.props.changeStep(1);
    }
  }

  componentDidUpdate(prevProps) {
    if (
      prevProps.experiments.length == 0 &&
      this.props.experiments.length > 0
    ) {
      const { variant } =
        this.props.experiments.find(
          e => (e.experimentId = unintendedDonationsExperiment.experimentId)
        ) || {};
      console.log(this.props);
      if (variant && variant === '1' && this.props.idMismatch) {
        this.props.resetMember();
        this.props.changeStep(0);
      }
    }
  }

  selectAmount(amount) {
    this.props.selectAmount(amount);
    const userId =
      window.champaign.personalization.member.id || Cookie.get('__bpmx');
    if (typeof window.fbq === 'function') {
      window.fbq('track', 'InitiateCheckout', {
        value: amount,
        currency: this.props.fundraiser.currency,
        content_name: this.props.page.title,
        content_ids: [this.props.page.id],
        content_type: 'product',
        user_id: userId,
        product_catalog_id: 445876772724152,
        page_id: this.props.page.id,
      });
    }
  }

  supportedLocalCurrency() {
    const country = window.champaign.personalization.member.country;
    // Member is in a country where we are not concerned of confusion in currencies when we display the currency sign
    // - this is currently any country outside of Lat Am
    if (!Object.keys(localCurrencies).includes(country)) return true;
    return localCurrencies[country] === this.props.fundraiser.currency;
  }

  proceed() {
    this.props.changeStep(this.props.fundraiser.currentStep + 1);
  }

  showStepTwo() {
    const { variant } =
      this.props.experiments.find(
        e => (e.experimentId = unintendedDonationsExperiment.experimentId)
      ) || {};

    if (variant && variant === '1' && this.props.idMismatch) {
      return true;
    }

    const { outstandingFields } = this.props.fundraiser;
    return !outstandingFields || outstandingFields.length !== 0;
  }

  render() {
    const {
      fundraiser: {
        formId,
        fields,
        formValues,
        donationBands,
        donationAmount,
        donationFeaturedAmount,
        currency,
        currentStep,
        outstandingFields,
        submitting,
        oneClickError,
        supportedLocalCurrency,
      },
    } = this.props;

    // todo move this into AmountSelection (connect it to store)
    const firstStepButtonTitle = _.isEmpty(formValues) ? (
      <FormattedMessage
        id="fundraiser.proceed_to_details"
        defaultMessage="Proceed to details (default)"
      />
    ) : (
      <FormattedMessage
        id="fundraiser.proceed_to_payment"
        defaultMessage="Proceed to payment (default)"
      />
    );

    const classNames = classnames({
      'FundraiserView-container': true,
      'form--big': true,
    });

    const oneClickErrorMessage = oneClickError ? (

        <FormattedMessage
          id="fundraiser.one_click_failed"
          defaultMessage="We're sorry but we could not process your donation. Please try again with a different card"
        />

    ) : null;

    const supportedCurrencyDisclaimer = !supportedLocalCurrency ? (

        <FormattedMessage
          id="fundraiser.currency_disclaimer"
          defaultMessage="Hello! We're working hard to soon be able to accept donations in your local currency. Meanwhile, we appreciate your patience — your donation will be processed in the foreign currency you select. Please note that your credit card might impose fees which SumOfUs has no control of. We truly appreciate your understanding."
        />

    ) : null;

    if (this.props.oneClickDonate) {
      return (

          <OneClick />

      );
    }

    return (
      <Fragment>
        {this.state.isLoaded ? (

            <StepWrapper
              title={this.props.fundraiser.title}
              submitting={submitting}
              currentStep={currentStep}
              changeStep={this.props.changeStep}
            >
              <StepContent
                title={AmountSelection.title(donationAmount, currency)}
              >

                  {oneClickErrorMessage}
                  {supportedCurrencyDisclaimer}
                  <AmountSelection
                    donationAmount={donationAmount}
                    currency={currency}
                    donationBands={donationBands}
                    donationFeaturedAmount={donationFeaturedAmount}
                    nextStepTitle={firstStepButtonTitle}
                    changeCurrency={this.props.selectCurrency.bind(this)}
                    selectAmount={amount => this.selectAmount(amount)}
                    proceed={this.proceed.bind(this)}
                  />

              </StepContent>

              {this.showStepTwo() && (
                <StepContent
                  title={<FormattedMessage id="fundraiser.details" />}
                >
                  <MemberDetailsForm
                    buttonText={
                      <FormattedMessage
                        id="fundraiser.proceed_to_payment"
                        defaultMessage="Proceed to payment"
                      />
                    }
                    fields={fields}
                    outstandingFields={outstandingFields}
                    formValues={formValues}
                    formId={formId}
                    pageId={this.props.page.id}
                    proceed={this.proceed.bind(this)}
                  />
                </StepContent>
              )}

              <StepContent title={<FormattedMessage id="fundraiser.payment" />}>
                <Payment
                  page={this.props.page}
                  disableFormReveal={this.showStepTwo()}
                  setSubmitting={s => this.props.setSubmitting(s)}
                />
              </StepContent>
            </StepWrapper>

        ) : null}
      </Fragment>
    );
  }
}

export const mapStateToProps = state => ({
  paymentMethods: state.paymentMethods,
  features: state.features,
  fundraiser: state.fundraiser,
  member: state.member,
  page: state.page,
  oneClickError: state.fundraiser.oneClickError,
  oneClickDonate:
    state.fundraiser.oneClick &&
    state.paymentMethods.length > 0 &&
    !state.fundraiser.disableSavedPayments,
  supportedLocalCurrency: state.fundraiser.supportedLocalCurrency,
  experiments: state.abTests.experiments,
  idMismatch: state.fundraiser.id_mismatch,
});

export const mapDispatchToProps = dispatch => ({
  resetMember: () => dispatch(resetMember()),
  changeStep: step => dispatch(changeStep(step)),
  selectAmount: amount => dispatch(changeAmount(amount)),
  selectCurrency: currency => dispatch(changeCurrency(currency)),
  setSubmitting: submitting => dispatch(setSubmitting(submitting)),
  setSupportedLocalCurrency: value =>
    dispatch(setSupportedLocalCurrency(value)),
  setExperimentVariant: value => dispatch(setExperimentVariant(value)),
});

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


<commit_before>const REQUIRED_ENV_VARIABLES = [
  'TYMLY_GITHUB_TOKEN',
  'TYMLY_GITHUB_USER'
]
const path = require('path')

let LernaSync
try {
  // If the local lerna-sync package is available, then use that.
  LernaSync = require('../packages/lerna-sync')
} catch (e) {
  // If it's not been synced in yet and not available, then fallback to the lerna-sync dependency.
  // (as expected via an npm install).
  LernaSync = require('@wmfs/lerna-sync')
}

const process = require('process')

async function main () {
  REQUIRED_ENV_VARIABLES.forEach(
    varName => {
      if (!process.env.hasOwnProperty(varName)) {
        throw new Error(`Required environment variable ${varName} has not set!`)
      }
    }
  )

  const lernaSync = new LernaSync(
    {
      monorepoPath: path.resolve(__dirname, '..'),
      gitHubToken: process.env.TYMLY_GITHUB_TOKEN,
      gitHubOrgName: 'wmfs',
      gitHubUser: process.env.TYMLY_GITHUB_USER,
      lernaPackageRouterFunction: function (gitHubPackageObj) {
        if (gitHubPackageObj) {
          const keywordToPackageMap = [
            ['package', 'packages'],
            ['plugin', 'plugins'],
            ['blueprint', 'blueprints'],
            ['cardscript', 'cardscript'],
            ['app', 'apps'],
            ['mod', 'mods']
          ]
          if (gitHubPackageObj.hasOwnProperty('keywords') && gitHubPackageObj.keywords.indexOf('tymly') !== -1) {
            let lernaPackageName = null
            const keywords = gitHubPackageObj.keywords
            keywordToPackageMap.forEach(
              tuple => {
                if (keywords.indexOf(tuple[0]) !== -1) {
                  lernaPackageName = tuple[1]
                }
              }
            )
            return lernaPackageName
          }
        }
      }
    }
  )
  await lernaSync.sync()
}

(async () => {
  await main()
})().catch(e => {
  console.error(e)
})
<commit_msg>refactor: Pulled out callback function rather than doing it inline<commit_after>const REQUIRED_ENV_VARIABLES = [
  'TYMLY_GITHUB_TOKEN',
  'TYMLY_GITHUB_USER'
]
const path = require('path')

let LernaSync
try {
  // If the local lerna-sync package is available, then use that.
  LernaSync = require('../packages/lerna-sync')
} catch (e) {
  // If it's not been synced in yet and not available, then fallback to the lerna-sync dependency.
  // (as expected via an npm install).
  LernaSync = require('@wmfs/lerna-sync')
}

const process = require('process')

async function main () {
  REQUIRED_ENV_VARIABLES.forEach(
    varName => {
      if (!process.env.hasOwnProperty(varName)) {
        throw new Error(`Required environment variable ${varName} has not set!`)
      }
    }
  )

  const lernaSync = new LernaSync(
    {
      monorepoPath: path.resolve(__dirname, '..'),
      gitHubToken: process.env.TYMLY_GITHUB_TOKEN,
      gitHubOrgName: 'wmfs',
      gitHubUser: process.env.TYMLY_GITHUB_USER,
      lernaPackageRouterFunction: packageObjCallback
    }
  )
  await lernaSync.sync()
}

(async () => {
  await main()
})().catch(e => {
  console.error(e)
})

function packageObjCallback (gitHubPackageObj) {
  if (gitHubPackageObj) {
    const keywordToPackageMap = [
      ['package', 'packages'],
      ['plugin', 'plugins'],
      ['blueprint', 'blueprints'],
      ['cardscript', 'cardscript'],
      ['app', 'apps'],
      ['mod', 'mods']
    ]

    if (gitHubPackageObj.hasOwnProperty('keywords') && gitHubPackageObj.keywords.indexOf('tymly') !== -1) {
      let lernaPackageName = null
      const keywords = gitHubPackageObj.keywords
      keywordToPackageMap.forEach(
        tuple => {
          if (keywords.indexOf(tuple[0]) !== -1) {
            lernaPackageName = tuple[1]
          }
        }
      )
      return lernaPackageName
    }
  }
}
<|endoftext|>


<commit_before>var core = require('./core');
var fs = require('fs');
var path = require('path');
var caller = require('./caller.js');
var nodeModulesPaths = require('./node-modules-paths.js');
var splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//;

module.exports = function resolve (x, opts, cb) {
    if (typeof opts === 'function') {
        cb = opts;
        opts = {};
    }
    if (!opts) opts = {};
    if (typeof x !== 'string') {
        return process.nextTick(function () {
            cb(new Error('path must be a string'));
        });
    }

    var isFile = opts.isFile || function (file, cb) {
        fs.stat(file, function (err, stat) {
            if (err && err.code === 'ENOENT') cb(null, false)
            else if (err) cb(err)
            else cb(null, stat.isFile() || stat.isFIFO())
        });
    };
    var readFile = opts.readFile || fs.readFile;

    var extensions = opts.extensions || [ '.js' ];
    var y = opts.basedir || path.dirname(caller());

    opts.paths = opts.paths || [];

    if (/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[\\\/])/.test(x)) {
        var res = path.resolve(y, x);
        if (x === '..') res += '/';
        loadAsFile(res, opts.package, function (err, m, pkg) {
            if (err) cb(err)
            else if (m) cb(null, m, pkg)
            else loadAsDirectory(path.resolve(y, x), function (err, d, pkg) {
                if (err) cb(err)
                else if (d) cb(null, d, pkg)
                else cb(new Error("Cannot find module '" + x + "' from '" + y + "'"))
            })
        });
    }
    else loadNodeModules(x, y, function (err, n, pkg) {
        if (err) cb(err)
        else if (n) cb(null, n, pkg)
        else if (core[x]) return cb(null, x);
        else cb(new Error("Cannot find module '" + x + "' from '" + y + "'"))
    });

    function loadAsFile (x, pkg, cb) {
        if (typeof pkg === 'function') {
            cb = pkg;
            pkg = undefined;
        }

        var exts = [''].concat(extensions);

        if (x === y) {
            return loadAsDirectory(y, pkg, cb);
        }
        else {
            return load(exts, x, pkg);
        }

		function load (exts, x, pkg) {
            if (exts.length === 0) return cb(null, undefined, pkg);
            var file = x + exts[0];

            isFile(file, function (err, ex) {
                if (err) return cb(err)
                if (!ex) return load(exts.slice(1), x, pkg)
                if (pkg) return cb(null, file, pkg)

                loadpkg(path.dirname(file), function (err, pkg, dir) {
                    if (err) return cb(err)
                    if (pkg && opts.pathFilter) {
                        var rel = path.relative(dir, file)
                            .slice(0, -exts[0].length)
                        ;
                        var r = opts.pathFilter(pkg, x, rel);
                        if (r) return load(
                            extensions.slice(),
                            path.resolve(dir, r),
                            pkg
                        );
                    }
                    cb(null, file, pkg)
                });
            });
        }
    }

    function loadpkg (dir, cb) {
        if (dir === '' || dir === '/') return cb(null);
        if (process.platform === 'win32' && /^\w:[\\\/]*$/.test(dir)) {
            return cb(null);
        }
        if (/[\\\/]node_modules[\\\/]*$/.test(dir)) return cb(null);

        var pkgfile = path.join(dir, 'package.json');
        isFile(pkgfile, function (err, ex) {
            if (err) return cb(err);
            if (!ex) return loadpkg(
                dir.replace(/[\\\/]*[^\\\/]+[\\\/]*/, ''), cb
            );

            readFile(pkgfile, function (err, body) {
                if (err) cb(err);
                try { var pkg = JSON.parse(body) }
                catch (err) {}

                if (pkg && opts.packageFilter) {
                    pkg = opts.packageFilter(pkg, pkgfile);
                }
                cb(null, pkg, dir);
            });
        });
    }

    function loadAsDirectory (x, fpkg, cb) {
        if (typeof fpkg === 'function') {
            cb = fpkg;
            fpkg = opts.package;
        }

        var pkgfile = path.join(x, '/package.json');
        isFile(pkgfile, function (err, ex) {
            if (err) return cb(err);
            if (!ex) return loadAsFile(path.join(x, '/index'), fpkg, cb);

            readFile(pkgfile, function (err, body) {
                if (err) return cb(err);
                try {
                    var pkg = JSON.parse(body);
                }
                catch (err) {}

                if (opts.packageFilter) {
                    pkg = opts.packageFilter(pkg, pkgfile);
                }

                if (pkg.main) {
                    if (pkg.main === '.' || pkg.main === './'){
                        pkg.main = 'index'
                    }
                    loadAsFile(path.resolve(x, pkg.main), pkg, function (err, m, pkg) {
                        if (err) return cb(err);
                        if (m) return cb(null, m, pkg);
                        if (!pkg) return loadAsFile(path.join(x, '/index'), pkg, cb);

                        var dir = path.resolve(x, pkg.main);
                        loadAsDirectory(dir, pkg, function (err, n, pkg) {
                            if (err) return cb(err);
                            if (n) return cb(null, n, pkg);
                            loadAsFile(path.join(x, '/index'), pkg, cb);
                        });
                    });
                    return;
                }

                loadAsFile(path.join(x, '/index'), pkg, cb);
            });
        });
    }

    function loadNodeModules (x, start, cb) {
        (function process (dirs) {
            if (dirs.length === 0) return cb(null, undefined);
            var dir = dirs[0];

            loadAsFile(path.join(dir, '/', x), undefined, function (err, m, pkg) {
                if (err) return cb(err);
                if (m) return cb(null, m, pkg);
                loadAsDirectory(path.join(dir, '/', x), undefined, function (err, n, pkg) {
                    if (err) return cb(err);
                    if (n) return cb(null, n, pkg);
                    process(dirs.slice(1));
                });
            });
        })(nodeModulesPaths(start, opts));
    }
};
<commit_msg>nearly nearly working<commit_after>var core = require('./core');
var fs = require('fs');
var path = require('path');
var caller = require('./caller.js');
var nodeModulesPaths = require('./node-modules-paths.js');
var splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//;

module.exports = function resolve (x, opts, cb) {
    if (typeof opts === 'function') {
        cb = opts;
        opts = {};
    }
    if (!opts) opts = {};
    if (typeof x !== 'string') {
        return process.nextTick(function () {
            cb(new Error('path must be a string'));
        });
    }

    var isFile = opts.isFile || function (file, cb) {
        fs.stat(file, function (err, stat) {
            if (err && err.code === 'ENOENT') cb(null, false)
            else if (err) cb(err)
            else cb(null, stat.isFile() || stat.isFIFO())
        });
    };
    var readFile = opts.readFile || fs.readFile;

    var extensions = opts.extensions || [ '.js' ];
    var y = opts.basedir || path.dirname(caller());

    opts.paths = opts.paths || [];

    if (/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[\\\/])/.test(x)) {
        var res = path.resolve(y, x);
        if (x === '..') res += '/';
        loadAsFile(res, opts.package, function (err, m, pkg) {
            if (err) cb(err)
            else if (m) cb(null, m, pkg)
            else loadAsDirectory(res, function (err, d, pkg) {
                if (err) cb(err)
                else if (d) cb(null, d, pkg)
                else cb(new Error("Cannot find module '" + x + "' from '" + y + "'"))
            })
        });
    }
    else loadNodeModules(x, y, function (err, n, pkg) {
        if (err) cb(err)
        else if (n) cb(null, n, pkg)
        else if (core[x]) return cb(null, x);
        else cb(new Error("Cannot find module '" + x + "' from '" + y + "'"))
    });

    function loadAsFile (x, pkg, cb, again) {
        if (typeof pkg === 'function') {
            cb = pkg;
            pkg = undefined;
        }

        var exts = [''].concat(extensions);

        if (x === y && !again) {
            loadAsDirectory(y, pkg, function (err, d, pkg) {
                if (d) cb(err, d, pkg)
                else loadAsFile(x, pkg, cb, true)
            });
        }
        else load(exts, x, pkg)

		function load (exts, x, pkg) {
            if (exts.length === 0) return cb(null, undefined, pkg);
            var file = x + exts[0];

            isFile(file, function (err, ex) {
                if (err) return cb(err)
                if (!ex) return load(exts.slice(1), x, pkg)
                if (pkg) return cb(null, file, pkg)

                loadpkg(path.dirname(file), function (err, pkg, dir) {
                    if (err) return cb(err)
                    if (pkg && opts.pathFilter) {
                        var rel = path.relative(dir, file)
                            .slice(0, -exts[0].length)
                        ;
                        var r = opts.pathFilter(pkg, x, rel);
                        if (r) return load(
                            extensions.slice(),
                            path.resolve(dir, r),
                            pkg
                        );
                    }
                    cb(null, file, pkg)
                });
            });
        }
    }

    function loadpkg (dir, cb) {
        if (dir === '' || dir === '/') return cb(null);
        if (process.platform === 'win32' && /^\w:[\\\/]*$/.test(dir)) {
            return cb(null);
        }
        if (/[\\\/]node_modules[\\\/]*$/.test(dir)) return cb(null);

        var pkgfile = path.join(dir, 'package.json');
        isFile(pkgfile, function (err, ex) {
            if (err) return cb(err);
            if (!ex) return loadpkg(
                dir.replace(/[\\\/]*[^\\\/]+[\\\/]*/, ''), cb
            );

            readFile(pkgfile, function (err, body) {
                if (err) cb(err);
                try { var pkg = JSON.parse(body) }
                catch (err) {}

                if (pkg && opts.packageFilter) {
                    pkg = opts.packageFilter(pkg, pkgfile);
                }
                cb(null, pkg, dir);
            });
        });
    }

    function loadAsDirectory (x, fpkg, cb) {
        if (typeof fpkg === 'function') {
            cb = fpkg;
            fpkg = opts.package;
        }

        var pkgfile = path.join(x, '/package.json');
        isFile(pkgfile, function (err, ex) {
            if (err) return cb(err);
            if (!ex) return loadAsFile(path.join(x, '/index'), fpkg, cb);

            readFile(pkgfile, function (err, body) {
                if (err) return cb(err);
                try {
                    var pkg = JSON.parse(body);
                }
                catch (err) {}

                if (opts.packageFilter) {
                    pkg = opts.packageFilter(pkg, pkgfile);
                }

                if (pkg.main) {
                    if (pkg.main === '.' || pkg.main === './'){
                        pkg.main = 'index'
                    }
                    loadAsFile(path.resolve(x, pkg.main), pkg, function (err, m, pkg) {
                        if (err) return cb(err);
                        if (m) return cb(null, m, pkg);
                        if (!pkg) return loadAsFile(path.join(x, '/index'), pkg, cb);

                        var dir = path.resolve(x, pkg.main);
                        loadAsDirectory(dir, pkg, function (err, n, pkg) {
                            if (err) return cb(err);
                            if (n) return cb(null, n, pkg);
                            loadAsFile(path.join(x, '/index'), pkg, cb);
                        });
                    });
                    return;
                }

                loadAsFile(path.join(x, '/index'), pkg, cb);
            });
        });
    }

    function loadNodeModules (x, start, cb) {
        (function process (dirs) {
            if (dirs.length === 0) return cb(null, undefined);
            var dir = dirs[0];

            loadAsFile(path.join(dir, '/', x), undefined, function (err, m, pkg) {
                if (err) return cb(err);
                if (m) return cb(null, m, pkg);
                loadAsDirectory(path.join(dir, '/', x), undefined, function (err, n, pkg) {
                    if (err) return cb(err);
                    if (n) return cb(null, n, pkg);
                    process(dirs.slice(1));
                });
            });
        })(nodeModulesPaths(start, opts));
    }
};
<|endoftext|>