<commit_before>
(function($, window, document){

    var DEBUG = true;
    // Log a message if DEBUG is true
    function debugLog(message){
        DEBUG && console.log(message);
    }

    $(document).ready(function() {
        var final_transcript = '';
        var ignore_onend;
        var start_timestamp;
        var $prompt = $("#prompt");
        var $mic = $("#mic");

        var micStates = {
            notListening: "/static/mic.gif",
            listening: "/static/mic-animate.gif",
            disabled: "/static/mic-slash.gif"
        };

        function setMic(state) {
            $mic.attr("src", micStates[state]);
        }

        // Currently only supported in Chrome
        if (('webkitSpeechRecognition' in window)) {
            $mic.show();

            function stopListening() {
                setMic('notListening');
                recognition.isListening = false;
                recognition.stop();
            }

            var recognition = new webkitSpeechRecognition();
            // Return and show results before the speech ends
            recognition.interimResults = true;
            recognition.isListening = false;

            recognition.onstart = function () {
                debugLog("Beginning voice recognition");
                recognition.isListening = true;
                setMic('listening');
            };

            recognition.onerror = function (event) {
                debugLog("Recognition Error: " + event.error);
                stopListening();
                if (event.error == 'no-speech') {
                    ignore_onend = true;
                }
                if (event.error == 'audio-capture') {
                    ignore_onend = true;
                }
            };

            recognition.onend = function () {
                if (ignore_onend || !final_transcript) {
                    return;
                }
                stopListening();
                debugLog("Ending recognition");
                $prompt.val(final_transcript);
            };

            recognition.onresult = function (event) {
                if (final_transcript){
                    $prompt.val(final_transcript);
                    return;
                }
                var interim_transcript = '';
                for (var i = event.resultIndex; i < event.results.length; ++i) {
                    if (event.results[i].isFinal) {
                        final_transcript += event.results[i][0].transcript;
                        debugLog("Final: " + final_transcript);
                        $prompt.val(final_transcript);
                        stopListening();
                    } else {
                        interim_transcript += event.results[i][0].transcript;
                        debugLog("Interim: " + interim_transcript);
                        $prompt.val(interim_transcript);
                    }
                }
            };
        }
        else {
            $mic.hide();
        }

        $mic.on("click", function (event) {
            debugLog("clicked mic");
            if (recognition.isListening) {
                stopListening();
                return;
            }
            final_transcript = '';
            $prompt.val('');
            ignore_onend = false;
            setMic('disabled');
            recognition.start();
            start_timestamp = event.timeStamp;
        });
    });
})(jQuery, window, document);<commit_msg>Stop listening if user seems remotely done talking<commit_after>
(function($, window, document){

    var DEBUG = false;
    // Log a message if DEBUG is true
    function debugLog(message){
        DEBUG && console.log(message);
    }

    $(document).ready(function() {
        var final_transcript = '';
        var ignore_onend;
        var start_timestamp;
        var $prompt = $("#prompt");
        var $mic = $("#mic");
        var $goBtn = $("#go-btn");

        var micStates = {
            notListening: "/static/mic.gif",
            listening: "/static/mic-animate.gif",
            disabled: "/static/mic-slash.gif"
        };

        function setMic(state) {
            $mic.attr("src", micStates[state]);
        }

        // Currently only supported in Chrome
        if (!('webkitSpeechRecognition' in window)) {
            $mic.hide();
        }
        else{
            $mic.show();

            function stopListening() {
                setMic('notListening');
                recognition.isListening = false;
                recognition.stop();
                debugLog("Stopped listening");
            }

            var recognition = new webkitSpeechRecognition();
            // Return and show results before the speech ends
            recognition.interimResults = true;
            recognition.isListening = false;

            recognition.onstart = function () {
                debugLog("Beginning voice recognition");
                recognition.isListening = true;
                setMic('listening');
            };

            recognition.onerror = function (event) {
                debugLog("Recognition Error: " + event.error);
                stopListening();
                if (event.error == 'no-speech') {
                    ignore_onend = true;
                }
                if (event.error == 'audio-capture') {
                    ignore_onend = true;
                }
            };

            recognition.onend = function () {
                if (ignore_onend || !final_transcript) {
                    debugLog("Ignoring onend");
                    return;
                }
                stopListening();
                debugLog("Ending recognition");
                $prompt.val(final_transcript);
                $prompt.focus();
            };

            recognition.onresult = function (event) {
                if (final_transcript){
                    $prompt.val(final_transcript);
                    stopListening();
                    return;
                }
                var interim_transcript = '';
                for (var i = event.resultIndex; i < event.results.length; ++i) {
                    if (event.results[i].isFinal) {
                        final_transcript += event.results[i][0].transcript;
                        debugLog("Final: " + final_transcript);
                        $prompt.val(final_transcript);
                        stopListening();
                    } else {
                        interim_transcript += event.results[i][0].transcript;
                        debugLog("Interim: " + interim_transcript);
                        $prompt.val(interim_transcript);
                    }
                }
            };

            $mic.on("click", function(event) {
                debugLog("clicked mic");
                if (recognition.isListening) {
                    stopListening();
                    return;
                }
                final_transcript = '';
                $prompt.val('');
                ignore_onend = false;
                setMic('disabled');
                recognition.start();
                start_timestamp = event.timeStamp;
            });

            // If the user clicks Go or starts typing,
            // we shouldn't be listening
            $goBtn.on("click", stopListening);
            $prompt.on("keypress", stopListening);
        }
    });
})(jQuery, window, document);<|endoftext|>


<commit_before>function getParent() {
  return this.getFromStore('parent')
}
function setEnv(parent, baseClass) {
  // Checking if env object is sent instead of parent
  if (parent.isEnvVariable) {
    this.environment = parent
  } else {
    // Every component must call super with their parent
    // which is supposed to be instance of Base
    if (!(this instanceof baseClass)) {
      throw Error('Make sure first parameter is the parent component which is an instance of Base component')
    }
    this.environment = parent.environment
    this.addToStore('parent', parent)
    this.getParent = getParent
  }
}

/**
 * Function that can get complex attributes from
 * object, e.g 'abc.xyz.ijk'
 * @param {Object} ob Object to find the result
 * @param {string} key complex or simple string attribute
 */
function deepGet(ob, key) {
  let result = ob
  // Split key by '.' delimeter
  key.split('.').forEach((attr) => {
    result = result[attr]
  })
  return result
}
/**
 * Function to get props from binded object
 * @return if one prop is send that prop value is return otherwise
 * object is returned having all requested keys
 * @param {String} keys key of property to get it
 */
function getter(ob, keys) {
  let result
  if (keys.length === 1) {
    result = deepGet(ob, keys[0])
  } else {
    result = {}
    keys.forEach((key) => {
      result[key] = deepGet(ob, key)
    })
  }
  return result
}
/**
 * A class that will be base class for all other components
 * so initialize states and add basic functionalities
 */
export default class Base {
  constructor(parent) {
    this.state = {}
    this.store = {}
    this.props = {}
    setEnv.call(this, parent, Base)
  }
  /* Setter for store */
  addToStore(key, val) {
    this.store[key] = val
  }
  /* Getter for store */
  getFromStore(...keys) {
    return getter(this.store, keys)
  }
  /* Setter for state */
  setState(key, val) {
    this.state[key] = val
  }
  /* Getter for state */
  getState(...keys) {
    return getter(this.state, keys)
  }
  /* Setter for props */
  setProps(key, val) {
    this.props[key] = val
  }
  /* Getter for props */
  getProps(...keys) {
    return getter(this.props, keys)
  }
  /** Get from common environment */
  getFromEnv(...keys) {
    return getter(this.environment, keys)
  }
  /* Add to environment */
  addToEnv(key, val) {
    this.environment[key] = val
  }
}
<commit_msg>Return value that was set in addTo* Base functions<commit_after>function getParent() {
  return this.getFromStore('parent')
}
function setEnv(parent, baseClass) {
  // Checking if env object is sent instead of parent
  if (parent.isEnvVariable) {
    this.environment = parent
  } else {
    // Every component must call super with their parent
    // which is supposed to be instance of Base
    if (!(this instanceof baseClass)) {
      throw Error('Make sure first parameter is the parent component which is an instance of Base component')
    }
    this.environment = parent.environment
    this.addToStore('parent', parent)
    this.getParent = getParent
  }
}

/**
 * Function that can get complex attributes from
 * object, e.g 'abc.xyz.ijk'
 * @param {Object} ob Object to find the result
 * @param {string} key complex or simple string attribute
 */
function deepGet(ob, key) {
  let result = ob
  // Split key by '.' delimeter
  key.split('.').forEach((attr) => {
    result = result[attr]
  })
  return result
}
/**
 * Function to get props from binded object
 * @return if one prop is send that prop value is return otherwise
 * object is returned having all requested keys
 * @param {String} keys key of property to get it
 */
function getter(ob, keys) {
  let result
  if (keys.length === 1) {
    result = deepGet(ob, keys[0])
  } else {
    result = {}
    keys.forEach((key) => {
      result[key] = deepGet(ob, key)
    })
  }
  return result
}
/**
 * A class that will be base class for all other components
 * so initialize states and add basic functionalities
 */
export default class Base {
  constructor(parent) {
    this.state = {}
    this.store = {}
    this.props = {}
    setEnv.call(this, parent, Base)
  }
  /* Setter for store */
  addToStore(key, val) {
    this.store[key] = val
    return val
  }
  /* Getter for store */
  getFromStore(...keys) {
    return getter(this.store, keys)
  }
  /* Setter for state */
  setState(key, val) {
    this.state[key] = val
    return val
  }
  /* Getter for state */
  getState(...keys) {
    return getter(this.state, keys)
  }
  /* Setter for props */
  setProps(key, val) {
    this.props[key] = val
    return val
  }
  /* Getter for props */
  getProps(...keys) {
    return getter(this.props, keys)
  }
  /** Get from common environment */
  getFromEnv(...keys) {
    return getter(this.environment, keys)
  }
  /* Add to environment */
  addToEnv(key, val) {
    this.environment[key] = val
    return val
  }
}
<|endoftext|>


<commit_before>var Entities = require('html-entities').AllHtmlEntities
var config = require('../../config.js')
const entities = new Entities()
const Dash = require('rethinkdbdash')
const r = new Dash()

var commands = []

commands.initializeTop = {
  internal: true,
  fn: function (bot, uv) {
    setInterval(() => generateTop(bot, uv), 3600000) // update the top 10 hourly
  }
}

commands.regenerate = {
  adminOnly: true,
  modOnly: false,
  fn: function (bot, msg, suffix, uv) {
    msg.reply('regenerating the top 10, this could take a while...').then((msg) => {
      generateTop(bot, uv).then(() => {
        msg.edit('done!, you can check the results at <#268812972401360906>')
      })
    })
  }
}

