<commit_before>const assert = require('chai').assert

const trackChinaPost = require('../src/trackChinaPost')

describe('TrackChinaPost', function () {
    this.timeout(0)

    describe('#TrackChinaPost', function () {
        it('should extract the messages from the website with success', function (done) {
            this.retries(6); // Track china post may be busy

            const id = 'RF622875135CN'
            trackChinaPost.getInfo(id, (err, info) => {
                assert.isNotNull(info)
                assert.isNull(err)

                assert.equal(info.id, 'RF622875135CN')
                assert.equal(info.state, 'Shanghai Transit Station export security scan')
                assert.deepEqual(info.states, [
                    {
                        "date": "2017-03-31T14:44:54+08:00",
                        "state": "Shanghai Transit Station export security scan"
                    },
                    {
                        "date": "2017-03-30T15:32:38+08:00",
                        "state": "Transit Station export customs scan (domestic transit )"
                    },
                    {
                        "date": "2017-03-30T10:33:34+08:00",
                        "state": "Transit Station export security scan"
                    },
                    {
                        "date": "2017-03-29T17:35:17+08:00",
                        "state": "leaving China Post Group city eCommerce dept. ,next station center"
                    },
                    {
                        "date": "2017-03-29T17:32:10+08:00",
                        "state": "China Post Group city eCommerce dept. customs scan"
                    },
                    {
                        "date": "2017-03-29T15:50:16+08:00",
                        "state": "China Post Group city eCommerce dept. received"
                    },
                    {
                        "date": "2017-03-29T08:28:51+08:00",
                        "state": "Electronic Data Received"
                    }
                ])

                console.log(id + ' attempts: ' + info.retries + ' busy_count: ' + info.busy_count)
                done()
            })

        });

        it('should fail to extract', function (done) {
            this.retries(6);

            const id = 'RE84521'
            trackChinaPost.getInfo(id, (err, info) => {
                assert.isNotNull(err)

                done()
            })

        });
    });
});<commit_msg>update to track china post test<commit_after>const assert = require('chai').assert

const trackChinaPost = require('../src/trackChinaPost')

