<commit_before>/**
 * @module Keo
 * @link https://github.com/Wildhoney/Keo
 * @author Adam Timberlake
 */
import objectAssign from 'object-assign';
import {createClass} from 'react';
import * as fnkl from 'funkel';
export {memoize, trace, partial} from 'funkel';
export {objectAssign};

/**
 * @method isFunction
 * @param {*} fn
 * @return {Boolean}
 */
const isFunction = fn => typeof fn === 'function';

/**
 * @property resolving
 * @type {Object}
 */
const resolving = {};

/**
 * @method resolutionMap
 * @param {Array} args
 * @return {Array}
 */
export const resolutionMap = args => {

    return objectAssign({}, args, {
        props: { ...args.props, resolving }
    });

};

/**
 * @method isPromise
 * @param {*} x
 * @return {Boolean}
 */
function isPromise(x) {
    return 'then' in Object(x);
}

/**
 * @method isObject
 * @param {*} x
 * @return {Boolean}
 */
function isObject(x) {
    return typeof x === 'object';
}

/**
 * @method createWithCompose
 * @param {Object} component
 * @return {createClass}
 */
export const createWithCompose = component => {

    /**
     * @method passArguments
     * @return {Object}
     */
    function passArguments() {

        /**
         * @method orObject
         * @param {*} x
         * @return {Object}
         */
        const orObject = x => x || {};

        /**
         * @method element
         * @param {String} ref
         * @return {HTMLElement}
         */
        const element = ref => {
            return this.refs[ref];
        };

        /**
         * @method refs
         * @type {Proxy|Object}
         */
        const refs = typeof Proxy === 'undefined' ? {} : new Proxy(this.refs, {

            /**
             * @method get
             * @param {Object} target
             * @param {String} key
             */
            get: (target, key) => this.refs[key]

        });

        const props = orObject(this.props);
        const state = orObject(this.state);
        const context = orObject(this.context);
        const forceUpdate = this::this.forceUpdate;

        /**
         * @method dispatch
         * @param {*} model
         * @type {*|Function}
         */
        const dispatch = (...model) => {

            if (isPromise(model)) {
                return model.then(x => dispatch(model));
            }

            model != null && props.dispatch && props.dispatch(...model);
            return model;

        };

        /**
         * @method setState
         * @param {Object} state
         * @return {Object}
         */
        const setState = state => {

            if (isPromise(state)) {
                return state.then(x => setState(x));
            }

            /**
             * @method keyToState
             * @param {Object} accumulator
             * @param {String} key
             * @return {Object}
             */
            const keyToState = (accumulator, key) => {
                accumulator[key] = state[key];
                return accumulator;
            };

            /**
             * @property immediateState
             * @type {Object}
             */
            const immediateState = (() => {

                if (isPromise(state)) {

                    // Defer promise states until they have been resolved.
                    state.then(value => setState(value));
                    return null;

                }

                if (state && isObject(state)) {

                    const keys = Object.keys(state);

                    /**
                     * @method containsPromise
                     * @param {String} key
                     * @return {Boolean}
                     */
                    const containsPromise = key => {

                        const cursor = state[key];

                        return isPromise(cursor) || (() => {

                            if (Array.isArray(cursor)) {

                                // Determine if an array was passed, which includes a promise.
                                return cursor.some(item => isPromise(item));

                            }

                            return false;

                        })();

                    };

                    // Determine which state items yield promises, and which yield immediate values.
                    const futureStates = keys.filter(key => containsPromise(key)).reduce(keyToState, {});

                    // Iterate over each future state to apply the state once the promise has been resolved.
                    Object.keys(futureStates).map(key => {

                        const cursor = state[key];

                        if (isPromise(cursor)) {

                            resolving[key] = true;

                            // Resolve a simple promise contained within an object.
                            state[key].then(value => {

                                // Succeeded! We'll therefore update the value.
                                resolving[key] = false;
                                setState({ [key]: value });

                            }).catch(() => {

                                // Failed! In which case we'll simply re-render.
                                resolving[key] = false;
                                forceUpdate();

                            });

                        }

                        if (Array.isArray(cursor)) {

                            // Await all promises to resolve before setting the state.
                            const promises = cursor.filter(item => isPromise(item));
                            const items = cursor.filter(item => !isPromise(item));

                            resolving[key] = true;

                            Promise.all(promises).then(array => {

                                // Succeeded! Therefore we'll merge the new items in with the existing items.
                                resolving[key] = false;
                                setState({ [key]: [...items, ...array] });

                            }).catch(() => {

                                // Failed! We'll therefore display only the existing items.
                                resolving[key] = false;
                                setState({ [key]: items });

                            });

                        }

                    });

                    return keys.filter(key => !containsPromise(key)).reduce(keyToState, {});

                }

            })();

            const notEmpty = isObject(immediateState) ? Object.keys(immediateState).length : immediateState != null;
            notEmpty && this.setState(immediateState);
            return immediateState;

        };

        return { props, state, setState, dispatch, element, refs, context, forceUpdate };

    }

    /**
     * @method orFunction
     * @param {Function} fn
     * @return {Function}
     */
    function orFunction(fn) {
        return isFunction(fn) ? fn : () => {};
    }

    return createClass(objectAssign({}, component, {

        /**
         * @method componentWillMount
         * @return {*}
         */
        componentWillMount: compose(passArguments, orFunction(component.componentWillMount)),

        /**
         * @method componentDidMount
         * @return {*}
         */
        componentDidMount: compose(passArguments, orFunction(component.componentDidMount)),

        /**
         * @method componentWillUnmount
         * @return {*}
         */
        componentWillUnmount: compose(passArguments, orFunction(component.componentWillUnmount)),

        /**
         * @method componentDidUpdate
         * @param prevProps {Object}
         * @param prevState {Object}
         * @return {*}
         */
        componentDidUpdate(prevProps, prevState) {
            orFunction(component.componentDidUpdate)(prevProps, prevState, passArguments.apply(this));
        },

        /**
         * @method componentWillReceiveProps
         * @param nextProps {Object}
         * @return {*}
         */
        componentWillReceiveProps(nextProps) {
            orFunction(component.componentWillReceiveProps)(nextProps, passArguments.apply(this));
        },

        /**
         * @method render
         * @return {XML}
         */
        render: compose(passArguments, component.render)

    }));

};

/**
 * @method stitch
 * @param {Object|Function} component
 * @return {createClass}
 */
export const stitch = component => {
    return createWithCompose(wrap(component));
};

/**
 * @method wrap
 * @param {Object|Function} object
 * @return {Object}
 */
export const wrap = object => {
    return isFunction(object) ? { render: object } : object;
};

/**
 * @method compose
 * @param {Function} fns
 * @return {Function}
 */
export const compose = (...fns) => {
    return fnkl.compose(...fns.reverse());
};

/**
 * @method composeDeferred
 * @param {Function} fns
 * @return {Promise}
 */
export const composeDeferred = (...fns) => {
    return fnkl.composeDeferred(...fns.reverse());
};
<commit_msg>Added 'componentWillUpdate'<commit_after>/**
 * @module Keo
 * @link https://github.com/Wildhoney/Keo
 * @author Adam Timberlake
 */
import objectAssign from 'object-assign';
import {createClass} from 'react';
import * as fnkl from 'funkel';
export {memoize, trace, partial} from 'funkel';
export {objectAssign};

/**
 * @method isFunction
 * @param {*} fn
 * @return {Boolean}
 */
const isFunction = fn => typeof fn === 'function';

/**
 * @property resolving
 * @type {Object}
 */
const resolving = {};

/**
 * @method resolutionMap
 * @param {Array} args
 * @return {Array}
 */
export const resolutionMap = args => {

    return objectAssign({}, args, {
        props: { ...args.props, resolving }
    });

};

/**
 * @method isPromise
 * @param {*} x
 * @return {Boolean}
 */
function isPromise(x) {
    return 'then' in Object(x);
}

/**
 * @method isObject
 * @param {*} x
 * @return {Boolean}
 */
function isObject(x) {
    return typeof x === 'object';
}

/**
 * @method createWithCompose
 * @param {Object} component
 * @return {createClass}
 */
export const createWithCompose = component => {

    /**
     * @method passArguments
     * @return {Object}
     */
    function passArguments() {

        /**
         * @method orObject
         * @param {*} x
         * @return {Object}
         */
        const orObject = x => x || {};

        /**
         * @method element
         * @param {String} ref
         * @return {HTMLElement}
         */
        const element = ref => {
            return this.refs[ref];
        };

        /**
         * @method refs
         * @type {Proxy|Object}
         */
        const refs = typeof Proxy === 'undefined' ? {} : new Proxy(this.refs, {

            /**
             * @method get
             * @param {Object} target
             * @param {String} key
             */
            get: (target, key) => this.refs[key]

        });

        const props = orObject(this.props);
        const state = orObject(this.state);
        const context = orObject(this.context);
        const forceUpdate = this::this.forceUpdate;

        /**
         * @method dispatch
         * @param {*} model
         * @type {*|Function}
         */
        const dispatch = (...model) => {

            if (isPromise(model)) {
                return model.then(x => dispatch(model));
            }

            model != null && props.dispatch && props.dispatch(...model);
            return model;

        };

        /**
         * @method setState
         * @param {Object} state
         * @return {Object}
         */
        const setState = state => {

            if (isPromise(state)) {
                return state.then(x => setState(x));
            }

            /**
             * @method keyToState
             * @param {Object} accumulator
             * @param {String} key
             * @return {Object}
             */
            const keyToState = (accumulator, key) => {
                accumulator[key] = state[key];
                return accumulator;
            };

            /**
             * @property immediateState
             * @type {Object}
             */
            const immediateState = (() => {

                if (isPromise(state)) {

                    // Defer promise states until they have been resolved.
                    state.then(value => setState(value));
                    return null;

                }

                if (state && isObject(state)) {

                    const keys = Object.keys(state);

                    /**
                     * @method containsPromise
                     * @param {String} key
                     * @return {Boolean}
                     */
                    const containsPromise = key => {

                        const cursor = state[key];

                        return isPromise(cursor) || (() => {

                            if (Array.isArray(cursor)) {

                                // Determine if an array was passed, which includes a promise.
                                return cursor.some(item => isPromise(item));

                            }

                            return false;

                        })();

                    };

                    // Determine which state items yield promises, and which yield immediate values.
                    const futureStates = keys.filter(key => containsPromise(key)).reduce(keyToState, {});

                    // Iterate over each future state to apply the state once the promise has been resolved.
                    Object.keys(futureStates).map(key => {

                        const cursor = state[key];

                        if (isPromise(cursor)) {

                            resolving[key] = true;

                            // Resolve a simple promise contained within an object.
                            state[key].then(value => {

                                // Succeeded! We'll therefore update the value.
                                resolving[key] = false;
                                setState({ [key]: value });

                            }).catch(() => {

                                // Failed! In which case we'll simply re-render.
                                resolving[key] = false;
                                forceUpdate();

                            });

                        }

                        if (Array.isArray(cursor)) {

                            // Await all promises to resolve before setting the state.
                            const promises = cursor.filter(item => isPromise(item));
                            const items = cursor.filter(item => !isPromise(item));

                            resolving[key] = true;

                            Promise.all(promises).then(array => {

                                // Succeeded! Therefore we'll merge the new items in with the existing items.
                                resolving[key] = false;
                                setState({ [key]: [...items, ...array] });

                            }).catch(() => {

                                // Failed! We'll therefore display only the existing items.
                                resolving[key] = false;
                                setState({ [key]: items });

                            });

                        }

                    });

                    return keys.filter(key => !containsPromise(key)).reduce(keyToState, {});

                }

            })();

            const notEmpty = isObject(immediateState) ? Object.keys(immediateState).length : immediateState != null;
            notEmpty && this.setState(immediateState);
            return immediateState;

        };

        return { props, state, setState, dispatch, element, refs, context, forceUpdate };

    }

    /**
     * @method orFunction
     * @param {Function} fn
     * @return {Function}
     */
    function orFunction(fn) {
        return isFunction(fn) ? fn : () => {};
    }

    return createClass(objectAssign({}, component, {

        /**
         * @method componentWillMount
         * @return {*}
         */
        componentWillMount: compose(passArguments, orFunction(component.componentWillMount)),

        /**
         * @method componentDidMount
         * @return {*}
         */
        componentDidMount: compose(passArguments, orFunction(component.componentDidMount)),

        /**
         * @method componentWillUnmount
         * @return {*}
         */
        componentWillUnmount: compose(passArguments, orFunction(component.componentWillUnmount)),

        /**
         * @method componentWillUpdate
         * @param prevProps {Object}
         * @return {*}
         */
        componentWillUpdate(prevProps) {
            orFunction(component.componentDidUpdate)(prevProps, passArguments.apply(this));
        },

        /**
         * @method componentDidUpdate
         * @param prevProps {Object}
         * @param prevState {Object}
         * @return {*}
         */
        componentDidUpdate(prevProps, prevState) {
            orFunction(component.componentDidUpdate)(prevProps, prevState, passArguments.apply(this));
        },

        /**
         * @method componentWillReceiveProps
         * @param nextProps {Object}
         * @return {*}
         */
        componentWillReceiveProps(nextProps) {
            orFunction(component.componentWillReceiveProps)(nextProps, passArguments.apply(this));
        },

        /**
         * @method render
         * @return {XML}
         */
        render: compose(passArguments, component.render)

    }));

};