function generateTop (bot, uv) {
  return new Promise(function(resolve, reject) {
    let channel = bot.Channels.find(c => c.name === 'top-10-suggestions')
    let messages
    channel.fetchMessages().then(msgs => {
      messages = msgs.messages.filter(y => y.author.id === bot.User.id)
    })
    uv.v1.loginAsOwner().then(f => {
      f.get(`forums/${config.uservoice.forumId}/suggestions.json`).then(data => {
        for (let suggestion of data.suggestions) {
          generateEmbed(suggestion).then(embed => {
            let message = messages.pop()
            if (!message) {
              channel.sendMessage('', false, embed).then(msg => {
                r.db('DFB').table('queue').insert({
                  id: msg.id,
                  type: 'upvoteOnly',
                  UvId: suggestion.id
                }).then(() => {
                  msg.addReaction({
                    id: '302138464986595339',
                    name: 'upvote'
                  })
                })
              })
            } else {
              message.edit('', embed).then(msg => {
                r.db('DFB').table('queue').get(msg.id).update({
                  type: 'upvoteOnly',
                  UvId: suggestion.id
                })
              })
            }
          })
        }
        return resolve()
      })
    })
  })
}

function generateEmbed (data) {
  return new Promise(function(resolve, reject) {
    try {
      let embedFields = (data.response) ? [{
        name: data.status ? `${entities.decode(data.status_changed_by.name)} set the status to ${entities.decode(data.status.name)}` : `${entities.decode(data.status_changed_by.name)} responded:`,
        value: (data.response) ? entities.decode(data.response.text).length > 2000 ? '*Content too long, check the feedback website instead.*' : entities.decode(data.response.text) : 'No comment',
        inline: false
      }, {
        name: "Votes",
        value: data.vote_count,
        inline: false
      }] : [{
        name: "Votes",
        value: data.vote_count,
        inline: false
      }]
      return resolve({
        title: entities.decode(data.title),
        description: entities.decode(data.text).length > 2000 ? '*Content too long, check the feedback website instead.*' : entities.decode(data.text),
        url: data.url,
        timestamp: new Date(data.created_at),
        color: (data.status) ? parseInt(data.status.hex_color.substr(1), 16) : 0x595f68,
        footer: {
          text: (data.topic.forum.name) ? entities.decode(data.topic.forum.name) : 'Uncategorised'
        },
        author: {
          name: entities.decode(data.creator.name),
          url: data.creator.url,
          icon_url: data.creator.avatar_url
        },
        fields: embedFields
      })
    } catch (e) {
      return reject(e)
    }
  })
}

exports.Commands = commands
<commit_msg>Whoops<commit_after>var Entities = require('html-entities').AllHtmlEntities
var config = require('../../config.js')
const entities = new Entities()
const Dash = require('rethinkdbdash')
const r = new Dash()

var commands = []

commands.initializeTop = {
  internal: true,
  fn: function (bot, uv) {
    setInterval(() => generateTop(bot, uv), 3600000) // update the top 10 hourly
  }
}

commands.regenerate = {
  adminOnly: true,
  modOnly: false,
  fn: function (bot, msg, suffix, uv) {
    msg.reply('regenerating the top 10, this could take a while...').then((msg) => {
      generateTop(bot, uv).then(() => {
        msg.edit('Done!, you can check the results at <#268812972401360906>')
      })
    })
  }
}

function generateTop (bot, uv) {
  return new Promise(function(resolve, reject) {
    let channel = bot.Channels.find(c => c.name === 'top-10-suggestions')
    let messages
    channel.fetchMessages().then(msgs => {
      messages = msgs.messages.filter(y => y.author.id === bot.User.id)
    })
    uv.v1.loginAsOwner().then(f => {
      f.get(`forums/${config.uservoice.forumId}/suggestions.json`).then(data => {
        for (let suggestion of data.suggestions) {
          generateEmbed(suggestion).then(embed => {
            let message = messages.pop()
            if (!message) {
              channel.sendMessage('', false, embed).then(msg => {
                r.db('DFB').table('queue').insert({
                  id: msg.id,
                  type: 'upvoteOnly',
                  UvId: suggestion.id
                }).then(() => {
                  msg.addReaction({
                    id: '302138464986595339',
                    name: 'upvote'
                  })
                })
              })
            } else {
              message.edit('', embed).then(msg => {
                r.db('DFB').table('queue').get(msg.id).update({
                  type: 'upvoteOnly',
                  UvId: suggestion.id
                })
              })
            }
          })
        }
        return resolve()
      })
    })
  })
}

function generateEmbed (data) {
  return new Promise(function(resolve, reject) {
    try {
      let embedFields = (data.response) ? [{
        name: data.status ? `${entities.decode(data.status_changed_by.name)} set the status to ${entities.decode(data.status.name)}` : `${entities.decode(data.status_changed_by.name)} responded:`,
        value: (data.response) ? entities.decode(data.response.text).length > 2000 ? '*Content too long, check the feedback website instead.*' : entities.decode(data.response.text) : 'No comment',
        inline: false
      }, {
        name: "Votes",
        value: data.vote_count,
        inline: false
      }] : [{
        name: "Votes",
        value: data.vote_count,
        inline: false
      }]
      return resolve({
        title: entities.decode(data.title),
        description: entities.decode(data.text).length > 2000 ? '*Content too long, check the feedback website instead.*' : entities.decode(data.text),
        url: data.url,
        timestamp: new Date(data.created_at),
        color: (data.status) ? parseInt(data.status.hex_color.substr(1), 16) : 0x595f68,
        footer: {
          text: (data.topic.forum.name) ? entities.decode(data.topic.forum.name) : 'Uncategorised'
        },
        author: {
          name: entities.decode(data.creator.name),
          url: data.creator.url,
          icon_url: data.creator.avatar_url
        },
        fields: embedFields
      })
    } catch (e) {
      return reject(e)
    }
  })
}

exports.Commands = commands
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import moment from 'moment-timezone';

const BASE_UNIT = 'milliseconds';

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

    const date = props.date || props.children || null;
    const timesatmp = moment();
    const baseTime = date ? moment(new Date(date).getTime()) : timesatmp;

    this.state = {
      realTime: !date,
      now: baseTime,
      baseTime,
      startTime: timesatmp,
      formattedString: ''
    };
  }

  componentDidMount() {
    const {ticking, interval} = this.props;

    if (ticking && interval) {
      this.tickTimer = setInterval(() => {
        this.updateClock();
      }, interval);
    }
  }

  componentWillUnmount() {
    if (this.tickTimer) {
      clearInterval(this.tickTimer);
    }
  }

  formatTime(time) {
    const {filter, format, timezone} = this.props;

    if (timezone) {
      time.tz(timezone);
    }

    const formattedTime = time.format(format);
    const filteredTime = filter(formattedTime);

    return filteredTime;
  }

  updateClock() {
    const {realTime, formattedString} = this.state;
    const {onChange} = this.props;
    let now;

    if (realTime) {
      now = moment();
    } else {
      const {baseTime, startTime} = this.state;
      const newTime = moment();
      const diff = newTime.diff(startTime, BASE_UNIT);

      now = baseTime.clone().add(diff, BASE_UNIT);
    }

    const formattedTime = this.formatTime(now);

    if (formattedTime !== formattedString) {
      onChange({
        moment: now,
        output: formattedTime,
        previousOutput: formattedString
      });
    }

    this.setState({
      now,
      formattedString: formattedTime
    });
  }

  render() {
    const {formattedString} = this.state;

    const childProps = Object.keys(this.props)
      .filter(key => !['date', 'interval', 'ticking', 'filter', 'format', 'timezone'].includes(key))
      .reduce((acc, key) => {
        acc[key] = this.props[key];
        return acc;
      }, {});

    return (
      <time {...childProps}>{ formattedString }</time>
    );
  }
}

ReactLiveClock.propTypes = {
  children: PropTypes.string,
  date: PropTypes.oneOfType([
    PropTypes.number,
    PropTypes.string
  ]),
  format: PropTypes.string,
  interval: PropTypes.number,
  ticking: PropTypes.bool,
  timezone: PropTypes.string,
  filter: PropTypes.func,
  onChange: PropTypes.func
};

ReactLiveClock.defaultProps = {
  date: null,
  format: 'HH:mm',
  interval: 1000,
  ticking: false,
  timezone: null,
  filter: date => date,
  onChange: date => date
};
<commit_msg>Wrong word correction (#33)<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import moment from 'moment-timezone';

const BASE_UNIT = 'milliseconds';

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

    const date = props.date || props.children || null;
    const timestamp = moment();
    const baseTime = date ? moment(new Date(date).getTime()) : timestamp;

    this.state = {
      realTime: !date,
      now: baseTime,
      baseTime,
      startTime: timestamp,
      formattedString: ''
    };
  }

  componentDidMount() {
    const {ticking, interval} = this.props;

    if (ticking && interval) {
      this.tickTimer = setInterval(() => {
        this.updateClock();
      }, interval);
    }
  }

  componentWillUnmount() {
    if (this.tickTimer) {
      clearInterval(this.tickTimer);
    }
  }

  formatTime(time) {
    const {filter, format, timezone} = this.props;

    if (timezone) {
      time.tz(timezone);
    }

    const formattedTime = time.format(format);
    const filteredTime = filter(formattedTime);

    return filteredTime;
  }

  updateClock() {
    const {realTime, formattedString} = this.state;
    const {onChange} = this.props;
    let now;

    if (realTime) {
      now = moment();
    } else {
      const {baseTime, startTime} = this.state;
      const newTime = moment();
      const diff = newTime.diff(startTime, BASE_UNIT);

      now = baseTime.clone().add(diff, BASE_UNIT);
    }

    const formattedTime = this.formatTime(now);

    if (formattedTime !== formattedString) {
      onChange({
        moment: now,
        output: formattedTime,
        previousOutput: formattedString
      });
    }

    this.setState({
      now,
      formattedString: formattedTime
    });
  }

  render() {
    const {formattedString} = this.state;

    const childProps = Object.keys(this.props)
      .filter(key => !['date', 'interval', 'ticking', 'filter', 'format', 'timezone'].includes(key))
      .reduce((acc, key) => {
        acc[key] = this.props[key];
        return acc;
      }, {});

    return (
      <time {...childProps}>{ formattedString }</time>
    );
  }
}

ReactLiveClock.propTypes = {
  children: PropTypes.string,
  date: PropTypes.oneOfType([
    PropTypes.number,
    PropTypes.string
  ]),
  format: PropTypes.string,
  interval: PropTypes.number,
  ticking: PropTypes.bool,
  timezone: PropTypes.string,
  filter: PropTypes.func,
  onChange: PropTypes.func
};

ReactLiveClock.defaultProps = {
  date: null,
  format: 'HH:mm',
  interval: 1000,
  ticking: false,
  timezone: null,
  filter: date => date,
  onChange: date => date
};
<|endoftext|>


