<commit_before><commit_msg>Test actions<commit_after>import * as actions from '@/store/actions'

jest.mock('vuexfire')
jest.mock('@/firebaseApp')
jest.mock('lodash/debounce', () => {
  return (fn) => {
    return fn
  }
})

// helper for testing action with expected mutations and actions
const testAction = (action, payload, state, expectedMutations, expectedActions, done) => {
  // mock commit and dispatch
  const commit = jest.fn(done)
  const dispatch = jest.fn(done)

  // call the action with mocked store and arguments
  action({ dispatch, commit, state }, payload)

  // expect mutations and actions to be called with arguments
  expectedMutations.forEach(({ type, payload }) => {
    if (payload != null) {
      expect(commit).toBeCalledWith(type, payload)
    } else {
      expect(commit).toBeCalledWith(type)
    }
  })
  expectedActions.forEach(({ type, payload }) => {
    if (payload != null) {
      expect(dispatch).toBeCalledWith(type, payload)
    } else {
      expect(dispatch).toBeCalledWith(type)
    }
  })

  expect(commit.mock.calls.length).toBe(expectedMutations.length)
  expect(dispatch.mock.calls.length).toBe(expectedActions.length)

  // if no mutations or actions should have been dispatched, end
  if (expectedMutations.length === 0 && expectedActions.length === 0) {
    done()
  }
}

describe('actions', () => {
  it('setNotesRef', done => {
    testAction(actions.setNotesRef, 'fakeRef', {}, [], [{
      type: 'asyncLoading',
      payload: true
    }, {
      type: 'asyncLoading',
      payload: false
    }], done)
  })

  it('setNotesOrderRef', done => {
    testAction(actions.setNotesOrderRef, 'fakeRef', {}, [], [{
      type: 'asyncLoading',
      payload: true
    }, {
      type: 'asyncLoading',
      payload: false
    }], done)
  })

  it('signInWithEmailAndPassword', done => {
    testAction(actions.signInWithEmailAndPassword, {}, {}, [], [], done)
  })

  it('asyncLoading', done => {
    const payload = true
    testAction(actions.asyncLoading, payload, {}, [{
      type: 'ASYNC_LOADING',
      payload
    }], [], done)
  })

  it('createNote', done => {
    testAction(actions.createNote, {
      title: 'title',
      text: 'text',
      markdown: false,
      color: 'white'
    }, {}, [{ type: 'CLEAR_NOTE_FORM' }], [{
      type: 'asyncLoading',
      payload: true
    }, {
      type: 'asyncLoading',
      payload: false
    }], done)
  })

  it('updateNote', done => {
    testAction(actions.updateNote, {
      title: 'title',
      text: 'text',
      markdown: false,
      color: 'white'
    }, {}, [], [{
      type: 'asyncLoading',
      payload: true
    }, {
      type: 'asyncLoading',
      payload: false
    }], done)
  })

  it('removeNote', done => {
    testAction(actions.removeNote, {}, {}, [], [{
      type: 'asyncLoading',
      payload: true
    }, {
      type: 'asyncLoading',
      payload: false
    }], done)
    done()
  })

  it('updateNoteColor', done => {
    testAction(actions.updateNoteColor, {
      title: 'title',
      text: 'text',
      markdown: false,
      color: 'white'
    }, {}, [], [{
      type: 'asyncLoading',
      payload: true
    }, {
      type: 'asyncLoading',
      payload: false
    }], done)
  })

  it('updateNotesOrder', done => {
    testAction(actions.updateNotesOrder, {}, {}, [], [{
      type: 'asyncLoading',
      payload: true
    }, {
      type: 'asyncLoading',
      payload: false
    }], done)
  })
})
<|endoftext|>


<commit_before>'use strict';

module.exports = {
    getClassesFromSelector: function (selector) {
        if (!selector) {
            return [];
        }
        var classRegEx = /[_a-zA-Z][_a-zA-Z0-9-]*/g;
        return selector.match(classRegEx);
    },
    getSelectorLength: function (selector) {
        var classes = this.getClassesFromSelector(selector);
        return classes ? classes.length : 0;
    }
};
<commit_msg>Return empty list on non match<commit_after>'use strict';

module.exports = {
    getClassesFromSelector: function (selector) {
        if (!selector) {
            return [];
        }
        var classRegEx = /[_a-zA-Z][_a-zA-Z0-9-]*/g;
        return selector.match(classRegEx) || [];
    },
    getSelectorLength: function (selector) {
        var classes = this.getClassesFromSelector(selector);
        return classes.length;
    }
};
<|endoftext|>


<commit_before>function TweetsTimeline(timelineId, manager, template) {
  this.timelineId = timelineId;
  this.manager = manager;
  this.template = template;

  this.tweetsCache = [];
  this.newTweetsCache = [];
  this.unreadNotified = [];

  this.timerId = null;
  this.currentError = null;
  this.currentCallback = null;
  this.currentScroll = 0;
  this.firstRun = true;
  this.timelinePath = null;
  this.timelineId = timelineId;
  this.timelineStopped = false;
  this.timelinePath = this.template.templatePath;
}

TweetsTimeline.prototype = {
  init: function() {
    this.giveMeTweets(function() {});
  },

  remove: function(){
    this.template.setVisible(false);
    if(!this.template.includeInUnified) {
      this.killTimeline();
      return true;
    }
    return false;
  },

  getError: function() {
    return this.currentError;
  },

  killTimeline: function() {
    this.timelineStopped = true;
    this._stopTimer();
  },

  giveMeTweets: function(callback, syncNew, cacheOnly, keepCache, suggestedCount) {
    if(!this.timelinePath) {
      callback([], this.timelineId);
      return;
    }
    if(this.currentCallback) {
      //Handling multiple calls to giveMeTweets, just update the registered
      //callback and let the first request finish.
      this.currentCallback = callback;
      return;
    }
    if(syncNew) {
      //We should fetch new tweets, update the cache and then return the
      //cached results.
      var oldNewTweetsCallback = this.manager.newTweetsCallback;
      var _this = this;
      this.currentCallback = callback;
      this.manager.newTweetsCallback = null;
      var onFinishCallback = function() {
        var tweetsCallback = _this.currentCallback;
        _this.currentCallback = null;

        _this.updateNewTweets();
        _this.manager.updateAlert();
        _this.giveMeTweets(tweetsCallback, false, true);
        _this.manager.newTweetsCallback = oldNewTweetsCallback;
      }
      this._fetchNewTweets(onFinishCallback);
      return;
    }
    if(cacheOnly && !this.firstRun) {
      //Only return cached results if this is not the first run.
      if(!keepCache) {
        this._cleanUpCache();
      }
      try {
        callback(this.tweetsCache, this.timelineId);
      } catch(e) {
        /* ignoring exception, popup might be closed */
      }
      return;
    }
    //If we didn't return yet it's because we want to fetch old tweets
    //from twitter's API.

    this.currentCallback = callback;
    var _this = this;
    var params = this._makeOldTweetsRequestParams(suggestedCount);
    var context = {
      usingMaxId: !!params.max_id
    };
    this._doBackendRequest(this.timelinePath, function(success, tweets, status, context) {
      _this._onFetch.call(_this, success, _this._filterBlockedTweets(tweets), status, context);
    }, context, params);
  },

  updateNewTweets: function() {
    this.tweetsCache = this.newTweetsCache.concat(this.tweetsCache);
    this.newTweetsCache = [];
    this.unreadNotified = [];
  },

  newTweetsCount: function() {
    var unreadCount = 0;
    for(var i = this.newTweetsCache.length - 1; i >= 0; --i) {
      if(!this.manager.isTweetRead(this.newTweetsCache[i].id)) {
        ++unreadCount;
      }
    }
    return [this.newTweetsCache.length, unreadCount];
  },

  getNewUnreadTweets: function() {
    var unreadNewList = [];
    for(var i = 0; i < this.newTweetsCache.length; ++i) {
      if(!this.manager.isTweetRead(this.newTweetsCache[i].id) && !this.unreadNotified[this.newTweetsCache[i].id]) {
        unreadNewList.push(this.newTweetsCache[i]);
        this.unreadNotified[this.newTweetsCache[i].id] = true;
      }
    }
    return unreadNewList;
  },

  getNewUnreadIds: function() {
    var unreadNewIds = [];
    for(var i = 0; i < this.newTweetsCache.length; ++i) {
      if(!this.manager.isTweetRead(this.newTweetsCache[i].id)) {
        unreadNewIds.push(this.newTweetsCache[i].id);
      }
    }
    return unreadNewIds;
  },

  removeFromCache: function(id) {
    var i = 0;
    for(; i < this.tweetsCache.length; ++i) {
      if(this.tweetsCache[i].id == id)
        break;
    }
    if(i != this.tweetsCache.length) {
      this.tweetsCache.splice(i, 1);
    }
  },

  findTweet: function(id) {
    var i = 0;
    for(; i < this.tweetsCache.length; ++i) {
      if(this.tweetsCache[i].id == id)
        return this.tweetsCache[i];
    }
    return null;
  },

  getNewTweetsCache: function() {
    return this.newTweetsCache;
  },

  getTweetsCache: function() {
    return this.tweetsCache;
  },

  /* Private Methods */

  _setError: function(status) {
    this.currentError = status;
  },

  _setTimelinePath: function(path) {
    this.timelinePath = path;
  },

  _stopTimer: function() {
    if(this.timerId) {
      clearTimeout(this.timerId);
      this.timerId = null;
    }
  },

  _onFetchNew: function(success, tweets, status, context) {
    if(this.timelineStopped) {
      return;
    }
    var _this = this;
    if(!success) {
      this._setError(status);
      if(context.onFinish)
        context.onFinish(0);
      this.timerId = setTimeout(function() { _this._fetchNewTweets.call(_this); }, this.template.refreshInterval);
      return;
    }
    this._setError(null);

    this._syncNewTweets(tweets, context);

    if(tweets.length > 0) {
      this.manager.notifyNewTweets();
    }
    if(context.onFinish)
      context.onFinish(tweets.length);
    this.timerId = setTimeout(function() { _this._fetchNewTweets.call(_this); }, this.template.refreshInterval);
  },

  _doBackendRequest: function(path, callback, context, params) {
    this.manager.twitterBackend.timeline(path, callback, context, params);
  },

  _fetchNewTweets: function(onFinishCallback) {
    this._stopTimer();
    var _this = this;
    if ( this.manager.suspend ) {
      this.timerId = setTimeout(function() { _this._fetchNewTweets.call(_this); }, this.template.refreshInterval);
      return;
    }
    var context = { onFinish: onFinishCallback };
    var params = this._makeNewTweetsRequestParams();
    this._doBackendRequest(this.timelinePath, function(success, tweets, status, context) {
      _this._onFetchNew.call(_this, success, _this._filterBlockedTweets(tweets), status, context);
    }, context, params);
  },

  _onFetch: function(success, tweets, status, context) {
    if(this.timelineStopped) {
      return;
    }
    if(!success) {
      this._setError(status);
      try {
        this.currentCallback(null);
      } catch(e) {
        /* ignoring exception, popup might be closed */
      }

      this._setError(null);
      this.currentCallback = null;
      return;
    }
    this._setError(null);
    this._syncOldTweets(tweets, context);

    // Let's clean this.currentCallback before calling it as
    // there might be unexpected errors and this should not block
    // the extension.
    var callback = this.currentCallback;
    this.currentCallback = null;
    try {
      callback(this.tweetsCache, this.timelineId);
    } catch(e) {
      /* ignoring exception, popup might be closed */
    }

    if(this.firstRun) {
      this.firstRun = false;
      var _this = this;
      this.timerId = setTimeout(function() { _this._fetchNewTweets.call(_this); }, this.template.refreshInterval);
    }
  },

  _cleanUpCache: function() {
    if(this.currentScroll != 0) {
      return;
    }
    var len = this.tweetsCache.length;
    if(len <= OptionsBackend.get('max_cached_tweets'))
      return;
    this.tweetsCache = this.tweetsCache.slice(0, OptionsBackend.get('max_cached_tweets') + 1);
  },

  _makeOldTweetsRequestParams: function(suggestedCount) {
    if(!suggestedCount) {
      suggestedCount = OptionsBackend.get('tweets_per_page');
    }
    var params = {count: suggestedCount, per_page: suggestedCount};
    var maxId = null;
    if(this.tweetsCache.length > 0) {
      maxId = this.tweetsCache[this.tweetsCache.length - 1].id;
    }
    if(maxId) {
      params.max_id = maxId;
    }
    return params;
  },

  _makeNewTweetsRequestParams: function() {
    var lastId = null;
    if(this.newTweetsCache.length > 0) {
      lastId = this.newTweetsCache[0].id;
    } else if(this.tweetsCache.length > 0) {
      lastId = this.tweetsCache[0].id;
    }
    var params = {};
    if(lastId) {
      params.since_id = lastId;
    }
    return params;
  },

  _syncOldTweets: function(tweets, context) {
    var i = 0;
    if(context.usingMaxId) {
      // If we're fetching using maxId, ignore the first one (we already have it)
      i = 1;
    }
    for(; i < tweets.length; ++i) {
      this.tweetsCache.push(tweets[i]);
    }
  },

  _syncNewTweets: function(tweets, context) {
    for(var i = tweets.length - 1; i >= 0; --i) {
      this.newTweetsCache.unshift(tweets[i]);
      var tid = tweets[i].id;
      if(context.onFinish) {
        this.manager.readTweet(tid);
      } else if(!this.manager.readTweets[tid]) {
        this.manager.unreadTweets[tid] = true;
      }
    }
  },

  /**
  * Filter-out all tweets and retweets that contain a status.user.id
  * or status.retweeted_status.user.id in this.manager.blockedUserIds.
  *
  * @param json tweets - response as returned by a Twitter timeline REST method
  * @return json
  */
  _filterBlockedTweets: function(tweets) {
    var filteredTweets = [];
    for(var i in tweets) {
      if(!(tweets[i].user && tweets[i].user.id in this.manager.blockedUserIds || tweets[i].retweeted_status && tweets[i].retweeted_status.user.id in this.manager.blockedUserIds)) {
        filteredTweets.push(tweets[i]);
      }
    }
    return filteredTweets;
  }
};<commit_msg>Correctly manually refreshing even if automatic updates are suspended<commit_after>function TweetsTimeline(timelineId, manager, template) {
  this.timelineId = timelineId;
  this.manager = manager;
  this.template = template;

  this.tweetsCache = [];
  this.newTweetsCache = [];
  this.unreadNotified = [];

  this.timerId = null;
  this.currentError = null;
  this.currentCallback = null;
  this.currentScroll = 0;
  this.firstRun = true;
  this.timelinePath = null;
  this.timelineId = timelineId;
  this.timelineStopped = false;
  this.timelinePath = this.template.templatePath;
}