/**
 * @method stitch
 * @param {Object|Function} component
 * @return {createClass}
 */
export const stitch = component => {
    return createWithCompose(wrap(component));
};

/**
 * @method wrap
 * @param {Object|Function} object
 * @return {Object}
 */
export const wrap = object => {
    return isFunction(object) ? { render: object } : object;
};

/**
 * @method compose
 * @param {Function} fns
 * @return {Function}
 */
export const compose = (...fns) => {
    return fnkl.compose(...fns.reverse());
};

/**
 * @method composeDeferred
 * @param {Function} fns
 * @return {Promise}
 */
export const composeDeferred = (...fns) => {
    return fnkl.composeDeferred(...fns.reverse());
};
<|endoftext|>


<commit_before>import { indexOf, binToRaw } from './bintools.js'
import { assert } from './assert.js'

export let STATUS_CODES = {
  '100': 'Continue',
  '101': 'Switching Protocols',
  '102': 'Processing', // RFC 2518, obsoleted by RFC 4918
  '200': 'OK',
  '201': 'Created',
  '202': 'Accepted',
  '203': 'Non-Authoritative Information',
  '204': 'No Content',
  '205': 'Reset Content',
  '206': 'Partial Content',
  '207': 'Multi-Status', // RFC 4918
  '300': 'Multiple Choices',
  '301': 'Moved Permanently',
  '302': 'Moved Temporarily',
  '303': 'See Other',
  '304': 'Not Modified',
  '305': 'Use Proxy',
  '307': 'Temporary Redirect',
  '400': 'Bad Request',
  '401': 'Unauthorized',
  '402': 'Payment Required',
  '403': 'Forbidden',
  '404': 'Not Found',
  '405': 'Method Not Allowed',
  '406': 'Not Acceptable',
  '407': 'Proxy Authentication Required',
  '408': 'Request Time-out',
  '409': 'Conflict',
  '410': 'Gone',
  '411': 'Length Required',
  '412': 'Precondition Failed',
  '413': 'Request Entity Too Large',
  '414': 'Request-URI Too Large',
  '415': 'Unsupported Media Type',
  '416': 'Requested Range Not Satisfiable',
  '417': 'Expectation Failed',
  '418': 'I\'m a teapot', // RFC 2324
  '422': 'Unprocessable Entity', // RFC 4918
  '423': 'Locked', // RFC 4918
  '424': 'Failed Dependency', // RFC 4918
  '425': 'Unordered Collection', // RFC 4918
  '426': 'Upgrade Required', // RFC 2817
  '500': 'Internal Server Error',
  '501': 'Not Implemented',
  '502': 'Bad Gateway',
  '503': 'Service Unavailable',
  '504': 'Gateway Time-out',
  '505': 'HTTP Version not supported',
  '506': 'Variant Also Negotiates', // RFC 2295
  '507': 'Insufficient Storage', // RFC 4918
  '509': 'Bandwidth Limit Exceeded',
  '510': 'Not Extended' // RFC 2774
}

export function encoder () {
  let mode

  function encodeHead (item) {
    if (!item || item.constructor !== Object) {
      return item
    } else if (typeof item !== 'object') {
      throw new Error(
        'expected an object but got a ' + (typeof item) + ' when encoding data'
      )
    }
    let head, chunkedEncoding
    let version = item.version || 1.1
    if (item.method) {
      let path = item.path
      assert(path && path.length > 0, 'expected non-empty path')
      head = [item.method + ' ' + item.path + ' HTTP/' + version + '\r\n']
    } else {
      let reason = item.reason || STATUS_CODES[item.code]
      head = ['HTTP/' + version + ' ' + item.code + ' ' + reason + '\r\n']
    }
    let headers = item.headers
    if (Array.isArray(headers)) {
      for (let i = 0, l = headers.length; i < l; i += 2) {
        processHeader(headers[i], headers[i + 1])
      }
    } else {
      for (let key in headers) {
        processHeader(key, headers[key])
      }
    }
    function processHeader (key, value) {
      let lowerKey = key.toLowerCase()
      if (lowerKey === 'transfer-encoding') {
        chunkedEncoding = value.toLowerCase() === 'chunked'
      }
      value = ('' + value).replace(/[\r\n]+/, ' ')
      head[head.length] = key + ': ' + value + '\r\n'
    }

    head[head.length] = '\r\n'

    mode = chunkedEncoding ? encodeChunked : encodeRaw
    return head.join('')
  }

  function encodeRaw (item) {
    if (typeof item !== 'string') {
      mode = encodeHead
      return encodeHead(item)
    }
    return item
  }

  function encodeChunked (item) {
    if (typeof item !== 'string') {
      mode = encodeHead
      let extra = encodeHead(item)
      if (extra) {
        return '0\r\n\r\n' + extra
      } else {
        return '0\r\n\r\n'
      }
    }
    if (item.length === 0) {
      mode = encodeHead
    }
    return item.length.toString(16) + '\r\n' + item + '\r\n'
  }

  mode = encodeHead
  function encode (item) {
    return mode(item)
  }
  return encode
}

export function decoder () {
  // This decoder is somewhat stateful with 5 different parsing states.
  let mode // state variable that points to various decoders
  let bytesLeft // For counted decoder

  // This state is for decoding the status line and headers.
  function decodeHead (chunk, offset) {
    if (!chunk || chunk.length <= offset) return

    // First make sure we have all the head before continuing
    let index = indexOf(chunk, '\r\n\r\n', offset)
    if (index < 0) {
      if ((chunk.length - offset) < 8 * 1024) return
      // But protect against evil clients by refusing heads over 8K long.
      throw new Error('entity too large')
    }
    // Remember where the head ended and the body started
    let bodyStart = index + 4

    // Parse the status/request line
    let head = {}

    index = indexOf(chunk, '\n', offset) + 1
    let line = binToRaw(chunk, offset, index)
    let match = line.match(/^HTTP\/(\d\.\d) (\d+) ([^\r\n]+)/)
    let version
    if (match) {
      version = match[1]
      head.code = parseInt(match[2], 10)
      head.reason = match[3]
    } else {
      match = line.match(/^([A-Z]+) ([^ ]+) HTTP\/(\d\.\d)/)
      if (match) {
        head.method = match[1]
        head.path = match[2]
        version = match[3]
      } else {
        throw new Error('expected HTTP data')
      }
    }
    head.version = parseFloat(version)
    head.keepAlive = head.version > 1.0

    // We need to inspect some headers to know how to parse the body.
    let contentLength
    let chunkedEncoding

    let headers = head.headers = []
    // Parse the header lines
    let start = index
    while ((index = indexOf(chunk, '\n', index) + 1)) {
      line = binToRaw(chunk, start, index)
      if (line === '\r\n') break
      start = index
      let match = line.match(/^([^:\r\n]+): *([^\r\n]*)/)
      if (!match) {
        throw new Error('Malformed HTTP header: ' + line)
      }
      let key = match[1]
      let value = match[2]
      let lowerKey = key.toLowerCase()

      // Inspect a few headers and remember the values
      if (lowerKey === 'content-length') {
        contentLength = parseInt(value)
      } else if (lowerKey === 'transfer-encoding') {
        chunkedEncoding = value.toLowerCase() === 'chunked'
      } else if (lowerKey === 'connection') {
        head.keepAlive = value.toLowerCase() === 'keep-alive'
      }
      headers.push(key, value)
    }

    if (head.keepAlive
      ? !(chunkedEncoding || (contentLength !== undefined && contentLength > 0))
      : (head.method === 'GET' || head.method === 'HEAD')
    ) {
      mode = decodeEmpty
    } else if (chunkedEncoding) {
      mode = decodeChunked
    } else if (contentLength !== undefined) {
      bytesLeft = contentLength
      mode = decodeCounted
    } else if (!head.keepAlive) {
      mode = decodeRaw
    }
    return [head, bodyStart]
  }

  // This is used for inserting a single empty string into the output string for known empty bodies
  function decodeEmpty (chunk, offset) {
    mode = decodeHead
    return [new Uint8Array(0), offset]
  }

  function decodeRaw (chunk, offset) {
    if (!chunk || chunk.length >= offset) return [new Uint8Array(0)]
    if (chunk.length === 0) return
    return [chunk.slice(offset), chunk.length]
  }

  function decodeChunked (chunk, offset) {
    // Make sure we have at least the length header
    let index = indexOf(chunk, '\r\n', offset)
    if (index < 0) return

    // And parse it
    let hex = binToRaw(chunk, offset, index)
    let length = parseInt(hex, 16)

    // Wait till we have the rest of the body
    let start = hex.length + 2
    let end = start + length
    if ((chunk.length - offset) < end + 2) return

    // An empty chunk means end of stream; reset state.
    if (length === 0) mode = decodeHead

    // Make sure the chunk ends in '\r\n'
    assert(binToRaw(chunk, end, end + 2) === '\r\n', 'Invalid chunk tail')

    return [chunk.slice(start, end), end + 2]
  }

  function decodeCounted (chunk, offset) {
    if (bytesLeft === 0) {
      mode = decodeEmpty
      return mode(chunk, offset)
    }
    let length = (chunk && chunk.length) - offset
    // Make sure we have at least one byte to process
    if (length <= 0) return

    if (length >= bytesLeft) { mode = decodeEmpty }

    // If the entire chunk fits, pass it all through
    if (length <= bytesLeft) {
      bytesLeft -= length
      return [chunk.slice(offset), chunk.length]
    }

    return [chunk.slice(offset, bytesLeft), offset + bytesLeft + 1]
  }

  // Switch between states by changing which decoder mode points to
  mode = decodeHead
  function decode (chunk, offset) {
    return mode(chunk, offset)
  }
  return decode
}
<commit_msg>Fix decodeRaw to match new socket wrapper<commit_after>import { indexOf, binToRaw } from './bintools.js'
import { assert } from './assert.js'