<commit_before>var DateRange = (function() {
  return function(clock) {
    var startDate, endDate, period = "WEEK";

    updateRange(clock.currentDate());

    return {
      startDate: function() {
        return startDate;
      },
      endDate: function() {
        return endDate;
      },
      useMonth: function() {
        period = "MONTH";
        updateRange(clock.currentDate());
      },
      useYear: function() {
        period = "YEAR";
        updateRange(clock.currentDate());
      }
    };

    function updateRange(currentDate) {
      if(usingWeekPeriod()) {
        startDate = monday(currentDate).toDate();
        endDate = sunday(currentDate).toDate();
      } else if(usingMonthPeriod()) {
        startDate = firstDayOfMonth(currentDate).toDate();
        endDate = lastDayOfMonth(currentDate).toDate();
      } else {
        startDate = firstDayOfYear(currentDate).toDate();
        endDate = lastDayOfYear(currentDate).toDate();
      }
    }

    function usingWeekPeriod() {
      return period === "WEEK";
    }

    function usingMonthPeriod() {
      return period === "MONTH";
    }

    function monday(date) {
      return moment(date).day("Monday");
    }

    function sunday(date) {
      return monday(date).add(6, "days");
    }

    function firstDayOfMonth(date) {
      return moment(date).date(1);
    }

    function lastDayOfMonth(date) {
      var daysInMonth = moment(date).daysInMonth();
      return firstDayOfMonth(date).add(daysInMonth - 1, "days");
    }

    function firstDayOfYear(date) {
      return moment(date).dayOfYear(1);
    }

    function lastDayOfYear(date) {
      return firstDayOfYear(date).add(1,"years").add(-1, "days");
    }
  };
})();<commit_msg>Created a setter for date range so that use of toDate is hidden there<commit_after>var DateRange = (function() {
  return function(clock) {
    var startDate, endDate, period = "WEEK";

    updateRange(clock.currentDate());

    return {
      startDate: function() {
        return startDate;
      },
      endDate: function() {
        return endDate;
      },
      useMonth: function() {
        period = "MONTH";
        updateRange(clock.currentDate());
      },
      useYear: function() {
        period = "YEAR";
        updateRange(clock.currentDate());
      }
    };

    function updateRange(currentDate) {
      if(usingWeekPeriod()) {
        setRange(monday(currentDate), sunday(currentDate));
      } else if(usingMonthPeriod()) {
        setRange(firstDayOfMonth(currentDate), lastDayOfMonth(currentDate));
      } else {
        setRange(firstDayOfYear(currentDate), lastDayOfYear(currentDate));
      }
    }

    function setRange(newStartDate, newEndDate) {
      startDate = newStartDate.toDate();
      endDate = newEndDate.toDate();
    }

    function usingWeekPeriod() {
      return period === "WEEK";
    }

    function usingMonthPeriod() {
      return period === "MONTH";
    }

    function monday(date) {
      return moment(date).day("Monday");
    }

    function sunday(date) {
      return monday(date).add(6, "days");
    }

    function firstDayOfMonth(date) {
      return moment(date).date(1);
    }

    function lastDayOfMonth(date) {
      var daysInMonth = moment(date).daysInMonth();
      return firstDayOfMonth(date).add(daysInMonth - 1, "days");
    }

    function firstDayOfYear(date) {
      return moment(date).dayOfYear(1);
    }

    function lastDayOfYear(date) {
      return firstDayOfYear(date).add(1,"years").add(-1, "days");
    }
  };
})();<|endoftext|>


<commit_before>var appModuleExists = require('./../../utils').appModuleExists;
var removeGitkeep = require('./../../utils').removeGitkeep;

module.exports = plop => {
    plop.setGenerator('component', {
        description: 'Create new shared component.',
        prompts: [
            {
                type: 'list',
                name: 'type',
                default: 'Stateless',
                message: 'Select the type of component?',
                choices: () => ['Stateless', 'React.PureComponent', 'React.Component', 'Styled.Component'],
            },
            {
                type: 'input',
                name: 'name',
                message: 'Component name',
                validate: value => {
                    if (/.+/.test(value)) {
                        return appModuleExists(value) ? 'A component or container with this name already exists' : true;
                    }

                    return 'The name is required';
                },
            },
        ],
        actions: function(data) {
            var actions = [
                {
                    type: 'add',
                    path: './../../src/app/components/__tests__/{{pascalCase name}}.test.tsx',
                    templateFile: 'component/component.test.tsx.tpl',
                },
            ];

            switch (data.type) {
                case 'Stateless':
                    var component = {
                        type: 'add',
                        path: './../../src/app/components/{{pascalCase name}}.tsx',
                        templateFile: 'component/sfcComponent.tsx.tpl',
                    };
                    actions = actions.concat(component);
                    break;
                case 'React.PureComponent':
                    var component = {
                        type: 'add',
                        path: './../../src/app/components/{{pascalCase name}}.tsx',
                        templateFile: 'component/pureComponent.tsx.tpl',
                    };
                    actions = actions.concat(component);
                    break;
                case 'React.Component':
                    var component = {
                        type: 'add',
                        path: './../../src/app/components/{{pascalCase name}}.tsx',
                        templateFile: 'component/component.tsx.tpl',
                    };
                    actions = actions.concat(component);
                    break;
                case 'Styled.Component':
                    var component = {
                        type: 'add',
                        path: './../../src/app/components/{{pascalCase name}}.tsx',
                        templateFile: 'component/styledComponent.tsx.tpl',
                    };

                    actions = actions.concat(component);
                    break;
                default:
                    break;
            }

            removeGitkeep('components')
            return actions;
        },
    });
};
<commit_msg>feat(parent): adding parent folder prompt<commit_after>var utils = require('./../../utils');
var appModuleExists = utils.appModuleExists;
var componentModuleExists = utils.componentModuleExists;
var removeGitkeep = require('./../../utils').removeGitkeep;

module.exports = plop => {
    plop.setGenerator('component', {
        description: 'Create new shared component.',
        prompts: [
            {
                type: 'list',
                name: 'type',
                default: 'Stateless',
                message: 'Select the type of component?',
                choices: () => ['Stateless', 'React.PureComponent', 'React.Component', 'Styled.Component'],
            },
            {
                type: 'input',
                name: 'parent',
                message: 'Parent folder (leave blank if none):'
            },
            {
                type: 'input',
                name: 'name',
                message: 'Component name',
                validate: value => {
                    if (/.+/.test(value)) {
                        console.log(value);
                        return appModuleExists(value) ? 'A component with this name already exists' : true;
                    }

                    return 'The name is required';
                },
            },
        ],
        actions: function(data) {
            var folderPath = './../../src/app/components/{{pascalCase name}}';
            const componentPath = folderPath + '{{pascalCase name}}.tsx';

            var actions = [
                {
                    type: 'add',
                    path: './../../src/app/components/__tests__/{{pascalCase name}}.test.tsx',
                    templateFile: 'component/component.test.tsx.tpl',
                },
            ];

            switch (data.type) {
                case 'Stateless':
                    var component = {
                        type: 'add',
                        path: componentPath,
                        templateFile: 'component/sfcComponent.tsx.tpl',
                    };
                    actions = actions.concat(component);
                    break;
                case 'React.PureComponent':
                    var component = {
                        type: 'add',
                        path: componentPath,
                        templateFile: 'component/pureComponent.tsx.tpl',
                    };
                    actions = actions.concat(component);
                    break;
                case 'React.Component':
                    var component = {
                        type: 'add',
                        path: componentPath,
                        templateFile: 'component/component.tsx.tpl',
                    };
                    actions = actions.concat(component);
                    break;
                case 'Styled.Component':
                    var component = {
                        type: 'add',
                        path: componentPath,
                        templateFile: 'component/styledComponent.tsx.tpl',
                    };

                    actions = actions.concat(component);
                    break;
                default:
                    break;
            }

            removeGitkeep('components');
            return actions;
        },
    });
};
<|endoftext|>


<commit_before>let $ = IMPORT_JQUERY ? require('jquery') : window.jQuery;
import FilterControls from './FilterControls';
import FilterContainer from './FilterContainer';
import Positions from './Positions';
import DefaultOptions from './DefaultOptions';
import {
  FILTERIZR_STATE,
  allStringsOfArray1InArray2,
  checkOptionForErrors,
  cssEasingValuesRegexp,
  debounce,
  filterItemArraysHaveSameSorting,
  intersection,
  merge,
  shuffle,
  sortBy,
  stringInArray,
} from './utils';

class Filterizr {
  constructor(selector = '.filtr-container', userOptions) {
    // Make the options a property of the Filterizr instance
    // so that we can later easily modify/update them.
    this.options = merge(DefaultOptions, userOptions);

    // Try to find and instantiate the FilterContainer
    const filterContainer = new FilterContainer(selector, this.options);

    if (!filterContainer.$node.length) {
      // Throw because the selector given was not
      // found to initialize a FilterContainer.
      throw new Error(`Filterizr: could not find a container with the selector ${selector}, to initialize Filterizr.`);
    }

    // Setup FilterControls
    new FilterControls(this, this.options.controlsSelector);

    // define props
    this.props = {
      filterizrState: FILTERIZR_STATE.IDLE,
      searchTerm: '',
      sort: 'index',
      sortOrder: 'asc',
      FilterContainer: filterContainer,
      FilterItems: filterContainer.props.FilterItems,
      FilteredItems: [],
    };

    // set up events needed by Filterizr
    this.bindEvents();

    // Init Filterizr
    this.filter(this.options.filter);
  }

  /**
   * Public API of Filterizr
   */

  /**
   * Filters the items in the grid by a category
   * @param {String} category by which to filter
   */
  filter(category) {
    const {
      searchTerm,
      FilterContainer,
      FilterItems,
    } = this.props;

    // Trigger filteringStart event
    FilterContainer.trigger('filteringStart');

    // Set animation state to trigger callbacks
    this.props.filterizrState = FILTERIZR_STATE.FILTERING;

    // Cast category to string or array of strings
    category = Array.isArray(category)
      ? category.map(c => c.toString())
      : category.toString();

    // Filter items and optionally apply search if a search term exists
    const FilteredItems = this.searchFilterItems(
      this.filterFilterItems(FilterItems, category),
      searchTerm
    );

    // Update props
    this.props.FilteredItems = FilteredItems;

    // Render the items
    this.render(FilteredItems);
  }

  /**
   * Destroys the Filterizr instance and unbinds all events.
   */
  destroy() {
    const { FilterContainer } = this.props;
    const { controlsSelector } = this.options;
    // Unbind all events of FilterContainer and Filterizr
    // and remove inline styles.
    FilterContainer.destroy();
    $(window).off('resize.Filterizr');
    // Destroy all controls of the instance
    $(`${controlsSelector}[data-filter]`).off('click.Filterizr');
    $(`${controlsSelector}[data-multifilter]`).off('click.Filterizr');
    $(`${controlsSelector}[data-shuffle]`).off('click.Filterizr');
    $(`${controlsSelector}[data-search]`).off('keyup.Filterizr');
    $(`${controlsSelector}[data-sortAsc]`).off('click.Filterizr');
    $(`${controlsSelector}[data-sortDesc]`).off('click.Filterizr');
  }

  /**
   * Inserts a new FilterItem in the Filterizr grid
   * @param {Object} $node the jQuery of the HTML item to append
   */
  insertItem($node) {
    const { FilterContainer } = this.props;
    // Add the item to the FilterContainer
    const $nodeModified = $node.clone().attr('style', '');
    FilterContainer.push($nodeModified, this.options);
    // Retrigger filter for new item to assume position in the grid
    const FilteredItems = this.filterFilterItems(this.props.FilterItems, this.options.filter);
    this.render(FilteredItems);
  }