TweetsTimeline.prototype = {
  init: function() {
    this.giveMeTweets(function() {});
  },

  remove: function(){
    this.template.setVisible(false);
    if(!this.template.includeInUnified) {
      this.killTimeline();
      return true;
    }
    return false;
  },

  getError: function() {
    return this.currentError;
  },

  killTimeline: function() {
    this.timelineStopped = true;
    this._stopTimer();
  },

  giveMeTweets: function(callback, syncNew, cacheOnly, keepCache, suggestedCount) {
    if(!this.timelinePath) {
      callback([], this.timelineId);
      return;
    }
    if(this.currentCallback) {
      //Handling multiple calls to giveMeTweets, just update the registered
      //callback and let the first request finish.
      this.currentCallback = callback;
      return;
    }
    if(syncNew) {
      //We should fetch new tweets, update the cache and then return the
      //cached results.
      var oldNewTweetsCallback = this.manager.newTweetsCallback;
      var _this = this;
      this.currentCallback = callback;
      this.manager.newTweetsCallback = null;
      var onFinishCallback = function() {
        var tweetsCallback = _this.currentCallback;
        _this.currentCallback = null;

        _this.updateNewTweets();
        _this.manager.updateAlert();
        _this.giveMeTweets(tweetsCallback, false, true);
        _this.manager.newTweetsCallback = oldNewTweetsCallback;
      }
      this._fetchNewTweets(onFinishCallback);
      return;
    }
    if(cacheOnly && !this.firstRun) {
      //Only return cached results if this is not the first run.
      if(!keepCache) {
        this._cleanUpCache();
      }
      try {
        callback(this.tweetsCache, this.timelineId);
      } catch(e) {
        /* ignoring exception, popup might be closed */
      }
      return;
    }
    //If we didn't return yet it's because we want to fetch old tweets
    //from twitter's API.

    this.currentCallback = callback;
    var _this = this;
    var params = this._makeOldTweetsRequestParams(suggestedCount);
    var context = {
      usingMaxId: !!params.max_id
    };
    this._doBackendRequest(this.timelinePath, function(success, tweets, status, context) {
      _this._onFetch.call(_this, success, _this._filterBlockedTweets(tweets), status, context);
    }, context, params);
  },

  updateNewTweets: function() {
    this.tweetsCache = this.newTweetsCache.concat(this.tweetsCache);
    this.newTweetsCache = [];
    this.unreadNotified = [];
  },

  newTweetsCount: function() {
    var unreadCount = 0;
    for(var i = this.newTweetsCache.length - 1; i >= 0; --i) {
      if(!this.manager.isTweetRead(this.newTweetsCache[i].id)) {
        ++unreadCount;
      }
    }
    return [this.newTweetsCache.length, unreadCount];
  },

  getNewUnreadTweets: function() {
    var unreadNewList = [];
    for(var i = 0; i < this.newTweetsCache.length; ++i) {
      if(!this.manager.isTweetRead(this.newTweetsCache[i].id) && !this.unreadNotified[this.newTweetsCache[i].id]) {
        unreadNewList.push(this.newTweetsCache[i]);
        this.unreadNotified[this.newTweetsCache[i].id] = true;
      }
    }
    return unreadNewList;
  },

  getNewUnreadIds: function() {
    var unreadNewIds = [];
    for(var i = 0; i < this.newTweetsCache.length; ++i) {
      if(!this.manager.isTweetRead(this.newTweetsCache[i].id)) {
        unreadNewIds.push(this.newTweetsCache[i].id);
      }
    }
    return unreadNewIds;
  },

  removeFromCache: function(id) {
    var i = 0;
    for(; i < this.tweetsCache.length; ++i) {
      if(this.tweetsCache[i].id == id)
        break;
    }
    if(i != this.tweetsCache.length) {
      this.tweetsCache.splice(i, 1);
    }
  },

  findTweet: function(id) {
    var i = 0;
    for(; i < this.tweetsCache.length; ++i) {
      if(this.tweetsCache[i].id == id)
        return this.tweetsCache[i];
    }
    return null;
  },

  getNewTweetsCache: function() {
    return this.newTweetsCache;
  },

  getTweetsCache: function() {
    return this.tweetsCache;
  },

  /* Private Methods */

  _setError: function(status) {
    this.currentError = status;
  },

  _setTimelinePath: function(path) {
    this.timelinePath = path;
  },

  _stopTimer: function() {
    if(this.timerId) {
      clearTimeout(this.timerId);
      this.timerId = null;
    }
  },

  _onFetchNew: function(success, tweets, status, context) {
    if(this.timelineStopped) {
      return;
    }
    var _this = this;
    if(!success) {
      this._setError(status);
      if(context.onFinish)
        context.onFinish(0);
      this.timerId = setTimeout(function() { _this._fetchNewTweets.call(_this); }, this.template.refreshInterval);
      return;
    }
    this._setError(null);

    this._syncNewTweets(tweets, context);

    if(tweets.length > 0) {
      this.manager.notifyNewTweets();
    }
    if(context.onFinish)
      context.onFinish(tweets.length);
    this.timerId = setTimeout(function() { _this._fetchNewTweets.call(_this); }, this.template.refreshInterval);
  },

  _doBackendRequest: function(path, callback, context, params) {
    this.manager.twitterBackend.timeline(path, callback, context, params);
  },

  _fetchNewTweets: function(onFinishCallback) {
    this._stopTimer();
    var _this = this;
    if(this.manager.suspend && !onFinishCallback) {
      this.timerId = setTimeout(function() { _this._fetchNewTweets.call(_this); }, this.template.refreshInterval);
      return;
    }
    var context = { onFinish: onFinishCallback };
    var params = this._makeNewTweetsRequestParams();
    this._doBackendRequest(this.timelinePath, function(success, tweets, status, context) {
      _this._onFetchNew.call(_this, success, _this._filterBlockedTweets(tweets), status, context);
    }, context, params);
  },

  _onFetch: function(success, tweets, status, context) {
    if(this.timelineStopped) {
      return;
    }
    if(!success) {
      this._setError(status);
      try {
        this.currentCallback(null);
      } catch(e) {
        /* ignoring exception, popup might be closed */
      }

      this._setError(null);
      this.currentCallback = null;
      return;
    }
    this._setError(null);
    this._syncOldTweets(tweets, context);

    // Let's clean this.currentCallback before calling it as
    // there might be unexpected errors and this should not block
    // the extension.
    var callback = this.currentCallback;
    this.currentCallback = null;
    try {
      callback(this.tweetsCache, this.timelineId);
    } catch(e) {
      /* ignoring exception, popup might be closed */
    }

    if(this.firstRun) {
      this.firstRun = false;
      var _this = this;
      this.timerId = setTimeout(function() { _this._fetchNewTweets.call(_this); }, this.template.refreshInterval);
    }
  },

  _cleanUpCache: function() {
    if(this.currentScroll != 0) {
      return;
    }
    var len = this.tweetsCache.length;
    if(len <= OptionsBackend.get('max_cached_tweets'))
      return;
    this.tweetsCache = this.tweetsCache.slice(0, OptionsBackend.get('max_cached_tweets') + 1);
  },

  _makeOldTweetsRequestParams: function(suggestedCount) {
    if(!suggestedCount) {
      suggestedCount = OptionsBackend.get('tweets_per_page');
    }
    var params = {count: suggestedCount, per_page: suggestedCount};
    var maxId = null;
    if(this.tweetsCache.length > 0) {
      maxId = this.tweetsCache[this.tweetsCache.length - 1].id;
    }
    if(maxId) {
      params.max_id = maxId;
    }
    return params;
  },

  _makeNewTweetsRequestParams: function() {
    var lastId = null;
    if(this.newTweetsCache.length > 0) {
      lastId = this.newTweetsCache[0].id;
    } else if(this.tweetsCache.length > 0) {
      lastId = this.tweetsCache[0].id;
    }
    var params = {};
    if(lastId) {
      params.since_id = lastId;
    }
    return params;
  },

  _syncOldTweets: function(tweets, context) {
    var i = 0;
    if(context.usingMaxId) {
      // If we're fetching using maxId, ignore the first one (we already have it)
      i = 1;
    }
    for(; i < tweets.length; ++i) {
      this.tweetsCache.push(tweets[i]);
    }
  },

  _syncNewTweets: function(tweets, context) {
    for(var i = tweets.length - 1; i >= 0; --i) {
      this.newTweetsCache.unshift(tweets[i]);
      var tid = tweets[i].id;
      if(context.onFinish) {
        this.manager.readTweet(tid);
      } else if(!this.manager.readTweets[tid]) {
        this.manager.unreadTweets[tid] = true;
      }
    }
  },

  /**
  * Filter-out all tweets and retweets that contain a status.user.id
  * or status.retweeted_status.user.id in this.manager.blockedUserIds.
  *
  * @param json tweets - response as returned by a Twitter timeline REST method
  * @return json
  */
  _filterBlockedTweets: function(tweets) {
    var filteredTweets = [];
    for(var i in tweets) {
      if(!(tweets[i].user && tweets[i].user.id in this.manager.blockedUserIds || tweets[i].retweeted_status && tweets[i].retweeted_status.user.id in this.manager.blockedUserIds)) {
        filteredTweets.push(tweets[i]);
      }
    }
    return filteredTweets;
  }
};<|endoftext|>