describe('TrackChinaPost', function () {
    this.timeout(0)

    describe('#TrackChinaPost', function () {
        it('should extract the messages from the website with success', function (done) {
            this.retries(6); // Track china post may be busy

            const id = 'RF622875135CN'
            trackChinaPost.getInfo(id, (err, info) => {
                assert.isNotNull(info)
                assert.isNull(err)

                assert.equal(info.id, 'RF622875135CN')
                assert.equal(info.state, 'Shanghai Transit Station export customs cleared')
                assert.deepEqual(info.states, [
                    {
                        "date": "2017-04-01T02:14:49+08:00",
                        "state": "Shanghai Transit Station export customs cleared"
                    },
                    {
                        "date": "2017-03-31T14:44:54+08:00",
                        "state": "Shanghai Transit Station export security scan"
                    },
                    {
                        "date": "2017-03-30T15:32:38+08:00",
                        "state": "Transit Station export customs scan (domestic transit )"
                    },
                    {
                        "date": "2017-03-30T10:33:34+08:00",
                        "state": "Transit Station export security scan"
                    },
                    {
                        "date": "2017-03-29T17:35:17+08:00",
                        "state": "leaving China Post Group city eCommerce dept. ,next station center"
                    },
                    {
                        "date": "2017-03-29T17:32:10+08:00",
                        "state": "China Post Group city eCommerce dept. customs scan"
                    },
                    {
                        "date": "2017-03-29T15:50:16+08:00",
                        "state": "China Post Group city eCommerce dept. received"
                    },
                    {
                        "date": "2017-03-29T08:28:51+08:00",
                        "state": "Electronic Data Received"
                    }
                ])

                console.log(id + ' attempts: ' + info.retries + ' busy_count: ' + info.busy_count)
                done()
            })

        });

        it('should fail to extract', function (done) {
            this.retries(6);

            const id = 'RE84521'
            trackChinaPost.getInfo(id, (err, info) => {
                assert.isNotNull(err)

                done()
            })

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


<commit_before>import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import Modal from 'react-bootstrap/lib/Modal';
import { connect } from 'react-redux';
import Toggle from 'react-toggle';

import injectT from '../../../../app/i18n/injectT';
import CompactReservationList from '../../../../app/shared/compact-reservation-list/CompactReservationList';

const mapStateToProps = (state) => {
  return {
    userId: state.auth.userId,
    users: state.data.users
  };
};

const ReservationCancelModal = ({
  onEditReservation, parentToggle, reservation, toggleShow, t, userId, users
}) => {
  const [show, setShow] = useState(toggleShow);
  const [checkboxDisabled, handleCheckbox] = useState(false);
  const handleClose = () => {
    setShow(() => false);
    parentToggle(false);
  };

  /**
   * Both <root>/varaamo/app/shared/modals/reservation-cancel/ReservationCancelModalContainer.js
   * and ReservationCancelModal are using CompactReservationList to output resource name, date, etc.
   * We need to alter reservation a little bit before passing it to CompactReservationList.
   */
  const reservationCopyId = JSON.parse(JSON.stringify(reservation));
  const id = reservationCopyId.resource.id;
  reservationCopyId.resource = id;

  const reservationCopy = JSON.parse(JSON.stringify(reservation));
  const name = reservationCopy.resource.name.fi;
  reservationCopy.resource.name = name;

  useEffect(() => {
    setShow(toggleShow);
  }, [toggleShow]);

  const renderCheckBox = (notice, onConfirm) => {
    return (

{notice}

        <Toggle
          defaultChecked={false}
          id="checkbox"
          onChange={e => onConfirm(e.target.checked)}
        />

    );
  };

  return (
    <Modal
      onHide={handleClose}
      show={show}
    >
      <Modal.Header closeButton>
        <Modal.Title>{t('ReservationCancelModal.cancelAllowedTitle')}</Modal.Title>
      </Modal.Header>

      <Modal.Body>

{t('ReservationCancelModal.lead')}

          {reservation.resource
            && (
              <CompactReservationList
                reservations={[reservationCopyId]}
                resources={{ [reservationCopy.resource.id]: reservationCopy.resource }}
              />
            )
          }
          {
            reservation.resource
            && renderCheckBox(
              t('ReservationInformationForm.refundCheckBox'),
              () => console.log('--- FOO ---')
            )
          }

      </Modal.Body>

      <Modal.Footer>
        Modal footer
      </Modal.Footer>
    </Modal>
  );
};

ReservationCancelModal.propTypes = {
  onEditReservation: PropTypes.func.isRequired,
  parentToggle: PropTypes.func.isRequired,
  reservation: PropTypes.object.isRequired,
  toggleShow: PropTypes.bool.isRequired,
  t: PropTypes.func.isRequired,
  userId: PropTypes.string.isRequired,
  users: PropTypes.object.isRequired
};

export default connect(mapStateToProps)(injectT(ReservationCancelModal));
<commit_msg>Added buttons to modal footer.<commit_after>import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import Modal from 'react-bootstrap/lib/Modal';
import { connect } from 'react-redux';
import Toggle from 'react-toggle';
import Button from 'react-bootstrap/lib/Button';

import injectT from '../../../../app/i18n/injectT';
import CompactReservationList from '../../../../app/shared/compact-reservation-list/CompactReservationList';

const mapStateToProps = (state) => {
  return {
    userId: state.auth.userId,
    users: state.data.users
  };
};

const ReservationCancelModal = ({
  onEditReservation, parentToggle, reservation, toggleShow, t, userId, users
}) => {
  const [show, setShow] = useState(toggleShow);
  const [checkboxDisabled, handleCheckbox] = useState(false);
  const handleClose = () => {
    setShow(() => false);
    parentToggle(false);
  };

  /**
   * Both <root>/varaamo/app/shared/modals/reservation-cancel/ReservationCancelModalContainer.js
   * and ReservationCancelModal are using CompactReservationList to output resource name, date, etc.
   * We need to alter reservation a little bit before passing it to CompactReservationList.
   */
  const reservationCopyId = JSON.parse(JSON.stringify(reservation));
  const id = reservationCopyId.resource.id;
  reservationCopyId.resource = id;

  const reservationCopy = JSON.parse(JSON.stringify(reservation));
  const name = reservationCopy.resource.name.fi;
  reservationCopy.resource.name = name;

  useEffect(() => {
    setShow(toggleShow);
  }, [toggleShow]);

  const renderCheckBox = (notice, onConfirm) => {
    return (

{notice}

        <Toggle
          defaultChecked={false}
          id="checkbox"
          onChange={e => onConfirm(e.target.checked)}
        />

    );
  };

  return (
    <Modal
      onHide={handleClose}
      show={show}
    >
      <Modal.Header closeButton>
        <Modal.Title>
          {t('ReservationCancelModal.cancelAllowedTitle')}
        </Modal.Title>
      </Modal.Header>

      <Modal.Body>

{t('ReservationCancelModal.lead')}

          {reservation.resource
            && (
              <CompactReservationList
                reservations={[reservationCopyId]}
                resources={{ [reservationCopy.resource.id]: reservationCopy.resource }}
              />
            )
          }
          {
            reservation.resource
            && renderCheckBox(
              t('ReservationInformationForm.refundCheckBox'),
              () => console.log('checkbox')
            )
          }

      </Modal.Body>

      <Modal.Footer>
        <Button
          bsStyle="default"
          onClick={() => console.log('cancelAllowedCancel')}
        >
          {t('ReservationCancelModal.cancelAllowedCancel')}
        </Button>
        <Button
          bsStyle="danger"
          disabled
          onClick={() => console.log('cancelAllowedConfirm')}
        >
          {t('ReservationCancelModal.cancelAllowedConfirm')}
        </Button>
      </Modal.Footer>
    </Modal>
  );
};

ReservationCancelModal.propTypes = {
  onEditReservation: PropTypes.func.isRequired,
  parentToggle: PropTypes.func.isRequired,
  reservation: PropTypes.object.isRequired,
  toggleShow: PropTypes.bool.isRequired,
  t: PropTypes.func.isRequired,
  userId: PropTypes.string.isRequired,
  users: PropTypes.object.isRequired
};

export default connect(mapStateToProps)(injectT(ReservationCancelModal));
<|endoftext|>


<commit_before>var Entry = require('./models/entry');
var Category = require('./models/category');

module.exports = function(app) {

    // API
    // get all WIDT entries
    app.get('/api/entries', function(req, res) {
        // use mongoose to get all entries in the database
            Entry.find(function(err, entries) {
            if (err)
                res.send(err)
            res.json(entries);
        });
    });

    // create an entry
    app.post('/api/entries', function(req, res) {
        Entry.create({
            text : req.body.text,
            categories : req.body.categories
            }, function(err, entry) {
            err ? res.send(err) : res.send(entry);
            });
    });

    //update an enrty
    app.put('/api/entries', function(req, res) {
        Entry.findOne({_id : req.body._id}, function(err, entry) {
            if (err) {
                res.send(err);
            } else {
                entry.text = req.body.text;
                entry.modified = new Date;
                console.log(entry.modified);
                entry.save(function(err, newEntry) {
                    err ? res.send(err) : res.send(newEntry);
                });
            }
        });
    });

    // delete an entry
    app.delete('/api/entries/:entry_id', function(req, res) {
        Entry.remove({_id : req.params.entry_id}, function(err, entry) {
            err ? res.send(err) : res.send(entry);
        });
    });

    // categories
    app.get('/api/categories', function(req, res) {
        Category.find(function(err, categories) {
            if (err)
                res.send(err)
            res.json(categories);
        });
    });
    app.post('/api/categories', function(req, res) {
        Category.create({text : req.body.text}, function(err, category) {
            err ? res.send(err) : res.send(category);
        });

    });
    app.delete('/api/categories/:category_id', function(req, res) {
        Category.remove({_id : req.params.category_id}, function(err, category) {
            err ? res.send(err) : res.send(category);
        });
    });

    // application
    app.get('*', function(req, res) {
        res.sendfile('./public/index.html');
    });
};
<commit_msg>minor fixes<commit_after>var Entry = require('./models/entry');
var Category = require('./models/category');

module.exports = function(app) {

    // API
    // get all WIDT entries
    app.get('/api/entries', function(req, res) {
        // use mongoose to get all entries in the database
            Entry.find(function(err, entries) {
            if (err)
                res.send(err)
            res.json(entries);
        });
    });

    // create an entry
    app.post('/api/entries', function(req, res) {
        Entry.create({
            text : req.body.text,
            categories : req.body.categories
            }, function(err, entry) {
            err ? res.send(err) : res.send(entry);
            });
    });

    //update an enrty
    app.put('/api/entries', function(req, res) {
        Entry.findById(req.body._id, function(err, entry) {
            if (err) {
                res.send(err);
            } else {
                entry.text = req.body.text;
                entry.modified = new Date;
                entry.save(function(err, updatedEntry) {
                    err ? res.send(err) : res.send(updatedEntry);
                });
            }
        });
    });

    // delete an entry
    app.delete('/api/entries/:entry_id', function(req, res) {
        Entry.remove({_id : req.params.entry_id}, function(err, entry) {
            err ? res.send(err) : res.send(entry);
        });
    });

    // categories
    app.get('/api/categories', function(req, res) {
        Category.find(function(err, categories) {
            if (err)
                res.send(err)
            res.json(categories);
        });
    });
    app.post('/api/categories', function(req, res) {
        Category.create({text : req.body.text}, function(err, category) {
            err ? res.send(err) : res.send(category);
        });

    });
    app.delete('/api/categories/:category_id', function(req, res) {
        Category.remove({_id : req.params.category_id}, function(err, category) {
            err ? res.send(err) : res.send(category);
        });
    });

    // application
    app.get('*', function(req, res) {
        res.sendfile('./public/index.html');
    });
};
<|endoftext|>


<commit_before>/*
 * IFrameTransport - Storage Client
 *
 * Persist data across domains.
 * Targets modern browsers, IE8+
*/

(function (root, factory) {
  if (typeof define === 'function' && define.amd) define('ift-client-storage', ['ift'], factory);
  else root.IFT = factory(root.IFT);
}(this, function(IFT) {

  var support = IFT.support,
      util = IFT.util;

  util.mixin(support, {
    storageEventTarget: ('onstorage' in window ? window : document)
  });

  var Storage = IFT.Client.Storage = {};

  var StorageClient = IFT.Client.extend({
    type: 'storage',
    get: function() {},
    set: function() {},
    unset: function() {},
  });

  // Parent
  // ------

  // Implement the LocalStorage client from the parent's perspective.
  var Parent = Storage.Parent = StorageClient.extend({

    get: function(key, callback) {
      this.send('invoke', 'get', [key], callback);
    },

    set: function(key, value, options, callback) {
      if (typeof options === 'function') {
        callback = options;
        options = {};
      } else options = options || {};

      this.send('invoke', 'set', [key, value, options], callback);
    },

    unset: function(keys, callback) {
      this.send('invoke', 'unset', [keys], callback);
    }

  });

  // Wrap localStorage so it may be swapped out.
  var lsWrapper = {
    get: function(key) {
      return localStorage.getItem(key);
    },
    set: function(key, value) {
      return localStorage.setItem(key, value);
    },
    unset: function(keys) {
      if (!(keys instanceof Array)) keys = [keys];
      for (i = 0; i < keys.length; i++) localStorage.removeItem(keys[i]);
    }
  };

  // Implement the LocalStorage client from the child's perspective.
  var Child = Storage.Child = StorageClient.extend({

    constructor: function(ift, storage) {
      this.storage = storage || lsWrapper;
      this.listen();
      IFT.Client.apply(this, arguments);
    },

    get: function(key) {
      return this.storage.get(key);
    },

    set: function(key, value, options) {
      return this.storage.set(key, value);
    },

    unset: function(keys) {
      return this.storage.unset(keys);
    },

    onStorage: function(evt) {
      if (evt) {
        // IE9+: Don't trigger if value didn't change
        if (evt.oldValue === evt.newValue) return;
      } else {
        // IE8: Don't throw an exception as `evt` is undefined
        evt = {};
      }

      this.send('trigger', 'change', [{
        key: evt.key,
        oldValue: evt.oldValue,
        newValue: evt.newValue
      }]);
    },

    listen: function() {
      var self = this, target = support.storageEventTarget;
      support.on(target, 'storage', function(evt) { self.onStorage(evt); });
    }

  });

  return IFT;

}));
<commit_msg>Fix set with options<commit_after>/*
 * IFrameTransport - Storage Client
 *
 * Persist data across domains.
 * Targets modern browsers, IE8+
*/

(function (root, factory) {
  if (typeof define === 'function' && define.amd) define('ift-client-storage', ['ift'], factory);
  else root.IFT = factory(root.IFT);
}(this, function(IFT) {

  var support = IFT.support,
      util = IFT.util;

  util.mixin(support, {
    storageEventTarget: ('onstorage' in window ? window : document)
  });

  var Storage = IFT.Client.Storage = {};

  var StorageClient = IFT.Client.extend({
    type: 'storage',
    get: function() {},
    set: function() {},
    unset: function() {},
  });

  // Parent
  // ------

  // Implement the LocalStorage client from the parent's perspective.
  var Parent = Storage.Parent = StorageClient.extend({

    get: function(key, callback) {
      this.send('invoke', 'get', [key], callback);
    },

    set: function(key, value, options, callback) {
      if (typeof options === 'function') {
        callback = options;
        options = {};
      } else options = options || {};

      this.send('invoke', 'set', [key, value, options], callback);
    },

    unset: function(keys, callback) {
      this.send('invoke', 'unset', [keys], callback);
    }

  });

  // Wrap localStorage so it may be swapped out.
  var lsWrapper = {
    get: function(key) {
      return localStorage.getItem(key);
    },
    set: function(key, value) {
      return localStorage.setItem(key, value);
    },
    unset: function(keys) {
      if (!(keys instanceof Array)) keys = [keys];
      for (i = 0; i < keys.length; i++) localStorage.removeItem(keys[i]);
    }
  };

  // Implement the LocalStorage client from the child's perspective.
  var Child = Storage.Child = StorageClient.extend({

    constructor: function(ift, storage) {
      this.storage = storage || lsWrapper;
      this.listen();
      IFT.Client.apply(this, arguments);
    },

    get: function(key) {
      return this.storage.get(key);
    },

    set: function(key, value, options) {
      return this.storage.set(key, value, options);
    },

    unset: function(keys) {
      return this.storage.unset(keys);
    },

    onStorage: function(evt) {
      if (evt) {
        // IE9+: Don't trigger if value didn't change
        if (evt.oldValue === evt.newValue) return;
      } else {
        // IE8: Don't throw an exception as `evt` is undefined
        evt = {};
      }

      this.send('trigger', 'change', [{
        key: evt.key,
        oldValue: evt.oldValue,
        newValue: evt.newValue
      }]);
    },

    listen: function() {
      var self = this, target = support.storageEventTarget;
      support.on(target, 'storage', function(evt) { self.onStorage(evt); });
    }

  });

  return IFT;

}));
<|endoftext|>


<commit_before>/*
 * Say Cheese!
 * Lee Machin, 2012
 * http://leemach.in, http://new-bamboo.co.uk
 *
 * Minimal javascript library for integrating a webcam and snapshots into your app.
 *
 * Handles starting up the webcam and rendering the element, and also capturing shots
 * in a separate canvas element.
 *
 * Depends on video and canvas, and of course, getUserMedia. It's unlikely to work
 * on anything but the newest browsers.
 */

var SayCheese = (function($) {

  var SayCheese;

  navigator.getUserMedia = (navigator.getUserMedia ||
                            navigator.webkitGetUserMedia ||
                            navigator.mozGetUserMedia ||
                            navigator.msGetUserMedia ||
                            false);

  window.URL = (window.URL ||
                window.webkitURL);

  function eventCoords(evt) {
    return { x: evt.offsetX || evt.layerX, y: evt.offsetY || evt.layerY };
  };

  SayCheese = function SayCheese(element) {
    this.snapshots = [],
    this.canvas = null,
    this.context = null,
    this.video = null,
    this.events = {},
    this.stream = null;

    this.element = document.querySelectorAll(element)[0];
    this.element.style.position = 'relative';

    return this;
  };

  /**
   * Wrap the jQuery stuff so as to minimise the impact of the framework on
   * the rest of the code.
   */
  SayCheese.prototype.on = function on(evt, handler) {
    return $(this).on(evt, handler);
  };

  SayCheese.prototype.off = function off(evt, handler) {
    return $(this).off(evt, handler);
  };

  SayCheese.prototype.trigger = function trigger(evt, data) {
    // bubbling up the DOM makes things go a bit crazy. This assumes
    // preventDefault
    return $(this).triggerHandler(evt, data);
  };

  SayCheese.prototype.getStreamUrl = function getStreamUrl() {
    if (window.URL && window.URL.createObjectURL) {
      return window.URL.createObjectURL(this.stream);
    } else {
      return this.stream;
    }
  };

  SayCheese.prototype.createVideo = function createVideo() {
    this.video = document.createElement('video');
  };

  SayCheese.prototype.setupCanvas = function setupCanvas() {
    this.canvas = document.createElement('canvas');
    this.canvas.width = this.video.offsetWidth;
    this.canvas.height = this.video.offsetHeight;

    this.canvas.style.position = 'absolute';
    this.canvas.style.top = this.video.offsetTop;
    this.canvas.style.left = this.video.offsetLeft;

    this.context = this.canvas.getContext('2d');
    this.element.appendChild(this.canvas);

    return this.trigger('start');
  };

  SayCheese.prototype.takeSnapshot = function takeSnapshot() {
    var snapshot = document.createElement('canvas'),
        ctx      = snapshot.getContext('2d');

    snapshot.width  = this.video.width;
    snapshot.height = this.video.height;

    ctx.drawImage(this.video, 0, 0);

    this.snapshots.push(snapshot);
    this.trigger('snapshot', snapshot);

    ctx = null;
  };

  /* Start up the stream, if possible */
  SayCheese.prototype.start = function start() {

    // fail fast and softly if browser not supported
    if (navigator.getUserMedia === false) {
      this.trigger('error', 'NOT_SUPPORTED');
      return false;
    }

    var success = function success(stream) {
      this.stream = stream;
      this.createVideo();

      if (navigator.mozGetUserMedia) {
        this.video.mozSrcObject = stream;
      } else {
        this.video.src = this.getStreamUrl();
      }

      this.video.addEventListener('loadedmetadata', this.setupCanvas.bind(this));
      this.element.appendChild(this.video);
      this.video.play();
    }.bind(this);

    /* error is also called when someone denies access */
    var error = function error(error) {
      this.trigger('error', error);
    }.bind(this);

    return navigator.getUserMedia({ video: true, audio: false }, success, error);
  };

  SayCheese.prototype.stop = function stop() {
    this.stream.stop();
    window.revokeObjectURL();
    this.trigger('stop');
  };

  return SayCheese;

})(jQuery);
<commit_msg>remove unneeded function<commit_after>/*
 * Say Cheese!
 * Lee Machin, 2012
 * http://leemach.in, http://new-bamboo.co.uk
 *
 * Minimal javascript library for integrating a webcam and snapshots into your app.
 *
 * Handles starting up the webcam and rendering the element, and also capturing shots
 * in a separate canvas element.
 *
 * Depends on video and canvas, and of course, getUserMedia. It's unlikely to work
 * on anything but the newest browsers.
 */

var SayCheese = (function($) {

  var SayCheese;

  navigator.getUserMedia = (navigator.getUserMedia ||
                            navigator.webkitGetUserMedia ||
                            navigator.mozGetUserMedia ||
                            navigator.msGetUserMedia ||
                            false);

  window.URL = (window.URL ||
                window.webkitURL);

  SayCheese = function SayCheese(element) {
    this.snapshots = [],
    this.canvas = null,
    this.context = null,
    this.video = null,
    this.events = {},
    this.stream = null;

    this.element = document.querySelectorAll(element)[0];
    this.element.style.position = 'relative';

    return this;
  };

  /**
   * Wrap the jQuery stuff so as to minimise the impact of the framework on
   * the rest of the code.
   */
  SayCheese.prototype.on = function on(evt, handler) {
    return $(this).on(evt, handler);
  };

  SayCheese.prototype.off = function off(evt, handler) {
    return $(this).off(evt, handler);
  };

  SayCheese.prototype.trigger = function trigger(evt, data) {
    // bubbling up the DOM makes things go a bit crazy. This assumes
    // preventDefault
    return $(this).triggerHandler(evt, data);
  };

  SayCheese.prototype.getStreamUrl = function getStreamUrl() {
    if (window.URL && window.URL.createObjectURL) {
      return window.URL.createObjectURL(this.stream);
    } else {
      return this.stream;
    }
  };

  SayCheese.prototype.createVideo = function createVideo() {
    this.video = document.createElement('video');
  };

  SayCheese.prototype.setupCanvas = function setupCanvas() {
    this.canvas = document.createElement('canvas');
    this.canvas.width = this.video.offsetWidth;
    this.canvas.height = this.video.offsetHeight;

    this.canvas.style.position = 'absolute';
    this.canvas.style.top = this.video.offsetTop;
    this.canvas.style.left = this.video.offsetLeft;

    this.context = this.canvas.getContext('2d');
    this.element.appendChild(this.canvas);

    return this.trigger('start');
  };

  SayCheese.prototype.takeSnapshot = function takeSnapshot() {
    var snapshot = document.createElement('canvas'),
        ctx      = snapshot.getContext('2d');

    snapshot.width  = this.video.width;
    snapshot.height = this.video.height;

    ctx.drawImage(this.video, 0, 0);

    this.snapshots.push(snapshot);
    this.trigger('snapshot', snapshot);

    ctx = null;
  };

  /* Start up the stream, if possible */
  SayCheese.prototype.start = function start() {

    // fail fast and softly if browser not supported
    if (navigator.getUserMedia === false) {
      this.trigger('error', 'NOT_SUPPORTED');
      return false;
    }

    var success = function success(stream) {
      this.stream = stream;
      this.createVideo();

      if (navigator.mozGetUserMedia) {
        this.video.mozSrcObject = stream;
      } else {
        this.video.src = this.getStreamUrl();
      }

      this.video.addEventListener('loadedmetadata', this.setupCanvas.bind(this));
      this.element.appendChild(this.video);
      this.video.play();
    }.bind(this);

    /* error is also called when someone denies access */
    var error = function error(error) {
      this.trigger('error', error);
    }.bind(this);

    return navigator.getUserMedia({ video: true, audio: false }, success, error);
  };

  SayCheese.prototype.stop = function stop() {
    this.stream.stop();
    window.revokeObjectURL();
    this.trigger('stop');
  };

  return SayCheese;

})(jQuery);
<|endoftext|>


<commit_before>$(function () {

// Row 1 Dashboards
if (document.getElementById('dashboard')) {

  $.getJSON('api/dashboard/widgets', function (response) {

    var count_options = {
      useEasing: true,
      useGrouping: true,
      separator: ',',
      decimal: '.',
      prefix: '',
      suffix: ''
    };

    // Number of Games
    if (response.number_of_games) {
      new CountUp('number-of-games-value', 0, response.number_of_games, 0, 1, count_options).start();
    }

    // Number of Systems
    if (response.number_of_systems) {
      new CountUp('number-of-systems-value', 0, response.number_of_systems, 0, 1, count_options).start();
    }

    // Games Beaten
    if (response.number_of_games_beaten) {
      new CountUp('number-of-games-completed-value', 0, response.number_of_games_beaten, 0, 1, count_options).start(function () {

        // Clean up star ratings based on the percentage of games beaten
        var earned_stars = 0;

        if (response.percentage_games_beaten < 20) {
          earned_stars = 1;
        }
        else if (response.percentage_games_beaten >= 20 && response.percentage_games_beaten < 40) {
          earned_stars = 2;
        }
        else if (response.percentage_games_beaten >= 40 && response.percentage_games_beaten < 60) {
          earned_stars = 3;
        }
        else if (response.percentage_games_beaten >= 60 && response.percentage_games_beaten < 80) {
          earned_stars = 4;
        }
        else if (response.percentage_games_beaten >= 80) {
          earned_stars = 5;
        }
        else {
          // No need to remove any stars
        }

        if (earned_stars !== 0) {
          $('i', '#percentage-games-beaten').slice(earned_stars).hide();
        }

        $('#percentage-games-beaten > span').text(response.percentage_games_beaten + '%').parent().fadeIn(250);
      });
    }

    // Favorite System
    $('strong i', '#favorite-system-box').fadeOut(250, function () {
      $(this).parents('strong').hide().text(response.favorite_system).animate({ height: 'toggle' }, 250, function () {

        var plural = ((response.favorite_system_games !== 1) ? 's' : '');
        $('#favorite-system-games').text(response.favorite_system_games + ' game' + plural).fadeIn(250);
      });
    });

    // Favorite Genre
    $('strong i', '#favorite-genre-box').fadeOut(250, function () {
      $(this).parents('strong').hide().text(response.favorite_genre).animate({ height: 'toggle' }, 250, function () {

        var plural = ((response.favorite_genre_games !== 1) ? 's' : '');
        $('#favorite-genre-games').text(response.favorite_genre_games + ' game' + plural).fadeIn(250);
      });
    });

    // Last Game Added
    $('strong i', '#last-game-added-box').fadeOut(250, function () {
      $(this).parents('strong').hide().text(response.last_game_added).animate({ height: 'toggle' }, 250, function () {
        $('#last-game-added-date').text(response.last_game_added_date).fadeIn(250);
      });
    });
  });

  // Genre Breakdown
  $.getJSON('api/dashboard/genres', function (response) {

    new Chartist.Bar('#genre-breakdown', {
      labels: response.labels,
      series: response.series
    },
    {
      distributeSeries: true,
      seriesBarDistance: 10,
      reverseData: true,
      horizontalBars: true,
      axisY: {
        offset: 125,
        showGrid: false,
        labelInterpolationFnc: function (value, index) {
          return ((value.length <= 15) ? value : value.substr(0, 15) + '...');
        }
      },
      axisX: {
        onlyInteger: true,
      }
    });

    $('h4 i', '#genre-breakdown-box').fadeOut(250);
  });

  // System Breakdown
  $.getJSON('api/dashboard/systems', function (response) {

    new Chartist.Bar('#system-breakdown', {
      labels: response.labels,
      series: response.series
    },
    {
      distributeSeries: true,
      seriesBarDistance: 10,
      reverseData: true,
      horizontalBars: true,
      axisY: {
        offset: 125,
        showGrid: false,
        labelInterpolationFnc: function (value, index) {
          return ((value.length <= 15) ? value : value.substr(0, 15) + '...');
        }
      },
      axisX: {
        onlyInteger: true
      }
    });

    $('h4 i', '#system-breakdown-box').fadeOut(250);
  });

  // Video Game Timeline
  $.getJSON('api/dashboard/timeline', function (response) {

    new Chartist.Line('#video-game-timeline', {
      labels: response.labels,
      series: [ response.series ]
    },
    {
      showArea: true,
      lineSmooth: Chartist.Interpolation.simple({
        divisor: 7
      }),
      high: _.max(response.series) +1,
      fullWidth: true,
      chartPadding: {
        right: 40
      },
      axisY: {
        onlyInteger: true
      },
      axisX: {
        labelInterpolationFnc: function (value, index) {
          if (response.series.length > 25) {
            return '\'' + value.slice(2, 4);
          }
          else {
            return value;
          }
        }
      }
    },
    [
      ['screen and (max-width: 1199px)', {
        axisX: {
          labelInterpolationFnc: function (value, index) {

            // @TODO Would love to concoct a formula here to more precisely plot labels on this axis
            value = '\'' + value.slice(2, 4);
            return index % 2  === 0 ? value : null;
          }
        }
      }],
      ['screen and (max-width: 991px)', {
        axisX: {
          labelInterpolationFnc: function (value, index) {

            // @TODO Ditto
            value = '\'' + value.slice(2, 4);
            return index % 3 === 0 ? value : null;
          }
        }
      }],
      ['screen and (max-width: 767px)', {
        axisX: {
          labelInterpolationFnc: function (value, index) {

            // @TODO Ditto
            value = '\'' + value.slice(2, 4);
            return index % 5  === 0 ? value : null;
          }
        }
      }]
    ]);

    $('h4 i', '#video-game-timeline-box').fadeOut(250);
  });
} // dashboard

// Catalog
if (document.getElementById('catalog')) {

  $('#add-record').tooltip();

  Handlebars.registerHelper('prettyDate', function (date) {
    if (moment(date).isValid()) {
      return '' + moment(date).format('YYYYMMDDHHmmss') + ''
        + moment(date).format('MMM. Do, YYYY');
    }
    else {
      return '-';
    }
  });

  Handlebars.registerHelper('prettyList', function (list) {
    list = list || '';

    var a = list.toString().replace(', ', ' ').split(',');
    if (a.length > 1) {
      var h = '
';
      _.each(a, function (g) {
        h += '
' + g.trim() + '
';
      })
      return h + '
';
    }
    else {
      if (list.length) {
        return list;
      }
      else {
        return '-';
      }
    }
  });

  Handlebars.registerHelper('toHTML', function (s) {
    return s;
  });

  var games = new Games();
  games.fetch({
    success: function () {
      var gamesView = new GamesView({ collection: games }),
          inventory = gamesView.render().$parent;

      $('.loader').fadeOut(200, function () {
        $('.box', '#catalog').append($(inventory).fadeIn(400));
      });
    }
  });

  Backbone.history.start({ root: '/catalog/' });
  _.extend(Backbone.Model.prototype, Backbone.Validation.mixin);
} // catalog

});
<commit_msg>"prettyList()" fix<commit_after>$(function () {

// Row 1 Dashboards
if (document.getElementById('dashboard')) {

  $.getJSON('api/dashboard/widgets', function (response) {

    var count_options = {
      useEasing: true,
      useGrouping: true,
      separator: ',',
      decimal: '.',
      prefix: '',
      suffix: ''
    };

    // Number of Games
    if (response.number_of_games) {
      new CountUp('number-of-games-value', 0, response.number_of_games, 0, 1, count_options).start();
    }

    // Number of Systems
    if (response.number_of_systems) {
      new CountUp('number-of-systems-value', 0, response.number_of_systems, 0, 1, count_options).start();
    }

    // Games Beaten
    if (response.number_of_games_beaten) {
      new CountUp('number-of-games-completed-value', 0, response.number_of_games_beaten, 0, 1, count_options).start(function () {

        // Clean up star ratings based on the percentage of games beaten
        var earned_stars = 0;

        if (response.percentage_games_beaten < 20) {
          earned_stars = 1;
        }
        else if (response.percentage_games_beaten >= 20 && response.percentage_games_beaten < 40) {
          earned_stars = 2;
        }
        else if (response.percentage_games_beaten >= 40 && response.percentage_games_beaten < 60) {
          earned_stars = 3;
        }
        else if (response.percentage_games_beaten >= 60 && response.percentage_games_beaten < 80) {
          earned_stars = 4;
        }
        else if (response.percentage_games_beaten >= 80) {
          earned_stars = 5;
        }
        else {
          // No need to remove any stars
        }

        if (earned_stars !== 0) {
          $('i', '#percentage-games-beaten').slice(earned_stars).hide();
        }

        $('#percentage-games-beaten > span').text(response.percentage_games_beaten + '%').parent().fadeIn(250);
      });
    }

    // Favorite System
    $('strong i', '#favorite-system-box').fadeOut(250, function () {
      $(this).parents('strong').hide().text(response.favorite_system).animate({ height: 'toggle' }, 250, function () {

        var plural = ((response.favorite_system_games !== 1) ? 's' : '');
        $('#favorite-system-games').text(response.favorite_system_games + ' game' + plural).fadeIn(250);
      });
    });

    // Favorite Genre
    $('strong i', '#favorite-genre-box').fadeOut(250, function () {
      $(this).parents('strong').hide().text(response.favorite_genre).animate({ height: 'toggle' }, 250, function () {

        var plural = ((response.favorite_genre_games !== 1) ? 's' : '');
        $('#favorite-genre-games').text(response.favorite_genre_games + ' game' + plural).fadeIn(250);
      });
    });

    // Last Game Added
    $('strong i', '#last-game-added-box').fadeOut(250, function () {
      $(this).parents('strong').hide().text(response.last_game_added).animate({ height: 'toggle' }, 250, function () {
        $('#last-game-added-date').text(response.last_game_added_date).fadeIn(250);
      });
    });
  });

  // Genre Breakdown
  $.getJSON('api/dashboard/genres', function (response) {

    new Chartist.Bar('#genre-breakdown', {
      labels: response.labels,
      series: response.series
    },
    {
      distributeSeries: true,
      seriesBarDistance: 10,
      reverseData: true,
      horizontalBars: true,
      axisY: {
        offset: 125,
        showGrid: false,
        labelInterpolationFnc: function (value, index) {
          return ((value.length <= 15) ? value : value.substr(0, 15) + '...');
        }
      },
      axisX: {
        onlyInteger: true,
      }
    });

    $('h4 i', '#genre-breakdown-box').fadeOut(250);
  });

  // System Breakdown
  $.getJSON('api/dashboard/systems', function (response) {

    new Chartist.Bar('#system-breakdown', {
      labels: response.labels,
      series: response.series
    },
    {
      distributeSeries: true,
      seriesBarDistance: 10,
      reverseData: true,
      horizontalBars: true,
      axisY: {
        offset: 125,
        showGrid: false,
        labelInterpolationFnc: function (value, index) {
          return ((value.length <= 15) ? value : value.substr(0, 15) + '...');
        }
      },
      axisX: {
        onlyInteger: true
      }
    });

    $('h4 i', '#system-breakdown-box').fadeOut(250);
  });

  // Video Game Timeline
  $.getJSON('api/dashboard/timeline', function (response) {

    new Chartist.Line('#video-game-timeline', {
      labels: response.labels,
      series: [ response.series ]
    },
    {
      showArea: true,
      lineSmooth: Chartist.Interpolation.simple({
        divisor: 7
      }),
      high: _.max(response.series) +1,
      fullWidth: true,
      chartPadding: {
        right: 40
      },
      axisY: {
        onlyInteger: true
      },
      axisX: {
        labelInterpolationFnc: function (value, index) {
          if (response.series.length > 25) {
            return '\'' + value.slice(2, 4);
          }
          else {
            return value;
          }
        }
      }
    },
    [
      ['screen and (max-width: 1199px)', {
        axisX: {
          labelInterpolationFnc: function (value, index) {

            // @TODO Would love to concoct a formula here to more precisely plot labels on this axis
            value = '\'' + value.slice(2, 4);
            return index % 2  === 0 ? value : null;
          }
        }
      }],
      ['screen and (max-width: 991px)', {
        axisX: {
          labelInterpolationFnc: function (value, index) {

            // @TODO Ditto
            value = '\'' + value.slice(2, 4);
            return index % 3 === 0 ? value : null;
          }
        }
      }],
      ['screen and (max-width: 767px)', {
        axisX: {
          labelInterpolationFnc: function (value, index) {

            // @TODO Ditto
            value = '\'' + value.slice(2, 4);
            return index % 5  === 0 ? value : null;
          }
        }
      }]
    ]);

    $('h4 i', '#video-game-timeline-box').fadeOut(250);
  });
} // dashboard

// Catalog
if (document.getElementById('catalog')) {

  $('#add-record').tooltip();

  Handlebars.registerHelper('prettyDate', function (date) {
    if (moment(date).isValid()) {
      return '' + moment(date).format('YYYYMMDDHHmmss') + ''
        + moment(date).format('MMM. Do, YYYY');
    }
    else {
      return '-';
    }
  });

  Handlebars.registerHelper('prettyList', function (list) {
    list = list || '';

    // Workaround for parsing and splitting a string with commas built in
    var a = list.replace(new RegExp(', ', 'g'), '||').split(',');
    for (var i=0; i  1) {
      var h = '
';
      _.each(a, function (g) {
        h += '
' + g.trim() + '
';
      })
      return h + '
';
    }
    else {
      if (list.length) {
        return list;
      }
      else {
        return '-';
      }
    }
  });

  Handlebars.registerHelper('toHTML', function (s) {
    return s;
  });

  var games = new Games();
  games.fetch({
    success: function () {
      var gamesView = new GamesView({ collection: games }),
          inventory = gamesView.render().$parent;

      $('.loader').fadeOut(200, function () {
        $('.box', '#catalog').append($(inventory).fadeIn(400));
      });
    }
  });

  Backbone.history.start({ root: '/catalog/' });
  _.extend(Backbone.Model.prototype, Backbone.Validation.mixin);
} // catalog

});
<|endoftext|>


<commit_before>// = autoexpandable textarea, jQuery plugin =
//
// * author: Marek 'saji' Augustynowicz
// * license: MIT (LICENSE.md file should be distributed with the code)
// * http://github.com/marek-saji/jquery.autoexpandable
//
// == USAGE ==
// {{{
// <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
// <script type="text/javascript" src="jquery.autoexpandable.js"></script>
// <script type="text/javascript">
//    $(function(){
//        $('textarea.foo').autoexpandable();
//
//        // you may also specify settings here
//        $('textarea.bar').autoexpandable({
//            timeout: 100
//        });
//    });
// </script>
//
// You can also specify settings with data-autoexpandable attribute:
//
// <textarea data-autoexpandable='{"debug": true}'>
//     Lorem ipsum dolor sit amet neque. Nunc a diam. Suspendisse diam...
// </textarea>
//
// }}}

(function($){ // context scope begin

    // == {{{default_settings}}} ==
    var default_settings = {
        // Timeout after which height is measured and applied to textarea.
        timeout: 200,
        // Height below which textarea will not shrink.
        minHeight: undefined,
        // Number of lines to pad after entered text.
        paddingBottomLines: 2,
        // Duration of transition between textareas' heights
        transitionDuration: '0.1s',
        // Does nothing so far.
        debug: false
    };

    var TRANSITION_PREFIXES = ['', '-webkit-', '-moz-'];
    var transitionDurationProperty;

    function getTransitionDurationProperty ($element)
    {
        var idx;
        if (undefined === transitionDurationProperty)
        {
            for (idx in TRANSITION_PREFIXES)
            {
                transitionDurationProperty = TRANSITION_PREFIXES[idx] + 'transition-duration';
                if (undefined !== $element.css(transitionDurationProperty))
                {
                    break;
                }
            }
        }
        return transitionDurationProperty;
    }

    // == {{{autoexpandable}}} ==
    // function called with {{{$(selector).autoexpandable()}}},
    // {{{this}}} is a set of matched elements
    $.fn.autoexpandable = function(user_settings){

        var invoke_settings = {};

        // merge default and user settings
        $.extend(invoke_settings, default_settings, user_settings);

        return this.each(function(){

            var $this = $(this),
                data = $this.data('autoexpandable'),
                settings = {};

            data || $this.data('autoexpandable', {});

            // merge-in settings specified in `data-autoexpandable` attribute
            $.extend(settings, invoke_settings, data);

            $this.bind('keypress.autoexpandable', function(e){

                var $this = $(this),
                    data = $this.data('autoexpandable');

                if (data.timeoutID)
                    return;

                // ==== setTimeout ===
                // Modyfying textarea height after `settings.timeout`.
                data.timeoutID = window.setTimeout(function(){

                    data.timeoutID = null;

                    if (settings.minHeight === undefined)
                    {
                        settings.minHeight = $this.height();
                    }

                    if (!settings.paddingBottom)
                    {
                        // ==== determinig 1em ====
                        // To determine how much px 1em has, we create
                        // dummy element with some of css attributes cloned.
                        var $foo = $('<div />', {
                            'text' : 'Mj',
                            'css' : {
                                'white-space' : 'pre',
                                'font-family' : $this.css('font-family'),
                                'font-size'   : $this.css('font-size'),
                                'line-height' : $this.css('line-height')
                            }
                        });
                        $foo.insertAfter($this);
                        data.paddingBottom = $foo.outerHeight();
                        $foo.remove();
                    }

                    var padding = data.paddingBottom,
                        transitionDurationProperty = getTransitionDurationProperty($this),
                        transitionDuration = $this.css(transitionDurationProperty),
                        oldHeight,
                        height;

                    if ('0s' !== transitionDuration)
                    {
                        // disable transitions so that setting height(0)
                        // allows to read scrollHeight immediatelly
                        $this.css(transitionDurationProperty, '0s');
                    }

                    oldHeight = $this.height();
                    $this.height(0); // to get proper scrollHeight
                    height = $this[0].scrollHeight;
                    height += padding * settings.paddingBottomLines;
                    $this.height( oldHeight );
                    $this[0].scrollHeight; // recalculate layout

                    $this.css(transitionDurationProperty, settings.transitionDuration);
                    $this.height(Math.max(settings.minHeight, height));
                    $this.css(transitionDurationProperty, transitionDuration);

                }, settings.timeout); // setTimeout

            }).trigger('keypress.autoexpandable');

        }); // return each this

    }; // $.fn.autoexpandable

})(jQuery); // context scope end

<commit_msg>Also bind to keyup<commit_after>// = autoexpandable textarea, jQuery plugin =
//
// * author: Marek 'saji' Augustynowicz
// * license: MIT (LICENSE.md file should be distributed with the code)
// * http://github.com/marek-saji/jquery.autoexpandable
//
// == USAGE ==
// {{{
// <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
// <script type="text/javascript" src="jquery.autoexpandable.js"></script>
// <script type="text/javascript">
//    $(function(){
//        $('textarea.foo').autoexpandable();
//
//        // you may also specify settings here
//        $('textarea.bar').autoexpandable({
//            timeout: 100
//        });
//    });
// </script>
//
// You can also specify settings with data-autoexpandable attribute:
//
// <textarea data-autoexpandable='{"debug": true}'>
//     Lorem ipsum dolor sit amet neque. Nunc a diam. Suspendisse diam...
// </textarea>
//
// }}}

(function($){ // context scope begin

    // == {{{default_settings}}} ==
    var default_settings = {
        // Timeout after which height is measured and applied to textarea.
        timeout: 200,
        // Height below which textarea will not shrink.
        minHeight: undefined,
        // Number of lines to pad after entered text.
        paddingBottomLines: 2,
        // Duration of transition between textareas' heights
        transitionDuration: '0.1s',
        // Does nothing so far.
        debug: false
    };

    var TRANSITION_PREFIXES = ['', '-webkit-', '-moz-'];
    var transitionDurationProperty;

    function getTransitionDurationProperty ($element)
    {
        var idx;
        if (undefined === transitionDurationProperty)
        {
            for (idx in TRANSITION_PREFIXES)
            {
                transitionDurationProperty = TRANSITION_PREFIXES[idx] + 'transition-duration';
                if (undefined !== $element.css(transitionDurationProperty))
                {
                    break;
                }
            }
        }
        return transitionDurationProperty;
    }

    // == {{{autoexpandable}}} ==
    // function called with {{{$(selector).autoexpandable()}}},
    // {{{this}}} is a set of matched elements
    $.fn.autoexpandable = function(user_settings){

        var invoke_settings = {};

        // merge default and user settings
        $.extend(invoke_settings, default_settings, user_settings);

        return this.each(function(){

            var $this = $(this),
                data = $this.data('autoexpandable'),
                settings = {};

            data || $this.data('autoexpandable', {});

            // merge-in settings specified in `data-autoexpandable` attribute
            $.extend(settings, invoke_settings, data);

            $this.bind('keypress.autoexpandable keyup.autoexpandable', function(e){

                var $this = $(this),
                    data = $this.data('autoexpandable');

                if (data.timeoutID)
                    return;

                // ==== setTimeout ===
                // Modyfying textarea height after `settings.timeout`.
                data.timeoutID = window.setTimeout(function(){

                    data.timeoutID = null;

                    if (settings.minHeight === undefined)
                    {
                        settings.minHeight = $this.height();
                    }

                    if (!settings.paddingBottom)
                    {
                        // ==== determinig 1em ====
                        // To determine how much px 1em has, we create
                        // dummy element with some of css attributes cloned.
                        var $foo = $('<div />', {
                            'text' : 'Mj',
                            'css' : {
                                'white-space' : 'pre',
                                'font-family' : $this.css('font-family'),
                                'font-size'   : $this.css('font-size'),
                                'line-height' : $this.css('line-height')
                            }
                        });
                        $foo.insertAfter($this);
                        data.paddingBottom = $foo.outerHeight();
                        $foo.remove();
                    }

                    var padding = data.paddingBottom,
                        transitionDurationProperty = getTransitionDurationProperty($this),
                        transitionDuration = $this.css(transitionDurationProperty),
                        oldHeight,
                        height;

                    if ('0s' !== transitionDuration)
                    {
                        // disable transitions so that setting height(0)
                        // allows to read scrollHeight immediatelly
                        $this.css(transitionDurationProperty, '0s');
                    }

                    oldHeight = $this.height();
                    $this.height(0); // to get proper scrollHeight
                    height = $this[0].scrollHeight;
                    height += padding * settings.paddingBottomLines;
                    $this.height( oldHeight );
                    $this[0].scrollHeight; // recalculate layout

                    $this.css(transitionDurationProperty, settings.transitionDuration);
                    $this.height(Math.max(settings.minHeight, height));
                    $this.css(transitionDurationProperty, transitionDuration);

                }, settings.timeout); // setTimeout

            }).trigger('keypress.autoexpandable');

        }); // return each this

    }; // $.fn.autoexpandable

})(jQuery); // context scope end

<|endoftext|>


<commit_before>const chai = require( 'chai' );
const chaiAsPromised = require( 'chai-as-promised' );
const tripLocations = require( '../app/models/trip-location' );
import { connectToDb, disconnectFromDb, resetDb, models, mockUsers, mockTrips, mockLocations, mockTripLocations } from './bootstrap';

chai.use( chaiAsPromised );
const expect = chai.expect;

describe( 'tripLocations', function() {
  before( function( done ) {
    connectToDb( done );
  } );

  after( function() {
    disconnectFromDb();
  } );

  beforeEach( function( done ) {
    resetDb( done );
  } );

  describe( '.listTripLocationsForUser', function() {
    it( 'returns an Array', function() {
      return expect( tripLocations.listTripLocationsForUser( mockUsers.testUserId ) ).to.eventually.be.an.instanceOf( Array );
    } );

    it( 'returns an array with all current TripLocations', function() {
      return tripLocations.listTripLocationsForUser( mockUsers.testUserId2 )
      .then( function( data ) {
        expect( data.map( x => x.location ) ).to.eql( mockTrips.testUserTrip2.tripLocations.map( x => x.location._id ) );
      } );
    } );

    it( 'returns an array that does not include TripLocations from other users', function() {
      return tripLocations.listTripLocationsForUser( mockUsers.testUserId )
      .then( function( data ) {
        expect( data.map( x => x.location ) ).to.eql( mockTrips.testUserTrip.tripLocations.map( x => x.location._id ) );
      } );
    } );

    it( 'removes any TripLocations that have no associated Location', function() {
      const currentTripLocations = mockTrips.testUserTrip.tripLocations.map( x => x._id )
      .reduce( ( prev, next ) => {
        if ( next === mockTripLocations.homeTripLocation._id ) return prev;
        return prev.concat( next );
      }, [] );
      return models.Location.findOneAndRemove( { _id: mockLocations.homeLocation._id }, {} )
      .then( function() {
        return tripLocations.listTripLocationsForUser( mockUsers.testUserId )
        .then( function( data ) {
          expect( data.map( x => x._id ) ).to.eql( currentTripLocations );
        } );
      } );
    } );
  } );

  describe( '.addLocationToTrip', function() {
    it( 'creates a new TripLocation with the parameters specified', function() {
      const params = { location: mockLocations.gameLocation._id };
      return tripLocations.addLocationToTrip( mockUsers.testUserId, params )
      .then( function( data ) {
        expect( data.location ).to.eql( params.location );
      } );
    } );

    it( 'creates a new TripLocation without non-whitelisted parameters', function() {
      const params = { foo: 'bar', location: mockLocations.gameLocation._id };
      return tripLocations.addLocationToTrip( mockUsers.testUserId, params )
      .then( function( data ) {
        expect( data.foo ).to.not.exist;
      } );
    } );

    it( 'adds the TripLocation to the end of the user\'s list', function() {
      const params = { location: mockLocations.workLocation._id };
      return tripLocations.addLocationToTrip( mockUsers.testUserId2, params )
      .then( () => tripLocations.listTripLocationsForUser( mockUsers.testUserId2 ) )
      .then( function( data ) {
        const last = data[ data.length - 1 ];
        expect( last.location ).to.eql( params.location );
      } );
    } );
  } );

  describe( '.removeAllTripLocations', function() {
    it( 'removes all the TripLocations for the user', function() {
      return tripLocations.removeAllTripLocations( mockUsers.testUserId2 )
      .then( () => tripLocations.listTripLocationsForUser( mockUsers.testUserId2 ) )
      .then( ( data ) => {
        expect( data ).to.be.empty;
      } );
    } );

    it( 'does not remove TripLocations for other users', function() {
      return tripLocations.removeAllTripLocations( mockUsers.testUserId2 )
      .then( () => tripLocations.listTripLocationsForUser( mockUsers.testUserId ) )
      .then( ( data ) => {
        expect( data ).to.not.be.empty;
      } );
    } );

    it( 'returns the empty list', function() {
      return tripLocations.removeAllTripLocations( mockUsers.testUserId2 )
      .then( ( data ) => {
        expect( data ).to.be.empty;
      } );
    } );
  } );

  describe( '.removeTripLocationForUser', function() {
    it( 'removes the TripLocation from the database', function() {
      let locationCount = 0;
      return models.TripLocation.find()
      .then( ( initialData ) => {
        locationCount = initialData.length;
        return tripLocations.removeTripLocationForUser( mockUsers.testUserId2, mockTripLocations.teaTripLocation )
      } )
      .then( () => models.TripLocation.find() )
      .then( function( data ) {
        expect( data ).to.have.length( locationCount - 1 );
      } );
    } );

    it( 'removes the TripLocation from the user\'s trip', function() {
      const currentTripLocations = mockTrips.testUserTrip2.tripLocations.map( x => x._id )
      .reduce( ( prev, next ) => {
        if ( next === mockTripLocations.teaTripLocation._id ) return prev;
        return prev.concat( next );
      }, [] );
      return tripLocations.removeTripLocationForUser( mockUsers.testUserId2, mockTripLocations.teaTripLocation )
      .then( () => tripLocations.listTripLocationsForUser( mockUsers.testUserId2 ) )
      .then( function( data ) {
        expect( data.map( x => x._id ) ).to.eql( currentTripLocations );
      } );
    } );

    it( 'does not remove the TripLocation if it exists for a different user', function( done ) {
      return tripLocations.removeTripLocationForUser( mockUsers.testUserId, mockTripLocations.teaTripLocation._id )
      .then( function( data ) {
        done( `expected a rejection, but got ${data}` );
      } )
      .catch( function() {
        done();
      } );
    } );

    it( 'returns the removed TripLocation', function() {
      return tripLocations.removeTripLocationForUser( mockUsers.testUserId2, mockTripLocations.teaTripLocation._id )
      .then( function( tripLocation ) {
        expect( tripLocation.location ).to.eql( mockTripLocations.teaTripLocation.location._id );
      } );
    } );
  } );

  describe( '.getTripLocationForUser', function() {
    it( 'returns the TripLocation if it exists for a user', function() {
      return tripLocations.getTripLocationForUser( mockUsers.testUserId2, mockTripLocations.teaTripLocation._id )
      .then( function( data ) {
        expect( data ).to.have.property( '_id' ).eql( mockTripLocations.teaTripLocation._id );
        expect( data.location ).to.eql( mockTripLocations.teaTripLocation.location._id );
      } );
    } );

    it( 'does not return the location if it exists for a different user', function( done ) {
      return tripLocations.getTripLocationForUser( mockUsers.testUserId, mockTripLocations.teaTripLocation._id )
      .catch( function() {
        done();
      } );
    } );
  } );

  describe( '.updateTripForUser', function() {
    it( 'returns re-ordered TripLocations', function() {
      const ids = [ mockTripLocations.foodTripLocation._id, mockTripLocations.teaTripLocation._id ];
      expect( tripLocations.updateTripForUser( mockUsers.testUserId2, ids ) ).to.eventually.eql( ids );
    } );

    it( 're-orders existing TripLocations', function( done ) {
      const ids = [ mockTripLocations.foodTripLocation._id, mockTripLocations.teaTripLocation._id ];
      tripLocations.updateTripForUser( mockUsers.testUserId2, ids )
      .then( () => tripLocations.listTripLocationsForUser( mockUsers.testUserId2 ) )
      .then( function( data ) {
        const newIds = data.map( loc => loc._id );
        if ( newIds.toString() === ids.toString() ) return done();
        done( `TripLocations were not re-ordered; expected ${ids.toString()}, got ${newIds.toString()}` );
      } );
    } );

    it( 'does not re-order collection if params include a duplicate TripLocation ID', function() {
      const ids = [ mockTripLocations.foodTripLocation._id, mockTripLocations.teaTripLocation._id, mockTripLocations.teaTripLocation._id ];
      const oldIds = [ mockTripLocations.teaTripLocation._id, mockTripLocations.foodTripLocation._id ];
      expect( tripLocations.updateTripForUser( mockUsers.testUserId2, ids ) ).to.eventually.eql( oldIds );
    } );

    it( 'does not re-order collection if params do not include all TripLocation IDs', function() {
      const ids = [ mockTripLocations.foodTripLocation._id ];
      const oldIds = [ mockTripLocations.teaTripLocation._id, mockTripLocations.foodTripLocation._id ];
      expect( tripLocations.updateTripForUser( mockUsers.testUserId2, ids ) ).to.eventually.eql( oldIds );
    } );

    it( 'does not re-order collection if params include a TripLocation ID for another user', function() {
      const ids = [ mockTripLocations.foodTripLocation._id, mockTripLocations.homeTripLocation._id ];
      const oldIds = [ mockTripLocations.teaTripLocation._id, mockTripLocations.foodTripLocation._id ];
      expect( tripLocations.updateTripForUser( mockUsers.testUserId2, ids ) ).to.eventually.eql( oldIds );
    } );
  } );
} );
<commit_msg>Update TripLocation test<commit_after>const chai = require( 'chai' );
const chaiAsPromised = require( 'chai-as-promised' );
const tripLocations = require( '../app/models/trip-location' );
import { connectToDb, disconnectFromDb, resetDb, models, mockUsers, mockTrips, mockLocations, mockTripLocations } from './bootstrap';
import { removeLocationForUser } from '../app/models/location';

chai.use( chaiAsPromised );
const expect = chai.expect;

describe( 'tripLocations', function() {
  before( function( done ) {
    connectToDb( done );
  } );

  after( function() {
    disconnectFromDb();
  } );

  beforeEach( function( done ) {
    resetDb( done );
  } );

  describe( '.listTripLocationsForUser', function() {
    it( 'returns an Array', function() {
      return expect( tripLocations.listTripLocationsForUser( mockUsers.testUserId ) ).to.eventually.be.an.instanceOf( Array );
    } );

    it( 'returns an array with all current TripLocations', function() {
      return tripLocations.listTripLocationsForUser( mockUsers.testUserId2 )
      .then( function( data ) {
        expect( data.map( x => x.location ) ).to.eql( mockTrips.testUserTrip2.tripLocations.map( x => x.location._id ) );
      } );
    } );

    it( 'returns an array that does not include TripLocations from other users', function() {
      return tripLocations.listTripLocationsForUser( mockUsers.testUserId )
      .then( function( data ) {
        expect( data.map( x => x.location ) ).to.eql( mockTrips.testUserTrip.tripLocations.map( x => x.location._id ) );
      } );
    } );

    it( 'does not return any TripLocations that have no associated Location', function() {
      const currentTripLocations = mockTrips.testUserTrip.tripLocations.map( x => x._id )
      .reduce( ( prev, next ) => {
        if ( next === mockTripLocations.homeTripLocation._id ) return prev;
        return prev.concat( next );
      }, [] );
      return removeLocationForUser( mockUsers.testUserId, mockLocations.homeLocation._id )
      .then( function() {
        return tripLocations.listTripLocationsForUser( mockUsers.testUserId )
        .then( function( data ) {
          expect( data.map( x => x._id ) ).to.eql( currentTripLocations );
        } );
      } );
    } );
  } );

  describe( '.addLocationToTrip', function() {
    it( 'creates a new TripLocation with the parameters specified', function() {
      const params = { location: mockLocations.gameLocation._id };
      return tripLocations.addLocationToTrip( mockUsers.testUserId, params )
      .then( function( data ) {
        expect( data.location ).to.eql( params.location );
      } );
    } );

    it( 'creates a new TripLocation without non-whitelisted parameters', function() {
      const params = { foo: 'bar', location: mockLocations.gameLocation._id };
      return tripLocations.addLocationToTrip( mockUsers.testUserId, params )
      .then( function( data ) {
        expect( data.foo ).to.not.exist;
      } );
    } );

    it( 'adds the TripLocation to the end of the user\'s list', function() {
      const params = { location: mockLocations.workLocation._id };
      return tripLocations.addLocationToTrip( mockUsers.testUserId2, params )
      .then( () => tripLocations.listTripLocationsForUser( mockUsers.testUserId2 ) )
      .then( function( data ) {
        const last = data[ data.length - 1 ];
        expect( last.location ).to.eql( params.location );
      } );
    } );
  } );

  describe( '.removeAllTripLocations', function() {
    it( 'removes all the TripLocations for the user', function() {
      return tripLocations.removeAllTripLocations( mockUsers.testUserId2 )
      .then( () => tripLocations.listTripLocationsForUser( mockUsers.testUserId2 ) )
      .then( ( data ) => {
        expect( data ).to.be.empty;
      } );
    } );

    it( 'does not remove TripLocations for other users', function() {
      return tripLocations.removeAllTripLocations( mockUsers.testUserId2 )
      .then( () => tripLocations.listTripLocationsForUser( mockUsers.testUserId ) )
      .then( ( data ) => {
        expect( data ).to.not.be.empty;
      } );
    } );

    it( 'returns the empty list', function() {
      return tripLocations.removeAllTripLocations( mockUsers.testUserId2 )
      .then( ( data ) => {
        expect( data ).to.be.empty;
      } );
    } );
  } );

  describe( '.removeTripLocationForUser', function() {
    it( 'removes the TripLocation from the database', function() {
      let locationCount = 0;
      return models.TripLocation.find()
      .then( ( initialData ) => {
        locationCount = initialData.length;
        return tripLocations.removeTripLocationForUser( mockUsers.testUserId2, mockTripLocations.teaTripLocation )
      } )
      .then( () => models.TripLocation.find() )
      .then( function( data ) {
        expect( data ).to.have.length( locationCount - 1 );
      } );
    } );

    it( 'removes the TripLocation from the user\'s trip', function() {
      const currentTripLocations = mockTrips.testUserTrip2.tripLocations.map( x => x._id )
      .reduce( ( prev, next ) => {
        if ( next === mockTripLocations.teaTripLocation._id ) return prev;
        return prev.concat( next );
      }, [] );
      return tripLocations.removeTripLocationForUser( mockUsers.testUserId2, mockTripLocations.teaTripLocation )
      .then( () => tripLocations.listTripLocationsForUser( mockUsers.testUserId2 ) )
      .then( function( data ) {
        expect( data.map( x => x._id ) ).to.eql( currentTripLocations );
      } );
    } );

    it( 'does not remove the TripLocation if it exists for a different user', function( done ) {
      return tripLocations.removeTripLocationForUser( mockUsers.testUserId, mockTripLocations.teaTripLocation._id )
      .then( function( data ) {
        done( `expected a rejection, but got ${data}` );
      } )
      .catch( function() {
        done();
      } );
    } );

    it( 'returns the removed TripLocation', function() {
      return tripLocations.removeTripLocationForUser( mockUsers.testUserId2, mockTripLocations.teaTripLocation._id )
      .then( function( tripLocation ) {
        expect( tripLocation.location ).to.eql( mockTripLocations.teaTripLocation.location._id );
      } );
    } );
  } );

  describe( '.getTripLocationForUser', function() {
    it( 'returns the TripLocation if it exists for a user', function() {
      return tripLocations.getTripLocationForUser( mockUsers.testUserId2, mockTripLocations.teaTripLocation._id )
      .then( function( data ) {
        expect( data ).to.have.property( '_id' ).eql( mockTripLocations.teaTripLocation._id );
        expect( data.location ).to.eql( mockTripLocations.teaTripLocation.location._id );
      } );
    } );

    it( 'does not return the location if it exists for a different user', function( done ) {
      return tripLocations.getTripLocationForUser( mockUsers.testUserId, mockTripLocations.teaTripLocation._id )
      .catch( function() {
        done();
      } );
    } );
  } );

  describe( '.updateTripForUser', function() {
    it( 'returns re-ordered TripLocations', function() {
      const ids = [ mockTripLocations.foodTripLocation._id, mockTripLocations.teaTripLocation._id ];
      expect( tripLocations.updateTripForUser( mockUsers.testUserId2, ids ) ).to.eventually.eql( ids );
    } );

    it( 're-orders existing TripLocations', function( done ) {
      const ids = [ mockTripLocations.foodTripLocation._id, mockTripLocations.teaTripLocation._id ];
      tripLocations.updateTripForUser( mockUsers.testUserId2, ids )
      .then( () => tripLocations.listTripLocationsForUser( mockUsers.testUserId2 ) )
      .then( function( data ) {
        const newIds = data.map( loc => loc._id );
        if ( newIds.toString() === ids.toString() ) return done();
        done( `TripLocations were not re-ordered; expected ${ids.toString()}, got ${newIds.toString()}` );
      } );
    } );

    it( 'does not re-order collection if params include a duplicate TripLocation ID', function() {
      const ids = [ mockTripLocations.foodTripLocation._id, mockTripLocations.teaTripLocation._id, mockTripLocations.teaTripLocation._id ];
      const oldIds = [ mockTripLocations.teaTripLocation._id, mockTripLocations.foodTripLocation._id ];
      expect( tripLocations.updateTripForUser( mockUsers.testUserId2, ids ) ).to.eventually.eql( oldIds );
    } );

    it( 'does not re-order collection if params do not include all TripLocation IDs', function() {
      const ids = [ mockTripLocations.foodTripLocation._id ];
      const oldIds = [ mockTripLocations.teaTripLocation._id, mockTripLocations.foodTripLocation._id ];
      expect( tripLocations.updateTripForUser( mockUsers.testUserId2, ids ) ).to.eventually.eql( oldIds );
    } );

    it( 'does not re-order collection if params include a TripLocation ID for another user', function() {
      const ids = [ mockTripLocations.foodTripLocation._id, mockTripLocations.homeTripLocation._id ];
      const oldIds = [ mockTripLocations.teaTripLocation._id, mockTripLocations.foodTripLocation._id ];
      expect( tripLocations.updateTripForUser( mockUsers.testUserId2, ids ) ).to.eventually.eql( oldIds );
    } );
  } );
} );
<|endoftext|>


<commit_before>'use strict';

import React from 'react';
import PropTypes from 'prop-types';
import _ from 'underscore';
import { Checkbox, MenuItem, Dropdown, DropdownButton } from 'react-bootstrap';
import { console, object, Schemas } from './../util';
import { FormattedInfoBlock, TabbedView, ExperimentSetTables, ExperimentSetTablesLoaded, WorkflowNodeElement,
    SimpleFilesTableLoaded, SimpleFilesTable, Publications, OverviewHeadingContainer } from './components';
import { OverViewBodyItem } from './DefaultItemView';
import { ExperimentSetDetailPane, ResultRowColumnBlockValue } from './../browse/components';

export default class ExperimentTypeView extends DefaultItemView {

    getTabViewContents(){

        var initTabs = [],
            width = this.getTabViewWidth();

        return initTabs.concat(this.getCommonTabs());
    }

    /**
     * What is to be displayed below Item description and above the TabbedView, if anything. Can return an array or single item.
     *
     * @returns {JSX.Element[]} React elements or components to display between Item header and Item TabbedView.
     */
    itemMidSection(){
        return [
            <Publications.ProducedInPublicationBelowHeaderRow produced_in_pub={this.props.context.reference_pubs} />,
            <OverviewHeading context={this.props.context} />
        ];
    }

}

/**
 * This is rendered in middle of ExperimentView, between Item header and TabbedView.
 * @see ExperimentTypeView.itemMidSection()
 */
class OverviewHeading extends React.Component {
    render(){
        var { context, schemas } = this.props,
            tips = object.tipsFromSchema(schemas || Schemas.get(), context), // In form of { 'description' : {'title', 'description', 'type'}, 'experiment_type' : {'title', 'description', ...}, ... }
            commonProps = {
                'tips'          : tips,                 // Object containing 'properties' from Schema for Experiment ItemType. Informs the property title (from schema) & tooltip you get when hover over property title. Obtained from schemas.
                'result'        : context,              // The Item from which are getting value for 'property'.
                'wrapInColumn'  : "col-xs-6 col-md-3"   // Optional. Size of the block. @see http://getbootstrap.com/docs/3.3/examples/grid/.
            };

        return (
            <OverviewHeadingContainer>
                <OverViewBodyItem {...commonProps} property='sop' fallbackTitle="4DN-Approved SOP" />
                <OverViewBodyItem {...commonProps} property='raw_files' fallbackTitle="Raw Files Available" fallbackValue="No" />
                <OverViewBodyItem {...commonProps} property='reference_pubs' fallbackTitle="Reference Publication" />
            </OverviewHeadingContainer>
        );
    }
}
<commit_msg>Added Overview header and tab to ExperimentTypeView<commit_after>'use strict';

import React from 'react';
import PropTypes from 'prop-types';
import _ from 'underscore';
import { Checkbox, MenuItem, Dropdown, DropdownButton } from 'react-bootstrap';
import { console, object, Schemas } from './../util';
import DefaultItemView, { OverViewBodyItem } from './DefaultItemView';
import { FormattedInfoBlock, TabbedView, ExperimentSetTables, ExperimentSetTablesLoaded, WorkflowNodeElement,
    SimpleFilesTableLoaded, SimpleFilesTable, Publications, Protocols, OverviewHeadingContainer } from './components';
import { ExperimentSetDetailPane, ResultRowColumnBlockValue } from './../browse/components';

export default class ExperimentTypeView extends DefaultItemView {

    getTabViewContents(){

        var initTabs = [],
            width = this.getTabViewWidth();
        var context = this.props.context;

        initTabs.push(ExperimentTypeViewOverview.getTabObject(context, this.props.schemas));

        return initTabs.concat(this.getCommonTabs());
    }

    /**
     * What is to be displayed at top left of page, under title, to the left of accession (if any).
     *
     * @returns {{ title: string|JSX.Element, description: string }} JS Object ascribing what to display.
     */
    typeInfo(){
        return null;
    }

    /**
     * What is to be displayed below Item description and above the TabbedView, if anything. Can return an array or single item.
     *
     * @returns {JSX.Element[]} React elements or components to display between Item header and Item TabbedView.
     */
    itemMidSection(){
        return [
            <Publications.ReferencePubBelowHeaderRow reference_pubs={this.props.context.reference_pubs} />,
            <Protocols.SopBelowHeaderRow sop={this.props.context.sop} />
        ];
    }

}

// /**
//  * This is rendered in middle of ExperimentView, between Item header and TabbedView.
//  * @see ExperimentTypeView.itemMidSection()
//  */
// class OverviewHeading extends React.Component {
//     render(){
//         var { context, schemas } = this.props,
//             tips = object.tipsFromSchema(schemas || Schemas.get(), context), // In form of { 'description' : {'title', 'description', 'type'}, 'experiment_type' : {'title', 'description', ...}, ... }
//             commonProps = {
//                 'tips'          : tips,                 // Object containing 'properties' from Schema for Experiment ItemType. Informs the property title (from schema) & tooltip you get when hover over property title. Obtained from schemas.
//                 'result'        : context,              // The Item from which are getting value for 'property'.
//                 'wrapInColumn'  : "col-xs-6 col-md-3"   // Optional. Size of the block. @see http://getbootstrap.com/docs/3.3/examples/grid/.
//             };
//
//         return (
//             <OverviewHeadingContainer>
//                 <OverViewBodyItem {...commonProps} property='sop' fallbackTitle="4DN-Approved SOP" />
//                 <OverViewBodyItem {...commonProps} property='raw_file_types' fallbackTitle="Raw Files Available" fallbackValue="No" />
//                 <OverViewBodyItem {...commonProps} property='reference_pubs' fallbackTitle="Reference Publication" />
//             </OverviewHeadingContainer>
//         );
//     }
// }

// /**
//  * This is rendered in middle of ExperimentView, between Item header and TabbedView.
//  * @see ExperimentTypeView.itemMidSection()
//  */
// class OverviewHeading extends React.Component {
//     render(){
//         if (!this.props.context.sop) return null;
//         return (
//

//

//                     <DetailBlock protocol={this.props.context.sop} singularTitle="Approved SOP" >
//

//                             <ShortAttribution protocol={this.props.context.sop} />
//

//                     </DetailBlock>
//

//

//         );
//     }
// }

class ExperimentTypeViewOverview extends React.Component {

    /**
     * Get overview tab object for tabpane.
     *
     * @param {Object} context - Current ExperimentType Item being shown.
     * @param {Object} schemas - Schemas passed down from app.state.schemas (or Schemas.get()).
     */
    static getTabObject(context, schemas){
        return {
            'tab' :  Overview,
            'key' : 'overview',
            //'disabled' : !Array.isArray(context.experiments),
            'content' : (

                        Overview

                    <ExperimentTypeViewOverview context={context} schemas={schemas} />

            )
        };
    }

    render(){
        var { context } = this.props;

        return (

                <OverViewBody result={this.props.context} schemas={this.props.schemas} />

        );

    }

}

class OverViewBody extends React.Component {

    render(){
        var result = this.props.result;
        var tips = object.tipsFromSchema(this.props.schemas || Schemas.get(), result);

        return (

                        <OverViewBodyItem {...{ result, tips }} property='experiment_category' fallbackTitle="Experiment Category" wrapInColumn />
                        <OverViewBodyItem {...{ result, tips }} property='assay_classification' fallbackTitle="Assay Classification" wrapInColumn />
                        <OverViewBodyItem {...{ result, tips }} property='assay_subclassification' fallbackTitle="Experimental Purpose" wrapInColumn />
                        <OverViewBodyItem {...{ result, tips }} property='raw_file_types' fallbackTitle="Raw Files Available" wrapInColumn />

        );
    }
}
<|endoftext|>


<commit_before>
var connect = require( 'connect' ),
    shell = require( 'shelljs' ),
    flick = require( '..' ),
    handler = flick(),
    app = connect();

handler.use( 'romac/romac.github.com', gitPull( '/var/www/romac.me', { rebase: true } ) );

function gitPull( root, options )
{
    return function( req, res, next )
    {
        var cmd = 'git pull' + ( options.rebase ? ' --rebase' : '' );

        shell.cd( root );
        shell.exec( cmd, function( code, output )
        {
            console.log( cmd ' exited with code ' + code );
        } );

        next();
    };
}

app.use( connect.bodyParser() );

// 1.
app.use( flick.whitelist( { local: true } ) );
app.use( flick.payload() );
app.use( handler );

// 2.
// handler.use( flick.whitelist( { local: true } ) );
// handler.use( flick.payload() );
// app.use( handler );

// 3.
// app.use( flick.default() );

app.use( function( req, res )
{
    res.writeHead( 200 );
    res.end( 'Thank you, dear friend.\n' );
} );

app.listen( 4001 );
console.log( 'flick is listening on port 4001' );
<commit_msg>Fix a typo.<commit_after>var connect = require( 'connect' ),
    shell = require( 'shelljs' ),
    flick = require( '..' ),
    handler = flick(),
    app = connect();

handler.use( 'romac/romac.github.com', gitPull( '/var/www/romac.me', { rebase: true } ) );

function gitPull( root, options )
{
    return function( req, res, next )
    {
        var cmd = 'git pull' + ( options.rebase ? ' --rebase' : '' );

        shell.cd( root );
        shell.exec( cmd, function( code, output )
        {
            console.log( cmd + ' exited with code ' + code );
        } );

        next();
    };
}

app.use( connect.bodyParser() );

// 1.
app.use( flick.whitelist( { local: true } ) );
app.use( flick.payload() );
app.use( handler );

// 2.
// handler.use( flick.whitelist( { local: true } ) );
// handler.use( flick.payload() );
// app.use( handler );

// 3.
// app.use( flick.default() );

app.use( function( req, res )
{
    res.writeHead( 200 );
    res.end( 'Thank you, dear friend.\n' );
} );

app.listen( 4001 );
console.log( 'flick is listening on port 4001' );
<|endoftext|>


<commit_before>import React, { Component, PropTypes, findDOMNode } from 'react';
import { CompositeDisposable, SerialDisposable, Disposable } from 'rx-lite';
import ComponentDragSource from './ComponentDragSource';
import ComponentDropTarget from './ComponentDropTarget';
import shallowEqual from './utils/shallowEqual';
import shallowEqualScalar from './utils/shallowEqualScalar';
import assign from 'lodash/object/assign';
import memoize from 'lodash/function/memoize';
import invariant from 'react/lib/invariant';

const DEFAULT_KEY = '__default__';

export default function configureDragDrop(InnerComponent, {
  configure,
  collect,
  arePropsEqual = shallowEqualScalar,
  managerName = 'dragDropManager'
}) {
  class DragDropContainer extends Component {
    shouldComponentUpdate(nextProps, nextState) {
      return !arePropsEqual(nextProps, this.props) ||
             !shallowEqual(nextState, this.state);
    }

    constructor(props, context) {
      super(props);
      this.handleChange = this.handleChange.bind(this);
      this.getComponentRef = this.getComponentRef.bind(this);
      this.setComponentRef = this.setComponentRef.bind(this);

      this.manager = context[managerName];
      invariant(this.manager, 'Could not read manager from context.');

      this.handlerIds = {};
      this.handlers = {};
      this.resources = {};

      this.componentRef = null;
      this.componentConnector = this.createComponentConnector();
      this.attachHandlers(this.getNextHandlers(props));
      this.state = this.getCurrentState();
    }

    setComponentRef(ref) {
      this.componentRef = ref;
    }

    getComponentRef() {
      return this.componentRef;
    }

    componentWillMount() {
      const monitor = this.manager.getMonitor();
      monitor.addChangeListener(this.handleChange);
    }

    componentWillReceiveProps(nextProps) {
      if (arePropsEqual(nextProps, this.props)) {
        return;
      }

      const monitor = this.manager.getMonitor();
      monitor.removeChangeListener(this.handleChange);
      this.receiveHandlers(this.getNextHandlers(nextProps));
      monitor.addChangeListener(this.handleChange);

      this.handleChange();
    }

    componentWillUnmount() {
      const monitor = this.manager.getMonitor();
      monitor.removeChangeListener(this.handleChange);

      this.detachHandlers();
      this.componentConnector = null;
    }

    handleChange() {
      const nextState = this.getCurrentState();
      if (!shallowEqual(nextState, this.state)) {
        this.setState(nextState);
      }
    }

    getNextHandlers(props) {
      props = assign({}, props);

      const register = {
        dragSource: (type, spec) => {
          return new ComponentDragSource(type, spec, props, this.getComponentRef);
        },
        dropTarget: (type, spec) => {
          return new ComponentDropTarget(type, spec, props, this.getComponentRef);
        }
      };

      let handlers = configure(register, props);
      if (handlers instanceof ComponentDragSource ||
          handlers instanceof ComponentDropTarget) {

        handlers = {
          [DEFAULT_KEY]: handlers
        };
      }

      return handlers;
    }

    attachHandlers(handlers) {
      this.handlers = assign({}, this.handlers);
      this.handlerIds = assign({}, this.handlerIds);

      Object.keys(handlers).forEach(key => {
        this.attachHandler(key, handlers[key]);
      });
    }

    detachHandlers() {
      this.handlers = assign({}, this.handlers);
      this.handlerIds = assign({}, this.handlerIds);

      Object.keys(this.handlerIds).forEach(key => {
        this.detachHandler(key);
      });
    }

    receiveHandlers(nextHandlers) {
      this.handlers = assign({}, this.handlers);
      this.handlerIds = assign({}, this.handlerIds);

      const keys = Object.keys(this.handlers);
      const nextKeys = Object.keys(nextHandlers);

      invariant(
        keys.every(k => nextKeys.indexOf(k) > -1) &&
        nextKeys.every(k => keys.indexOf(k) > -1) &&
        keys.length === nextKeys.length,
        'Expected handlers to have stable keys at runtime.'
      );

      keys.forEach(key => {
        this.receiveHandler(key, nextHandlers[key]);
      });
    }

    attachHandler(key, handler) {
      const registry = this.manager.getRegistry();

      let handlerId;
      if (handler instanceof ComponentDragSource) {
        handlerId = registry.addSource(handler.type, handler);
      } else if (handler instanceof ComponentDropTarget) {
        handlerId = registry.addTarget(handler.type, handler);
      } else {
        invariant(false, 'Handle is neither a source nor a target.');
      }

      this.handlerIds[key] = handlerId;
      this.handlers[key] = handler;

      this.resources[handlerId] = new CompositeDisposable();
    }

    detachHandler(key) {
      const registry = this.manager.getRegistry();
      const handlerId = this.handlerIds[key];

      if (registry.isSourceId(handlerId)) {
        registry.removeSource(handlerId);
      } else if (registry.isTargetId(handlerId)) {
        registry.removeTarget(handlerId);
      } else {
        invariant(false, 'Handle is neither a source nor a target.');
      }

      this.resources[handlerId].dispose();
      delete this.resources[handlerId];

      delete this.handlerIds[key];
      delete this.handlers[key];
    }

    receiveHandler(key, nextHandler) {
      const handler = this.handlers[key];
      if (handler.receive(nextHandler)) {
        return;
      }

      this.detachHandler(key);
      this.attachHandler(key, nextHandler);
    }

    useResource(handlerId, disposable) {
      this.resources[handlerId].add(disposable);
      return disposable;
    }

    getCurrentState() {
      const monitor = this.manager.getMonitor();

      let handlerIds = this.handlerIds;
      if (typeof handlerIds[DEFAULT_KEY] !== 'undefined') {
        handlerIds = handlerIds[DEFAULT_KEY];
      }

      return collect(this.componentConnector, monitor, handlerIds);
    }

    createComponentConnector() {
      const backend = this.manager.getBackend();
      const backendConnector = backend.connect();
      const componentConnector = {};

      Object.keys(backendConnector).forEach(key => {
        const connectBackend = backendConnector[key].bind(backendConnector);
        const connectComponent = this.wrapConnectBackend(key, connectBackend);

        componentConnector[key] = memoize(connectComponent);
      });

      return componentConnector;
    }

    wrapConnectBackend(key, connectBackend) {
      return (handlerId) => {
        const serialDisposable = this.useResource(handlerId, new SerialDisposable());
        let currentNode = null;

        return (componentOrNode) => {
          var nextNode = findDOMNode(componentOrNode);
          if (nextNode === currentNode) {
            return;
          }

          serialDisposable.setDisposable(null);

          if (nextNode) {
            const dispose = connectBackend(handlerId, nextNode);
            serialDisposable.setDisposable(new Disposable(dispose));
            currentNode = nextNode;
          }
        };
      };
    }

    render() {
      return (
        <InnerComponent {...this.props}
                        {...this.state}
                        ref={this.setComponentRef} />
      );
    }
  }

  DragDropContainer.contextTypes = {
    [managerName]: PropTypes.object.isRequired
  };

  return DragDropContainer;
}<commit_msg>Fix disposal<commit_after>import React, { Component, PropTypes, findDOMNode } from 'react';
import { CompositeDisposable, SerialDisposable, Disposable } from 'rx-lite';
import ComponentDragSource from './ComponentDragSource';
import ComponentDropTarget from './ComponentDropTarget';
import shallowEqual from './utils/shallowEqual';
import shallowEqualScalar from './utils/shallowEqualScalar';
import assign from 'lodash/object/assign';
import memoize from 'lodash/function/memoize';
import invariant from 'react/lib/invariant';

const DEFAULT_KEY = '__default__';

export default function configureDragDrop(InnerComponent, {
  configure,
  collect,
  arePropsEqual = shallowEqualScalar,
  managerName = 'dragDropManager'
}) {
  class DragDropContainer extends Component {
    shouldComponentUpdate(nextProps, nextState) {
      return !arePropsEqual(nextProps, this.props) ||
             !shallowEqual(nextState, this.state);
    }

    constructor(props, context) {
      super(props);
      this.handleChange = this.handleChange.bind(this);
      this.getComponentRef = this.getComponentRef.bind(this);
      this.setComponentRef = this.setComponentRef.bind(this);

      this.manager = context[managerName];
      invariant(this.manager, 'Could not read manager from context.');

      this.handlerIds = {};
      this.handlers = {};
      this.resources = {};

      this.componentRef = null;
      this.componentConnector = this.createComponentConnector();
      this.attachHandlers(this.getNextHandlers(props));
      this.state = this.getCurrentState();
    }

    setComponentRef(ref) {
      this.componentRef = ref;
    }

    getComponentRef() {
      return this.componentRef;
    }

    componentWillMount() {
      const monitor = this.manager.getMonitor();
      monitor.addChangeListener(this.handleChange);
    }

    componentWillReceiveProps(nextProps) {
      if (arePropsEqual(nextProps, this.props)) {
        return;
      }

      const monitor = this.manager.getMonitor();
      monitor.removeChangeListener(this.handleChange);
      this.receiveHandlers(this.getNextHandlers(nextProps));
      monitor.addChangeListener(this.handleChange);

      this.handleChange();
    }

    componentWillUnmount() {
      const monitor = this.manager.getMonitor();
      monitor.removeChangeListener(this.handleChange);

      this.detachHandlers();
      this.componentConnector = null;
    }

    handleChange() {
      const nextState = this.getCurrentState();
      if (!shallowEqual(nextState, this.state)) {
        this.setState(nextState);
      }
    }

    getNextHandlers(props) {
      props = assign({}, props);

      const register = {
        dragSource: (type, spec) => {
          return new ComponentDragSource(type, spec, props, this.getComponentRef);
        },
        dropTarget: (type, spec) => {
          return new ComponentDropTarget(type, spec, props, this.getComponentRef);
        }
      };

      let handlers = configure(register, props);
      if (handlers instanceof ComponentDragSource ||
          handlers instanceof ComponentDropTarget) {

        handlers = {
          [DEFAULT_KEY]: handlers
        };
      }

      return handlers;
    }

    attachHandlers(handlers) {
      this.handlers = assign({}, this.handlers);
      this.handlerIds = assign({}, this.handlerIds);

      Object.keys(handlers).forEach(key => {
        this.attachHandler(key, handlers[key]);
      });
    }

    detachHandlers() {
      this.handlers = assign({}, this.handlers);
      this.handlerIds = assign({}, this.handlerIds);

      Object.keys(this.handlerIds).forEach(key => {
        this.detachHandler(key);
      });
    }

    receiveHandlers(nextHandlers) {
      this.handlers = assign({}, this.handlers);
      this.handlerIds = assign({}, this.handlerIds);

      const keys = Object.keys(this.handlers);
      const nextKeys = Object.keys(nextHandlers);

      invariant(
        keys.every(k => nextKeys.indexOf(k) > -1) &&
        nextKeys.every(k => keys.indexOf(k) > -1) &&
        keys.length === nextKeys.length,
        'Expected handlers to have stable keys at runtime.'
      );

      keys.forEach(key => {
        this.receiveHandler(key, nextHandlers[key]);
      });
    }

    attachHandler(key, handler) {
      const registry = this.manager.getRegistry();

      let handlerId;
      if (handler instanceof ComponentDragSource) {
        handlerId = registry.addSource(handler.type, handler);
      } else if (handler instanceof ComponentDropTarget) {
        handlerId = registry.addTarget(handler.type, handler);
      } else {
        invariant(false, 'Handle is neither a source nor a target.');
      }

      this.handlerIds[key] = handlerId;
      this.handlers[key] = handler;

      this.resources[handlerId] = new CompositeDisposable();
    }

    detachHandler(key) {
      const registry = this.manager.getRegistry();
      const handlerId = this.handlerIds[key];

      if (registry.isSourceId(handlerId)) {
        registry.removeSource(handlerId);
      } else if (registry.isTargetId(handlerId)) {
        registry.removeTarget(handlerId);
      } else {
        invariant(false, 'Handle is neither a source nor a target.');
      }

      this.resources[handlerId].dispose();
      delete this.resources[handlerId];

      delete this.handlerIds[key];
      delete this.handlers[key];
    }

    receiveHandler(key, nextHandler) {
      const handler = this.handlers[key];
      if (handler.receive(nextHandler)) {
        return;
      }

      this.detachHandler(key);
      this.attachHandler(key, nextHandler);
    }

    useResource(handlerId, disposable) {
      this.resources[handlerId].add(disposable);
      return disposable;
    }

    getCurrentState() {
      const monitor = this.manager.getMonitor();

      let handlerIds = this.handlerIds;
      if (typeof handlerIds[DEFAULT_KEY] !== 'undefined') {
        handlerIds = handlerIds[DEFAULT_KEY];
      }

      return collect(this.componentConnector, monitor, handlerIds);
    }

    createComponentConnector() {
      const backend = this.manager.getBackend();
      const backendConnector = backend.connect();
      const componentConnector = {};

      Object.keys(backendConnector).forEach(key => {
        const connectBackend = backendConnector[key].bind(backendConnector);
        const connectComponent = this.wrapConnectBackend(key, connectBackend);

        componentConnector[key] = memoize(connectComponent);
      });

      return componentConnector;
    }

    wrapConnectBackend(key, connectBackend) {
      return (handlerId) => {
        const serialDisposable = this.useResource(handlerId, new SerialDisposable());
        let currentNode = null;

        return (componentOrNode) => {
          var nextNode = findDOMNode(componentOrNode);
          if (nextNode === currentNode) {
            return;
          }

          currentNode = nextNode;
          serialDisposable.setDisposable(null);

          if (nextNode) {
            const nextDispose = connectBackend(handlerId, nextNode);
            serialDisposable.setDisposable(new Disposable(nextDispose));
          }
        };
      };
    }

    render() {
      return (
        <InnerComponent {...this.props}
                        {...this.state}
                        ref={this.setComponentRef} />
      );
    }
  }

  DragDropContainer.contextTypes = {
    [managerName]: PropTypes.object.isRequired
  };

  return DragDropContainer;
}<|endoftext|>