  /**
   * Sorts the FilterItems in the grid
   * @param {String} sortAttr the attribute by which to perform the sort
   * @param {String} sortOrder ascending or descending
   */
  sort(sortAttr = 'index', sortOrder = 'asc') {
    const {
      FilterContainer,
      FilterItems,
    } = this.props;

    // Trigger filteringStart event
    FilterContainer.trigger('sortingStart');

    // Set animation state to trigger callbacks
    this.props.filterizrState = FILTERIZR_STATE.SORTING;

    // sort main array
    this.props.FilterItems = this.sortFilterItems(FilterItems, sortAttr, sortOrder);

    // apply filters
    const FilteredItems = this.filterFilterItems(this.props.FilterItems, this.options.filter);
    this.props.FilteredItems = FilteredItems;

    // Update and render the sorted items
    this.render(FilteredItems);
  }

  /**
   * Searches through the FilterItems for a given string and adds an additional filter layer.
   * @param {String} searchTerm the term for which to search
   */
  search(searchTerm = this.props.searchTerm) {
    const { FilterItems } = this.props;

    // filter items and optionally apply search if a search term exists
    const FilteredItems = this.searchFilterItems(this.filterFilterItems(FilterItems, this.options.filter), searchTerm);
    this.props.FilteredItems = FilteredItems;

    // render the items
    this.render(FilteredItems);
  }

  /**
   * Shuffles the FilterItems in the grid, making sure their positions have changed.
   */
  shuffle() {
    const {
      FilterContainer,
      FilteredItems,
    } = this.props;

    // Trigger filteringStart event
    FilterContainer.trigger('shufflingStart');

    // Set animation state to trigger callbacks
    this.props.filterizrState = FILTERIZR_STATE.SHUFFLING;

    const ShuffledItems = this.shuffleFilterItems(FilteredItems);
    this.props.FilteredItems = ShuffledItems;

    this.render(ShuffledItems);
  }

  /**
   * Updates the perferences of the users for rendering the Filterizr grid,
   * additionally performs error checking on the new options passed.
   * @param {Object} newOptions to override the defaults.
   */
  setOptions(newOptions) {
    // error checking
    checkOptionForErrors('animationDuration', newOptions.animationDuration, 'number');
    checkOptionForErrors('callbacks', newOptions.callbacks, 'object');
    checkOptionForErrors('controlsSelector', newOptions.controlsSelector, 'string');
    checkOptionForErrors('delay', newOptions.delay, 'number');
    checkOptionForErrors(
      'easing',
      newOptions.easing,
      'string',
      cssEasingValuesRegexp,
      'https://www.w3schools.com/cssref/css3_pr_transition-timing-function.asp'
    );
    checkOptionForErrors(
      'delayMode',
      newOptions.delayMode,
      'string',
      ['progressive', 'alternate']
    );
    checkOptionForErrors('filter', newOptions.filter, 'string|number|array');
    checkOptionForErrors('filterOutCss', newOptions.filterOutCss, 'object');
    checkOptionForErrors('filterInCss', newOptions.filterOutCss, 'object');
    checkOptionForErrors(
      'layout',
      newOptions.layout,
      'string',
      ['sameSize', 'vertical', 'horizontal', 'sameHeight', 'sameWidth', 'packed']
    );
    checkOptionForErrors(
      'multifilterLogicalOperator',
      newOptions.multifilterLogicalOperator,
      'string',
      ['and', 'or']
    );
    checkOptionForErrors('setupControls', newOptions.setupControls, 'boolean');

    // Merge options
    this.options = merge(this.options, newOptions);

    // If one of the options that updates the transition properties
    // of the .filtr-item elements is set, call the update method
    if (newOptions.animationDuration || newOptions.delay || newOptions.delayMode || newOptions.easing) {
      this.props.FilterContainer.updateFilterItemsTransitionStyle(
        newOptions.animationDuration,
        newOptions.easing,
        newOptions.delay,
        newOptions.delayMode
      );
    }

    // If inside the new options the callbacks object has been defined
    // then the FilterContainer events need to be reset.
    // Same if the animationDuration is defined as it is a parameter to
    // the debounce wrapper of the transitionEnd callback.
    if (newOptions.callbacks || newOptions.animationDuration) {
      this.rebindFilterContainerEvents();
    }

    // If the filter is explicitly set in the new options object, trigger a refiltering.
    if (newOptions.filter) {
      this.filter(newOptions.filter);
    }

    // If the multifilterLogicalOperator has been defined and its
    // value changed then a refilter should be trigger.
    if (newOptions.multifilterLogicalOperator) {
      this.filter(this.options.filter);
    }
  }

  /**
   * Performs multifiltering with AND/OR logic.
   * @param {String} toggledFilter the filter to toggle
   */
  toggleFilter(toggledFilter) {
    let activeFilters = this.options.filter;

    if (activeFilters === 'all') {
      // If set to all then just set to new category
      activeFilters = toggledFilter;
    } else {
      if (Array.isArray(activeFilters)) {
        // If the activeFilters are an array
        if (stringInArray(activeFilters, toggledFilter)) {
          // Check if the toggledFilter is in the array and remove it
          activeFilters = activeFilters.filter(f => f !== toggledFilter);
          // In case there is only 1 item now left in the array, flatten it
          if (activeFilters.length === 1) activeFilters = activeFilters[0];
        } else {
          // If the item is not in the array then simply push it
          activeFilters.push(toggledFilter);
        }
      } else {
        activeFilters = activeFilters === toggledFilter
          ? 'all' // If the activeFilters === toggledFilter revert to 'all'
          : [activeFilters, toggledFilter]; // Otherwise start array
      }
    }

    // Update active filter in Filterizr's options
    this.options.filter = activeFilters;

    // Trigger filter
    this.filter(this.options.filter);
  }

  // Helper methods
  filterFilterItems(FilterItems, filters) {
    const { multifilterLogicalOperator } = this.options;
    // Get filtered items
    const FilteredItems = (filters === 'all') ?
      // in this case return all items
      FilterItems :
      // otherwise return filtered array
      FilterItems.filter(FilterItem => {
        const categories = FilterItem.getCategories();
        const multiFilteringEnabled = Array.isArray(filters);
        if (multiFilteringEnabled) {
          if (multifilterLogicalOperator === 'or') {
            return intersection(categories, filters).length;
          } else {
            return allStringsOfArray1InArray2(filters, categories);
          }
        } else {
          return stringInArray(categories, filters);
        }
      });

    return FilteredItems;
  }

  sortFilterItems(FilterItems ,sortAttr = 'index', sortOrder = 'asc') {
    // Sort the FilterItems and reverse the array if order is descending
    let SortedItems = sortBy(FilterItems, (FilterItem) => {
      return (sortAttr !== 'index' && sortAttr !== 'sortData') ?
        // if the user has not used one of the two default sort attributes
        // then search for custom data attributes on the filter items to sort
        FilterItem.props.data[sortAttr] :
        // otherwise use the defaults
        FilterItem.props[sortAttr];
    });

    // Return the sorted items with correct order
    return sortOrder === 'asc'
      ? SortedItems
      : SortedItems.reverse();
  }

  searchFilterItems(FilterItems, searchTerm = this.props.searchTerm) {
    if (!searchTerm) return FilterItems; // exit case when no search is applied

    const SoughtItems = FilterItems.filter(FilterItem => FilterItem.contentsMatchSearch(searchTerm));

    return SoughtItems;
  }

  shuffleFilterItems(FilterItems) {
    let ShuffledItems = shuffle(FilterItems);
    // shuffle items until they are different from the initial FilteredItems
    while (FilterItems.length > 1 && filterItemArraysHaveSameSorting(FilterItems, ShuffledItems)) {
      ShuffledItems = shuffle(FilterItems);
    }

    return ShuffledItems;
  }

  render(FilterItems) {
    const {
      filter,
      filterInCss,
      filterOutCss,
      layout,
      multifilterLogicalOperator,
    } = this.options;

    // Get items to be filtered out
    const FilteredOutItems = this.props.FilterItems.filter(FilterItem => {
      const categories = FilterItem.getCategories();
      const multiFilteringEnabled = Array.isArray(filter);
      // Flags that determine whether item should be filtered out
      let filtersMatch;
      const contentsMatchSearch = FilterItem.contentsMatchSearch(this.props.searchTerm);

      if (multiFilteringEnabled) {
        filtersMatch = multifilterLogicalOperator === 'or'
          ? intersection(categories, filter).length
          : allStringsOfArray1InArray2(filter, categories);
      } else {
        filtersMatch = stringInArray(categories, filter);
      }

      return !filtersMatch || !contentsMatchSearch;
    });
    // filter out old items
    FilteredOutItems.forEach(FilterItem => {
      FilterItem.filterOut(filterOutCss);
    });

    // Determine target positions for items to be filtered in
    const PositionsArray = Positions(layout, this);

    // filter in new items
    FilterItems.forEach((FilterItem, index) => {
      FilterItem.filterIn(PositionsArray[index], filterInCss);
    });
  }

  onTransitionEndCallback() {
    const {
      filterizrState,
      FilterContainer,
    } = this.props;

    switch(filterizrState) {
      case FILTERIZR_STATE.FILTERING:
        FilterContainer.trigger('filteringEnd');
        break;
      case FILTERIZR_STATE.SORTING:
        FilterContainer.trigger('sortingEnd');
        break;
      case FILTERIZR_STATE.SHUFFLING:
        FilterContainer.trigger('shufflingEnd');
        break;
    }

    // Reset filterizrState to idle
    this.props.filterizrState = FILTERIZR_STATE.IDLE;
  }

  rebindFilterContainerEvents() {
    const { FilterContainer } = this.props;
    const {
      animationDuration,
      callbacks,
    } = this.options;
    // cancel existing evts
    FilterContainer.unbindEvents();
    // rebind evts
    FilterContainer.bindEvents(callbacks);
    FilterContainer.bindTransitionEnd(() => { this.onTransitionEndCallback(); }, animationDuration);
  }

  bindEvents() {
    const { FilterContainer } = this.props;
    //- FilterContainer events
    this.rebindFilterContainerEvents();
    //- Generic Filterizr events
    // set up a window resize event to fire refiltering
    $(window).on('resize.Filterizr', debounce(() => {
      // update dimensions of items based on new window size
      FilterContainer.updateWidth();
      FilterContainer.updateFilterItemsDimensions();
      // refilter the grid to assume new positions
      this.filter(this.options.filter);
    }, 250));
  }
}

export default Filterizr;
<commit_msg>Clean up code<commit_after>let $ = IMPORT_JQUERY ? require('jquery') : window.jQuery;
import FilterControls from './FilterControls';
import FilterContainer from './FilterContainer';
import Positions from './Positions';
import DefaultOptions from './DefaultOptions';
import {
  FILTERIZR_STATE,
  allStringsOfArray1InArray2,
  checkOptionForErrors,
  cssEasingValuesRegexp,
  debounce,
  filterItemArraysHaveSameSorting,
  intersection,
  merge,
  shuffle,
  sortBy,
  stringInArray,
} from './utils';