<commit_before>define(function (require, exports, module) {
  var ecmaIdentifiers = [
    'Array',
    'Boolean',
    'Date',
    'decodeURI',
    'decodeURIComponent',
    'encodeURI',
    'encodeURIComponent',
    'Error',
    'eval',
    'EvalError',
    'Function',
    'hasOwnProperty',
    'isFinite',
    'isNaN',
    'JSON',
    'Math',
    'Map',
    'NaN',
    'Number',
    'Object',
    'parseInt',
    'parseFloat',
    'RangeError',
    'ReferenceError',
    'RegExp',
    'Set',
    'String',
    'SyntaxError',
    'TypeError',
    'URIError',
    'WeakMap'
  ];

  var browserGlobals = [
    'Audio',
    'Blob',
    'addEventListener',
    'applicationCache',
    'atob',
    'blur',
    'btoa',
    'clearInterval',
    'clearTimeout',
    'close',
    'closed',
    'CustomEvent',
    'DOMParser',
    'defaultStatus',
    'document',
    'Element',
    'ElementTimeControl',
    'event',
    'FileReader',
    'FormData',
    'focus',
    'frames',
    'getComputedStyle',
    'HTMLElement',
    'HTMLAnchorElement',
    'HTMLBaseElement',
    'HTMLBlockquoteElement',
    'HTMLBodyElement',
    'HTMLBRElement',
    'HTMLButtonElement',
    'HTMLCanvasElement',
    'HTMLDirectoryElement',
    'HTMLDivElement',
    'HTMLDListElement',
    'HTMLFieldSetElement',
    'HTMLFontElement',
    'HTMLFormElement',
    'HTMLFrameElement',
    'HTMLFrameSetElement',
    'HTMLHeadElement',
    'HTMLHeadingElement',
    'HTMLHRElement',
    'HTMLHtmlElement',
    'HTMLIFrameElement',
    'HTMLImageElement',
    'HTMLInputElement',
    'HTMLIsIndexElement',
    'HTMLLabelElement',
    'HTMLLayerElement',
    'HTMLLegendElement',
    'HTMLLIElement',
    'HTMLLinkElement',
    'HTMLMapElement',
    'HTMLMenuElement',
    'HTMLMetaElement',
    'HTMLModElement',
    'HTMLObjectElement',
    'HTMLOListElement',
    'HTMLOptGroupElement',
    'HTMLOptionElement',
    'HTMLParagraphElement',
    'HTMLParamElement',
    'HTMLPreElement',
    'HTMLQuoteElement',
    'HTMLScriptElement',
    'HTMLSelectElement',
    'HTMLStyleElement',
    'HTMLTableCaptionElement',
    'HTMLTableCellElement',
    'HTMLTableColElement',
    'HTMLTableElement',
    'HTMLTableRowElement',
    'HTMLTableSectionElement',
    'HTMLTextAreaElement',
    'HTMLTitleElement',
    'HTMLUListElement',
    'HTMLVideoElement',
    'history',
    'Image',
    'length',
    'localStorage',
    'location',
    'MessageChannel',
    'MessageEvent',
    'MessagePort',
    'MouseEvent',
    'moveBy',
    'moveTo',
    'MutationObserver',
    'name',
    'Node',
    'NodeFilter',
    'navigator',
    'onbeforeunload',
    'onblur',
    'onerror',
    'onfocus',
    'onload',
    'onresize',
    'onunload',
    'open',
    'openDatabase',
    'opener',
    'Option',
    'parent',
    'print',
    'removeEventListener',
    'resizeBy',
    'resizeTo',
    'screen',
    'scroll',
    'scrollBy',
    'scrollTo',
    'sessionStorage',
    'setInterval',
    'setTimeout',
    'SharedWorker',
    'status',
    'SVGAElement',
    'SVGAltGlyphDefElement',
    'SVGAltGlyphElement',
    'SVGAltGlyphItemElement',
    'SVGAngle',
    'SVGAnimateColorElement',
    'SVGAnimateElement',
    'SVGAnimateMotionElement',
    'SVGAnimateTransformElement',
    'SVGAnimatedAngle',
    'SVGAnimatedBoolean',
    'SVGAnimatedEnumeration',
    'SVGAnimatedInteger',
    'SVGAnimatedLength',
    'SVGAnimatedLengthList',
    'SVGAnimatedNumber',
    'SVGAnimatedNumberList',
    'SVGAnimatedPathData',
    'SVGAnimatedPoints',
    'SVGAnimatedPreserveAspectRatio',
    'SVGAnimatedRect',
    'SVGAnimatedString',
    'SVGAnimatedTransformList',
    'SVGAnimationElement',
    'SVGCSSRule',
    'SVGCircleElement',
    'SVGClipPathElement',
    'SVGColor',
    'SVGColorProfileElement',
    'SVGColorProfileRule',
    'SVGComponentTransferFunctionElement',
    'SVGCursorElement',
    'SVGDefsElement',
    'SVGDescElement',
    'SVGDocument',
    'SVGElement',
    'SVGElementInstance',
    'SVGElementInstanceList',
    'SVGEllipseElement',
    'SVGExternalResourcesRequired',
    'SVGFEBlendElement',
    'SVGFEColorMatrixElement',
    'SVGFEComponentTransferElement',
    'SVGFECompositeElement',
    'SVGFEConvolveMatrixElement',
    'SVGFEDiffuseLightingElement',
    'SVGFEDisplacementMapElement',
    'SVGFEDistantLightElement',
    'SVGFEFloodElement',
    'SVGFEFuncAElement',
    'SVGFEFuncBElement',
    'SVGFEFuncGElement',
    'SVGFEFuncRElement',
    'SVGFEGaussianBlurElement',
    'SVGFEImageElement',
    'SVGFEMergeElement',
    'SVGFEMergeNodeElement',
    'SVGFEMorphologyElement',
    'SVGFEOffsetElement',
    'SVGFEPointLightElement',
    'SVGFESpecularLightingElement',
    'SVGFESpotLightElement',
    'SVGFETileElement',
    'SVGFETurbulenceElement',
    'SVGFilterElement',
    'SVGFilterPrimitiveStandardAttributes',
    'SVGFitToViewBox',
    'SVGFontElement',
    'SVGFontFaceElement',
    'SVGFontFaceFormatElement',
    'SVGFontFaceNameElement',
    'SVGFontFaceSrcElement',
    'SVGFontFaceUriElement',
    'SVGForeignObjectElement',
    'SVGGElement',
    'SVGGlyphElement',
    'SVGGlyphRefElement',
    'SVGGradientElement',
    'SVGHKernElement',
    'SVGICCColor',
    'SVGImageElement',
    'SVGLangSpace',
    'SVGLength',
    'SVGLengthList',
    'SVGLineElement',
    'SVGLinearGradientElement',
    'SVGLocatable',
    'SVGMPathElement',
    'SVGMarkerElement',
    'SVGMaskElement',
    'SVGMatrix',
    'SVGMetadataElement',
    'SVGMissingGlyphElement',
    'SVGNumber',
    'SVGNumberList',
    'SVGPaint',
    'SVGPathElement',
    'SVGPathSeg',
    'SVGPathSegArcAbs',
    'SVGPathSegArcRel',
    'SVGPathSegClosePath',
    'SVGPathSegCurvetoCubicAbs',
    'SVGPathSegCurvetoCubicRel',
    'SVGPathSegCurvetoCubicSmoothAbs',
    'SVGPathSegCurvetoCubicSmoothRel',
    'SVGPathSegCurvetoQuadraticAbs',
    'SVGPathSegCurvetoQuadraticRel',
    'SVGPathSegCurvetoQuadraticSmoothAbs',
    'SVGPathSegCurvetoQuadraticSmoothRel',
    'SVGPathSegLinetoAbs',
    'SVGPathSegLinetoHorizontalAbs',
    'SVGPathSegLinetoHorizontalRel',
    'SVGPathSegLinetoRel',
    'SVGPathSegLinetoVerticalAbs',
    'SVGPathSegLinetoVerticalRel',
    'SVGPathSegList',
    'SVGPathSegMovetoAbs',
    'SVGPathSegMovetoRel',
    'SVGPatternElement',
    'SVGPoint',
    'SVGPointList',
    'SVGPolygonElement',
    'SVGPolylineElement',
    'SVGPreserveAspectRatio',
    'SVGRadialGradientElement',
    'SVGRect',
    'SVGRectElement',
    'SVGRenderingIntent',
    'SVGSVGElement',
    'SVGScriptElement',
    'SVGSetElement',
    'SVGStopElement',
    'SVGStringList',
    'SVGStylable',
    'SVGStyleElement',
    'SVGSwitchElement',
    'SVGSymbolElement',
    'SVGTRefElement',
    'SVGTSpanElement',
    'SVGTests',
    'SVGTextContentElement',
    'SVGTextElement',
    'SVGTextPathElement',
    'SVGTextPositioningElement',
    'SVGTitleElement',
    'SVGTransform',
    'SVGTransformList',
    'SVGTransformable',
    'SVGURIReference',
    'SVGUnitTypes',
    'SVGUseElement',
    'SVGVKernElement',
    'SVGViewElement',
    'SVGViewSpec',
    'SVGZoomAndPan',
    'TimeEvent',
    'top',
    'WebSocket',
    'window',
    'Worker',
    'XMLHttpRequest',
    'XMLSerializer',
    'XPathEvaluator',
    'XPathException',
    'XPathExpression',
    'XPathNamespace',
    'XPathNSResolver',
    'XPathResult'
  ];

  var developmentGlobals = [
    "alert",
    "confirm",
    "console",
    "Debug",
    "prompt"
  ];

  var workerGlobals = [
    "importScripts",
    "postMessage",
    "self"
  ];

  var nodeGlobals = [
    '__filename',
    '__dirname',
    'Buffer',
    'console',
    'exports',
    'GLOBAL',
    'global',
    'module',
    'process',
    'require',
    'setTimeout',
    'clearTimeout',
    'setInterval',
    'clearInterval',
    'setImmediate',
    'clearImmediate'
  ];

  var jquery = [
    '$',
    'jQuery'
  ];

  var globals = {};
  ecmaIdentifiers.concat(browserGlobals).concat(developmentGlobals).concat(workerGlobals).concat(nodeGlobals).concat(jquery).forEach(function (name) {
    globals[name] = true;
  });
  module.exports = globals;
});
<commit_msg>whitelist describe and it so mocha is slightly less annoying<commit_after>define(function (require, exports, module) {
  var ecmaIdentifiers = [
    'Array',
    'Boolean',
    'Date',
    'decodeURI',
    'decodeURIComponent',
    'encodeURI',
    'encodeURIComponent',
    'Error',
    'eval',
    'EvalError',
    'Function',
    'hasOwnProperty',
    'isFinite',
    'isNaN',
    'JSON',
    'Math',
    'Map',
    'NaN',
    'Number',
    'Object',
    'parseInt',
    'parseFloat',
    'RangeError',
    'ReferenceError',
    'RegExp',
    'Set',
    'String',
    'SyntaxError',
    'TypeError',
    'URIError',
    'WeakMap'
  ];

  var browserGlobals = [
    'Audio',
    'Blob',
    'addEventListener',
    'applicationCache',
    'atob',
    'blur',
    'btoa',
    'clearInterval',
    'clearTimeout',
    'close',
    'closed',
    'CustomEvent',
    'DOMParser',
    'defaultStatus',
    'document',
    'Element',
    'ElementTimeControl',
    'event',
    'FileReader',
    'FormData',
    'focus',
    'frames',
    'getComputedStyle',
    'HTMLElement',
    'HTMLAnchorElement',
    'HTMLBaseElement',
    'HTMLBlockquoteElement',
    'HTMLBodyElement',
    'HTMLBRElement',
    'HTMLButtonElement',
    'HTMLCanvasElement',
    'HTMLDirectoryElement',
    'HTMLDivElement',
    'HTMLDListElement',
    'HTMLFieldSetElement',
    'HTMLFontElement',
    'HTMLFormElement',
    'HTMLFrameElement',
    'HTMLFrameSetElement',
    'HTMLHeadElement',
    'HTMLHeadingElement',
    'HTMLHRElement',
    'HTMLHtmlElement',
    'HTMLIFrameElement',
    'HTMLImageElement',
    'HTMLInputElement',
    'HTMLIsIndexElement',
    'HTMLLabelElement',
    'HTMLLayerElement',
    'HTMLLegendElement',
    'HTMLLIElement',
    'HTMLLinkElement',
    'HTMLMapElement',
    'HTMLMenuElement',
    'HTMLMetaElement',
    'HTMLModElement',
    'HTMLObjectElement',
    'HTMLOListElement',
    'HTMLOptGroupElement',
    'HTMLOptionElement',
    'HTMLParagraphElement',
    'HTMLParamElement',
    'HTMLPreElement',
    'HTMLQuoteElement',
    'HTMLScriptElement',
    'HTMLSelectElement',
    'HTMLStyleElement',
    'HTMLTableCaptionElement',
    'HTMLTableCellElement',
    'HTMLTableColElement',
    'HTMLTableElement',
    'HTMLTableRowElement',
    'HTMLTableSectionElement',
    'HTMLTextAreaElement',
    'HTMLTitleElement',
    'HTMLUListElement',
    'HTMLVideoElement',
    'history',
    'Image',
    'length',
    'localStorage',
    'location',
    'MessageChannel',
    'MessageEvent',
    'MessagePort',
    'MouseEvent',
    'moveBy',
    'moveTo',
    'MutationObserver',
    'name',
    'Node',
    'NodeFilter',
    'navigator',
    'onbeforeunload',
    'onblur',
    'onerror',
    'onfocus',
    'onload',
    'onresize',
    'onunload',
    'open',
    'openDatabase',
    'opener',
    'Option',
    'parent',
    'print',
    'removeEventListener',
    'resizeBy',
    'resizeTo',
    'screen',
    'scroll',
    'scrollBy',
    'scrollTo',
    'sessionStorage',
    'setInterval',
    'setTimeout',
    'SharedWorker',
    'status',
    'SVGAElement',
    'SVGAltGlyphDefElement',
    'SVGAltGlyphElement',
    'SVGAltGlyphItemElement',
    'SVGAngle',
    'SVGAnimateColorElement',
    'SVGAnimateElement',
    'SVGAnimateMotionElement',
    'SVGAnimateTransformElement',
    'SVGAnimatedAngle',
    'SVGAnimatedBoolean',
    'SVGAnimatedEnumeration',
    'SVGAnimatedInteger',
    'SVGAnimatedLength',
    'SVGAnimatedLengthList',
    'SVGAnimatedNumber',
    'SVGAnimatedNumberList',
    'SVGAnimatedPathData',
    'SVGAnimatedPoints',
    'SVGAnimatedPreserveAspectRatio',
    'SVGAnimatedRect',
    'SVGAnimatedString',
    'SVGAnimatedTransformList',
    'SVGAnimationElement',
    'SVGCSSRule',
    'SVGCircleElement',
    'SVGClipPathElement',
    'SVGColor',
    'SVGColorProfileElement',
    'SVGColorProfileRule',
    'SVGComponentTransferFunctionElement',
    'SVGCursorElement',
    'SVGDefsElement',
    'SVGDescElement',
    'SVGDocument',
    'SVGElement',
    'SVGElementInstance',
    'SVGElementInstanceList',
    'SVGEllipseElement',
    'SVGExternalResourcesRequired',
    'SVGFEBlendElement',
    'SVGFEColorMatrixElement',
    'SVGFEComponentTransferElement',
    'SVGFECompositeElement',
    'SVGFEConvolveMatrixElement',
    'SVGFEDiffuseLightingElement',
    'SVGFEDisplacementMapElement',
    'SVGFEDistantLightElement',
    'SVGFEFloodElement',
    'SVGFEFuncAElement',
    'SVGFEFuncBElement',
    'SVGFEFuncGElement',
    'SVGFEFuncRElement',
    'SVGFEGaussianBlurElement',
    'SVGFEImageElement',
    'SVGFEMergeElement',
    'SVGFEMergeNodeElement',
    'SVGFEMorphologyElement',
    'SVGFEOffsetElement',
    'SVGFEPointLightElement',
    'SVGFESpecularLightingElement',
    'SVGFESpotLightElement',
    'SVGFETileElement',
    'SVGFETurbulenceElement',
    'SVGFilterElement',
    'SVGFilterPrimitiveStandardAttributes',
    'SVGFitToViewBox',
    'SVGFontElement',
    'SVGFontFaceElement',
    'SVGFontFaceFormatElement',
    'SVGFontFaceNameElement',
    'SVGFontFaceSrcElement',
    'SVGFontFaceUriElement',
    'SVGForeignObjectElement',
    'SVGGElement',
    'SVGGlyphElement',
    'SVGGlyphRefElement',
    'SVGGradientElement',
    'SVGHKernElement',
    'SVGICCColor',
    'SVGImageElement',
    'SVGLangSpace',
    'SVGLength',
    'SVGLengthList',
    'SVGLineElement',
    'SVGLinearGradientElement',
    'SVGLocatable',
    'SVGMPathElement',
    'SVGMarkerElement',
    'SVGMaskElement',
    'SVGMatrix',
    'SVGMetadataElement',
    'SVGMissingGlyphElement',
    'SVGNumber',
    'SVGNumberList',
    'SVGPaint',
    'SVGPathElement',
    'SVGPathSeg',
    'SVGPathSegArcAbs',
    'SVGPathSegArcRel',
    'SVGPathSegClosePath',
    'SVGPathSegCurvetoCubicAbs',
    'SVGPathSegCurvetoCubicRel',
    'SVGPathSegCurvetoCubicSmoothAbs',
    'SVGPathSegCurvetoCubicSmoothRel',
    'SVGPathSegCurvetoQuadraticAbs',
    'SVGPathSegCurvetoQuadraticRel',
    'SVGPathSegCurvetoQuadraticSmoothAbs',
    'SVGPathSegCurvetoQuadraticSmoothRel',
    'SVGPathSegLinetoAbs',
    'SVGPathSegLinetoHorizontalAbs',
    'SVGPathSegLinetoHorizontalRel',
    'SVGPathSegLinetoRel',
    'SVGPathSegLinetoVerticalAbs',
    'SVGPathSegLinetoVerticalRel',
    'SVGPathSegList',
    'SVGPathSegMovetoAbs',
    'SVGPathSegMovetoRel',
    'SVGPatternElement',
    'SVGPoint',
    'SVGPointList',
    'SVGPolygonElement',
    'SVGPolylineElement',
    'SVGPreserveAspectRatio',
    'SVGRadialGradientElement',
    'SVGRect',
    'SVGRectElement',
    'SVGRenderingIntent',
    'SVGSVGElement',
    'SVGScriptElement',
    'SVGSetElement',
    'SVGStopElement',
    'SVGStringList',
    'SVGStylable',
    'SVGStyleElement',
    'SVGSwitchElement',
    'SVGSymbolElement',
    'SVGTRefElement',
    'SVGTSpanElement',
    'SVGTests',
    'SVGTextContentElement',
    'SVGTextElement',
    'SVGTextPathElement',
    'SVGTextPositioningElement',
    'SVGTitleElement',
    'SVGTransform',
    'SVGTransformList',
    'SVGTransformable',
    'SVGURIReference',
    'SVGUnitTypes',
    'SVGUseElement',
    'SVGVKernElement',
    'SVGViewElement',
    'SVGViewSpec',
    'SVGZoomAndPan',
    'TimeEvent',
    'top',
    'WebSocket',
    'window',
    'Worker',
    'XMLHttpRequest',
    'XMLSerializer',
    'XPathEvaluator',
    'XPathException',
    'XPathExpression',
    'XPathNamespace',
    'XPathNSResolver',
    'XPathResult'
  ];

  var developmentGlobals = [
    "alert",
    "confirm",
    "console",
    "Debug",
    "prompt"
  ];

  var workerGlobals = [
    "importScripts",
    "postMessage",
    "self"
  ];

  var nodeGlobals = [
    '__filename',
    '__dirname',
    'Buffer',
    'console',
    'exports',
    'GLOBAL',
    'global',
    'module',
    'process',
    'require',
    'setTimeout',
    'clearTimeout',
    'setInterval',
    'clearInterval',
    'setImmediate',
    'clearImmediate'
  ];

  var jquery = [
    '$',
    'jQuery'
  ];

  var mocha = [
    'describe',
    'it'
  ];

  var globals = {};
  ecmaIdentifiers.concat(browserGlobals).concat(developmentGlobals).concat(workerGlobals).concat(nodeGlobals).concat(jquery).concat(mocha).forEach(function (name) {
    globals[name] = true;
  });
  module.exports = globals;
});
<|endoftext|>