export let STATUS_CODES = {
  '100': 'Continue',
  '101': 'Switching Protocols',
  '102': 'Processing', // RFC 2518, obsoleted by RFC 4918
  '200': 'OK',
  '201': 'Created',
  '202': 'Accepted',
  '203': 'Non-Authoritative Information',
  '204': 'No Content',
  '205': 'Reset Content',
  '206': 'Partial Content',
  '207': 'Multi-Status', // RFC 4918
  '300': 'Multiple Choices',
  '301': 'Moved Permanently',
  '302': 'Moved Temporarily',
  '303': 'See Other',
  '304': 'Not Modified',
  '305': 'Use Proxy',
  '307': 'Temporary Redirect',
  '400': 'Bad Request',
  '401': 'Unauthorized',
  '402': 'Payment Required',
  '403': 'Forbidden',
  '404': 'Not Found',
  '405': 'Method Not Allowed',
  '406': 'Not Acceptable',
  '407': 'Proxy Authentication Required',
  '408': 'Request Time-out',
  '409': 'Conflict',
  '410': 'Gone',
  '411': 'Length Required',
  '412': 'Precondition Failed',
  '413': 'Request Entity Too Large',
  '414': 'Request-URI Too Large',
  '415': 'Unsupported Media Type',
  '416': 'Requested Range Not Satisfiable',
  '417': 'Expectation Failed',
  '418': 'I\'m a teapot', // RFC 2324
  '422': 'Unprocessable Entity', // RFC 4918
  '423': 'Locked', // RFC 4918
  '424': 'Failed Dependency', // RFC 4918
  '425': 'Unordered Collection', // RFC 4918
  '426': 'Upgrade Required', // RFC 2817
  '500': 'Internal Server Error',
  '501': 'Not Implemented',
  '502': 'Bad Gateway',
  '503': 'Service Unavailable',
  '504': 'Gateway Time-out',
  '505': 'HTTP Version not supported',
  '506': 'Variant Also Negotiates', // RFC 2295
  '507': 'Insufficient Storage', // RFC 4918
  '509': 'Bandwidth Limit Exceeded',
  '510': 'Not Extended' // RFC 2774
}

export function encoder () {
  let mode

  function encodeHead (item) {
    if (!item || item.constructor !== Object) {
      return item
    } else if (typeof item !== 'object') {
      throw new Error(
        'expected an object but got a ' + (typeof item) + ' when encoding data'
      )
    }
    let head, chunkedEncoding
    let version = item.version || 1.1
    if (item.method) {
      let path = item.path
      assert(path && path.length > 0, 'expected non-empty path')
      head = [item.method + ' ' + item.path + ' HTTP/' + version + '\r\n']
    } else {
      let reason = item.reason || STATUS_CODES[item.code]
      head = ['HTTP/' + version + ' ' + item.code + ' ' + reason + '\r\n']
    }
    let headers = item.headers
    if (Array.isArray(headers)) {
      for (let i = 0, l = headers.length; i < l; i += 2) {
        processHeader(headers[i], headers[i + 1])
      }
    } else {
      for (let key in headers) {
        processHeader(key, headers[key])
      }
    }
    function processHeader (key, value) {
      let lowerKey = key.toLowerCase()
      if (lowerKey === 'transfer-encoding') {
        chunkedEncoding = value.toLowerCase() === 'chunked'
      }
      value = ('' + value).replace(/[\r\n]+/, ' ')
      head[head.length] = key + ': ' + value + '\r\n'
    }

    head[head.length] = '\r\n'

    mode = chunkedEncoding ? encodeChunked : encodeRaw
    return head.join('')
  }

  function encodeRaw (item) {
    if (typeof item !== 'string') {
      mode = encodeHead
      return encodeHead(item)
    }
    return item
  }

  function encodeChunked (item) {
    if (typeof item !== 'string') {
      mode = encodeHead
      let extra = encodeHead(item)
      if (extra) {
        return '0\r\n\r\n' + extra
      } else {
        return '0\r\n\r\n'
      }
    }
    if (item.length === 0) {
      mode = encodeHead
    }
    return item.length.toString(16) + '\r\n' + item + '\r\n'
  }

  mode = encodeHead
  function encode (item) {
    return mode(item)
  }
  return encode
}

export function decoder () {
  // This decoder is somewhat stateful with 5 different parsing states.
  let mode // state variable that points to various decoders
  let bytesLeft // For counted decoder

  // This state is for decoding the status line and headers.
  function decodeHead (chunk, offset) {
    if (!chunk || chunk.length <= offset) return

    // First make sure we have all the head before continuing
    let index = indexOf(chunk, '\r\n\r\n', offset)
    if (index < 0) {
      if ((chunk.length - offset) < 8 * 1024) return
      // But protect against evil clients by refusing heads over 8K long.
      throw new Error('entity too large')
    }
    // Remember where the head ended and the body started
    let bodyStart = index + 4

    // Parse the status/request line
    let head = {}

    index = indexOf(chunk, '\n', offset) + 1
    let line = binToRaw(chunk, offset, index)
    let match = line.match(/^HTTP\/(\d\.\d) (\d+) ([^\r\n]+)/)
    let version
    if (match) {
      version = match[1]
      head.code = parseInt(match[2], 10)
      head.reason = match[3]
    } else {
      match = line.match(/^([A-Z]+) ([^ ]+) HTTP\/(\d\.\d)/)
      if (match) {
        head.method = match[1]
        head.path = match[2]
        version = match[3]
      } else {
        throw new Error('expected HTTP data')
      }
    }
    head.version = parseFloat(version)
    head.keepAlive = head.version > 1.0

    // We need to inspect some headers to know how to parse the body.
    let contentLength
    let chunkedEncoding

    let headers = head.headers = []
    // Parse the header lines
    let start = index
    while ((index = indexOf(chunk, '\n', index) + 1)) {
      line = binToRaw(chunk, start, index)
      if (line === '\r\n') break
      start = index
      let match = line.match(/^([^:\r\n]+): *([^\r\n]*)/)
      if (!match) {
        throw new Error('Malformed HTTP header: ' + line)
      }
      let key = match[1]
      let value = match[2]
      let lowerKey = key.toLowerCase()

      // Inspect a few headers and remember the values
      if (lowerKey === 'content-length') {
        contentLength = parseInt(value)
      } else if (lowerKey === 'transfer-encoding') {
        chunkedEncoding = value.toLowerCase() === 'chunked'
      } else if (lowerKey === 'connection') {
        head.keepAlive = value.toLowerCase() === 'keep-alive'
      }
      headers.push(key, value)
    }

    if (head.keepAlive
      ? !(chunkedEncoding || (contentLength !== undefined && contentLength > 0))
      : (head.method === 'GET' || head.method === 'HEAD')
    ) {
      mode = decodeEmpty
    } else if (chunkedEncoding) {
      mode = decodeChunked
    } else if (contentLength !== undefined) {
      bytesLeft = contentLength
      mode = decodeCounted
    } else if (!head.keepAlive) {
      mode = decodeRaw
    }
    return [head, bodyStart]
  }

  // This is used for inserting a single empty string into the output string for known empty bodies
  function decodeEmpty (chunk, offset) {
    mode = decodeHead
    return [new Uint8Array(0), offset]
  }

  function decodeRaw (chunk, offset) {
    if (!chunk || chunk.length >= offset || !chunk.length) return;
    return [chunk.slice(offset), chunk.length]
  }

  function decodeChunked (chunk, offset) {
    // Make sure we have at least the length header
    let index = indexOf(chunk, '\r\n', offset)
    if (index < 0) return

    // And parse it
    let hex = binToRaw(chunk, offset, index)
    let length = parseInt(hex, 16)

    // Wait till we have the rest of the body
    let start = hex.length + 2
    let end = start + length
    if ((chunk.length - offset) < end + 2) return

    // An empty chunk means end of stream; reset state.
    if (length === 0) mode = decodeHead

    // Make sure the chunk ends in '\r\n'
    assert(binToRaw(chunk, end, end + 2) === '\r\n', 'Invalid chunk tail')

    return [chunk.slice(start, end), end + 2]
  }

  function decodeCounted (chunk, offset) {
    if (bytesLeft === 0) {
      mode = decodeEmpty
      return mode(chunk, offset)
    }
    let length = (chunk && chunk.length) - offset
    // Make sure we have at least one byte to process
    if (length <= 0) return

    if (length >= bytesLeft) { mode = decodeEmpty }

    // If the entire chunk fits, pass it all through
    if (length <= bytesLeft) {
      bytesLeft -= length
      return [chunk.slice(offset), chunk.length]
    }

    return [chunk.slice(offset, bytesLeft), offset + bytesLeft + 1]
  }

  // Switch between states by changing which decoder mode points to
  mode = decodeHead
  function decode (chunk, offset) {
    return mode(chunk, offset)
  }
  return decode
}
<|endoftext|>


<commit_before>import _ from 'lodash'