class Filterizr {
  constructor(selector = '.filtr-container', userOptions) {
    // Make the options a property of the Filterizr instance
    // so that we can later easily modify/update them.
    this.options = merge(DefaultOptions, userOptions);

    // Try to find and instantiate the FilterContainer
    const filterContainer = new FilterContainer(selector, this.options);

    if (!filterContainer.$node.length) {
      // Throw because the selector given was not
      // found to initialize a FilterContainer.
      throw new Error(`Filterizr: could not find a container with the selector ${selector}, to initialize Filterizr.`);
    }

    // Setup FilterControls
    new FilterControls(this, this.options.controlsSelector);

    // define props
    this.props = {
      filterizrState: FILTERIZR_STATE.IDLE,
      searchTerm: '',
      sort: 'index',
      sortOrder: 'asc',
      FilterContainer: filterContainer,
      FilterItems: filterContainer.props.FilterItems,
      FilteredItems: [],
    };

    // set up events needed by Filterizr
    this.bindEvents();

    // Init Filterizr
    this.filter(this.options.filter);
  }

  /**
   * Public API of Filterizr
   */

  /**
   * Filters the items in the grid by a category
   * @param {String} category by which to filter
   */
  filter(category) {
    const {
      searchTerm,
      FilterContainer,
      FilterItems,
    } = this.props;

    // Trigger filteringStart event
    FilterContainer.trigger('filteringStart');

    // Set animation state to trigger callbacks
    this.props.filterizrState = FILTERIZR_STATE.FILTERING;

    // Cast category to string or array of strings
    category = Array.isArray(category)
      ? category.map(c => c.toString())
      : category.toString();

    // Filter items and optionally apply search if a search term exists
    const FilteredItems = this.searchFilterItems(
      this.filterFilterItems(FilterItems, category),
      searchTerm
    );

    // Update props
    this.props.FilteredItems = FilteredItems;

    // Render the items
    this.render(FilteredItems);
  }

  /**
   * Destroys the Filterizr instance and unbinds all events.
   */
  destroy() {
    const { FilterContainer } = this.props;
    const { controlsSelector } = this.options;

    // Unbind all events of FilterContainer and Filterizr
    // and remove inline styles.
    FilterContainer.destroy();
    $(window).off('resize.Filterizr');

    // Destroy all controls of the instance
    $(`${controlsSelector}[data-filter]`).off('click.Filterizr');
    $(`${controlsSelector}[data-multifilter]`).off('click.Filterizr');
    $(`${controlsSelector}[data-shuffle]`).off('click.Filterizr');
    $(`${controlsSelector}[data-search]`).off('keyup.Filterizr');
    $(`${controlsSelector}[data-sortAsc]`).off('click.Filterizr');
    $(`${controlsSelector}[data-sortDesc]`).off('click.Filterizr');
  }

  /**
   * Inserts a new FilterItem in the Filterizr grid
   * @param {Object} $node the jQuery of the HTML item to append
   */
  insertItem($node) {
    const { FilterContainer } = this.props;

    // Add the item to the FilterContainer
    const $nodeModified = $node.clone().attr('style', '');

    FilterContainer.push($nodeModified, this.options);

    // Retrigger filter for new item to assume position in the grid
    const FilteredItems = this.filterFilterItems(this.props.FilterItems, this.options.filter);

    this.render(FilteredItems);
  }

  /**
   * Sorts the FilterItems in the grid
   * @param {String} sortAttr the attribute by which to perform the sort
   * @param {String} sortOrder ascending or descending
   */
  sort(sortAttr = 'index', sortOrder = 'asc') {
    const {
      FilterContainer,
      FilterItems,
    } = this.props;

    // Trigger filteringStart event
    FilterContainer.trigger('sortingStart');

    // Set animation state to trigger callbacks
    this.props.filterizrState = FILTERIZR_STATE.SORTING;

    // sort main array
    this.props.FilterItems = this.sortFilterItems(FilterItems, sortAttr, sortOrder);

    // apply filters
    const FilteredItems = this.filterFilterItems(this.props.FilterItems, this.options.filter);

    this.props.FilteredItems = FilteredItems;

    // Update and render the sorted items
    this.render(FilteredItems);
  }

  /**
   * Searches through the FilterItems for a given string and adds an additional filter layer.
   * @param {String} searchTerm the term for which to search
   */
  search(searchTerm = this.props.searchTerm) {
    const { FilterItems } = this.props;

    // Filter items and optionally apply search if a search term exists
    const FilteredItems = this.searchFilterItems(this.filterFilterItems(FilterItems, this.options.filter), searchTerm);

    this.props.FilteredItems = FilteredItems;

    // Render the items
    this.render(FilteredItems);
  }

  /**
   * Shuffles the FilterItems in the grid, making sure their positions have changed.
   */
  shuffle() {
    const {
      FilterContainer,
      FilteredItems,
    } = this.props;

    // Trigger filteringStart event
    FilterContainer.trigger('shufflingStart');

    // Set animation state to trigger callbacks
    this.props.filterizrState = FILTERIZR_STATE.SHUFFLING;

    // Generate array of shuffled items
    const ShuffledItems = this.shuffleFilterItems(FilteredItems);

    // Update the FilteredItems to equal the array of the shuffled items
    this.props.FilteredItems = ShuffledItems;

    // Render the items after shuffling
    this.render(ShuffledItems);
  }

  /**
   * Updates the perferences of the users for rendering the Filterizr grid,
   * additionally performs error checking on the new options passed.
   * @param {Object} newOptions to override the defaults.
   */
  setOptions(newOptions) {
    // error checking
    checkOptionForErrors('animationDuration', newOptions.animationDuration, 'number');
    checkOptionForErrors('callbacks', newOptions.callbacks, 'object');
    checkOptionForErrors('controlsSelector', newOptions.controlsSelector, 'string');
    checkOptionForErrors('delay', newOptions.delay, 'number');
    checkOptionForErrors(
      'easing',
      newOptions.easing,
      'string',
      cssEasingValuesRegexp,
      'https://www.w3schools.com/cssref/css3_pr_transition-timing-function.asp'
    );
    checkOptionForErrors(
      'delayMode',
      newOptions.delayMode,
      'string',
      ['progressive', 'alternate']
    );
    checkOptionForErrors('filter', newOptions.filter, 'string|number|array');
    checkOptionForErrors('filterOutCss', newOptions.filterOutCss, 'object');
    checkOptionForErrors('filterInCss', newOptions.filterOutCss, 'object');
    checkOptionForErrors(
      'layout',
      newOptions.layout,
      'string',
      ['sameSize', 'vertical', 'horizontal', 'sameHeight', 'sameWidth', 'packed']
    );
    checkOptionForErrors(
      'multifilterLogicalOperator',
      newOptions.multifilterLogicalOperator,
      'string',
      ['and', 'or']
    );
    checkOptionForErrors('setupControls', newOptions.setupControls, 'boolean');

    // Merge options
    this.options = merge(this.options, newOptions);

    // If one of the options that updates the transition properties
    // of the .filtr-item elements is set, call the update method
    if (newOptions.animationDuration || newOptions.delay || newOptions.delayMode || newOptions.easing) {
      this.props.FilterContainer.updateFilterItemsTransitionStyle(
        newOptions.animationDuration,
        newOptions.easing,
        newOptions.delay,
        newOptions.delayMode
      );
    }

    // If inside the new options the callbacks object has been defined
    // then the FilterContainer events need to be reset.
    // Same if the animationDuration is defined as it is a parameter to
    // the debounce wrapper of the transitionEnd callback.
    if (newOptions.callbacks || newOptions.animationDuration) {
      this.rebindFilterContainerEvents();
    }

    // If the filter is explicitly set in the new options object, trigger a refiltering.
    if (newOptions.filter) {
      this.filter(newOptions.filter);
    }

    // If the multifilterLogicalOperator has been defined and its
    // value changed then a refilter should be trigger.
    if (newOptions.multifilterLogicalOperator) {
      this.filter(this.options.filter);
    }
  }

  /**
   * Performs multifiltering with AND/OR logic.
   * @param {String} toggledFilter the filter to toggle
   */
  toggleFilter(toggledFilter) {
    let activeFilters = this.options.filter;

    if (activeFilters === 'all') {
      // If set to all then just set to new category
      activeFilters = toggledFilter;
    } else {
      if (Array.isArray(activeFilters)) {
        // If the activeFilters are an array
        if (stringInArray(activeFilters, toggledFilter)) {
          // Check if the toggledFilter is in the array and remove it
          activeFilters = activeFilters.filter(f => f !== toggledFilter);
          // In case there is only 1 item now left in the array, flatten it
          if (activeFilters.length === 1) activeFilters = activeFilters[0];
        } else {
          // If the item is not in the array then simply push it
          activeFilters.push(toggledFilter);
        }
      } else {
        activeFilters = activeFilters === toggledFilter
          ? 'all' // If the activeFilters === toggledFilter revert to 'all'
          : [activeFilters, toggledFilter]; // Otherwise start array
      }
    }

    // Update active filter in Filterizr's options
    this.options.filter = activeFilters;

    // Trigger a refilter
    this.filter(this.options.filter);
  }

  // Helper methods
  filterFilterItems(FilterItems, filters) {
    const { multifilterLogicalOperator } = this.options;

    // Get filtered items
    const FilteredItems = (filters === 'all')
      ? FilterItems // Return all items
      : FilterItems.filter(FilterItem => { // Return filtered array
        const categories = FilterItem.getCategories();
        const multiFilteringEnabled = Array.isArray(filters);
        if (multiFilteringEnabled) {
          return multifilterLogicalOperator === 'or'
          ? intersection(categories, filters).length
          : allStringsOfArray1InArray2(filters, categories);
        }
        return stringInArray(categories, filters);
      });

    return FilteredItems;
  }

  sortFilterItems(FilterItems ,sortAttr = 'index', sortOrder = 'asc') {
    // Sort the FilterItems and reverse the array if order is descending
    let SortedItems = sortBy(FilterItems, (FilterItem) => {
      return (sortAttr !== 'index' && sortAttr !== 'sortData')
        ? FilterItem.props.data[sortAttr] // Search for custom data attrs to sort
        : FilterItem.props[sortAttr]; // Otherwise use defaults
    });

    // Return the sorted items with correct order
    return sortOrder === 'asc'
      ? SortedItems
      : SortedItems.reverse();
  }

  searchFilterItems(FilterItems, searchTerm = this.props.searchTerm) {
    if (!searchTerm) return FilterItems; // exit case when no search is applied

    const SoughtItems = FilterItems.filter(FilterItem => FilterItem.contentsMatchSearch(searchTerm));

    return SoughtItems;
  }

  shuffleFilterItems(FilterItems) {
    let ShuffledItems = shuffle(FilterItems);

    // Shuffle items until they are different from the initial FilteredItems
    while (FilterItems.length > 1 && filterItemArraysHaveSameSorting(FilterItems, ShuffledItems)) {
      ShuffledItems = shuffle(FilterItems);
    }

    return ShuffledItems;
  }

  render(FilterItems) {
    const {
      filter,
      filterInCss,
      filterOutCss,
      layout,
      multifilterLogicalOperator,
    } = this.options;

    // Get items to be filtered out
    const FilteredOutItems = this.props.FilterItems.filter(FilterItem => {
      const categories = FilterItem.getCategories();
      const multiFilteringEnabled = Array.isArray(filter);
      // Flags that determine whether item should be filtered out
      let filtersMatch;
      const contentsMatchSearch = FilterItem.contentsMatchSearch(this.props.searchTerm);

      if (multiFilteringEnabled) {
        filtersMatch = multifilterLogicalOperator === 'or'
          ? intersection(categories, filter).length
          : allStringsOfArray1InArray2(filter, categories);
      } else {
        filtersMatch = stringInArray(categories, filter);
      }

      return !filtersMatch || !contentsMatchSearch;
    });
    // filter out old items
    FilteredOutItems.forEach(FilterItem => {
      FilterItem.filterOut(filterOutCss);
    });

    // Determine target positions for items to be filtered in
    const PositionsArray = Positions(layout, this);

    // filter in new items
    FilterItems.forEach((FilterItem, index) => {
      FilterItem.filterIn(PositionsArray[index], filterInCss);
    });
  }