<commit_before>'use strict';

const express     = require('express');
const bodyParser  = require('body-parser');
const firebase    = require('firebase');
const app         = express();
const router      = express.Router();
const config      = require('./server/config');
const emailGateway = require('./server/email_gateway');
const port        = config.port;

const helpers     = require('./server/helpers.js');

firebase.initializeApp({
  "databaseURL": "https://project-6353258358688553392.firebaseio.com",
  "serviceAccount": {
    "type": "service_account",
    "project_id": process.env.PROJECT_ID,
    "private_key_id": process.env.FIREBASE_PRIVATE_KEY_ID,
    "private_key": process.env.FIREBASE_PRIVATE_KEY,
    "client_email": process.env.CLIENT_EMAIL,
    "client_id": process.env.CLIENT_ID,
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://accounts.google.com/o/oauth2/token",
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/subsystem33%40project-6353258358688553392.iam.gserviceaccount.com"
  }
});

var db = firebase.database();
var ref = db.ref("collections");

app.use(express.static(__dirname + '/build'));
app.use('/api', router);

router.use(bodyParser.json());

router
  .get('/collections/:date', (req, res) => {

    var date = req.params.date;

    var ref = firebase.database().ref("collections");
    ref.orderByChild("donation/date").equalTo(parseInt(date)).once('value').then(function(snapshot) {
      res.json(snapshot.val());
    });

  })
  .get('/collection/:key', (req, res) => {

    var key = req.params.key;

    var ref = firebase.database().ref("collections");
    ref.orderByKey().equalTo(key).once('value').then(function(snapshot) {
      res.json(snapshot.val());
    });

  })
  .post('/collection', (req, res) => {

    var key = req.query.key;

    if (key == undefined) {
      firebase.database().ref('/collections/').push(req.body).then(function(result) {
        console.log('blah')
        emailGateway.sendThankYouEmail({ to: req.customer.email });
        res.json({ response: 'request received!' });
      });
    } else {
      var updates = {};
      updates['/collections/' + key] = req.body;
      firebase.database().ref().update(updates).then(function(result) {
        console.log('blah1')
        emailGateway.sendThankYouEmail({ to: req.customer.email });
        res.json({ response: 'request received!' });
      });
    }

  });