const events = [
  {
    "title": "Socket.io",
    "start": new Date("Wed Nov 28 2016 18:00:00 GMT-0500 (EST)"),
    "end": new Date("Wed Nov 28 2016 20:00:00 GMT-0500 (EST)"),
    "location": "Klaus 2456",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/socketio-logo.png",
    "description": "Come to learn more about utilizing WebSocket technology, using a javascript and nodejs library, Socket.io"
  },
  {
    "title": "MongoDB",
    "start": new Date("Wed Nov 15 2016 18:00:00 GMT-0500 (EST)"),
    "end": new Date("Wed Nov 15 2016 20:00:00 GMT-0500 (EST)"),
    "location": "Klaus 2456",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/gt-webdev-icon.png",
    "description": "Come to learn more about MongoDB and other database systems"
  },
  {
    "title": "Code and Chill",
    "start": new Date("Wed Nov 9 2016 18:30:00 GMT-0500 (EST)"),
    "end": new Date("Wed Nov 9 2016 20:30:00 GMT-0500 (EST)"),
    "location": "CCB 340",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/gt-webdev-icon.png",
    "description": "Come to chill with gt-webdev officers and other club members!"
  },
  {
    "title": "Code and Chill",
    "start": new Date("Wed Nov 2 2016 18:30:00 GMT-0400 (EDT)"),
    "end": new Date("Wed Nov 2 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "CCB 340",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/gt-webdev-icon.png",
    "description": "Come to chill with gt-webdev officers and other club members!"
  },
  {
    "title": "Deployment",
    "start": new Date("Tue Nov 1 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Nov 1 2016 20:00:00 GMT-0400 (EDT)"),
    "location": "Klaus 2456",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/gt-webdev-icon.png",
    "description": "Come to learn how to deploy your website and make it available to the world."
  },
  {
    "title": "Code and Chill",
    "start": new Date("Wed Oct 19 2016 18:30:00 GMT-0400 (EDT)"),
    "end": new Date("Wed Oct 19 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "CCB 340",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/gt-webdev-icon.png",
    "description": "Come to chill with gt-webdev officers and other club members!"
  },
  {
    "title": "Redux Tutorial",
    "start": new Date("Tue Oct 18 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Oct 18 2016 20:00:00 GMT-0400 (EDT)"),
    "location": "Klaus 2456",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/react-logo.png",
    "description": "Learn Redux and master front-end development!"
  },
  {
    "title": "Hang out with gt-webdev officers and buddies!",
    "start": new Date("Wed Oct 12 2016 18:30:00 GMT-0400 (EDT)"),
    "end": new Date("Wed Oct 12 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "CCB 340",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/gt-webdev-icon.png",
    "description": "Come today to hangout with fellow web developers and get your questions answered!"
  },
  {
    "title": "Home Depot: TDD with Ruby on Rails",
    "start": new Date("Wed Oct 5 2016 18:30:00 GMT-0400 (EDT)"),
    "end": new Date("Wed Oct 5 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "CCB 340",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/homedepot-icon.png",
    "description": "Come see Home Depot talk about Test Driven Development using Ruby on Rails!"
  },
  {
    "title": "ReactJS",
    "start": new Date("Tue Oct 4 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Oct 4 2016 20:00:00 GMT-0400 (EDT)"),
    "location": "Klaus 2456",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/react-logo.png",
    "description": "Come to learn a really cool front-end framework, ReactJS, and make your website dynamic"
  },
  {
    "title": "Introduction to Front-end Frameworks and Angular 1.5",
    "start": new Date("Wed Sep 28 2016 18:30:00 GMT-0400 (EDT)"),
    "end": new Date("Wed Sep 28 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "CCB 340",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/angularjs-logo.png",
    "description": "Come to this meeting to learn using a front-end framework and make cool web apps!"
  },
  {
    "title": "DOM Manipulation",
    "start": new Date("Tue Sep 27 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Sep 27 2016 20:00:00 GMT-0400 (EDT)"),
    "location": "Klaus 2456",
    "rsvpLink": "https://www.facebook.com/events/1841593719403441/",
    "image": "/img/internet.png",
    "description": "Learn how to use Javascript and JQuery to manipulate your web page to make it interactive!"
  },
  {
    "title": "Microsoft Azure Workshop",
    "start": new Date("Wed Sep 14 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Wed Sep 14 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "Howey L4",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/microsoft-azure-logo.png",
    "description": "Come to this workshop co-hosted by Microsoft and learn about Microsoft Cloud Platform and introductory workshop to making web and mobile apps using Azure App Service. Bring your resume for a chance to win an XBOX ONE!"
  },
  {
    "title": "Javascript",
    "start": new Date("Tue Sep 13 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Sep 13 2016 20:00:00 GMT-0400 (EDT)"),
    "location": "Klaus 2456",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/javascript-logo.png",
    "description": "Learn JavaScript from 0 to 10 and become a master of dynamic web application developer!"
  },
  {
    "title": "Web API",
    "start": new Date("Tue Sep 7 2016 18:30:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Sep 7 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "CCB 340",
    "rsvpLink": "http://www.facebook.com/events/1135467673207360/",
    "image": "/img/internet.png",
    "description": "Have you ever wondered how your web browser communicates with a server? Did you know that you can integrate your web applications with other web apps like Facebook, Google, or anything? Come to this meeting to learn more about the basics of Web API. We're also going to build a web app that is integrated with Facebook and Microsoft's Machine Learning Service."
  },
  {
    "title": "HTML/CSS",
    "start": new Date("Tue Sep 6 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Sep 6 2016 20:00:00 GMT-0400 (EDT)"),
    "location": "Klaus 2456",
    "rsvpLink": " https://www.facebook.com/events/1780166582229539/",
    "image": "/img/html5-logo.png",
    "description": "A web app without HTML/CSS is like a bird without wings. Learn the basics of web development by mastering HTML/CSS."
  },
  {
    "title": "Login Systems (Webdev Talk)",
    "start": new Date("Wed Aug 31 2016 18:30:00 GMT-0400 (EDT)"),
    "end": new Date("Wed Aug 31 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "CCB 340",
    "rsvpLink": "https://facebook.com/events/171006130000571/",
    "image": "/img/auth0.png",
    "description": "Almost every web application needs a login system. Learn how to efficiently create a secure login system using auth0 API in this meeting."
  },
  {
    "title": "Introduction to gt-webdev!",
    "start": new Date("Tue Aug 30 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Aug 30 2016 20:00:00 GMT-0400 (EDT)"),
    "location": "Klaus 1443",
    "rsvpLink": "https://facebook.com/GtWebdev",
    "image": "/img/gt-webdev-icon.png",
    "description": "Welcome to gt-webdev! Learn what gt-webdev is all about and expect a great meeting!"
  }
];

const nextEvent = (() => {
  const now = new Date();
  return _.reduce(events, (result, e) => {
    return e.end > now && e.end < result.end ? e : result;
  });
})();

const upcomingEvents = (() => {
  const now = new Date();
  return _.filter(events, (e) => {
    return e.end > now && e.end != nextEvent.end;
  }).sort((a, b)  => {
    return a.start < b.start ? -1 : 1;
  });
})();

const pastEvents = (() => {
  const now = new Date();
  return _.filter(events, (e) => {
    return e.end < now;
  }).sort((a, b) => {
    return a.start < b.start ? 1 : -1;
  });
})();

module.exports = {
  events,
  nextEvent,
  upcomingEvents,
  pastEvents
}
<commit_msg>Fixed meeting date<commit_after>import _ from 'lodash'

const events = [
  {
    "title": "Socket.io",
    "start": new Date("Tue Nov 29 2016 18:00:00 GMT-0500 (EST)"),
    "end": new Date("Tue Nov 29 2016 20:00:00 GMT-0500 (EST)"),
    "location": "Klaus 2456",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/socketio-logo.png",
    "description": "Come to learn more about utilizing WebSocket technology, using a javascript and nodejs library, Socket.io"
  },
  {
    "title": "MongoDB",
    "start": new Date("Tue Nov 15 2016 18:00:00 GMT-0500 (EST)"),
    "end": new Date("Tue Nov 15 2016 20:00:00 GMT-0500 (EST)"),
    "location": "Klaus 2456",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/gt-webdev-icon.png",
    "description": "Come to learn more about MongoDB and other database systems"
  },
  {
    "title": "Code and Chill",
    "start": new Date("Wed Nov 9 2016 18:30:00 GMT-0500 (EST)"),
    "end": new Date("Wed Nov 9 2016 20:30:00 GMT-0500 (EST)"),
    "location": "CCB 340",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/gt-webdev-icon.png",
    "description": "Come to chill with gt-webdev officers and other club members!"
  },
  {
    "title": "Code and Chill",
    "start": new Date("Wed Nov 2 2016 18:30:00 GMT-0400 (EDT)"),
    "end": new Date("Wed Nov 2 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "CCB 340",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/gt-webdev-icon.png",
    "description": "Come to chill with gt-webdev officers and other club members!"
  },
  {
    "title": "Deployment",
    "start": new Date("Tue Nov 1 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Nov 1 2016 20:00:00 GMT-0400 (EDT)"),
    "location": "Klaus 2456",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/gt-webdev-icon.png",
    "description": "Come to learn how to deploy your website and make it available to the world."
  },
  {
    "title": "Code and Chill",
    "start": new Date("Wed Oct 19 2016 18:30:00 GMT-0400 (EDT)"),
    "end": new Date("Wed Oct 19 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "CCB 340",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/gt-webdev-icon.png",
    "description": "Come to chill with gt-webdev officers and other club members!"
  },
  {
    "title": "Redux Tutorial",
    "start": new Date("Tue Oct 18 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Oct 18 2016 20:00:00 GMT-0400 (EDT)"),
    "location": "Klaus 2456",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/react-logo.png",
    "description": "Learn Redux and master front-end development!"
  },
  {
    "title": "Hang out with gt-webdev officers and buddies!",
    "start": new Date("Wed Oct 12 2016 18:30:00 GMT-0400 (EDT)"),
    "end": new Date("Wed Oct 12 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "CCB 340",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/gt-webdev-icon.png",
    "description": "Come today to hangout with fellow web developers and get your questions answered!"
  },
  {
    "title": "Home Depot: TDD with Ruby on Rails",
    "start": new Date("Wed Oct 5 2016 18:30:00 GMT-0400 (EDT)"),
    "end": new Date("Wed Oct 5 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "CCB 340",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/homedepot-icon.png",
    "description": "Come see Home Depot talk about Test Driven Development using Ruby on Rails!"
  },
  {
    "title": "ReactJS",
    "start": new Date("Tue Oct 4 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Oct 4 2016 20:00:00 GMT-0400 (EDT)"),
    "location": "Klaus 2456",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/react-logo.png",
    "description": "Come to learn a really cool front-end framework, ReactJS, and make your website dynamic"
  },
  {
    "title": "Introduction to Front-end Frameworks and Angular 1.5",
    "start": new Date("Wed Sep 28 2016 18:30:00 GMT-0400 (EDT)"),
    "end": new Date("Wed Sep 28 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "CCB 340",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/angularjs-logo.png",
    "description": "Come to this meeting to learn using a front-end framework and make cool web apps!"
  },
  {
    "title": "DOM Manipulation",
    "start": new Date("Tue Sep 27 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Sep 27 2016 20:00:00 GMT-0400 (EDT)"),
    "location": "Klaus 2456",
    "rsvpLink": "https://www.facebook.com/events/1841593719403441/",
    "image": "/img/internet.png",
    "description": "Learn how to use Javascript and JQuery to manipulate your web page to make it interactive!"
  },
  {
    "title": "Microsoft Azure Workshop",
    "start": new Date("Wed Sep 14 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Wed Sep 14 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "Howey L4",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/microsoft-azure-logo.png",
    "description": "Come to this workshop co-hosted by Microsoft and learn about Microsoft Cloud Platform and introductory workshop to making web and mobile apps using Azure App Service. Bring your resume for a chance to win an XBOX ONE!"
  },
  {
    "title": "Javascript",
    "start": new Date("Tue Sep 13 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Sep 13 2016 20:00:00 GMT-0400 (EDT)"),
    "location": "Klaus 2456",
    "rsvpLink": "https://www.facebook.com/GtWebdev",
    "image": "/img/javascript-logo.png",
    "description": "Learn JavaScript from 0 to 10 and become a master of dynamic web application developer!"
  },
  {
    "title": "Web API",
    "start": new Date("Tue Sep 7 2016 18:30:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Sep 7 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "CCB 340",
    "rsvpLink": "http://www.facebook.com/events/1135467673207360/",
    "image": "/img/internet.png",
    "description": "Have you ever wondered how your web browser communicates with a server? Did you know that you can integrate your web applications with other web apps like Facebook, Google, or anything? Come to this meeting to learn more about the basics of Web API. We're also going to build a web app that is integrated with Facebook and Microsoft's Machine Learning Service."
  },
  {
    "title": "HTML/CSS",
    "start": new Date("Tue Sep 6 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Sep 6 2016 20:00:00 GMT-0400 (EDT)"),
    "location": "Klaus 2456",
    "rsvpLink": " https://www.facebook.com/events/1780166582229539/",
    "image": "/img/html5-logo.png",
    "description": "A web app without HTML/CSS is like a bird without wings. Learn the basics of web development by mastering HTML/CSS."
  },
  {
    "title": "Login Systems (Webdev Talk)",
    "start": new Date("Wed Aug 31 2016 18:30:00 GMT-0400 (EDT)"),
    "end": new Date("Wed Aug 31 2016 20:30:00 GMT-0400 (EDT)"),
    "location": "CCB 340",
    "rsvpLink": "https://facebook.com/events/171006130000571/",
    "image": "/img/auth0.png",
    "description": "Almost every web application needs a login system. Learn how to efficiently create a secure login system using auth0 API in this meeting."
  },
  {
    "title": "Introduction to gt-webdev!",
    "start": new Date("Tue Aug 30 2016 18:00:00 GMT-0400 (EDT)"),
    "end": new Date("Tue Aug 30 2016 20:00:00 GMT-0400 (EDT)"),
    "location": "Klaus 1443",
    "rsvpLink": "https://facebook.com/GtWebdev",
    "image": "/img/gt-webdev-icon.png",
    "description": "Welcome to gt-webdev! Learn what gt-webdev is all about and expect a great meeting!"
  }
];

const nextEvent = (() => {
  const now = new Date();
  return _.reduce(events, (result, e) => {
    return e.end > now && e.end < result.end ? e : result;
  });
})();

const upcomingEvents = (() => {
  const now = new Date();
  return _.filter(events, (e) => {
    return e.end > now && e.end != nextEvent.end;
  }).sort((a, b)  => {
    return a.start < b.start ? -1 : 1;
  });
})();

const pastEvents = (() => {
  const now = new Date();
  return _.filter(events, (e) => {
    return e.end < now;
  }).sort((a, b) => {
    return a.start < b.start ? 1 : -1;
  });
})();

module.exports = {
  events,
  nextEvent,
  upcomingEvents,
  pastEvents
}
<|endoftext|>


<commit_before>var radius = 0.00076346643;
var MongoClient = require('mongodb').MongoClient;

var url = 'mongodb://localhost:27017/trails';
var database;
var songCollection;
var userCollection;

var connectToDatabase = function () {
    MongoClient.connect(url, function (err, db) {
        if (err)
            throw err;

        console.log("Connected to mongodb!");

        database = db;

        songCollection = db.collection('songs');
        userCollection = db.collection('users');
    });
};

var validateDatabase = function() {
    if (!database) {
        connectToDatabase();
    }

    if (!database.serverConfig.isConnected())
        connectToDatabase();
};

module.exports = {

    /*
    Return an array of song objects.
    When the function complete, invoke the completedCallback function with the array as a parameter, if an error
    occurred, then invoke the errorCallback with the error as a parameter
     */
    getSongs: function(lat, long, completedCallback, errorCallback) {
        validateDatabase();

        var lowerLat = lat - radius;
        var highLat = lat + radius;
        var lowerLong = long - radius;
        var highLong = long + radius;

        songCollection.find({
            'lat': {$gte: lowerLat, $lte: highLat},
            'long': {$gte: lowerLong, $lte: highLong}
        }).toArray(function(err, docs) {
            if (err)
                errorCallback(err);
            else
                completedCallback(docs);
        });
    },

    /*
     Return the song object saved/found
     When the function complete, invoke the completedCallback function with the array as a parameter, if an error
     occurred, then invoke the errorCallback with the error as a parameter
     */
    pushSong: function(lat, long, name, artist, completedCallback, errorCallback) {
        validateDatabase();

        var lowerLat = lat - radius;
        var highLat = lat + radius;
        var lowerLong = long - radius;
        var highLong = long + radius;

        songCollection.find({
            'name': name,
            'artist': artist,
            'lat': {$gte: lowerLat, $lte: highLat},
            'long': {$gte: lowerLong, $lte: highLong}
        }).toArray(function (err, docs) {
            if (err) {
                errorCallback(err);
                return;
            }

            if (docs.length > 0) {
                completedCallback(docs[0]);
            } else {
                songCollection.count({}, function (err, numOfDocs) {
                    if (err) {
                        errorCallback(err);
                        return;
                    }

                    var song = {
                        'id': numOfDocs,
                        'latitude': lat,
                        'longitude': long,
                        'name': name,
                        'artist': artist,
                        'user_id': -1,
                        'timePosted': Math.floor(new Date() / 1000),
                        'genre': []
                    };

                    songCollection.insert(song, function (err, result) {
                        if (err) {
                            errorCallback(err);
                            return;
                        }

                        completedCallback(song);
                    });
                });
            }
        });
    }
};<commit_msg>Fixed validateDatabase function<commit_after>var radius = 0.00076346643;
var MongoClient = require('mongodb').MongoClient;

var url = 'mongodb://localhost:27017/trails';
var database;
var songCollection;
var userCollection;

var connectToDatabase = function (completed) {
    MongoClient.connect(url, function (err, db) {
        if (err)
            throw err;

        console.log("Connected to mongodb!");

        database = db;

        songCollection = db.collection('songs');
        userCollection = db.collection('users');

        completed();
    });
};

var validateDatabase = function(completed) {
    if (!database) {
        connectToDatabase(completed);
    }
    else if (!database.serverConfig.isConnected())
        connectToDatabase(completed);
};

module.exports = {

    /*
    Return an array of song objects.
    When the function complete, invoke the completedCallback function with the array as a parameter, if an error
    occurred, then invoke the errorCallback with the error as a parameter
     */
    getSongs: function(lat, long, completedCallback, errorCallback) {
        validateDatabase(function() {
            var lowerLat = lat - radius;
            var highLat = lat + radius;
            var lowerLong = long - radius;
            var highLong = long + radius;

            songCollection.find({
                'lat': {$gte: lowerLat, $lte: highLat},
                'long': {$gte: lowerLong, $lte: highLong}
            }).toArray(function(err, docs) {
                if (err)
                    errorCallback(err);
                else
                    completedCallback(docs);
            });
        });
    },

    /*
     Return the song object saved/found
     When the function complete, invoke the completedCallback function with the array as a parameter, if an error
     occurred, then invoke the errorCallback with the error as a parameter
     */
    pushSong: function(lat, long, name, artist, completedCallback, errorCallback) {
        validateDatabase(function() {

            var lowerLat = lat - radius;
            var highLat = lat + radius;
            var lowerLong = long - radius;
            var highLong = long + radius;

            songCollection.find({
                'name': name,
                'artist': artist,
                'lat': {$gte: lowerLat, $lte: highLat},
                'long': {$gte: lowerLong, $lte: highLong}
            }).toArray(function (err, docs) {
                if (err) {
                    errorCallback(err);
                    return;
                }

                if (docs.length > 0) {
                    completedCallback(docs[0]);
                } else {
                    songCollection.count({}, function (err, numOfDocs) {
                        if (err) {
                            errorCallback(err);
                            return;
                        }

                        var song = {
                            'id': numOfDocs,
                            'latitude': lat,
                            'longitude': long,
                            'name': name,
                            'artist': artist,
                            'user_id': -1,
                            'timePosted': Math.floor(new Date() / 1000),
                            'genre': []
                        };

                        songCollection.insert(song, function (err, result) {
                            if (err) {
                                errorCallback(err);
                                return;
                            }

                            completedCallback(song);
                        });
                    });
                }
            });
        });
    }
};<|endoftext|>


<commit_before>$(document).ready(function() {
  $("#btn-run").click(function() {
    websiteRun($("#program").val());
  });
  /* If real time checking, run the program after each keyup but do not show
     a response */
  $("#chkbox-real-time").click(function() {
    if($(this).prop("checked")) {
      run($("#program").val());
      $("#program").keyup(function() {
        run($("#program").val());
      });
    } else {
      $("#program").off("keyup");
      $("#program-form-group").removeClass("has-success");
      $("#program-form-group").removeClass("has-error");
    }
  });
});
/* Parse Expression
 * Type "value" is a string or number
 * Type "word" is an identifier
 * Type "apply" is an application
 */
function parseExpression(program) {
  program = skipSpace(program);
  var match, expr;
  /* Disable JSHint warning about assignment in conditional expression */
  /* jshint -W084 */
  if (match = /^"([^"]*)"/.exec(program))
    expr = {type: "value", value: match[1]};
  else if (match = /^\d+\b/.exec(program))
    expr = {type: "value", value: Number(match[0])};
  else if (match = /^[^\s(),"]+/.exec(program))
    expr = {type: "word", name: match[0]};
  else
    throw new SyntaxError("Unexpected syntax: " + program);
  /* jshint +W084 */

  return parseApply(expr, program.slice(match[0].length));
}

/* Parse the application. E.g. +(1, 2) */
function parseApply(expr, program) {
  program = skipSpace(program);
  if (program[0] != "(")
    return {expr: expr, rest: program};

  program = skipSpace(program.slice(1));
  expr = {type: "apply", operator: expr, args: []};
  while (program[0] != ")") {
    var arg = parseExpression(program);
    expr.args.push(arg.expr);
    program = skipSpace(arg.rest);
    if (program[0] == ",")
      program = skipSpace(program.slice(1));
    else if (program[0] != ")")
      throw new SyntaxError("Expected ',' or ')'");
  }
  return parseApply(expr, program.slice(1));
}

/* Remove space and comments */
function skipSpace(string) {
  var regex = /(\s+|#.*?\n)/;
  match = regex.exec(string);

  while(match !== null && match.index === 0 ) {
    string = string.slice(match[0].length);
    match = regex.exec(string);
  }

  return string;
}

/* Parses the program and returns an object containing expressions
   and statements */
function parse(program) {
  var result = parseExpression(program);
  if (skipSpace(result.rest).length > 0)
    throw new SyntaxError("Unexpected text after program");
  return result.expr;
}

/* Evaluate an expression */
function evaluate(expr, env) {
  switch(expr.type) {
    case "value":
      return expr.value;

    case "word":
      if (expr.name in env)
        return env[expr.name];
      else
      /* jshint -W086 */
        throw new ReferenceError("Undefined variable: " +
                                 expr.name);
    case "apply":
      /* jshint +W086 */
      if (expr.operator.type === "word" &&
          expr.operator.name in specialForms)
        return specialForms[expr.operator.name](expr.args,
                                                env);
      var op = evaluate(expr.operator, env);
      if (typeof op != "function")
        throw new TypeError("Applying a non-function.");
      return op.apply(null, expr.args.map(function(arg) {
        return evaluate(arg, env);
      }));
  }
}

var specialForms = Object.create(null);

/* A "if" statement */
specialForms["if"] = function(args, env) {
  if (args.length != 3)
    throw new SyntaxError("Bad number of args to if");

  if (evaluate(args[0], env) !== false)
    return evaluate(args[1], env);
  else
    return evaluate(args[2], env);
};

/* A "while" loop */
specialForms["while"] = function(args, env) {
  if (args.length != 2)
    throw new SyntaxError("Bad number of args to while");

  while (evaluate(args[0], env) !== false)
    evaluate(args[1], env);

  /* Since undefined does not exist in Egg, we return false,
     for lack of a meaningful result. */
  return false;
};

/* A "do" loop */
specialForms["do"] = function(args, env) {
  var value = false;
  args.forEach(function(arg) {
    value = evaluate(arg, env);
  });
  return value;
};

/* Defines a variable and assigns new values. */
/* jshint -W069 */
specialForms["define"] = function(args, env) {
  if (args.length != 2 || args[0].type != "word")
    throw new SyntaxError("Bad use of define");
  var value = evaluate(args[1], env);
  env[args[0].name] = value;
  return value;
};
/* jshint +W069 */

/* A function */
specialForms.fun = function(args, env) {
  if (!args.length)
    throw new SyntaxError("Functions need a body");
  function name(expr) {
    if (expr.type != "word")
      throw new SyntaxError("Arg names must be words");
    return expr.name;
  }
  var argNames = args.slice(0, args.length - 1).map(name);
  var body = args[args.length - 1];

  return function() {
    if (arguments.length != argNames.length)
      throw new TypeError("Wrong number of arguments. Expected " +
        argNames.length + " got " + arguments.length);
    var localEnv = Object.create(env);
    for (var i = 0; i < arguments.length; i++)
      localEnv[argNames[i]] = arguments[i];
    return evaluate(body, localEnv);
  };
};

/* Array type. */
specialForms.array = function(args, env) {
  if (!args.length) {
    throw new SyntaxError("No elements given for array.");
  }
  var array = [];
  args.forEach(function(e) {
    array.push(evaluate(e, env));
  });
  return array;
};
/* Return array length */
specialForms.length = function(args, env) {
  if (!args.length) {
    throw new SyntaxError("Array.length: No array given");
  }
  if (args.length > 1) {
    throw new SyntaxError("Array.length: Too many arguments given. Expected" +
    "1 got " + args.length);
  }
  var array = evaluate(args[0], env);
  return array.length;
};

/* Get an element from an array */
specialForms.element = function(args, env) {
  console.log("array.element");
  console.log(args);
  if (args.length > 2 || args.length <= 0) {
    throw new SyntaxError("Array.element:  Incorrect number of arguments " +
    "given. Expected 2 got " + args.length);
  }
  var index = evaluate(args[1], env);
  var indexType = typeof index;
  if(indexType !== "number") {
    throw new TypeError("Array.element: Expected \"number\", got \"" +
    indexType + "\"");
  }
  var array = evaluate(args[0], env);
  console.log(array);
  if (index < 0 || index > array.length) {
    throw new Error("Array.element: index " + index + " out of bounds.");
  }
  return(array[index]);
};

/* Global environment with basic functions. */
var topEnv = Object.create(null);
topEnv["true"] = true;
topEnv["false"] = false;
/* jshint -W054 */
["+", "-", "*", "/", "==", "<", ">"].forEach(function(op) {
  topEnv[op] = new Function("a, b", "return a " + op + " b;");
/* jshint +W054 */
});
topEnv.print = function(value) {
  console.log(value);
  $("#output").val($("#output").val() + value + "\n");
  return value;
};

/* Convenience function to run programs */
function run() {
  try {
    var env = Object.create(topEnv);
    var program = Array.prototype.slice
    .call(arguments, 0).join("\n");
    hasError(false);
    return evaluate(parse(program), env);
  } catch(error) {
    console.log(error);
    $("#output").val(error);
    hasError(true);
    return error.toString();
  }
}

/* Convenience function to put program output onto web page. */
function websiteRun(program) {
  $("#output").val("");
  (run(program));
}

/* Track whether the program has an error. */
function hasError(error) {
  if (error) {
    $("#program-form-group").removeClass("has-success");
    $("#program-form-group").addClass("has-error");
  } else {
    $("#program-form-group").removeClass("has-error");
    $("#program-form-group").addClass("has-success");
  }
}
<commit_msg>Add function "set".<commit_after>$(document).ready(function() {
  $("#btn-run").click(function() {
    websiteRun($("#program").val());
  });
  /* If real time checking, run the program after each keyup but do not show
     a response */
  $("#chkbox-real-time").click(function() {
    if($(this).prop("checked")) {
      run($("#program").val());
      $("#program").keyup(function() {
        run($("#program").val());
      });
    } else {
      $("#program").off("keyup");
      $("#program-form-group").removeClass("has-success");
      $("#program-form-group").removeClass("has-error");
    }
  });
});
/* Parse Expression
 * Type "value" is a string or number
 * Type "word" is an identifier
 * Type "apply" is an application
 */
function parseExpression(program) {
  program = skipSpace(program);
  var match, expr;
  /* Disable JSHint warning about assignment in conditional expression */
  /* jshint -W084 */
  if (match = /^"([^"]*)"/.exec(program))
    expr = {type: "value", value: match[1]};
  else if (match = /^\d+\b/.exec(program))
    expr = {type: "value", value: Number(match[0])};
  else if (match = /^[^\s(),"]+/.exec(program))
    expr = {type: "word", name: match[0]};
  else
    throw new SyntaxError("Unexpected syntax: " + program);
  /* jshint +W084 */

  return parseApply(expr, program.slice(match[0].length));
}

/* Parse the application. E.g. +(1, 2) */
function parseApply(expr, program) {
  program = skipSpace(program);
  if (program[0] != "(")
    return {expr: expr, rest: program};

  program = skipSpace(program.slice(1));
  expr = {type: "apply", operator: expr, args: []};
  while (program[0] != ")") {
    var arg = parseExpression(program);
    expr.args.push(arg.expr);
    program = skipSpace(arg.rest);
    if (program[0] == ",")
      program = skipSpace(program.slice(1));
    else if (program[0] != ")")
      throw new SyntaxError("Expected ',' or ')'");
  }
  return parseApply(expr, program.slice(1));
}

/* Remove space and comments */
function skipSpace(string) {
  var regex = /(\s+|#.*?\n)/;
  match = regex.exec(string);

  while(match !== null && match.index === 0 ) {
    string = string.slice(match[0].length);
    match = regex.exec(string);
  }

  return string;
}

/* Parses the program and returns an object containing expressions
   and statements */
function parse(program) {
  var result = parseExpression(program);
  if (skipSpace(result.rest).length > 0)
    throw new SyntaxError("Unexpected text after program");
  return result.expr;
}

/* Evaluate an expression */
function evaluate(expr, env) {
  switch(expr.type) {
    case "value":
      return expr.value;

    case "word":
      if (expr.name in env)
        return env[expr.name];
      else
      /* jshint -W086 */
        throw new ReferenceError("Undefined variable: " +
                                 expr.name);
    case "apply":
      /* jshint +W086 */
      if (expr.operator.type === "word" &&
          expr.operator.name in specialForms)
        return specialForms[expr.operator.name](expr.args,
                                                env);
      var op = evaluate(expr.operator, env);
      if (typeof op != "function")
        throw new TypeError("Applying a non-function.");
      return op.apply(null, expr.args.map(function(arg) {
        return evaluate(arg, env);
      }));
  }
}

var specialForms = Object.create(null);

/* A "if" statement */
specialForms["if"] = function(args, env) {
  if (args.length != 3)
    throw new SyntaxError("Bad number of args to if");

  if (evaluate(args[0], env) !== false)
    return evaluate(args[1], env);
  else
    return evaluate(args[2], env);
};

/* A "while" loop */
specialForms["while"] = function(args, env) {
  if (args.length != 2)
    throw new SyntaxError("Bad number of args to while");

  while (evaluate(args[0], env) !== false)
    evaluate(args[1], env);

  /* Since undefined does not exist in Egg, we return false,
     for lack of a meaningful result. */
  return false;
};

/* A "do" loop */
specialForms["do"] = function(args, env) {
  var value = false;
  args.forEach(function(arg) {
    value = evaluate(arg, env);
  });
  return value;
};

/* Defines a variable and assigns new values. */
/* jshint -W069 */
specialForms["define"] = function(args, env) {
  if (args.length != 2 || args[0].type != "word")
    throw new SyntaxError("Bad use of define");
  var value = evaluate(args[1], env);
  env[args[0].name] = value;
  return value;
};

/* Assigns a value to an existing variable. Updates the variable in the outer scope if it doesn't exist in the inner scope. If the variable is not defined at all, throws a ReferenceError. */
specialForms["set"] = function(args, env) {
  if (args.length != 2 || args[0].type != "word")
    throw new SyntaxError("Bad use of set");
  var value = evaluate(args[1], env);

  while (env !== null && !(Object.prototype.hasOwnProperty.call(env, args[0].name))) {
    env = Object.getPrototypeOf(env);
  }

  // Check whether the variable was found
  if (env === null) {
    throw new ReferenceError("set: Cannot find variable " + args[0].name);
  }

  // The variable was found. Set the value in the found scope and return value.
  env[args[0].name] = value;
  return value;
};
/* jshint +W069 */

/* A function */
specialForms.fun = function(args, env) {
  if (!args.length)
    throw new SyntaxError("Functions need a body");
  function name(expr) {
    if (expr.type != "word")
      throw new SyntaxError("Arg names must be words");
    return expr.name;
  }
  var argNames = args.slice(0, args.length - 1).map(name);
  var body = args[args.length - 1];

  return function() {
    if (arguments.length != argNames.length)
      throw new TypeError("Wrong number of arguments. Expected " +
        argNames.length + " got " + arguments.length);
    var localEnv = Object.create(env);
    for (var i = 0; i < arguments.length; i++)
      localEnv[argNames[i]] = arguments[i];
    return evaluate(body, localEnv);
  };
};

/* Array type. */
specialForms.array = function(args, env) {
  if (!args.length) {
    throw new SyntaxError("No elements given for array.");
  }
  var array = [];
  args.forEach(function(e) {
    array.push(evaluate(e, env));
  });
  return array;
};
/* Return array length */
specialForms.length = function(args, env) {
  if (!args.length) {
    throw new SyntaxError("Array.length: No array given");
  }
  if (args.length > 1) {
    throw new SyntaxError("Array.length: Too many arguments given. Expected" +
    "1 got " + args.length);
  }
  var array = evaluate(args[0], env);
  return array.length;
};

/* Get an element from an array */
specialForms.element = function(args, env) {
  console.log("array.element");
  console.log(args);
  if (args.length > 2 || args.length <= 0) {
    throw new SyntaxError("Array.element:  Incorrect number of arguments " +
    "given. Expected 2 got " + args.length);
  }
  var index = evaluate(args[1], env);
  var indexType = typeof index;
  if(indexType !== "number") {
    throw new TypeError("Array.element: Expected \"number\", got \"" +
    indexType + "\"");
  }
  var array = evaluate(args[0], env);
  console.log(array);
  if (index < 0 || index > array.length) {
    throw new Error("Array.element: index " + index + " out of bounds.");
  }
  return(array[index]);
};

/* Global environment with basic functions. */
var topEnv = Object.create(null);
topEnv["true"] = true;
topEnv["false"] = false;
/* jshint -W054 */
["+", "-", "*", "/", "==", "<", ">"].forEach(function(op) {
  topEnv[op] = new Function("a, b", "return a " + op + " b;");
/* jshint +W054 */
});
topEnv.print = function(value) {
  console.log(value);
  $("#output").val($("#output").val() + value + "\n");
  return value;
};

/* Convenience function to run programs */
function run() {
  try {
    var env = Object.create(topEnv);
    var program = Array.prototype.slice
    .call(arguments, 0).join("\n");
    hasError(false);
    return evaluate(parse(program), env);
  } catch(error) {
    console.log(error);
    $("#output").val(error);
    hasError(true);
    return error.toString();
  }
}

/* Convenience function to put program output onto web page. */
function websiteRun(program) {
  $("#output").val("");
  (run(program));
}

/* Track whether the program has an error. */
function hasError(error) {
  if (error) {
    $("#program-form-group").removeClass("has-success");
    $("#program-form-group").addClass("has-error");
  } else {
    $("#program-form-group").removeClass("has-error");
    $("#program-form-group").addClass("has-success");
  }
}
<|endoftext|>


<commit_before>//index script
$(document).ready(function(){

  var pages = [];

  $.get( 'Scripts/template.html' ).then( function ( template ) {

    var ractive = new Ractive({
      el: '#containerTotal',

      template: template,

      data: {
        name : 'Charlie Lovering',
        sections : [],
        current_page : 3,
        current_project: 0,
        classes : [],
        jobs: [],
        projects: [],
        showC : function() {
          var l = projects[current_project].visuals.length;
          return (l > 0);
        }
      }
    });

    var resources = $.getJSON('Messages/resources.json');
    $.when(resources).done(function(r){
      ractive.set('sections', r.sections);
    });

    var info = $.getJSON('Messages/info.json');
    $.when(info).done(function(r){
      ractive.set('jobs', r.jobs);
      ractive.set('classes', r.classes);
      ractive.set('projects', r.projects);
    });

    ractive.on( 'toggle', function ( event ) {
      this.toggle( event.keypath + '.expanded' );
    });

    ractive.on({
      show: function ( event, which ) {
        if(which != ractive.get('current_page'))
        ractive.set( 'current_page', null ).then( function () {
          ractive.set( 'current_page', which );
          });

      }});

    ractive.on({

      showProject: function ( event, which ) {
        ractive.set( 'current_project', null ).then( function () {
          ractive.set( 'current_project', which );
        })
      },
      next: function ( event ) {
          var n = ractive.get("current_project");
          var l = ractive.get('projects').length;
          n += 1;
          if (n == l) {
            n = 0;
          }

          ractive.set( 'current_project', null ).then( function () {
          ractive.set( 'current_project', n );
        })
      },
      prev: function ( event ) {
          var n = ractive.get("current_project");
          n -= 1;
          if (n < 0) {
            var l = ractive.get('projects').length;
            n = l - 1;
          }
          ractive.set( 'current_project', null ).then( function () {
          ractive.set( 'current_project', n );
        })
      }
    });
  });
});<commit_msg>changing starting index<commit_after>//index script
$(document).ready(function(){

  var pages = [];

  $.get( 'Scripts/template.html' ).then( function ( template ) {

    var ractive = new Ractive({
      el: '#containerTotal',

      template: template,

      data: {
        name : 'Charlie Lovering',
        sections : [],
        current_page : 0,
        current_project: 0,
        classes : [],
        jobs: [],
        projects: [],
        showC : function() {
          var l = projects[current_project].visuals.length;
          return (l > 0);
        }
      }
    });

    var resources = $.getJSON('Messages/resources.json');
    $.when(resources).done(function(r){
      ractive.set('sections', r.sections);
    });

    var info = $.getJSON('Messages/info.json');
    $.when(info).done(function(r){
      ractive.set('jobs', r.jobs);
      ractive.set('classes', r.classes);
      ractive.set('projects', r.projects);
    });

    ractive.on( 'toggle', function ( event ) {
      this.toggle( event.keypath + '.expanded' );
    });

    ractive.on({
      show: function ( event, which ) {
        if(which != ractive.get('current_page'))
        ractive.set( 'current_page', null ).then( function () {
          ractive.set( 'current_page', which );
          });

      }});

    ractive.on({

      showProject: function ( event, which ) {
        ractive.set( 'current_project', null ).then( function () {
          ractive.set( 'current_project', which );
        })
      },
      next: function ( event ) {
          var n = ractive.get("current_project");
          var l = ractive.get('projects').length;
          n += 1;
          if (n == l) {
            n = 0;
          }

          ractive.set( 'current_project', null ).then( function () {
          ractive.set( 'current_project', n );
        })
      },
      prev: function ( event ) {
          var n = ractive.get("current_project");
          n -= 1;
          if (n < 0) {
            var l = ractive.get('projects').length;
            n = l - 1;
          }
          ractive.set( 'current_project', null ).then( function () {
          ractive.set( 'current_project', n );
        })
      }
    });
  });
});<|endoftext|>


<commit_before>import { DocumentSchema } from 'substance'
import InternalArticleDocument from './InternalArticleDocument'
import {
  Article, ArticleRef, Body, Metadata, Funder, Group, Organisation, Person, Keyword, Subject, Abstract,
  BlockFormula, BlockQuote, Figure, FigurePanel, Footnote, Heading, List, ListItem, Preformat, Paragraph,
  Table, TableFigure, TableRow, TableCell, Reference, BookRef, ChapterRef, ConferencePaperRef, DataPublicationRef,
  JournalArticleRef, MagazineArticleRef, NewspaperArticleRef, ReportRef, PatentRef, Permission, SoftwareRef,
  ThesisRef, WebpageRef, RefContrib, UnsupportedNode, UnsupportedInlineNode, Graphic, InlineGraphic,
  Bold, Italic, Subscript, Superscript, Monospace, Overline, Underline, SmallCaps, StrikeThrough, Break,
  ExternalLink, InlineFormula, Xref, SupplementaryFile, CustomMetadataField,
  ArticleTitleTranslation, ArticleAbstractTranslation
} from './models'

export default new DocumentSchema({
  name: 'TextureInternalArticle',
  version: '0.1.0',
  DocumentClass: InternalArticleDocument,
  // ATTENTION: while we have found a solution for defaultTextType of a container
  // this is still necessary because there are more places where schema.getDefaultTextType()
  // is used
  // TODO: try to eliminate this
  defaultTextType: 'paragraph',
  nodes: [
    Abstract,
    Article,
    ArticleAbstractTranslation,
    ArticleRef,
    ArticleTitleTranslation,
    BlockFormula,
    BlockQuote,
    Body,
    Bold,
    BookRef,
    Break,
    ChapterRef,
    ConferencePaperRef,
    CustomMetadataField,
    DataPublicationRef,
    ExternalLink,
    Figure,
    FigurePanel,
    Footnote,
    Funder,
    Group,
    Graphic,
    Heading,
    InlineFormula,
    InlineGraphic,
    Italic,
    JournalArticleRef,
    Keyword,
    List,
    ListItem,
    MagazineArticleRef,
    Metadata,
    Monospace,
    NewspaperArticleRef,
    Organisation,
    Overline,
    PatentRef,
    Paragraph,
    Permission,
    Person,
    Preformat,
    RefContrib,
    Reference,
    ReportRef,
    SmallCaps,
    SoftwareRef,
    StrikeThrough,
    Subject,
    Subscript,
    Superscript,
    SupplementaryFile,
    Table,
    TableCell,
    TableFigure,
    TableRow,
    ThesisRef,
    Underline,
    UnsupportedInlineNode,
    UnsupportedNode,
    WebpageRef,
    Xref
  ]
})
<commit_msg>Add custom abstract to the schema.<commit_after>import { DocumentSchema } from 'substance'
import InternalArticleDocument from './InternalArticleDocument'
import {
  Article, ArticleRef, Body, Metadata, Funder, Group, Organisation, Person, Keyword, Subject, Abstract,
  BlockFormula, BlockQuote, Figure, FigurePanel, Footnote, Heading, List, ListItem, Preformat, Paragraph,
  Table, TableFigure, TableRow, TableCell, Reference, BookRef, ChapterRef, ConferencePaperRef, DataPublicationRef,
  JournalArticleRef, MagazineArticleRef, NewspaperArticleRef, ReportRef, PatentRef, Permission, SoftwareRef,
  ThesisRef, WebpageRef, RefContrib, UnsupportedNode, UnsupportedInlineNode, Graphic, InlineGraphic,
  Bold, Italic, Subscript, Superscript, Monospace, Overline, Underline, SmallCaps, StrikeThrough, Break,
  ExternalLink, InlineFormula, Xref, SupplementaryFile, CustomMetadataField,
  ArticleTitleTranslation, ArticleAbstractTranslation, CustomAbstract
} from './models'

export default new DocumentSchema({
  name: 'TextureInternalArticle',
  version: '0.1.0',
  DocumentClass: InternalArticleDocument,
  // ATTENTION: while we have found a solution for defaultTextType of a container
  // this is still necessary because there are more places where schema.getDefaultTextType()
  // is used
  // TODO: try to eliminate this
  defaultTextType: 'paragraph',
  nodes: [
    Abstract,
    Article,
    ArticleAbstractTranslation,
    ArticleRef,
    ArticleTitleTranslation,
    BlockFormula,
    BlockQuote,
    Body,
    Bold,
    BookRef,
    Break,
    ChapterRef,
    ConferencePaperRef,
    CustomAbstract,
    CustomMetadataField,
    DataPublicationRef,
    ExternalLink,
    Figure,
    FigurePanel,
    Footnote,
    Funder,
    Group,
    Graphic,
    Heading,
    InlineFormula,
    InlineGraphic,
    Italic,
    JournalArticleRef,
    Keyword,
    List,
    ListItem,
    MagazineArticleRef,
    Metadata,
    Monospace,
    NewspaperArticleRef,
    Organisation,
    Overline,
    PatentRef,
    Paragraph,
    Permission,
    Person,
    Preformat,
    RefContrib,
    Reference,
    ReportRef,
    SmallCaps,
    SoftwareRef,
    StrikeThrough,
    Subject,
    Subscript,
    Superscript,
    SupplementaryFile,
    Table,
    TableCell,
    TableFigure,
    TableRow,
    ThesisRef,
    Underline,
    UnsupportedInlineNode,
    UnsupportedNode,
    WebpageRef,
    Xref
  ]
})
<|endoftext|>


<commit_before>/* eslint-disable default-case*/
module.exports = function(suc, err, status){
  return function(xhr){
    switch (status(xhr.status, xhr.readyState)){
      case -1:
        err(xhr.statusText);
        break;
      case 1:
        suc(xhr.responseText);
        break;
    }
  };
};
/* eslint-enable */
<commit_msg>fixing error handling<commit_after>/* eslint-disable default-case*/
module.exports = function(suc, err, status){
  return function(xhr){
    switch (status(xhr.status, xhr.readyState)){
      case -1:
        err(xhr.responseText, xhr.statusText);
        break;
      case 1:
        suc(xhr.responseText);
        break;
    }
  };
};
/* eslint-enable */
<|endoftext|>


<commit_before>var http   = require("http"),
    url    = require("url"),
    wompt  = require("./includes"),
    logger = wompt.logger,
    SocketIO= wompt.socketIO,
    express = require("express");

function App(options){
	this.meta_users = new wompt.MetaUserManager();
	this.channels = new wompt.ChannelManager();
	this.config = options.config;
	this.pretty_print_config();
	this.clients = new wompt.ClientPool();
	this.express = this.create_express_server();
	this.client_connectors = new wompt.ClientConnectors();
}

App.prototype = {
	pretty_print_config: function(){
		logger.log("Wompt.com started with config: ");
		logger.dir(this.config);
	},

	create_express_server:function(){
		var config = this.config;
		var exp = express.createServer();
		var me = this;

		exp.configure(function(){
			exp.use(me.statusMiddleware());
			exp.use(wompt.Auth.forward_to_auth_app_middleware());
			exp.use(express.logger({format: ':method :url :status :response-time' }));
			exp.use(express.staticProvider({root:config.public_dir, cache: config.perform_caching}));
			exp.use('/js', wompt.middleware.staticProvider({
				root:config.root + '/vendor/Socket.IO/',
				match: /^\/socket\.io\.js$/,
				cache: config.perform_caching
			}));
			exp.use(express.cookieDecoder());
			exp.use(express.bodyDecoder());
			exp.use(wompt.Auth.one_time_token_middleware());
			exp.use(wompt.Auth.lookup_user_middleware());
			exp.use(wompt.Auth.meta_user_middleware(me.meta_users));
		});

		exp.helpers({
			assets: new wompt.Helpers.Assets(this.config.root + '/public')
		});

		exp.set('views', wompt.env.root + '/views');
		exp.set('view engine', 'jade');

		this.plain_routes(exp, [
			,'/support'
			,'/terms'
			,'/privacy'
		]);

		exp.get(/\/chat\/(.+)/, function(req, res, params){
			var meta_user = req.meta_user,
					channel = req.params[0];

			var token = wompt.Auth.get_or_set_token(req, res);

			var connector = me.client_connectors.add({
				meta_user:meta_user,
				token: token
			});

			var locals = me.standard_page_vars(req, {
				channel: channel,
				connector_id: connector.id,
				url: req.url
			});

			res.render('chat', {
				locals:locals
			});
		});

		exp.get("/", function(req, res, params){
			wompt.Auth.get_or_set_token(req, res);
			res.render('index', {
				locals: me.standard_page_vars(req, {
					subtitle: me.choose_subtitle()
				})
			});
		});

		exp.post("/", function(req, res, params){
			wompt.Auth.get_or_set_token(req, res);
			res.redirect('/chat/' + req.body.channel);
		});

		if(wompt.env.force_sign_in){
			exp.get("/users/force_sign_in/:num", function(req, res, params){
				var num = parseInt(req.params.num);
				wompt.User.find().skip(num-1).first(function(user){
					if(user){
						wompt.Auth.start_session(res, user);
					}
					res.redirect('/');
				});
			});
		}

		exp.get("/users/sign_out", function(req, res, params){
			wompt.Auth.sign_out_user(req, res);
			res.redirect('/');
		});

		return exp;
	},

	standard_page_vars: function(req, custom_vars){
		var vars = {
			url: req.url,
			user: req.meta_user,
			footer: true,
			host: req.headers.host.split(':')[0],
			config: this.config
		};

		if(custom_vars){
			for(var k in custom_vars){
				vars[k] = custom_vars[k];
			}
		}
		return {
			w:vars
		};
	},

	choose_subtitle: function(){
		var subtitles = [
			 "Try it free, no signup required"
			,"Always free, sign in using Facebook"
		];
		return subtitles[Math.floor(Math.random() * subtitles.length)];
	},

	start_server: function(){
		this.express.listen(this.config.port, this.config.host);
		this.start_socket_io();

		logger.log("Starting server on port: " + this.config.port);
	},

	start_socket_io: function(){
		if(this.socket) return;
		var app = this;

		this.socket = SocketIO.listen(this.express);
		this.socket.on('connection', function(client){
			app.new_connection(client);
		});
	},

	new_connection: function(client){
		logger.log("Connection from: " + client.sessionId);
		var app = this;

		this.clients.add(client);

		client.once('message', function(data){
			if(data && data.action == 'join'){
				var connector = app.client_connectors.get(data.connector_id),
				    user      = connector.meta_user || new wompt.MetaUser();
				client.user = user;

				logger.log('Handing off client:' + client.sessionId + ' to Channel: ' + data.channel)
				var channel = app.channels.get(data.channel);
				if(channel){
					channel.add_client(client, connector.token);
				}
				user.clients.add(client);
			}
		});
	},

	statusMiddleware: function(){
		return function(req, res, next){
			if(req.url == '/ok'){
				res.send("OK", 200);
				res.end();
			}else{
				next();
			}
		};
	},

	plain_routes: function(exp, urls){
		var me = this;
		urls.forEach(function(url){
			var view = url.substr(1);
			exp.get(url, function(req, res, params){
				res.render(view, {
						locals: me.standard_page_vars(req)
					});
			});
		});
	},
}

module.exports = App;
<commit_msg>When a client connector isn't found, DONT crash.<commit_after>var http   = require("http"),
    url    = require("url"),
    wompt  = require("./includes"),
    logger = wompt.logger,
    SocketIO= wompt.socketIO,
    express = require("express");

function App(options){
	this.meta_users = new wompt.MetaUserManager();
	this.channels = new wompt.ChannelManager();
	this.config = options.config;
	this.pretty_print_config();
	this.clients = new wompt.ClientPool();
	this.express = this.create_express_server();
	this.client_connectors = new wompt.ClientConnectors();
}

App.prototype = {
	pretty_print_config: function(){
		logger.log("Wompt.com started with config: ");
		logger.dir(this.config);
	},

	create_express_server:function(){
		var config = this.config;
		var exp = express.createServer();
		var me = this;

		exp.configure(function(){
			exp.use(me.statusMiddleware());
			exp.use(wompt.Auth.forward_to_auth_app_middleware());
			exp.use(express.logger({format: ':method :url :status :response-time' }));
			exp.use(express.staticProvider({root:config.public_dir, cache: config.perform_caching}));
			exp.use('/js', wompt.middleware.staticProvider({
				root:config.root + '/vendor/Socket.IO/',
				match: /^\/socket\.io\.js$/,
				cache: config.perform_caching
			}));
			exp.use(express.cookieDecoder());
			exp.use(express.bodyDecoder());
			exp.use(wompt.Auth.one_time_token_middleware());
			exp.use(wompt.Auth.lookup_user_middleware());
			exp.use(wompt.Auth.meta_user_middleware(me.meta_users));
		});

		exp.helpers({
			assets: new wompt.Helpers.Assets(this.config.root + '/public')
		});

		exp.set('views', wompt.env.root + '/views');
		exp.set('view engine', 'jade');

		this.plain_routes(exp, [
			,'/support'
			,'/terms'
			,'/privacy'
		]);

		exp.get(/\/chat\/(.+)/, function(req, res, params){
			var meta_user = req.meta_user,
					channel = req.params[0];

			var token = wompt.Auth.get_or_set_token(req, res);

			var connector = me.client_connectors.add({
				meta_user:meta_user,
				token: token
			});

			var locals = me.standard_page_vars(req, {
				channel: channel,
				connector_id: connector.id,
				url: req.url
			});

			res.render('chat', {
				locals:locals
			});
		});

		exp.get("/", function(req, res, params){
			wompt.Auth.get_or_set_token(req, res);
			res.render('index', {
				locals: me.standard_page_vars(req, {
					subtitle: me.choose_subtitle()
				})
			});
		});

		exp.post("/", function(req, res, params){
			wompt.Auth.get_or_set_token(req, res);
			res.redirect('/chat/' + req.body.channel);
		});

		if(wompt.env.force_sign_in){
			exp.get("/users/force_sign_in/:num", function(req, res, params){
				var num = parseInt(req.params.num);
				wompt.User.find().skip(num-1).first(function(user){
					if(user){
						wompt.Auth.start_session(res, user);
					}
					res.redirect('/');
				});
			});
		}

		exp.get("/users/sign_out", function(req, res, params){
			wompt.Auth.sign_out_user(req, res);
			res.redirect('/');
		});

		return exp;
	},

	standard_page_vars: function(req, custom_vars){
		var vars = {
			url: req.url,
			user: req.meta_user,
			footer: true,
			host: req.headers.host.split(':')[0],
			config: this.config
		};

		if(custom_vars){
			for(var k in custom_vars){
				vars[k] = custom_vars[k];
			}
		}
		return {
			w:vars
		};
	},

	choose_subtitle: function(){
		var subtitles = [
			 "Try it free, no signup required"
			,"Always free, sign in using Facebook"
		];
		return subtitles[Math.floor(Math.random() * subtitles.length)];
	},

	start_server: function(){
		this.express.listen(this.config.port, this.config.host);
		this.start_socket_io();

		logger.log("Starting server on port: " + this.config.port);
	},

	start_socket_io: function(){
		if(this.socket) return;
		var app = this;

		this.socket = SocketIO.listen(this.express);
		this.socket.on('connection', function(client){
			app.new_connection(client);
		});
	},

	new_connection: function(client){
		logger.log("Connection from: " + client.sessionId);
		var app = this;

		this.clients.add(client);

		client.once('message', function(data){
			if(data && data.action == 'join'){
				var connector = app.client_connectors.get(data.connector_id),
				    user      = (connector && connector.meta_user) || new wompt.MetaUser();
				client.user = user;

				logger.log('Handing off client:' + client.sessionId + ' to Channel: ' + data.channel)
				var channel = app.channels.get(data.channel);
				if(channel){
					channel.add_client(client, connector && connector.token);
				}
				user.clients.add(client);
			}
		});
	},

	statusMiddleware: function(){
		return function(req, res, next){
			if(req.url == '/ok'){
				res.send("OK", 200);
				res.end();
			}else{
				next();
			}
		};
	},

	plain_routes: function(exp, urls){
		var me = this;
		urls.forEach(function(url){
			var view = url.substr(1);
			exp.get(url, function(req, res, params){
				res.render(view, {
						locals: me.standard_page_vars(req)
					});
			});
		});
	},
}

module.exports = App;
<|endoftext|>