  onTransitionEndCallback() {
    const {
      filterizrState,
      FilterContainer,
    } = this.props;

    switch(filterizrState) {
      case FILTERIZR_STATE.FILTERING:
        FilterContainer.trigger('filteringEnd');
        break;
      case FILTERIZR_STATE.SORTING:
        FilterContainer.trigger('sortingEnd');
        break;
      case FILTERIZR_STATE.SHUFFLING:
        FilterContainer.trigger('shufflingEnd');
        break;
    }

    // Reset filterizrState to idle
    this.props.filterizrState = FILTERIZR_STATE.IDLE;
  }

  rebindFilterContainerEvents() {
    const { FilterContainer } = this.props;
    const {
      animationDuration,
      callbacks,
    } = this.options;

    // cancel existing evts
    FilterContainer.unbindEvents();

    // Rebind evts
    FilterContainer.bindEvents(callbacks);
    FilterContainer.bindTransitionEnd(() => { this.onTransitionEndCallback(); }, animationDuration);
  }

  bindEvents() {
    const { FilterContainer } = this.props;

    //- FilterContainer events
    this.rebindFilterContainerEvents();

    //- Generic Filterizr events
    // set up a window resize event to fire refiltering
    $(window).on('resize.Filterizr', debounce(() => {
      // Update dimensions of items based on new window size
      FilterContainer.updateWidth();
      FilterContainer.updateFilterItemsDimensions();

      // Refilter the grid to assume new positions
      this.filter(this.options.filter);
    }, 250));
  }
}

export default Filterizr;
<|endoftext|>


<commit_before>Ext.namespace('Vps.Auto.Form');

Vps.Auto.Form.Window = Ext.extend(Ext.Window, {
    initComponent : function()
    {
        if (!this.autoForm) {
            if (!this.formConfig) this.formConfig = {};

            Ext.applyIf(this.formConfig, {
                baseCls: 'x-plain',
                controllerUrl: this.controllerUrl,
                autoload: false
            });
            this.autoForm = new Vps.Auto.FormPanel(this.formConfig);
        } else if (typeof this.autoForm == 'string') {
            try {
                var d = eval(this.autoForm);
            } catch (e) {
                throw new Error("Invalid autoForm \'"+this.autoForm+"': "+e);
            }
            this.autoForm = new d({ baseCls: 'x-plain' });
        }

        var onRender = function() {
            this.getForm().waitMsgTarget = this.el;
            this.getForm().loadAfterSave = false; //dialog wird geschlossen nach speichern, ist also nicht nötig
        };
        if (!this.autoForm.rendered) {
            this.on('renderform', onRender, this);
        } else {
            onRender();
        }

        Ext.applyIf(this, {
            width: 400,
            height: 300,
            layout: 'fit',
            bodyStyle:'padding:5px;',
            plain: true,
            modal: true,
            baseCls: 'x-plain',
            buttons: [this.getAction('cancel'), this.getAction('save')]
        });
        this.closeAction = 'hide';

        this.items = [this.autoForm];

        this.relayEvents(this.autoForm, ['renderform', 'datachange', 'loadform', 'addaction']);

        Vps.Auto.Form.Window.superclass.initComponent.call(this);
    },

    getAction : function(type)
    {
        if (!this.actions) { this.actions = {}; }
        if (this.actions[type]) return this.actions[type];

        if (type == 'save') {
            this.actions[type] = new Ext.Action({
                text    : 'Save',
                handler : function() {
                    this.getAutoForm().submit({
                        success: function() {
                            this.hide();
                        },
                        scope: this
                    });
                },
                scope   : this
            });
        } else if (type == 'cancel') {
            this.actions[type] = new Ext.Action({
                text    : 'Cancel',
                handler : function() {
                    this.hide();
                },
                scope   : this
            });
        } else {
            throw 'unknown action-type: ' + type;
        }
        return this.actions[type];
    },

    showAdd : function()
    {
        this.setTitle('add');
        this.show();
        this.getAutoForm().onAdd();
    },

    showEdit : function(id, options)
    {
        this.setTitle('edit');
        this.show();
        if (id) {
            this.getAutoForm().load(id, options);
        }
    },

    getAutoForm : function()
    {
        return this.autoForm;
    },

    getForm : function()
    {
        return this.getAutoForm().getForm();
    },

    findField: function(f)
    {
        return this.getAutoForm().findField(f);
    },

    getBaseParams: function()
    {
        return this.getAutoForm().getBaseParams();
    }
});
<commit_msg>möglichkeit titel von window selbst zu definieren können, mit verfünftigen standard-werten<commit_after>Ext.namespace('Vps.Auto.Form');

Vps.Auto.Form.Window = Ext.extend(Ext.Window, {
    initComponent : function()
    {
        if (!this.editTitle) {
            this.editTitle = 'Edit';
            if (this.title) this.editTitle = this.editTitle + ' ' + this.title;
        }
        if (!this.addTitle) {
            this.addTitle = 'Add';
            if (this.title) this.addTitle = this.addTitle + ' ' + this.title;
        }
        if (!this.autoForm) {
            if (!this.formConfig) this.formConfig = {};

            Ext.applyIf(this.formConfig, {
                baseCls: 'x-plain',
                controllerUrl: this.controllerUrl,
                autoload: false
            });
            this.autoForm = new Vps.Auto.FormPanel(this.formConfig);
        } else if (typeof this.autoForm == 'string') {
            try {
                var d = eval(this.autoForm);
            } catch (e) {
                throw new Error("Invalid autoForm \'"+this.autoForm+"': "+e);
            }
            this.autoForm = new d({ baseCls: 'x-plain' });
        }

        var onRender = function() {
            this.getForm().waitMsgTarget = this.el;
            this.getForm().loadAfterSave = false; //dialog wird geschlossen nach speichern, ist also nicht nötig
        };
        if (!this.autoForm.rendered) {
            this.on('renderform', onRender, this);
        } else {
            onRender();
        }

        Ext.applyIf(this, {
            width: 400,
            height: 300,
            layout: 'fit',
            bodyStyle:'padding:5px;',
            plain: true,
            modal: true,
            baseCls: 'x-plain',
            buttons: [this.getAction('cancel'), this.getAction('save')]
        });
        this.closeAction = 'hide';

        this.items = [this.autoForm];

        this.relayEvents(this.autoForm, ['renderform', 'datachange', 'loadform', 'addaction']);

        Vps.Auto.Form.Window.superclass.initComponent.call(this);
    },

    getAction : function(type)
    {
        if (!this.actions) { this.actions = {}; }
        if (this.actions[type]) return this.actions[type];

        if (type == 'save') {
            this.actions[type] = new Ext.Action({
                text    : 'Save',
                handler : function() {
                    this.getAutoForm().submit({
                        success: function() {
                            this.hide();
                        },
                        scope: this
                    });
                },
                scope   : this
            });
        } else if (type == 'cancel') {
            this.actions[type] = new Ext.Action({
                text    : 'Cancel',
                handler : function() {
                    this.hide();
                },
                scope   : this
            });
        } else {
            throw 'unknown action-type: ' + type;
        }
        return this.actions[type];
    },

    showAdd : function()
    {
        this.setTitle(this.addTitle);
        this.show();
        this.getAutoForm().onAdd();
    },

    showEdit : function(id, options)
    {
        this.setTitle(this.editTitle);
        this.show();
        if (id) {
            this.getAutoForm().load(id, options);
        }
    },

    getAutoForm : function()
    {
        return this.autoForm;
    },

    getForm : function()
    {
        return this.getAutoForm().getForm();
    },

    findField: function(f)
    {
        return this.getAutoForm().findField(f);
    },

    getBaseParams: function()
    {
        return this.getAutoForm().getBaseParams();
    }
});
<|endoftext|>


<commit_before>// ==UserScript==
// @name Oopsie
// @version 0.6
// @description Tweaks the F5 UI
// @match https://*/tmui/Control/*
// @match https://*/sam/admin/reports/*
// @run-at          document-end
// @updateURL https://github.com/jangins101/F5/edit/master/TamperMonkey/test.js
// @downloadURL https://github.com/jangins101/F5/edit/master/TamperMonkey/test.js
// @grant none
// @require http://code.jquery.com/jquery-latest.js
// ==/UserScript==

 alert("testing");
 alert("testing2");
<commit_msg>Update test.js<commit_after>// ==UserScript==
// @name Oopsie
// @version 0.6
// @description Tweaks the F5 UI
// @match https://*/tmui/Control/*
// @match https://*/sam/admin/reports/*
// @run-at          document-end
// @updateURL https://raw.githubusercontent.com/jangins101/F5/master/TamperMonkey/test.js
// @downloadURL https://raw.githubusercontent.com/jangins101/F5/master/TamperMonkey/test.js
// @grant none
// @require http://code.jquery.com/jquery-latest.js
// ==/UserScript==

 alert("testing");
 alert("testing2");
<|endoftext|>


<commit_before>import { run } from '@ember/runloop';

import { module, test } from 'qunit';
import { defer } from 'rsvp';

import DS from 'ember-data';
import { setupTest } from 'ember-qunit';

import JSONAPISerializer from '@ember-data/serializer/json-api';