router.route('/emails/thank-you')
  .post((req, res) => {
    emailGateway.sendThankYouEmail({ to: req.body.to });

    res.json({ status: 'ok' });
  });

app.listen(port, () => {
  console.log(`Now listening on ${ port }`);
});
<commit_msg>server update<commit_after>'use strict';

const express     = require('express');
const bodyParser  = require('body-parser');
const firebase    = require('firebase');
const app         = express();
const router      = express.Router();
const config      = require('./server/config');
const emailGateway = require('./server/email_gateway');
const port        = config.port;

const helpers     = require('./server/helpers.js');

firebase.initializeApp({
  "databaseURL": "https://project-6353258358688553392.firebaseio.com",
  "serviceAccount": {
    "type": "service_account",
    "project_id": process.env.PROJECT_ID,
    "private_key_id": process.env.FIREBASE_PRIVATE_KEY_ID,
    "private_key": process.env.FIREBASE_PRIVATE_KEY,
    "client_email": process.env.CLIENT_EMAIL,
    "client_id": process.env.CLIENT_ID,
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://accounts.google.com/o/oauth2/token",
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/subsystem33%40project-6353258358688553392.iam.gserviceaccount.com"
  }
});

var db = firebase.database();
var ref = db.ref("collections");

app.use(express.static(__dirname + '/build'));
app.use('/api', router);

router.use(bodyParser.json());

router
  .get('/collections/:date', (req, res) => {

    var date = req.params.date;

    var ref = firebase.database().ref("collections");
    ref.orderByChild("donation/date").equalTo(parseInt(date)).once('value').then(function(snapshot) {
      res.json(snapshot.val());
    });

  })
  .get('/collection/:key', (req, res) => {

    var key = req.params.key;

    var ref = firebase.database().ref("collections");
    ref.orderByKey().equalTo(key).once('value').then(function(snapshot) {
      res.json(snapshot.val());
    });

  })
  .post('/collection', (req, res) => {

    var key = req.query.key;

    if (key == undefined) {
      firebase.database().ref('/collections/').push(req.body).then(function(result) {
        console.log('blah');
        res.json({ response: 'request received!' });
        emailGateway.sendThankYouEmail({ to: req.customer.email });
      });
    } else {
      var updates = {};
      updates['/collections/' + key] = req.body;
      firebase.database().ref().update(updates).then(function(result) {
        console.log('blah1')
        res.json({ response: 'request received!' });
        emailGateway.sendThankYouEmail({ to: req.customer.email });
      });
    }

  });
router.route('/emails/thank-you')
  .post((req, res) => {
    emailGateway.sendThankYouEmail({ to: req.body.to });

    res.json({ status: 'ok' });
  });

app.listen(port, () => {
  console.log(`Now listening on ${ port }`);
});
<|endoftext|>


<commit_before>import { create_float_buffer, create_index_buffer, gl, program } from './context.js';
import { mat4 } from 'gl-matrix';

const zero_vector = {
  x: 0,
  y: 0,
  z: 0
};

const unit_vector = {
  x: 1,
  y: 1,
  z: 1
};

let id = 0;

const to_vec = (obj) => [obj.x, obj.y, obj.z];

class Entity {
  constructor(options) {
    this.id = id++;
    this.position = Object.assign({}, zero_vector);
    this.rotation = Object.assign({}, zero_vector);
    this.scale = Object.assign({}, unit_vector);

    this.indices = options.indices;
    this.vertices = options.vertices;

    this.create_buffers();

    this.rotation_offset = Math.random();
  }

  create_buffers() {
    this.buffers = {
      vertices: create_float_buffer(this.vertices),
      indices: create_index_buffer(this.indices),
      qty: this.indices.length
    }
  }

  update() {
    const model_view_matrix = mat4.identity(mat4.create());
    mat4.translate(model_view_matrix, model_view_matrix, to_vec(this.position));
    mat4.rotate(model_view_matrix, model_view_matrix, this.rotation.x, [1, 0, 0]);
    mat4.rotate(model_view_matrix, model_view_matrix, this.rotation.y, [0, 1, 0]);
    mat4.rotate(model_view_matrix, model_view_matrix, this.rotation.z, [0, 0, 1]);
    mat4.scale(model_view_matrix, model_view_matrix, to_vec(this.scale));

    this.model_view_matrix = model_view_matrix;
  }

  render() {
    gl.bindBuffer(gl.ARRAY_BUFFER, this.buffers.vertices);
    gl.vertexAttribPointer(gl.getAttribLocation(program, "aVertex"), 3, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.buffers.indices);
    gl.drawElements(gl.TRIANGLES, this.buffers.qty, gl.UNSIGNED_SHORT, 0);

    gl.uniformMatrix4fv(
      gl.getUniformLocation(program, "uModelView"),
      false,
      this.model_view_matrix
    );
  }
}

export { Entity }
<commit_msg>:cactus: Use utils from util.js<commit_after>import { create_float_buffer, create_index_buffer, gl, program } from './context.js';
import { mat4 } from 'gl-matrix';
import { obj_to_vec } from './utils.js';

const zero_vector = {
  x: 0,
  y: 0,
  z: 0
};

const unit_vector = {
  x: 1,
  y: 1,
  z: 1
};

class Entity {
  constructor(options) {
    this.position = Object.assign({}, zero_vector);
    this.rotation = Object.assign({}, zero_vector);
    this.scale = Object.assign({}, unit_vector);

    this.indices = options.indices;
    this.vertices = options.vertices;

    this.create_buffers();

    this.rotation_offset = Math.random();
  }

  create_buffers() {
    this.buffers = {
      vertices: create_float_buffer(this.vertices),
      indices: create_index_buffer(this.indices),
      qty: this.indices.length
    }
  }

  update() {
    const model_view_matrix = mat4.identity(mat4.create());
    mat4.translate(model_view_matrix, model_view_matrix, obj_to_vec(this.position));
    mat4.rotate(model_view_matrix, model_view_matrix, this.rotation.x, [1, 0, 0]);
    mat4.rotate(model_view_matrix, model_view_matrix, this.rotation.y, [0, 1, 0]);
    mat4.rotate(model_view_matrix, model_view_matrix, this.rotation.z, [0, 0, 1]);
    mat4.scale(model_view_matrix, model_view_matrix, obj_to_vec(this.scale));

    this.model_view_matrix = model_view_matrix;
  }

  render() {
    gl.bindBuffer(gl.ARRAY_BUFFER, this.buffers.vertices);
    gl.vertexAttribPointer(gl.getAttribLocation(program, "aVertex"), 3, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.buffers.indices);
    gl.drawElements(gl.TRIANGLES, this.buffers.qty, gl.UNSIGNED_SHORT, 0);

    gl.uniformMatrix4fv(
      gl.getUniformLocation(program, "uModelView"),
      false,
      this.model_view_matrix
    );
  }
}

export { Entity }
<|endoftext|>