module('unit/store/finders', function(hooks) {
  setupTest(hooks);

  hooks.beforeEach(function() {
    this.Person = DS.Model.extend({
      updatedAt: DS.attr('string'),
      name: DS.attr('string'),
      firstName: DS.attr('string'),
      lastName: DS.attr('string'),
    });

    this.Dog = DS.Model.extend({
      name: DS.attr('string'),
    });

    this.owner.register('model:person', this.Person);
    this.owner.register('model:dog', this.Dog);
    this.owner.register('serializer:application', JSONAPISerializer.extend());

    this.store = this.owner.lookup('service:store');
    this.adapter = this.store.adapterFor('application');
  });

  test('findRecord does not load a serializer until the adapter promise resolves', function(assert) {
    assert.expect(2);

    let deferedFind = defer();

    this.owner.register(
      'adapter:person',
      DS.Adapter.extend({
        findRecord: () => deferedFind.promise,
      })
    );

    let serializerLoaded = false;
    let serializerFor = this.store.serializerFor;
    this.store.serializerFor = modelName => {
      if (modelName === 'person') {
        serializerLoaded = true;
      }
      return serializerFor.call(this.store, modelName);
    };

    let storePromise = run(() => this.store.findRecord('person', 1));
    assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded');

    return run(() => {
      deferedFind.resolve({
        data: { id: 1, type: 'person', attributes: { name: 'John Churchill' } },
      });
      return storePromise.then(() => {
        assert.equal(true, serializerLoaded, 'serializer is loaded');
      });
    });
  });

  test('findMany does not load a serializer until the adapter promise resolves', function(assert) {
    assert.expect(2);

    let deferedFind = defer();

    this.owner.register(
      'adapter:person',
      DS.Adapter.extend({
        findMany: () => deferedFind.promise,
      })
    );

    let serializerLoaded = false;
    let serializerFor = this.store.serializerFor;
    this.store.serializerFor = modelName => {
      if (modelName === 'person') {
        serializerLoaded = true;
      }
      return serializerFor.call(this.store, modelName);
    };

    let storePromise = run(() => {
      this.store.findRecord('person', 1);
      return this.store.findRecord('person', 2);
    });
    assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded');

    return run(() => {
      deferedFind.resolve({
        data: [
          { id: 1, type: 'person', attributes: { name: 'John Churchill' } },
          { id: 2, type: 'person', attributes: { name: 'Louis Joseph' } },
        ],
      });
      return storePromise.then(() => {
        assert.equal(true, serializerLoaded, 'serializer is loaded');
      });
    });
  });

  test('findHasMany does not load a serializer until the adapter promise resolves', function(assert) {
    assert.expect(2);

    let deferedFind = defer();

    this.owner.register(
      'adapter:person',
      DS.Adapter.extend({
        findHasMany: () => deferedFind.promise,
      })
    );

    this.Person.reopen({
      dogs: DS.hasMany('dog', { async: true }),
    });

    let serializerLoaded = false;
    let serializerFor = this.store.serializerFor;
    this.store.serializerFor = modelName => {
      if (modelName === 'dog') {
        serializerLoaded = true;
      }
      return serializerFor.call(this.store, modelName);
    };

    let storePromise = run(() => {
      this.store.push({
        data: {
          type: 'person',
          id: '1',
          attributes: {
            name: 'John Churchill',
          },
          relationships: {
            dogs: {
              links: {
                related: 'http://exmaple.com/person/1/dogs',
              },
            },
          },
        },
      });

      return this.store.peekRecord('person', 1).get('dogs');
    });
    assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded');

    return run(() => {
      deferedFind.resolve({
        data: [
          { id: 1, type: 'dog', attributes: { name: 'Scooby' } },
          { id: 2, type: 'dog', attributes: { name: 'Scrappy' } },
        ],
      });
      return storePromise.then(() => {
        assert.equal(true, serializerLoaded, 'serializer is loaded');
      });
    });
  });

  test('findBelongsTo does not load a serializer until the adapter promise resolves', function(assert) {
    assert.expect(2);

    let deferedFind = defer();

    this.owner.register(
      'adapter:person',
      DS.Adapter.extend({
        findBelongsTo: () => deferedFind.promise,
      })
    );

    this.Person.reopen({
      favoriteDog: DS.belongsTo('dog', { async: true }),
    });

    let serializerLoaded = false;
    let serializerFor = this.store.serializerFor;
    this.store.serializerFor = modelName => {
      if (modelName === 'dog') {
        serializerLoaded = true;
      }
      return serializerFor.call(this.store, modelName);
    };

    let storePromise = run(() => {
      this.store.push({
        data: {
          type: 'person',
          id: '1',
          attributes: {
            name: 'John Churchill',
          },
          relationships: {
            favoriteDog: {
              links: {
                related: 'http://exmaple.com/person/1/favorite-dog',
              },
            },
          },
        },
      });

      return this.store.peekRecord('person', 1).get('favoriteDog');
    });
    assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded');

    return run(() => {
      deferedFind.resolve({ data: { id: 1, type: 'dog', attributes: { name: 'Scooby' } } });
      return storePromise.then(() => {
        assert.equal(true, serializerLoaded, 'serializer is loaded');
      });
    });
  });

  test('findAll does not load a serializer until the adapter promise resolves', function(assert) {
    assert.expect(2);

    let deferedFind = defer();

    this.owner.register(
      'adapter:person',
      DS.Adapter.extend({
        findAll: () => deferedFind.promise,
      })
    );

    let serializerLoaded = false;
    let serializerFor = this.store.serializerFor;
    this.store.serializerFor = modelName => {
      if (modelName === 'person') {
        serializerLoaded = true;
      }
      return serializerFor.call(this.store, modelName);
    };

    let storePromise = run(() => this.store.findAll('person'));
    assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded');

    return run(() => {
      deferedFind.resolve({
        data: [{ id: 1, type: 'person', attributes: { name: 'John Churchill' } }],
      });
      return storePromise.then(() => {
        assert.equal(true, serializerLoaded, 'serializer is loaded');
      });
    });
  });

  test('query does not load a serializer until the adapter promise resolves', function(assert) {
    assert.expect(2);

    let deferedFind = defer();

    this.owner.register(
      'adapter:person',
      DS.Adapter.extend({
        query: () => deferedFind.promise,
      })
    );

    let serializerLoaded = false;
    let serializerFor = this.store.serializerFor;
    this.store.serializerFor = modelName => {
      if (modelName === 'person') {
        serializerLoaded = true;
      }
      return serializerFor.call(this.store, modelName);
    };

    let storePromise = run(() => this.store.query('person', { first_duke_of_marlborough: true }));
    assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded');

    return run(() => {
      deferedFind.resolve({
        data: [{ id: 1, type: 'person', attributes: { name: 'John Churchill' } }],
      });
      return storePromise.then(() => {
        assert.equal(true, serializerLoaded, 'serializer is loaded');
      });
    });
  });

  test('queryRecord does not load a serializer until the adapter promise resolves', function(assert) {
    assert.expect(2);

    let deferedFind = defer();

    this.owner.register(
      'adapter:person',
      DS.Adapter.extend({
        queryRecord: () => deferedFind.promise,
      })
    );

    let serializerLoaded = false;
    let serializerFor = this.store.serializerFor;
    this.store.serializerFor = modelName => {
      if (modelName === 'person') {
        serializerLoaded = true;
      }
      return serializerFor.call(this.store, modelName);
    };

    let storePromise = run(() => this.store.queryRecord('person', { first_duke_of_marlborough: true }));
    assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded');

    return run(() => {
      deferedFind.resolve({
        data: { id: 1, type: 'person', attributes: { name: 'John Churchill' } },
      });
      return storePromise.then(() => {
        assert.equal(true, serializerLoaded, 'serializer is loaded');
      });
    });
  });
});
<commit_msg>[Chore]: Update finders-test to modern imports<commit_after>import { module, test } from 'qunit';
import { defer } from 'rsvp';

import { setupTest } from 'ember-qunit';

import Adapter from '@ember-data/adapter';
import Model, { attr, belongsTo, hasMany } from '@ember-data/model';
import JSONAPISerializer from '@ember-data/serializer/json-api';

class Person extends Model {
  @attr('string') updatedAt;
  @attr('string') name;
  @attr('string') firstName;
  @attr('string') lastName;
  @hasMany('dog', { async: true }) dogs;
  @belongsTo('dog', { async: true }) favoriteDog;
}

class Dog extends Model {
  @attr('string') name;
}

module('unit/store/finders', async function(hooks) {
  setupTest(hooks);

  hooks.beforeEach(function() {
    this.owner.register('model:person', Person);
    this.owner.register('model:dog', Dog);
    this.owner.register('serializer:application', JSONAPISerializer.extend());

    this.store = this.owner.lookup('service:store');
    this.adapter = this.store.adapterFor('application');
  });

  test('findRecord does not load a serializer until the adapter promise resolves', async function(assert) {
    assert.expect(2);

    let deferedFind = defer();

    this.owner.register(
      'adapter:person',
      Adapter.extend({
        findRecord: () => deferedFind.promise,
      })
    );

    let serializerLoaded = false;
    let serializerFor = this.store.serializerFor;
    this.store.serializerFor = modelName => {
      if (modelName === 'person') {
        serializerLoaded = true;
      }
      return serializerFor.call(this.store, modelName);
    };

    let storePromise = this.store.findRecord('person', 1);
    assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded');

    deferedFind.resolve({
      data: { id: 1, type: 'person', attributes: { name: 'John Churchill' } },
    });

    await storePromise;

    assert.equal(true, serializerLoaded, 'serializer is loaded');
  });

  test('findMany does not load a serializer until the adapter promise resolves', async function(assert) {
    assert.expect(2);

    let deferedFind = defer();

    this.owner.register(
      'adapter:person',
      Adapter.extend({
        findMany: () => deferedFind.promise,
      })
    );

    let serializerLoaded = false;
    let serializerFor = this.store.serializerFor;
    this.store.serializerFor = modelName => {
      if (modelName === 'person') {
        serializerLoaded = true;
      }
      return serializerFor.call(this.store, modelName);
    };

    this.store.findRecord('person', 1);
    let storePromise = this.store.findRecord('person', 2);

    assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded');

    deferedFind.resolve({
      data: [
        { id: 1, type: 'person', attributes: { name: 'John Churchill' } },
        { id: 2, type: 'person', attributes: { name: 'Louis Joseph' } },
      ],
    });

    await storePromise;

    assert.equal(true, serializerLoaded, 'serializer is loaded');
  });

  test('findHasMany does not load a serializer until the adapter promise resolves', async function(assert) {
    assert.expect(2);

    let deferedFind = defer();

    this.owner.register(
      'adapter:person',
      Adapter.extend({
        findHasMany: () => deferedFind.promise,
      })
    );

    let serializerLoaded = false;
    let serializerFor = this.store.serializerFor;
    this.store.serializerFor = modelName => {
      if (modelName === 'dog') {
        serializerLoaded = true;
      }
      return serializerFor.call(this.store, modelName);
    };

    this.store.push({
      data: {
        type: 'person',
        id: '1',
        attributes: {
          name: 'John Churchill',
        },
        relationships: {
          dogs: {
            links: {
              related: 'http://exmaple.com/person/1/dogs',
            },
          },
        },
      },
    });

    let storePromise = this.store.peekRecord('person', 1).get('dogs');
    assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded');

    deferedFind.resolve({
      data: [
        { id: 1, type: 'dog', attributes: { name: 'Scooby' } },
        { id: 2, type: 'dog', attributes: { name: 'Scrappy' } },
      ],
    });

    await storePromise;

    assert.equal(true, serializerLoaded, 'serializer is loaded');
  });

  test('findBelongsTo does not load a serializer until the adapter promise resolves', async function(assert) {
    assert.expect(2);

    let deferedFind = defer();

    this.owner.register(
      'adapter:person',
      Adapter.extend({
        findBelongsTo: () => deferedFind.promise,
      })
    );

    let serializerLoaded = false;
    let serializerFor = this.store.serializerFor;
    this.store.serializerFor = modelName => {
      if (modelName === 'dog') {
        serializerLoaded = true;
      }
      return serializerFor.call(this.store, modelName);
    };

    this.store.push({
      data: {
        type: 'person',
        id: '1',
        attributes: {
          name: 'John Churchill',
        },
        relationships: {
          favoriteDog: {
            links: {
              related: 'http://exmaple.com/person/1/favorite-dog',
            },
          },
        },
      },
    });

    let storePromise = this.store.peekRecord('person', 1).get('favoriteDog');

    assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded');

    deferedFind.resolve({ data: { id: 1, type: 'dog', attributes: { name: 'Scooby' } } });

    await storePromise;

    assert.equal(true, serializerLoaded, 'serializer is loaded');
  });

  test('findAll does not load a serializer until the adapter promise resolves', async function(assert) {
    assert.expect(2);

    let deferedFind = defer();

    this.owner.register(
      'adapter:person',
      Adapter.extend({
        findAll: () => deferedFind.promise,
      })
    );

    let serializerLoaded = false;
    let serializerFor = this.store.serializerFor;
    this.store.serializerFor = modelName => {
      if (modelName === 'person') {
        serializerLoaded = true;
      }
      return serializerFor.call(this.store, modelName);
    };

    let storePromise = this.store.findAll('person');
    assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded');

    deferedFind.resolve({
      data: [{ id: 1, type: 'person', attributes: { name: 'John Churchill' } }],
    });

    await storePromise;

    assert.equal(true, serializerLoaded, 'serializer is loaded');
  });

  test('query does not load a serializer until the adapter promise resolves', async function(assert) {
    assert.expect(2);

    let deferedFind = defer();

    this.owner.register(
      'adapter:person',
      Adapter.extend({
        query: () => deferedFind.promise,
      })
    );

    let serializerLoaded = false;
    let serializerFor = this.store.serializerFor;
    this.store.serializerFor = modelName => {
      if (modelName === 'person') {
        serializerLoaded = true;
      }
      return serializerFor.call(this.store, modelName);
    };

    let storePromise = this.store.query('person', { first_duke_of_marlborough: true });
    assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded');

    deferedFind.resolve({
      data: [{ id: 1, type: 'person', attributes: { name: 'John Churchill' } }],
    });

    await storePromise;

    assert.equal(true, serializerLoaded, 'serializer is loaded');
  });

  test('queryRecord does not load a serializer until the adapter promise resolves', async function(assert) {
    assert.expect(2);

    let deferedFind = defer();

    this.owner.register(
      'adapter:person',
      Adapter.extend({
        queryRecord: () => deferedFind.promise,
      })
    );

    let serializerLoaded = false;
    let serializerFor = this.store.serializerFor;
    this.store.serializerFor = modelName => {
      if (modelName === 'person') {
        serializerLoaded = true;
      }
      return serializerFor.call(this.store, modelName);
    };

    let storePromise = this.store.queryRecord('person', { first_duke_of_marlborough: true });
    assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded');

    deferedFind.resolve({
      data: { id: 1, type: 'person', attributes: { name: 'John Churchill' } },
    });

    await storePromise;

    assert.equal(true, serializerLoaded, 'serializer is loaded');
  });
});
<|endoftext|>