<commit_before>(function($) {

	Symphony.Language.add({
		'today': false,
		'yesterday': false,
		'tomorrow': false
	});

	Symphony.DateTime = {

		// Reduce timestamp to days
		reduce: function(timestamp) {
			return Math.floor((this.clearTime(timestamp) + 7200000) / 86400000);
		},

		// Given a timestamp, set the hours and minutes of the resulting
		// date to 0, for use with selection detection
		clearTime: function(timestamp) {
			if(timestamp == '') return timestamp;

			var date = new Date(parseInt(timestamp));
			date.setHours(0);
			date.setMinutes(0);

			return date.getTime();
		}
	};

	/**
	 * The Date and Time extension provides an interface to add
	 * one or more single dates or date ranges to an entry.
	 *
	 * @author: Nils Hörrmann, post@nilshoerrmann.de
	 * @source: http://github.com/nilshoerrmann/datetime
	 */
	$(document).ready(function() {

		// Date and time
		$('div.field-datetime').each(function() {
			var manager = $(this),
				stage = manager.find('div.stage'),
				selection = stage.find('ul.selection');

		/*---- Events -----------------------------------------------------------*/

			// Constructing
			stage.bind('constructanim', function(event, item) {
				var input = item.find('input.start'),
					all = item.prevAll(),
					prev;

				// Prepopulate with previous date, if possible
				if(stage.is('.prepopulate') && all.length > 0 && !(selection.is('.destructing') && all.length == 1)) {
					prev = all.filter(':first').find('input.start');
					input.val(prev.val()).attr('data-timestamp', prev.attr('data-timestamp'));
				}
			});
			stage.bind('constructstop', function(event, item) {
				var input = item.find('input.start');

				// Store and contextualise date
				input.data('validated', input.val());
				contextualise(input);
			});

			// Visualising
			selection.delegate('input', 'focus', function() {
				var input = $(this),
					item = input.parents('li'),
					calendar = item.find('div.calendar'),
					dates = input.parent().addClass('focus'),
					date = input.attr('data-timestamp'),
					start = dates.find('input.start').attr('data-timestamp'),
					end = dates.find('input.end').attr('data-timestamp');

				// Set focus
				dates.addClass('focus').siblings('.focus').removeClass('focus');

				// Visualise
				if(!dates.is('.invalid')) {
					item.trigger('visualise', [{
						start: start,
						end: end
					}, date]);
					calendar.slideDown('fast');
				}
			});

			// Setting
			selection.delegate('li', 'setdate.datetime', function(event, range, focus, mode) {
				var item = $(this),
					start = item.find('input.start'),
					end = item.find('input.end'),
					from = mergeTimes(start.attr('data-timestamp'), range.start, mode),
					to;

				// Move multiple day range to single day
				if(mode === 'single') {
					to = mergeTimes(start.attr('data-timestamp'), range.end, mode);
				}
				else {
					to = mergeTimes(end.attr('data-timestamp'), range.end, mode);
				}

				// Date range
				if(range.start && range.end) {
					validate(start, from, false);
					validate(end, to, false);
					end.slideDown('fast');
					item.addClass('range');
				}

				// Single date
				else {
					validate(start, from, false);
					empty(end);
					item.removeClass('range');
				}

				// Visualise
				item.trigger('visualise', [{
					start: from,
					end: to
				}, focus]);
			});
			selection.delegate('li', 'settime.datetime', function(event, first, last, mode, focus) {
				var item = $(this),
					start = item.find('.start'),
					end = item.find('.end'),
					range = {
						start: null,
						end: null
					},
					from, to;

				// Start time
				from = new Date(parseInt(start.attr('data-timestamp')));
				from.setHours(first.hours);
				from.setMinutes(first.minutes);
				range.start = from.getTime();

				// End time, date range over multiple days
				if(mode == 'multiple' && last != null) {
					to = new Date(parseInt(end.attr('data-timestamp')));
					to.setHours(last.hours);
					to.setMinutes(last.minutes);
					range.end = to.getTime();
				}

				// End time, date range on single day
				else if(mode == 'single' && last != null) {
					to = from;
					to.setHours(last.hours);
					to.setMinutes(last.minutes);
					range.end = to.getTime();
				}

				// Set focus
				if(focus == 'start') {
					focus = range.start;
				}
				else {
					focus = range.end;
				}

				// Visualise
				item.trigger('setdate', [range, focus, mode]);
			});

			// Keypress
			if(!stage.is('.simple')) {
				selection.delegate('input', 'keydown.datetime', function(event) {
					var input = $(this);

					// If tab is pressed while the user is in the first
					// date, allow the focus to shifted to the end date
					// instead of the calendar.
					if(event.which == 9 && !event.shiftKey && input.is('.start')) {
						input.nextAll('input.end').show().focus();
						event.preventDefault();
					}
				});
			}

			// Validating
			selection.delegate('input', 'blur.datetime', function(event) {
				var input = $(this),
					date = input.val(),
					validated = input.data('validated');

				// Empty date
				if(date == '') {
					empty(input);
				}

				// Validate
				else if(date != validated) {
					validate(input, date, true);
				}
			});

			// Closing
			$('body').bind('click.datetime', function() {

				// Hide calendar
				selection.find('div.calendar').slideUp('fast');
				selection.find('.focus').removeClass('focus');
			});

		/*---- Functions --------------------------------------------------------*/

			// Validate and set date
			var validate = function(input, date, visualise) {
				var item = input.parents('li'),
					dates = input.parent(),
					calendar = item.find('div.calendar');

				// Call validator
				if(input.attr('data-timestamp') != date) {
					$.ajax({
						type: 'GET',
						dataType: 'json',
						url: Symphony.Context.get('root') + '/symphony/extension/datetime/get/',
						data: {
							date: date,
							time: Math.min(calendar.find('.timeline').size(), 1)
						},
						success: function(parsed) {

							// Valid date
							if(parsed.status == 'valid') {
								input.attr('data-timestamp', parsed.timestamp).val(parsed.date).removeClass('invalid');

								// Visualise
								if(visualise === true) {
									item.trigger('visualise', [{
										start: dates.find('.start').attr('data-timestamp'),
										end: dates.find('.end').attr('data-timestamp')
									}, input.attr('data-timestamp')]);
								}
							}

							// Invalid date
							else {
								input.attr('data-timestamp', '').addClass('invalid');

								// Clear
								calendar.slideUp('fast');
							}

							// Store date
							input.data('validated', parsed.date);

							// Display status
							displayStatus(dates);

							// Get date context
							contextualise(input);
						}
					});
				}
			};

			// Merge new date with old times
			var mergeTimes = function(current, update, mode) {

				// Empty date
				if(update == null || update == '') {
					return '';
				}

				// New date
				else if(current == null || current == '') {
					return update;
				}

				// Existing date
				else {
					var time, date

					// Set date, keep time
					if(mode == 'date') {
						time = new Date(parseInt(current)),
						date = new Date(parseInt(update));
					}

					// Set time, keep date
					else {
						time = new Date(parseInt(update)),
						date = new Date(parseInt(current));
					}

					// Set hours and minutes
					date.setHours(time.getHours());
					date.setMinutes(time.getMinutes());

					return date.getTime();
				}
			}

			// Empty date
			var empty = function(input) {
				var item = input.parents('li'),
					dates = input.parent(),
					end = dates.find('.end');

				// Empty dates are valid
				input.removeClass('invalid');

				// Merge with end date
				if(input.is('.start') && end.val() != '') {
					input.val(end.val());
					end.val('');

					// Keep errors
					if(end.is('.invalid')) {
						end.removeClass('invalid');
						input.addClass('invalid');
					}
				}

				// Display status
				displayStatus(dates);

				// Hide end date
				end.attr('data-timestamp', '').slideUp('fast', function() {
					item.removeClass('range');
				});
			};

			// Display validity status
			var displayStatus = function(dates) {

				// At least one date is invalid
				if(dates.find('input.invalid').size() > 0) {
					dates.addClass('invalid');
				}

				// All dates are valid
				else {
					dates.removeClass('invalid');
				}
			};

			// Get context
			var contextualise = function(input) {
				var dates = input.parent(),
					time = parseInt(input.attr('data-timestamp')),
					now = new Date(),
					day, today, yesterday, tomorrow, label;

				// Reduze timestamps to days:
				day = Symphony.DateTime.reduce(time);
				today = Symphony.DateTime.reduce(now.getTime());

				// Create label
				if(day == today) {
					label = Symphony.Language.get('today');
				}
				else if(today - day == 1) {
					label = Symphony.Language.get('yesterday');
				}
				else if(day - today == 1) {
					label = Symphony.Language.get('tomorrow');
				}

				// Attach label
				if(label) {
					input.next('em.label').text(label).fadeIn('fast');
				}

				// Detach label
				else {
					input.next('em.label').fadeOut('fast');
				}
			};

		/*---- Initialisation ---------------------------------------------------*/

			// Create calendar and timer
			selection.symphonyCalendar();
			selection.symphonyTimer();

			// Store and contextualise dates
			selection.find('input').each(function() {
				var input = $(this);
				input.data('validated', input.val());
				contextualise(input);
			}).load();

			// Set errors
			selection.find('input.invalid').parents('span.dates').addClass('invalid');

		});

	});

})(jQuery.noConflict());
<commit_msg>Make sure end date is cleared when moving from a range to a single date<commit_after>(function($) {

	Symphony.Language.add({
		'today': false,
		'yesterday': false,
		'tomorrow': false
	});

	Symphony.DateTime = {

		// Reduce timestamp to days
		reduce: function(timestamp) {
			return Math.floor((this.clearTime(timestamp) + 7200000) / 86400000);
		},

		// Given a timestamp, set the hours and minutes of the resulting
		// date to 0, for use with selection detection
		clearTime: function(timestamp) {
			if(timestamp == '') return timestamp;

			var date = new Date(parseInt(timestamp));
			date.setHours(0);
			date.setMinutes(0);

			return date.getTime();
		}
	};

	/**
	 * The Date and Time extension provides an interface to add
	 * one or more single dates or date ranges to an entry.
	 *
	 * @author: Nils Hörrmann, post@nilshoerrmann.de
	 * @source: http://github.com/nilshoerrmann/datetime
	 */
	$(document).ready(function() {

		// Date and time
		$('div.field-datetime').each(function() {
			var manager = $(this),
				stage = manager.find('div.stage'),
				selection = stage.find('ul.selection');

		/*---- Events -----------------------------------------------------------*/

			// Constructing
			stage.bind('constructanim', function(event, item) {
				var input = item.find('input.start'),
					all = item.prevAll(),
					prev;

				// Prepopulate with previous date, if possible
				if(stage.is('.prepopulate') && all.length > 0 && !(selection.is('.destructing') && all.length == 1)) {
					prev = all.filter(':first').find('input.start');
					input.val(prev.val()).attr('data-timestamp', prev.attr('data-timestamp'));
				}
			});
			stage.bind('constructstop', function(event, item) {
				var input = item.find('input.start');

				// Store and contextualise date
				input.data('validated', input.val());
				contextualise(input);
			});

			// Visualising
			selection.delegate('input', 'focus', function() {
				var input = $(this),
					item = input.parents('li'),
					calendar = item.find('div.calendar'),
					dates = input.parent().addClass('focus'),
					date = input.attr('data-timestamp'),
					start = dates.find('input.start').attr('data-timestamp'),
					end = dates.find('input.end').attr('data-timestamp');

				// Set focus
				dates.addClass('focus').siblings('.focus').removeClass('focus');

				// Visualise
				if(!dates.is('.invalid')) {
					item.trigger('visualise', [{
						start: start,
						end: end
					}, date]);
					calendar.slideDown('fast');
				}
			});

			// Setting
			selection.delegate('li', 'setdate.datetime', function(event, range, focus, mode) {
				var item = $(this),
					start = item.find('input.start'),
					end = item.find('input.end'),
					from = mergeTimes(start.attr('data-timestamp'), range.start, mode),
					to;

				// Move multiple day range to single day
				if(mode === 'single') {
					to = mergeTimes(start.attr('data-timestamp'), range.end, mode);
				}
				else {
					to = mergeTimes(end.attr('data-timestamp'), range.end, mode);
				}

				// Date range
				if(range.start && range.end) {
					validate(start, from, false);
					validate(end, to, false);
					end.slideDown('fast');
					item.addClass('range');
				}

				// Single date
				else {
					validate(start, from, false);
					empty(end);
					item.removeClass('range');
				}

				// Visualise
				item.trigger('visualise', [{
					start: from,
					end: to
				}, focus]);
			});
			selection.delegate('li', 'settime.datetime', function(event, first, last, mode, focus) {
				var item = $(this),
					start = item.find('.start'),
					end = item.find('.end'),
					range = {
						start: null,
						end: null
					},
					from, to;

				// Start time
				from = new Date(parseInt(start.attr('data-timestamp')));
				from.setHours(first.hours);
				from.setMinutes(first.minutes);
				range.start = from.getTime();

				// End time, date range over multiple days
				if(mode == 'multiple' && last != null) {
					to = new Date(parseInt(end.attr('data-timestamp')));
					to.setHours(last.hours);
					to.setMinutes(last.minutes);
					range.end = to.getTime();
				}

				// End time, date range on single day
				else if(mode == 'single' && last != null) {
					to = from;
					to.setHours(last.hours);
					to.setMinutes(last.minutes);
					range.end = to.getTime();
				}

				// Set focus
				if(focus == 'start') {
					focus = range.start;
				}
				else {
					focus = range.end;
				}

				// Visualise
				item.trigger('setdate', [range, focus, mode]);
			});

			// Keypress
			if(!stage.is('.simple')) {
				selection.delegate('input', 'keydown.datetime', function(event) {
					var input = $(this);

					// If tab is pressed while the user is in the first
					// date, allow the focus to shifted to the end date
					// instead of the calendar.
					if(event.which == 9 && !event.shiftKey && input.is('.start')) {
						input.nextAll('input.end').show().focus();
						event.preventDefault();
					}
				});
			}

			// Validating
			selection.delegate('input', 'blur.datetime', function(event) {
				var input = $(this),
					date = input.val(),
					validated = input.data('validated');

				// Empty date
				if(date == '') {
					empty(input);
				}

				// Validate
				else if(date != validated) {
					validate(input, date, true);
				}
			});

			// Closing
			$('body').bind('click.datetime', function() {

				// Hide calendar
				selection.find('div.calendar').slideUp('fast');
				selection.find('.focus').removeClass('focus');
			});

		/*---- Functions --------------------------------------------------------*/

			// Validate and set date
			var validate = function(input, date, visualise) {
				var item = input.parents('li'),
					dates = input.parent(),
					calendar = item.find('div.calendar');

				// Call validator
				if(input.attr('data-timestamp') != date) {
					$.ajax({
						type: 'GET',
						dataType: 'json',
						url: Symphony.Context.get('root') + '/symphony/extension/datetime/get/',
						data: {
							date: date,
							time: Math.min(calendar.find('.timeline').size(), 1)
						},
						success: function(parsed) {

							// Valid date
							if(parsed.status == 'valid') {
								input.attr('data-timestamp', parsed.timestamp).val(parsed.date).removeClass('invalid');

								// Visualise
								if(visualise === true) {
									item.trigger('visualise', [{
										start: dates.find('.start').attr('data-timestamp'),
										end: dates.find('.end').attr('data-timestamp')
									}, input.attr('data-timestamp')]);
								}
							}

							// Invalid date
							else {
								input.attr('data-timestamp', '').addClass('invalid');

								// Clear
								calendar.slideUp('fast');
							}

							// Store date
							input.data('validated', parsed.date);

							// Display status
							displayStatus(dates);

							// Get date context
							contextualise(input);
						}
					});
				}
			};

			// Merge new date with old times
			var mergeTimes = function(current, update, mode) {

				// Empty date
				if(update == null || update == '') {
					return '';
				}

				// New date
				else if(current == null || current == '') {
					return update;
				}

				// Existing date
				else {
					var time, date

					// Set date, keep time
					if(mode == 'date') {
						time = new Date(parseInt(current)),
						date = new Date(parseInt(update));
					}

					// Set time, keep date
					else {
						time = new Date(parseInt(update)),
						date = new Date(parseInt(current));
					}

					// Set hours and minutes
					date.setHours(time.getHours());
					date.setMinutes(time.getMinutes());

					return date.getTime();
				}
			}

			// Empty date
			var empty = function(input) {
				var item = input.parents('li'),
					dates = input.parent(),
					end = dates.find('.end');

				// Empty dates are valid
				input.removeClass('invalid');

				// Merge with end date
				if(input.is('.start') && end.val() != '') {
					input.val(end.val());
					end.val('');

					// Keep errors
					if(end.is('.invalid')) {
						end.removeClass('invalid');
						input.addClass('invalid');
					}
				}

				// Display status
				displayStatus(dates);

				// Hide end date
				end.attr('data-timestamp', '').val('').slideUp('fast', function() {
					item.removeClass('range');
				});
			};

			// Display validity status
			var displayStatus = function(dates) {

				// At least one date is invalid
				if(dates.find('input.invalid').size() > 0) {
					dates.addClass('invalid');
				}

				// All dates are valid
				else {
					dates.removeClass('invalid');
				}
			};

			// Get context
			var contextualise = function(input) {
				var dates = input.parent(),
					time = parseInt(input.attr('data-timestamp')),
					now = new Date(),
					day, today, yesterday, tomorrow, label;

				// Reduze timestamps to days:
				day = Symphony.DateTime.reduce(time);
				today = Symphony.DateTime.reduce(now.getTime());

				// Create label
				if(day == today) {
					label = Symphony.Language.get('today');
				}
				else if(today - day == 1) {
					label = Symphony.Language.get('yesterday');
				}
				else if(day - today == 1) {
					label = Symphony.Language.get('tomorrow');
				}

				// Attach label
				if(label) {
					input.next('em.label').text(label).fadeIn('fast');
				}

				// Detach label
				else {
					input.next('em.label').fadeOut('fast');
				}
			};

		/*---- Initialisation ---------------------------------------------------*/

			// Create calendar and timer
			selection.symphonyCalendar();
			selection.symphonyTimer();

			// Store and contextualise dates
			selection.find('input').each(function() {
				var input = $(this);
				input.data('validated', input.val());
				contextualise(input);
			}).load();

			// Set errors
			selection.find('input.invalid').parents('span.dates').addClass('invalid');

		});

	});

})(jQuery.noConflict());
<|endoftext|>


<commit_before>var Q = require("q");
var request = Q.denodeify(require("request"));

function condense(options) {
  return request(options)
    .spread(function(response, body) {
      var code = response.statusCode;
      if (code === 200) {
        return Q(body);
      } else {
        throw new Error(JSON.stringify({statusCode: response.statusCode, body: body}));
      }
    });
}

function success(jsonObject) {
  var _ = require("lodash");
  return _.merge({
    response: "ok"
  }, jsonObject);
}

function fail(errCode, errMessage, jsonObject) {
  var _ = require("lodash");
  return _.merge({
    response: "fail",
    code: errCode,
    message: errMessage
  }, jsonObject);
}

function postJSONObject(url, JSONObject, timeout) {
  var options = {
    uri: url,
    json: true,
    body: JSONObject,
    method: "post"
  };
  if (timeout) {
    options.timeout = timeout;
  }
  return condense(options);
}

function postXML(url, xml) {
  var options = {
    uri: url,
    body: xml,
    headers: {
      'Content-Type': 'text/xml'
    },
    method: "post"
  };
  return condense(options);
}

function get(url) {
  var options = {
    uri: url,
    method: "get"
  };
  return condense(options);
}

function getJSON(url) {
  var options = {
    uri: url,
    json: true,
    header: {
      'Content-Type': 'application/json'
    },
    method: "get"
  };
  return condense(options);
}

function sendMail(to, subject, body) {
  var _ = require("lodash");
  var sendgrid = require('sendgrid')(sails.config.local.sendgrid.username, sails.config.local.sendgrid.password);

  compiled = _.template(body);
  var payload = {
    to: to,
    from: 'noreply@nodify.io',
    subject: subject,
    text: compiled()
  };
  var deferred = Q.defer();
  sendgrid.send(payload, function(err, json) {
    if (err) {
      deferred.reject(err);
    }
    deferred.resolve(json);
  });
  return deferred.promise;
}
;

// Functions which will be available to external callers
module.exports.success = success;
module.exports.fail = fail;
module.exports.postJSONObject = postJSONObject;
module.exports.postXML = postXML;
module.exports.get = get;
module.exports.sendMail = sendMail;
module.exports.getJSON = getJSON;<commit_msg>Adds existsIn function to check if any of the elements in an array exists in an other array<commit_after>var Q = require("q");
var request = Q.denodeify(require("request"));

function condense(options) {
  return request(options)
    .spread(function(response, body) {
      var code = response.statusCode;
      if (code === 200) {
        return Q(body);
      } else {
        throw new Error(JSON.stringify({statusCode: response.statusCode, body: body}));
      }
    });
}

function success(jsonObject) {
  var _ = require("lodash");
  return _.merge({
    response: "ok"
  }, jsonObject);
}

function fail(errCode, errMessage, jsonObject) {
  var _ = require("lodash");
  return _.merge({
    response: "fail",
    code: errCode,
    message: errMessage
  }, jsonObject);
}

function postJSONObject(url, JSONObject, timeout) {
  var options = {
    uri: url,
    json: true,
    body: JSONObject,
    method: "post"
  };
  if (timeout) {
    options.timeout = timeout;
  }
  return condense(options);
}

function postXML(url, xml) {
  var options = {
    uri: url,
    body: xml,
    headers: {
      'Content-Type': 'text/xml'
    },
    method: "post"
  };
  return condense(options);
}

function get(url) {
  var options = {
    uri: url,
    method: "get"
  };
  return condense(options);
}

function getJSON(url) {
  var options = {
    uri: url,
    json: true,
    header: {
      'Content-Type': 'application/json'
    },
    method: "get"
  };
  return condense(options);
}

function sendMail(to, subject, body) {
  var _ = require("lodash");
  var sendgrid = require('sendgrid')(sails.config.local.sendgrid.username, sails.config.local.sendgrid.password);

  compiled = _.template(body);
  var payload = {
    to: to,
    from: 'noreply@nodify.io',
    subject: subject,
    text: compiled()
  };
  var deferred = Q.defer();
  sendgrid.send(payload, function(err, json) {
    if (err) {
      deferred.reject(err);
    }
    deferred.resolve(json);
  });
  return deferred.promise;
}

function existsIn(sourceArray, itemsToMatch) {
  return sourceArray.some(function(sourceElement) {
    return itemsToMatch.some(function(matchElement) {
      return matchElement === sourceElement;
    });
  });
}

// Functions which will be available to external callers
module.exports.success = success;
module.exports.fail = fail;
module.exports.postJSONObject = postJSONObject;
module.exports.postXML = postXML;
module.exports.get = get;
module.exports.sendMail = sendMail;
module.exports.getJSON = getJSON;
module.exports.existsIn = existsIn;<|endoftext|>


<commit_before>#!/bin/env node
//  OpenShift sample Node application
var express = require('express');
var request = require('request');
var fs      = require('fs');
var url     = require('url');
var http    = require('http');
var im      = require('imagemagick');
var gm      = require('gm');

var ip_address = process.env.OPENSHIFT_NODEJS_IP;
var port       = process.env.OPENSHIFT_NODEJS_PORT || 8080;

var app = express();
var server = http.createServer(app);

app.configure(function(){
    app.use(express.bodyParser());
    app.use(app.router);
});

app.get('/test', function(req, res){
    console.log(req.query);
    /*im.convert(['./images/origin-sprite.png','-fill', 'red', '-tint', '100%', 'kittens-small.png'],
        function(err, stdout){
            if (err) throw err;
            console.log('stdout:', stdout);
        });
    var img = fs.readFileSync('./kittens-small.png');
    res.writeHead(200, {'Content-Type' : 'image/png' });
    res.end(img, 'binary');*/

});

app.post('/set-img', function(req, res){
    var imgArray = req.body.img_array;
    for (var i in imgArray){
        var imgName = imgArray[i].split('/').pop();
        console.log(imgName);
    }

   // }

});

var download = function(uri, filename, callback){
    request.head(uri, function(err, res, body){
        console.log('content-type:', res.headers['content-type']);
        console.log('content-length:', res.headers['content-length']);

        request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
    });
};

server.listen(port, ip_address,function(){
    console.log('server listening');
    var img="new_image.png";
    download('https://fbstatic-a.akamaihd.net/rsrc.php/v2/yu/r/PB0WpbyXBBt.png', 'google.png', function(){
        console.log('done');
    })
    im.convert(['./images/origin-sprite.png','-fill', 'red', '-tint', '100%', 'kittens-small.png'],
        function(err, stdout){
            if (err) throw err;
            console.log('stdout:', stdout);
        });

});
<commit_msg>adding request<commit_after>#!/bin/env node
//  OpenShift sample Node application
var express = require('express');
var request = require('request');
var fs      = require('fs');
var url     = require('url');
var http    = require('http');
var im      = require('imagemagick');
var gm      = require('gm');

var ip_address = process.env.OPENSHIFT_NODEJS_IP;
var port       = process.env.OPENSHIFT_NODEJS_PORT || 8080;

var app = express();
var server = http.createServer(app);

app.configure(function(){
    app.use(express.bodyParser());
    app.use(app.router);
});

app.get('/test', function(req, res){
    console.log(req.query);
    /*im.convert(['./images/origin-sprite.png','-fill', 'red', '-tint', '100%', 'kittens-small.png'],
        function(err, stdout){
            if (err) throw err;
            console.log('stdout:', stdout);
        });
    var img = fs.readFileSync('./kittens-small.png');
    res.writeHead(200, {'Content-Type' : 'image/png' });
    res.end(img, 'binary');*/

});

app.post('/set-img', function(req, res){
    var imgArray = req.body.img_array;
    for (var i in imgArray){
        var imgName = imgArray[i].split('/').pop();
        download(imgArray, './uploaded-images/' + imgName, function(){
            console.log('upload ' + imgName + ' done');
        });
    }
});

var download = function(uri, filename, callback){
    request.head(uri, function(err, res, body){
        console.log('content-type:', res.headers['content-type']);
        console.log('content-length:', res.headers['content-length']);

        request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
    });
};

server.listen(port, ip_address,function(){
    console.log('server listening');
    var img="new_image.png";
    download('https://fbstatic-a.akamaihd.net/rsrc.php/v2/yu/r/PB0WpbyXBBt.png', 'google.png', function(){
        console.log('done');
    })
    im.convert(['./images/origin-sprite.png','-fill', 'red', '-tint', '100%', 'kittens-small.png'],
        function(err, stdout){
            if (err) throw err;
            console.log('stdout:', stdout);
        });

});
<|endoftext|>