<commit_before>import fs from 'fs'
import path from 'path'
import webpack from 'webpack'
import parents from 'parents'
import resolveFrom from 'resolve-from'
import RoleResolverPlugin from '@sanity/webpack-loader'
import ExtractTextPlugin from '@sanity/extract-text-webpack-plugin'
import postcssPlugins from './postcssPlugins'

// Webpack 2 vs 1
const OccurrenceOrderPlugin = webpack.optimize.OccurrenceOrderPlugin || webpack.optimize.OccurenceOrderPlugin

const partLoaderPath = require.resolve('@sanity/webpack-loader/src/partLoader')

export default (config = {}) => {
  const basePath = config.basePath || process.cwd()
  const skipMinify = config.skipMinify || false

  const reactPath = resolveFrom(basePath, 'react')
  const reactDomPath = resolveFrom(basePath, 'react-dom')
  const missing = [!reactPath && '`react`', !reactDomPath && '`react-dom`'].filter(Boolean)
  if (!reactPath || !reactDomPath) {
    const missingErr = [
      `Could not find ${missing.join(', ')} dependencies in project directory`,
      'These need to be declared in `package.json` and be installed for Sanity to work'
    ].join('\n')

    throw new Error(missingErr)
  }

  const babelConfig = tryRead(path.join(basePath, '.babelrc'))
  const env = config.env || 'development'
  const isProd = env === 'production'
  const resolvePaths = parents(basePath).map(dir => path.join(dir, 'node_modules'))
  const resolverOpts = Object.assign({basePath}, config.resolver || {})

  const cssExtractor = isProd
    && new ExtractTextPlugin('css/main.css', {allChunks: true, ignoreOrder: true})

  const baseCssLoader = 'css-loader?modules&localIdentName=[name]_[local]_[hash:base64:5]&importLoaders=1'
  const cssLoader = isProd && !skipMinify
    ? `${baseCssLoader}&minimize`
    : `${baseCssLoader}&sourceMap`

  const commonChunkPlugin = (
    typeof config.commonChunkPlugin === 'undefined'
    || config.commonChunkPlugin
  ) && new webpack.optimize.CommonsChunkPlugin('vendor', 'js/vendor.bundle.js')

  return {
    entry: {
      app: [
        require.resolve('normalize.css'),
        path.join(__dirname, '..', 'browser', 'entry')
      ],
      vendor: ['react', 'react-dom']
    },
    output: {
      path: config.outputPath || path.join(__dirname, '..', '..', 'dist'),
      filename: 'js/[name].bundle.js',
      publicPath: '/static/'
    },
    resolve: {
      fallback: resolvePaths,
      alias: {
        'react': path.dirname(reactPath),
        'react-dom': path.dirname(reactDomPath)
      }
    },
    resolveLoader: {
      root: resolvePaths
    },
    module: {
      loaders: [{
        test: /\.jsx?/,
        exclude: modPath => modPath.indexOf('/node_modules/') >= 0,
        loader: 'babel',
        query: babelConfig || {
          presets: [
            require.resolve('babel-preset-react'),
            require.resolve('babel-preset-es2015')
          ],
          plugins: [
            require.resolve('babel-plugin-syntax-class-properties'),
            require.resolve('babel-plugin-transform-class-properties')
          ],
          cacheDirectory: true
        }
      }, {
        test: /\.json$/,
        loader: 'json'
      }, {
        test: /\.css(\?|$)/,
        loader: isProd && cssExtractor.extract([cssLoader, 'postcss-loader']),
        loaders: !isProd && ['style-loader', cssLoader, 'postcss-loader']
      }, {
        test: /\.(jpe?g|png|gif|svg|webp|woff|woff2|ttf|eot)$/,
        loader: require.resolve('file-loader'),
        query: {
          name: 'assets/[name]-[hash].[ext]'
        }
      }, {
        test: /[?&]sanityPart=/,
        loader: partLoaderPath
      }]
    },
    plugins: [
      cssExtractor,
      new OccurrenceOrderPlugin(),
      new webpack.ResolverPlugin([new RoleResolverPlugin(resolverOpts)], ['normal']),
      commonChunkPlugin
    ].filter(Boolean),
    postcss: postcssPlugins({basePath})
  }
}

function tryRead(filePath) {
  try {
    const content = fs.readFileSync(filePath)
    return JSON.parse(content)
  } catch (err) {
    return null
  }
}
<commit_msg>Pass on profile configuration option<commit_after>import fs from 'fs'
import path from 'path'
import webpack from 'webpack'
import parents from 'parents'
import resolveFrom from 'resolve-from'
import RoleResolverPlugin from '@sanity/webpack-loader'
import ExtractTextPlugin from '@sanity/extract-text-webpack-plugin'
import postcssPlugins from './postcssPlugins'

// Webpack 2 vs 1
const OccurrenceOrderPlugin = webpack.optimize.OccurrenceOrderPlugin || webpack.optimize.OccurenceOrderPlugin

const partLoaderPath = require.resolve('@sanity/webpack-loader/src/partLoader')

export default (config = {}) => {
  const basePath = config.basePath || process.cwd()
  const skipMinify = config.skipMinify || false

  const reactPath = resolveFrom(basePath, 'react')
  const reactDomPath = resolveFrom(basePath, 'react-dom')
  const missing = [!reactPath && '`react`', !reactDomPath && '`react-dom`'].filter(Boolean)
  if (!reactPath || !reactDomPath) {
    const missingErr = [
      `Could not find ${missing.join(', ')} dependencies in project directory`,
      'These need to be declared in `package.json` and be installed for Sanity to work'
    ].join('\n')

    throw new Error(missingErr)
  }

  const babelConfig = tryRead(path.join(basePath, '.babelrc'))
  const env = config.env || 'development'
  const isProd = env === 'production'
  const resolvePaths = parents(basePath).map(dir => path.join(dir, 'node_modules'))
  const resolverOpts = Object.assign({basePath}, config.resolver || {})

  const cssExtractor = isProd
    && new ExtractTextPlugin('css/main.css', {allChunks: true, ignoreOrder: true})

  const baseCssLoader = 'css-loader?modules&localIdentName=[name]_[local]_[hash:base64:5]&importLoaders=1'
  const cssLoader = isProd && !skipMinify
    ? `${baseCssLoader}&minimize`
    : `${baseCssLoader}&sourceMap`

  const commonChunkPlugin = (
    typeof config.commonChunkPlugin === 'undefined'
    || config.commonChunkPlugin
  ) && new webpack.optimize.CommonsChunkPlugin('vendor', 'js/vendor.bundle.js')

  return {
    entry: {
      app: [
        require.resolve('normalize.css'),
        path.join(__dirname, '..', 'browser', 'entry')
      ],
      vendor: ['react', 'react-dom']
    },
    output: {
      path: config.outputPath || path.join(__dirname, '..', '..', 'dist'),
      filename: 'js/[name].bundle.js',
      publicPath: '/static/'
    },
    resolve: {
      fallback: resolvePaths,
      alias: {
        'react': path.dirname(reactPath),
        'react-dom': path.dirname(reactDomPath)
      }
    },
    resolveLoader: {
      root: resolvePaths
    },
    module: {
      loaders: [{
        test: /\.jsx?/,
        exclude: modPath => modPath.indexOf('/node_modules/') >= 0,
        loader: 'babel',
        query: babelConfig || {
          presets: [
            require.resolve('babel-preset-react'),
            require.resolve('babel-preset-es2015')
          ],
          plugins: [
            require.resolve('babel-plugin-syntax-class-properties'),
            require.resolve('babel-plugin-transform-class-properties')
          ],
          cacheDirectory: true
        }
      }, {
        test: /\.json$/,
        loader: 'json'
      }, {
        test: /\.css(\?|$)/,
        loader: isProd && cssExtractor.extract([cssLoader, 'postcss-loader']),
        loaders: !isProd && ['style-loader', cssLoader, 'postcss-loader']
      }, {
        test: /\.(jpe?g|png|gif|svg|webp|woff|woff2|ttf|eot)$/,
        loader: require.resolve('file-loader'),
        query: {
          name: 'assets/[name]-[hash].[ext]'
        }
      }, {
        test: /[?&]sanityPart=/,
        loader: partLoaderPath
      }]
    },
    profile: config.profile || false,
    plugins: [
      cssExtractor,
      new OccurrenceOrderPlugin(),
      new webpack.ResolverPlugin([new RoleResolverPlugin(resolverOpts)], ['normal']),
      commonChunkPlugin
    ].filter(Boolean),
    postcss: postcssPlugins({basePath})
  }
}

function tryRead(filePath) {
  try {
    const content = fs.readFileSync(filePath)
    return JSON.parse(content)
  } catch (err) {
    return null
  }
}
<|endoftext|>