<commit_before>+function(t){"use strict";function s(){var t=document.createElement("bootstrap"),s={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var e in s)if(void 0!==t.style[e])return{end:s[e]};return!1}t.fn.emulateTransitionEnd=function(s){var e=!1,i=this;t(this).one(t.support.transition.end,function(){e=!0});var n=function(){e||t(i).trigger(t.support.transition.end)};return setTimeout(n,s),this},t(function(){t.support.transition=s()})}(jQuery),+function(t){"use strict";function s(s){t(i).remove(),t(n).each(function(){var i=e(t(this)),n={relatedTarget:this};i.hasClass("open")&&(i.trigger(s=t.Event("hide.bs.dropdown",n)),s.isDefaultPrevented()||i.removeClass("open").trigger("hidden.bs.dropdown",n))})}function e(s){var e=s.attr("data-target");e||(e=s.attr("href"),e=e&&/#[A-Za-z]/.test(e)&&e.replace(/.*(?=#[^\s]*$)/,""));var i=e&&t(e);return i&&i.length?i:s.parent()}var i=".dropdown-backdrop",n="[data-toggle=dropdown]",o=function(s){t(s).on("click.bs.dropdown",this.toggle)};o.prototype.toggle=function(i){var n=t(this);if(!n.is(".disabled, :disabled")){var o=e(n),a=o.hasClass("open");if(s(),!a){"ontouchstart"in document.documentElement&&!o.closest(".navbar-nav").length&&t('<div class="dropdown-backdrop"/>').insertAfter(t(this)).on("click",s);var r={relatedTarget:this};if(o.trigger(i=t.Event("show.bs.dropdown",r)),i.isDefaultPrevented())return;o.toggleClass("open").trigger("shown.bs.dropdown",r),n.focus()}return!1}},o.prototype.keydown=function(s){if(/(38|40|27)/.test(s.keyCode)){var i=t(this);if(s.preventDefault(),s.stopPropagation(),!i.is(".disabled, :disabled")){var o=e(i),a=o.hasClass("open");if(!a||a&&27==s.keyCode)return 27==s.which&&o.find(n).focus(),i.click();var r=" li:not(.divider):visible a",l=o.find("[role=menu]"+r+", [role=listbox]"+r);if(l.length){var c=l.index(l.filter(":focus"));38==s.keyCode&&c>0&&c--,40==s.keyCode&&c<l.length-1&&c++,~c||(c=0),l.eq(c).focus()}}}};var a=t.fn.dropdown;t.fn.dropdown=function(s){return this.each(function(){var e=t(this),i=e.data("bs.dropdown");i||e.data("bs.dropdown",i=new o(this)),"string"==typeof s&&i[s].call(e)})},t.fn.dropdown.Constructor=o,t.fn.dropdown.noConflict=function(){return t.fn.dropdown=a,this},t(document).on("click.bs.dropdown.data-api",s).on("click.bs.dropdown.data-api",".dropdown form",function(t){t.stopPropagation()}).on("click.bs.dropdown.data-api",n,o.prototype.toggle).on("keydown.bs.dropdown.data-api",n+", [role=menu], [role=listbox]",o.prototype.keydown)}(jQuery),+function(t){"use strict";var s=function(e,i){this.$element=t(e),this.options=t.extend({},s.DEFAULTS,i),this.state=null,this.placement=null,this.options.recalc&&(this.calcClone(),t(window).on("resize",t.proxy(this.recalc,this))),this.options.autohide&&t(document).on("click",t.proxy(this.autohide,this)),this.options.toggle&&this.toggle(),this.options.disablescrolling&&(this.options.disableScrolling=this.options.disablescrolling,delete this.options.disablescrolling)};s.DEFAULTS={toggle:!0,placement:"auto",autohide:!0,recalc:!0,disableScrolling:!0},s.prototype.offset=function(){switch(this.placement){case"left":case"right":return this.$element.outerWidth();case"top":case"bottom":return this.$element.outerHeight()}},s.prototype.calcPlacement=function(){function s(t,s){if("auto"===n.css(s))return t;if("auto"===n.css(t))return s;var e=parseInt(n.css(t),10),i=parseInt(n.css(s),10);return e>i?s:t}if("auto"!==this.options.placement)return void(this.placement=this.options.placement);this.$element.hasClass("in")||this.$element.css("visiblity","hidden !important").addClass("in");var e=t(window).width()/this.$element.width(),i=t(window).height()/this.$element.height(),n=this.$element;this.placement=e>=i?s("left","right"):s("top","bottom"),"hidden !important"===this.$element.css("visibility")&&this.$element.removeClass("in").css("visiblity","")},s.prototype.opposite=function(t){switch(t){case"top":return"bottom";case"left":return"right";case"bottom":return"top";case"right":return"left"}},s.prototype.getCanvasElements=function(){var s=this.options.canvas?t(this.options.canvas):this.$element,e=s.find("*").filter(function(){return"fixed"===t(this).css("position")}).not(this.options.exclude);return s.add(e)},s.prototype.slide=function(s,e,i){if(!t.support.transition){var n={};return n[this.placement]="+="+e,s.animate(n,350,i)}var o=this.placement,a=this.opposite(o);s.each(function(){"auto"!==t(this).css(o)&&t(this).css(o,(parseInt(t(this).css(o),10)||0)+e),"auto"!==t(this).css(a)&&t(this).css(a,(parseInt(t(this).css(a),10)||0)-e)}),this.$element.one(t.support.transition.end,i).emulateTransitionEnd(350)},s.prototype.disableScrolling=function(){var s=t("body").width(),e="padding-"+this.opposite(this.placement);if(void 0===t("body").data("offcanvas-style")&&t("body").data("offcanvas-style",t("body").attr("style")||""),t("body").css("overflow","hidden"),t("body").width()>s){var i=parseInt(t("body").css(e),10)+t("body").width()-s;setTimeout(function(){t("body").css(e,i)},1)}},s.prototype.show=function(){if(!this.state){var s=t.Event("show.bs.offcanvas");if(this.$element.trigger(s),!s.isDefaultPrevented()){this.state="slide-in",this.calcPlacement();var e=this.getCanvasElements(),i=this.placement,n=this.opposite(i),o=this.offset();-1!==e.index(this.$element)&&(t(this.$element).data("offcanvas-style",t(this.$element).attr("style")||""),this.$element.css(i,-1*o),this.$element.css(i)),e.addClass("canvas-sliding").each(function(){void 0===t(this).data("offcanvas-style")&&t(this).data("offcanvas-style",t(this).attr("style")||""),"static"===t(this).css("position")&&t(this).css("position","relative"),"auto"!==t(this).css(i)&&"0px"!==t(this).css(i)||"auto"!==t(this).css(n)&&"0px"!==t(this).css(n)||t(this).css(i,0)}),this.options.disableScrolling&&this.disableScrolling();var a=function(){"slide-in"==this.state&&(this.state="slid",e.removeClass("canvas-sliding").addClass("canvas-slid"),this.$element.trigger("shown.bs.offcanvas"))};setTimeout(t.proxy(function(){this.$element.addClass("in"),this.slide(e,o,t.proxy(a,this))},this),1)}}},s.prototype.hide=function(s){if("slid"===this.state){var e=t.Event("hide.bs.offcanvas");if(this.$element.trigger(e),!e.isDefaultPrevented()){this.state="slide-out";var i=t(".canvas-slid"),n=this.placement,o=-1*this.offset(),a=function(){"slide-out"==this.state&&(this.state=null,this.placement=null,this.$element.removeClass("in"),i.removeClass("canvas-sliding"),i.add(this.$element).add("body").each(function(){t(this).attr("style",t(this).data("offcanvas-style")).removeData("offcanvas-style")}),this.$element.trigger("hidden.bs.offcanvas"))};i.removeClass("canvas-slid").addClass("canvas-sliding"),setTimeout(t.proxy(function(){this.slide(i,o,t.proxy(a,this))},this),1)}}},s.prototype.toggle=function(){"slide-in"!==this.state&&"slide-out"!==this.state&&this["slid"===this.state?"hide":"show"]()},s.prototype.calcClone=function(){this.$calcClone=this.$element.clone().html("").addClass("offcanvas-clone").removeClass("in").appendTo(t("body"))},s.prototype.recalc=function(){if("none"!==this.$calcClone.css("display")&&("slid"===this.state||"slide-in"===this.state)){this.state=null,this.placement=null;var s=this.getCanvasElements();this.$element.removeClass("in"),s.removeClass("canvas-slid"),s.add(this.$element).add("body").each(function(){t(this).attr("style",t(this).data("offcanvas-style")).removeData("offcanvas-style")})}},s.prototype.autohide=function(s){0===t(s.target).closest(this.$element).length&&this.hide()};var e=t.fn.offcanvas;t.fn.offcanvas=function(e){return this.each(function(){var i=t(this),n=i.data("bs.offcanvas"),o=t.extend({},s.DEFAULTS,i.data(),"object"==typeof e&&e);n||i.data("bs.offcanvas",n=new s(this,o)),"string"==typeof e&&n[e]()})},t.fn.offcanvas.Constructor=s,t.fn.offcanvas.noConflict=function(){return t.fn.offcanvas=e,this},t(document).on("click.bs.offcanvas.data-api","[data-toggle=offcanvas]",function(s){var e=t(this),i,n=e.attr("data-target")||s.preventDefault()||(i=e.attr("href"))&&i.replace(/.*(?=#[^\s]+$)/,""),o=t(n),a=o.data("bs.offcanvas"),r=a?"toggle":e.data();s.stopPropagation(),a?a.toggle():o.offcanvas(r)})}(window.jQuery);<commit_msg>Renamed to app.js<commit_after><|endoftext|>


<commit_before>module.exports = {
  parameterMappings: {},

  getSupportedParameterFields: [
    'type', 'description', 'default', 'maximum', 'exclusiveMaximum', 'minimum', 'exclusiveMinimum',
    'maxLength', 'minLength', 'pattern', 'maxItems', 'minItems', 'uniqueItems', 'enum', 'multipleOf',
    'items', 'format'
  ],

  setParameterFields: function(source, target) {
    for(var prop in source) {
      if (this.getSupportedParameterFields.indexOf(prop) >= 0) {
        if (this.parameterMappings[prop]) {
          target[this.parameterMappings[prop]] = source[prop];
        } else {
          target[prop] = source[prop];
        }

        // enums must be arrays
        if (prop === 'enum' && typeof target[prop] === 'string') {
          try {
            target[prop] = JSON.parse(target[prop].replace(/\'/g, '\"'));
          } catch (e) {}
        }
      }
    }
    return target;
  }
};
<commit_msg>description should always be a string<commit_after>module.exports = {
  parameterMappings: {},

  getSupportedParameterFields: [
    'type', 'description', 'default', 'maximum', 'exclusiveMaximum', 'minimum', 'exclusiveMinimum',
    'maxLength', 'minLength', 'pattern', 'maxItems', 'minItems', 'uniqueItems', 'enum', 'multipleOf',
    'items', 'format'
  ],

  setParameterFields: function(source, target) {
    for(var prop in source) {
      if (this.getSupportedParameterFields.indexOf(prop) >= 0) {
        if (this.parameterMappings[prop]) {
          target[this.parameterMappings[prop]] = source[prop];
        } else {
          target[prop] = source[prop];
        }

        // description must be a string
        if (prop === 'description') {
          target[prop] = String(target[prop]);
        }

        // enums must be arrays
        if (prop === 'enum' && typeof target[prop] === 'string') {
          try {
            target[prop] = JSON.parse(target[prop].replace(/\'/g, '\"'));
          } catch (e) {}
        }
      }
    }
    return target;
  }
};
<|endoftext|>